views:

321

answers:

2

Hi guys, 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!

A: 

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+. :>

arul
A: 

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).

Ismael