I have this problem. I have an handler to the mainWindow of a certain application, and I want to simulate a keypress on that application...
I'm using sendMessage/postMessage api calls to do this. The reason why I don't use the .Net SendKeys function or the keybd_event of the win32 api, is that they simulate the keypress at a global level. In my case, I may have the application minimized and still want the keypress to be simulated.
The problem with sendMessage and postMessage is that you must pass the handler of the exact childwindow where you want the key to be pressed. For example, in notepad, if I send the key to the mainWindow, nothing happens, I have to send the key to the child window that basically consists of the white canvas where you can write.
With msPaint for example, if a user creates a new document, and opens a textbox in that drawing, and I want to simulate a keypress there, I have to get the childwindow of the childwindow of the mainwindow for it to works.
So I found a way that seemed to work for every situation, basically, I used getWindow with the parameter GW_CHILD, to get the child-window with the highest z-value. Then I do it again for the child window and continue doing it until a certain childWindow has no more childWindows..
And it seemed to work and I was very happy!
However... I found cases where this does not work. Firefox is one of them. Firefox has the mainWindow, and then has a childWindow that's pretty much the same as the mainWindow and then it has another childWindow which is the website area, ie, the area under the address bar and menus. If I am on www.google.com for example, and I want to simulate a keypress in the focused search box, it works, cause getting the child-window of the child-window gives me the correct childWindow. However, if the user clicks on the address bar for example, nothing changes in the way the getWindow works. It will still eventually get the childwindow that's under the address bar, doing nothing, instead of simulating the keypress on the address bar.
The thing is that I haven't found a way of getting the active child window of a certain application. I can only use the GetWindow method to get the child window of a certain window and do it until I find a child window with no childs. However, as you've seen in the firefox case, the active window is actually the parent of the child window that I get in the end.
I've tried other api calls like getTopWindow but I had no luck..
Anyone can put some light on this issue?
Thanks!
If the application violates the windowing rules of windows, you'll need an exception.
In Mozilla, it's like this (IIRC):
There's this 'god' window of the class MozillaUIWindowClass and with the "- Mozilla Firefox" string in its window text.
If you know the position of the address bar you can use the following function:
And provide it with the HWND of the 'god' window and the position of the address bar.
HWND ChildWindowFromPoint(HWND, POINT);
There is probably a better solution, I came up with this since I needed to automate mouse, which is position based.
For more information you might need to consult the sources of particular software, or spend whole day in Spy+. :>
You can use GetGUIThreadInfo to get info about the UI of a particular process.
If you have the main window you can call GetWindowThreadProcessId to obtain the process thread id. Then you can call GetGUIThreadInfo to get info about the active/focused windows, etc.
I also have to point that some applications only have one window and all its controls are windowsless (like Windows Live Messenger).
Related
I have seen several tools adding a custom button and/or drawing on the title bar of all windows of all applications in Windows. How is that done?
Extra points for an example in Delphi.
EDIT:
I found something for dotNET that does this:
http://www.thecodeking.co.uk/2007/09/adding-caption-buttons-to-non-client.html#.VdmioEDenqQ
How I see this job:
First of all we should be able to paint this button on the our own window caption. This procedure will be used later
This part of the program enumerates the active and visible windows
This part of the program using injection attach our dll to enumerated windows
From injected dll we can draw the button on the window caption
Inside this dll we should process the click on the button
We should have mechanism to send result to our main program
I haven't done this, so the following is what I would investigate if I were to try:
For each application / each top-level window:
Create a floating window and position it over the title bar wherever you want it to sit. Set up the parent / child relationship, but this window is part of your own process. (There are occasionally problems parenting a window from one process to one from another process, but try. I'd avoid injecting into other processes if possible.)
You can investigate the window flags to see if the window has a title bar (ie if you should add a button) via GetWindowLong with GWL_STYLE looking for WS_CAPTION. The same call will also let you see the type of caption / frame, which you can combine with GetSystemMetrics with, eg, SM_CYDLGFRAME to figure out the right size for your button on this specific window's title bar.
This window is now your button: paint, handle clicks etc as appropriate.
Make it a non-focusable window so that clicks to it don't take focus away from the window is is on the title bar of. You don't want clicking it to make the title bar change colour, for example. Do this by setting the WS_EX_NOACTIVATE window flag, something like: SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) orWS_EX_NOACTIVATE).
The main problem is to keep it positioned correctly when the window moves, is resized, etc. To do this, install a hook for the system move events. You can also hook minimize and restore via EVENT_SYSTEM_MINIMIZESTART and EVENT_SYSTEM_MINIMIZEEND. This will allow you to keep track of all windows moving around onscreen, such that you can adjust the button-window position if necessary.
That gives you a window which you can paint as a button (and respond to clicks etc), that visually is "attached" to other windows so it stays in the same place as the user drags the title bar, minimizes or maximises the app, etc, and that is in your own process without cross-process problems.
I've been trying to obtain text from a panel that's part of a third-party application; I have the process ID. To do this, I've gone through the usual EnumProcessModulesEx / GetModuleBaseName / EnumWindows / EnumChildWindows steps. This code works when the panel is shown, but when it's hidden, the panel is no longer seen by my code or Spy++. I'd figured the panel must be destroyed and re-created as the user hides and shows the panel, but it turns out that the HWND of the panel is valid in both situations (GetWindow, GetTitle, etc. all return without errors, and with the same information, so the handle hasn't been re-used); the only difference is that its parent is different. When I trace the parent chain back to the root, the topmost parent's title is WindowsFormsParkingWindow, same process ID. I searched for WindowsFormsParkingWindow, and it seems to be a temporary place to "park" a HWND when you don't need it, so you won't have to re-create the window and its children. Does anyone know of an API for traversing the WindowsFormsParkingWindow hierarchy, or some other way of getting to this panel? Thanks for any advice.
WindowsFormsParkingWindow is a message-only window.
You can enumerate message-only windows by calling FindWindowEx with the special window handle HWND_MESSAGE.
Based on information from this blog:
Flashback: Windows Forms Parking Window
The Parking Window is just a generic parent window used for arbitrarily re-parenting child windows onto during parent window recreations. There is no API to query information from the Packing Window itself, such as the original parent window for any given parked child window. Only the original parent/control knows which child HWND(s) have been parked so they can be retrieved when needed.
The best you are likely to accomplish is to detect when the panel is visible, remember that HWND, and then just use that HWND when needed, even when the panel is not visible. Or at least enumerate the WindowsFormsParkingWindow to check if that HWWND is still a child of it, etc. But if the panel is losing its text while parked, then you are likely to be out of luck.
I am trying to emulate simple mouse movement in a window belonging to another process. My app uses global hooks to inject DLL into the target process (WH_CBT and WH_GETMESSAGE) and the injection works like a charm. The intention is to fool the target process into thinking the mouse went over a portion of the screen. When I do a movement with the physical mouse, this triggers a certain app behavior (e.g. a tooltip is being shown). I would prefer if the actual mouse pointer remained in its current position when I perform the "trick".
I have established message monitoring with Spy++. Sending (or posting) plain WM_MOUSEMOVE messages to the target HWND is registered by Spy++ but has no desired effect. When the mouse is physically moved, the app does its thing. I have tried sending some other messages in conjunction to WM_MOUSEMOVE (e.g. WM_SETCURSOR) but things didn't improve. I have even hijacked GetCursorPos in the target process to return the same coordinate as posted in WM_MOUSEMOVE (former is screen, latter is client) but this didn't help either.
When I do a simple SetCursorPos, the app does what it's supposed to do. What other magic am I missing that the SetCursorPos is doing? The messages captured by Spy++ look more or less the same in both scenarios.
Any suggestions on how to send mouse movement are welcome. I do not want to use SendInput, mouse_event or other APIs. I need to target a specific HWND for a very brief period of time.
Usually a tooltip is shown as a result of the WM_NOTIFY message, which is sent with the TTN_SHOW notification code. Have you tried it?
To prevent users from clicking in my main_window when a MessageBox appears I have used:
EnableWindow(main_window,FALSE);
I got a sample MessageBox:
EnableWindow(main_window,FALSE);
MessageBox(NULL,"some text here","About me",MB_ICONASTERISK);
EnableWindow(main_window,TRUE);
The problem is that when I press "OK" on my MessageBox it closes and my main_window is send to back of all other system windows. Why this is happening?
I tried to put:
SetFocus(main_window);
SetActiveWindow(main_window);
after and before : EnableWindow(main_window,TRUE) the result was strange: it worked 50/50. Guess I do it the way it shouldn't be.
Btw.
Is there a better solution to BLOCK mouse click's on specific window than:
EnableWindow(main_window,FALSE);
Displaying modal UI requires that the modal child is enabled and the owner is disabled. When the modal child is finished the procedure has to be reversed. The code you posted looks like a straight forward way to implement this.
Except, it isn't.
The problem is in between the calls to MessageBox and EnableWindow, code that you did not write. MessageBox returns after the modal child (the message box) has been destroyed. Since this is the window with foreground activiation the window manager then tries to find a new window to activate. There is no owning window, so it starts searching from the top of the Z-order. The first window it finds is yours, but it is still disabled. So the window manager skips it and looks for another window, one that is not disabled. By the time the call to EnableWindow is executed it is too late - the window manager has already concluded that another window should be activated.
The correct order would be to enable the owner prior to destroying the modal UI.
This, however, is only necessary if you have a reason to implement modality yourself. The system provides a standard implementation for modal UI. To make use of it pass a handle to the owning window to calls like MessageBox or CreateDialog (*), and the window manager will do all the heavy lifting for you.
(*): The formal parameter to CreateDialog is unfortunately misnamed as hWndParent. Parent-child and owner-owned relationships are very different (see About Windows).
I am trying to insert a custom widget into the Internet Explorer 8 url bar, next to the stop and reload buttons. This is just a personal productivity enhancer for myself.
The "window model" for this part of the IE frame is an "address bar root" window that owns the windows which comprise the IE8 url bar: an edit box, a combo control, and the stop and reload buttons.
From another process, I create a new WS_CHILD window (with a custom class name) that is parented by IE's address bar root window, thus making it a sibling of the edit box and stop/reload. I call SetWindowPos with an hwndInsertAfter of HWND_TOP to make sure it appears "above" (i.e. "in") the urlbar. This works nicely, and I see my window painted initially inside the IE urlbar.
However, when I activate the IE window, the urlbar edit control jumps back in front of my window. I know this is happening because I still see my window painted behind the urlbar, and because when I print ->GetTopWindow() to the debug console on a timer, it becomes the HWND of the urlbar edit control.
If I update my message loop to call SetWindowPos with HWND_TOP on WM_PAINT, things are better -- now when I activate the IE window and move it around, my control properly stays planted above the edit control in the urlbar. However, as soon as I switch between IE tabs, which updates the text of IE's urlbar Edit control, my control shift backs behind the Edit control. (Note: This also happens when I maximize or restore the window.)
So my questions are:
1) Is it likely that IE is intentionally putting its urlbar edit control back on top of the z-order every time you click on a tab in IE, or is there a gap in my understanding of how Windows painting and z-ordering works? My understanding is that once you specify z-ordering of child windows (which are not manipulable by the end-user), that ordering should remain until programmatically changed. So even though IE is repainting its Edit control upon tab selection whereas I am not repainting or otherwise acting upon my window, my window should stil remain firmly on top.
2) Given that the z-order of my window is apparently changing, shouldn't it receive a WM_WINDOWPOSCHANGING/WM_WINDOWPOSCHANGED? If it did, I could at least respond to that event and keep myself on top of the Edit control. But even though I can see my window painting behind the urlbar Edit control when I click on a tab, and even though my debug window output confirms that the address bar root's GetTopWindow() becomes the HWND of the Edit control when I click on a tab, and even though I see WM_WINDOWPOSCHANGING/WM_WINDOWPOSCHANGED being sent to the Edit control with an hwndInsertAfter of HWND_TOP when I click on a tab, my own window receives no messages whatsoever that would allow me to keep the z-order constant. This seems wrong to me, and addressing it would force me to run in IE's process and hook all messages sent to its Edit control just to have an event to respond to :(
Thank you for your help!
It's quite likely that IE is juggling the Z-order of the controls when you change tabs. In IE9, the URL bar and the tabs have a common parent. When you select a new tab, it activates the URL bar (and activation usually brings the window to the top of its local Z order).
No. You get WM_WINDOWPOSCHANGED when a SetWindowPos function acts on your window. If some of the siblings have their z-orders changed, you don't get a message. Nobody called SetWindowPos on your window. You can see this by writing a test program that juggles the z-order of some child windows.
This makes sense because there might be an arbitrary number of sibling windows, and it could be an unbounded amount of overhead to notify all of them. It also would be nearly impossible to come up with a consistent set of rules for delivering these messages to all the siblings given that some of the siblings could react by further shuffling the z-order. Do the siblings that haven't yet received the first notification now have two pending notifications? Do they get posted or dispatched immediately? What if the queue grows and grows until it overflows?
This is different from WM_KILLFOCUS/WM_SETFOCUS notifications in that it affects, at most, two windows. That puts a reasonable bound on the number of notifications. Even if there's a runaway infinite loop because the losing control tries to steal the focus back, the queue won't overflow because there's only one SetFocus call for each WM_KILLFOCUS delivered.
Also, it's reasonable that windows might need to react to a loss of focus. It's much less likely that window C needs to know that B is now on top of A instead of the other way around, so why design the system to send a jillion unnecessary messages?
Hacking the UI of apps you don't control and that don't have well-defined APIs for doing the types of things you want to do is anywhere from hard to impossible, and it's always fragile. Groups that put out toolbars and browser customizations employee more people than you might expect, and they spend much of their day probing with Spy++ and experimenting. It is by nature hacking.