So, I have a plugin to an MFC program. I'm using a mouse event hook (from SetWindowsHookEx) to capture clicks. The host application can have any number of (possibly overlapping) child windows open, but I only want to intercept clicks in a particular child window.
Is there a way to figure out in the hook proc which of the child windows would process the click? I guess it's something like enumerate all child windows, looking at Z-order, but I'm very unfamiliar with the MFC/Win32 libraries, and I'm not able to find any good discussion about how to enumerate all children and calculate which is topmost.
Maybe the WindowFromPoint API function fits the bill?
Retrieves a handle to the window that contains the specified point.
The documentation does not explicitly mention Z ordering, but I can assure you from first-hand experience that "contains" implicitly means that no other window is in front.
There are several more of these, with slightly different behaviour: ChildWindowFromPoint, ChildWindowFromPointEx and RealChildWindowFromPoint.
It's been a long time since I did MFC, but I think that HitTest is the term you're looking for. A quick trawl through MSDN indicates that most windows implement a HitTest function that returns information about a particular point.
Related
I am new to Windows programming, mostly done Java(Java SE, Java ME, Android, Java EE), so be detailed and gentle.
I want to capture "the name of the file/path that was clicked in windows, like clicking a file on the desktop"?
Further research http://www.codeproject.com/Articles/6362/Global-System-Hooks-in-NET, which is a small c#/c++ nice app that uses Global System Hooks, to capture mouse events such as coordinates,clicks,etc.
So what is the right API or Global System Hook that captures events on file icons?
There is no single API that provides that level of detail.
The WH_MOUSE and WH_MOUSE_LL hooks of SetWindowsHookEx(), or the WM_INPUT message delivered by RegisterRawInputDevices(), can tell when the mouse is being intereacted with, and the GetCursorPos() function can tell you where the mouse cursor is located onscreen at the time of a click, but it cannot tell you what it is clicking on. You have to figure that out manually.
For instance, the Desktop is implemented as a ListView control, so you can use the WindowFromPoint() and GetDesktopWindow() functions to check if the mouse is located at coordinates corresponding to the desktop window itself instead of an application window, and if so then use the LVM_HITTEST and LVM_GETITEM messages to determine which icon onthe desktop is being clicked on and extract its display text. Then use the SHGetDesktopFolder() function and the IShellFolder interface, or the SHParseDisplayName() function, to parse that text and see if it returns a PIDL that represents a path/file, and if so then use SHGetPathFromIDList() to get the actual path/file name.
If you want to do the same thing with the Windows Explorer app, it gets a bit more complicated. Use WindowFromPoint(), GetWindowThreadProcessId(), OpenProcess(), and EnumProcessModules() to determine if the mouse is over the Windows Explorer app. However, its UI changes from on Windows version to the next, but the jist is that you have to manually locate the focused control via AttachThreadInput() and GetActiveWindow(), check if it is a TreeView/ListView control, and if so then use control-specific messages to get information about the item/icon underneath the mouse cursor coordinates, and use IShellFolder again to figure out what the text of that item/icon actually represents.
Shell programming is very complex system and not for the feint of heart to interact with. So you need to ask yourself, why do you need this information in the first place?
I need to move the mouse to the last opened window. This last window will be a popup created by whatever website.
I guess all I need is to get the position of the last opened window and use SetMousePos, right?
I'm not really familiar with the windows API and any help is welcome - Thanks!
Edit:
To answer the questions, we are writing a program that gets malware data. Unfortunately some malware only start working after the mouse moves to a popup they opened. Its a research-based application
I haven't tested this but I believe you could try the following:
Enumerate running processes and order by PID.
The highest number PID should be the "newest" process.
For the newest process enumerate its windows (use GetWindowThreadProcessId)
At this point I guess you'd have to pick which window you think is the "main" window, for example if the malware opens two windows I don't know how you're going to choose which one to give focus to?
Of your picked HWND get its position on the desktop.
Use SetMousePos to move the mouse to the position of the window.
I haven't included all the API's you'll need for these tasks as its generally quite easy to find on here :)
One way to track recently opened windows is to use SetWinEventHook to listen to the EVENT_OBJECT_CREATE and EVENT_OBJECT_SHOW events. In the callback, filter:
just events with a non-null HWND where idObject==OBJID_WINDOW to get just window creation events (vs other creation events such as for items within a listbox)
for top-level only windows, also filter by checking GetAncestor(hwnd, GA_PARENT) is GetDesktopWindow()
And check that the window is indeed currently visible (WS_VISIBLE style is set in GetWindowLong(GWL_STYLE)).
Also filter by GetWindowThreadProcessId() and via the thread/process you pass into SetWinEventHook if you only care about HWNDs from a specific app.
The reason for checking both of these events is that some windows are created hidden and then shown, others are created fully visible, while others are created once, then shown/hidden many times over their lifetime.
You can then cache this 'last known created hwnd' in a global and check it as needed, using GetWindowRect() to get its location, and SetCursorPos() to move the mouse to that location.
--
If the most recent popup is an active window which takes focus - as is the case with dialogs, but not usually the case with 'pop-under' windows - you can use GetGUIThreadInfo(NULL, ...) to determine the currently active HWND, which might be the one you are looking for, returned in the GUITHREADINFO.hwndActive member of the struct you pass it.
I want to develop Windows program who can stick into other
window.
I searching fastest-way to do this. I can get by WinAPI all
information about target window and move my window into good location
and after it Sniffing Windows Messages of target window to searching resize or move window and after this doing move my window again. But i don't know what is a simplest good working way (maybe somewhat on .NET? But i don't preffer answers in .NET i like free framework's).
I want to stick on the top, bottom, left, right of the target window, but this maybe never mind.
Can anyone help me something with this problem?
Thanks.
I used DLLInjection to get into target windows process, created some hooks using winapi calls and by XML over Message Pipe transporting this values to other application who stick to this windows.
You basically need to do two things:
Get a list of all windows to which your app is supposed to stick, and their locations/dimensions.
Listen to your application's main window's move event and if at any point your window gets close enough to any of the relevant windows from #1 you move it yourself so that they align.
You can do both in Win32 API or with .Net. You just need a good criterion for #1. Like, for example, all top level visible windows that are within the desktop's boundaries.
Might want to include the desktop itself in the list above, so that your app sticks to the edges of the desktop as well.
I want to make a C++ button on Start>Run i.e but when I do it will not do signalled event?
Im sorry I have seen that you do not get the question.
Ok basically when you create a button with CreateWindowEx(); I want to do that but put on a different window with SetPArent which I have already done now the button does not work so I need my program to someone get when it is clicked from the Run window as example!
And yes you have it, but it's not making the button is the problem it's getting when it's clicked with my program since it does not belong to it anymore!
You need to apply the ancient but still-supported technique known in Windows as subclassing; it is well explained here (15-years-old article, but still quite valid;-). As this article puts it,
Subclassing is a technique that allows
an application to intercept messages
destined for another window. An
application can augment, monitor, or
modify the default behavior of a
window by intercepting messages meant
for another window.
You'll want "instance subclassing", since you're interested only in a single window (either your new button, or, the one you've SetParented your new button to); if you decide to subclass a window belonging to another process, you'll also need to use the injection techniques explained in the article, such as, injecting your DLL into system processes and watching over events with a WH_CBT hook, and the like. But I think you could keep the button in your own process even though you're SetParenting it to a window belonging to a different process, in which case you can do your instance subclassing entirely within your own process, which is much simpler if feasible.
"Superclassing" is an alternative to "subclassing", also explained in the article, but doesn't seem to offer that many advantages when compared to instance subclassing (though it may compared with global subclassing... but, that's not what you need here anyway).
You'll find other interesting articles on such topics here, here, and here (developing a big, rich C++ library for subclassing -- but, also showing a simpler approach based on hooks which you might prefer). Each article has a pretty difference stance and code examples, so I think that having many to look at may help you find the right mindset and code for your specific needs!
OK, I'll do my very best - as I understand you, you're trying to inject a button into some existing window. That meaning: Your tool creates a button in some window that does not belong to your application. Now, you want to be notified when that button is pressed. Am I correct so far?
To be notified about the button being pressed, you need to get the respective window message, which will only work if you also "inject" a different WndProc into the window. Actually I have no idea how that should work, but I faintly remember functions like GetWindowLong and SetWindowLong. Maybe they will help?
EDIT
I've searched MSDN a little: While you can get the address of a window's WndProc using GetWindowLong, you can not set the WndProc using SetWindowLong on Windows NT/2000/XP (and up I suppose). See here (MSDN).
So what you could do is install a global message hook that intercepts all window messages, filter those for the window you've injected the button into and then find your message. If you have trouble with this, however, I'm the wrong person to ask, because it's been years ago since I've done anything like that, but it would be stuff for a new question.
EDIT 2
Please see Alex Martinellis answer for how to define the hook. I think he's describing the technique I was referring to when I talked about defining global message hooks to intercept the window messages for the window you injected your button into.
I need to enumerate all running applications. In particular, all top windows. And for every window I need to add my custom item to the system menu of that window.
How can I accomplish that in C++?
Update.
I would be more than happy to have a solution for Windows, MacOS, and Ubuntu (though, I'm not sure if MacOS and Ubuntu have such thing as 'system menu').
For Windows, another way to get the top-level windows (besides EnumWindows, which uses a callback) is to get the first child of the desktop and then retrieve all its siblings:
HWND wnd = GetWindow(GetDesktopWindow(), GW_CHILD);
while (wnd) {
// handle 'wnd' here
// ...
wnd = GetNextWindow(wnd, GW_HWNDNEXT);
}
As for getting the system menu, use the GetSystemMenu function, with FALSE as the second argument. The GetMenu mentioned in the other answers returns the normal window menu.
Note, however, that while adding a custom menu item to a foreign process's window is easy, responding to the selection of that item is a bit tricky. You'll either have to inject some code to the process in order to be able to subclass the window, or install a global hook (probably a WH_GETMESSAGE or WH_CBT type) to monitor WM_SYSCOMMAND messages.
Once you have another window's top level handle, you may be able to call GetMenu() to retrieve the Window's system menu and then modify it, eg:
HMENU hMenu = GetMenu(hwndNext);
You can use EnumWindows() to enumerate top level Windows.
I don't have a specific answer for the second part of your question, but if you subclass the window, I imagine you can modify the system menu.
EDIT: or do what Chris said: call GetMenu()
Re: the update - please note that not even Microsoft Windows requires windows to have a sytem menu. GetMenu( ) may return 0. You'll need to intercept window creation as well, because each new top window presumably needs it too.
Also, what you propose is rather intrusive to other applications. How are you going to ensure they don't break when you modify their menus? And how are you going to ensure you suppress the messages? In particular, how will you ensure you intercept them before anyone else sees them? To quote Raymond Chen, imagine what happens if two programs would try that.