Link to home
Start Free TrialLog in
Avatar of johanhz
johanhz

asked on

Posting Keystrokes to the top window

Hi,

I want to post keystrokes to the active Window (can be notepad, wordpad, ...)
I tried with the GetForegroundWindow and then PostMessage with WM_KEYDOWN, WM_KEYUP or PostMessage with WM_CHAR.

The only program however that accepts the input is a CMD prompt. No other programs.
What am I doing wrong here?

OS : XP

Thanks for your help,

JOHan.
Avatar of Salte
Salte

You find the wrong window is one possibility.

GetForegroundWindow can be used to get the window that is in the foreground at the moment and that window is very likely to be a CMD prompt window if you start your program from the CMD prompt.

Try FindWindow() or FindWindowEx() functions to find the correct window and send WM_CHAR to it.

If you do send the WM_CHAR messages to the active window and it doesn't respond to those messages it can be that the program doesn't care about WM_CHAR messages. When you press a key on the keyboard windows send several messages to the application. First windows send a WM_KEYDOWN message to tell the application that "a key has been pressed". This message send the key in "raw" form and uses an enumeration defined by windows so that the return key is called VK_RETURN, The F1 key is VK_F1 etc.

Next windows send a WM_CHAR message. This is only used for 'translated' characters, i.e. letters and other characters that are input to the program. However, function keys and other such keys do not send a WM_CHAR message.

Further, some programs uses IME to read their input incase the user has an IME. I would assume wordpad or something used IME input in which case you have another set of messages for handling IME.

So, the applications may very well receive WM_CHAR messages and ignore them if it handles the WM_KEYDOWN or similar messages instead.

Alf
Avatar of johanhz

ASKER

Thanks for your comment, Alf
The problem is I don't know what application will be on top. It can be notepad, it can be wordpad, Visual Studio, etc ... So i don't think I can use the functions findwindow, findwindow ex.

If you take eg notepad, it has two windows. The main window and an edit window. Only if you send messages to the edit window, it will work. With Getforgroundwindow you get the main window. This throws away the keys.
But this presumes I know what application is on top, which I don't know.

Do I really need to write a driver to accomplish my question.
A driver won't solve your problem.

What happened if you tried WM_KEYDOWN to the application? This is the most basic windows message telling an application "the user pressed a key on the keyboard". WM_CHAR is a 'processed message.

To be safe you need to send booth messages in the correct sequence (WM_KEYDOWN first and then WM_KEYUP and then WM_CHAR).

Sending this to the 'main' window of an application should give some form of result.

The only exception is if the application uses IME messages, in that case you need to send IME messages also.

Are you sure you get the correct window with GetForegroundWindow?

If you get the wrong window it won't throw away the keys but it won't be the right window.

You could try to show some debug info and show the title of the window you get as 'Foregroundwindow' if this is a different window it is no wonder the application doesn't respond.

If you get the right window, then try to send it WM_KEYDOWN, WM_KEYUP and then WM_CHAR.

If that doesn't work, then tell me what you got from the debug printout.

Alf
Avatar of johanhz

ASKER

This is what I did :
I used the SPy++ tool that comes with visual Studio.
studied case : notepad
There are 2 windows present: a "main window handle" and a "edit window handle". If I use getforegroundwindow : I get the main window handle. If I send the keys to this window, nothing happens (but with spy++ i see that they enter the window). If I send the messages to the "edit window handle" : works great (Also works with all edit boxes, but I just need to know what the handle is, and with spy++ i know)
As you say : the sequence is WM_KEYDOWN, WM_CHAR, WM_KEYUP (i can trace this also with spy++)
So I am pretty sure the keys that I send work, but I just don't know where to send them to.

JOHan.
First off, it is possible it is wrong to send the keys directory to the edit window. This is because the application might want to process them first. sending the keys directly to the edit box will just insert the data into the edit window and it won't even bother to tell the application that it did so, the only way the application can find out is that it intercept the messages to the edit box and explicitely check for this possibility (most applications don't).

Of course, if the application just take the raw data from the edit box and save them to a file that is no problem but if the application is supposed to process the input first you're likely to end up in trouble. In other words, this won't work independently of the application.

You can easily get the handle of all sub windows of an application by using the FindWindow and related function calls.

It is possible that the notepad application simply doesn't process input but just set the edit box to have focus and then let the processing be done by the edit box itself. In that case it won't help to send keys to the application window. However, I would imagine that the normal way to handle it would be instead to let the application window take keyboard input and then forward it to the edit box.

It is possible that this isn't what notepad does. If so, you just have to find that edit box and send the keys directly to it. However, this is very application specific and there simply isn't any way to do this independent of the application.

May I ask what is the purpose of your application? Why do you want to send keys to 'whatever program is in forground'? If you don't know what application it is, you're most likely to not be able to know what to send to it anyway so why bother to make it 'application independent'?

Alf
Avatar of johanhz

ASKER

Alf,

Just found something interesting : have a look at the GetGUIThreadInfo API.
This is exactly what I want. If you call this api, it tells you which "window" from the foregroundwindow has the keyboard focus. (amongst other things)
The only thing now is that i get an error when compiling : 'GUITHREADINFO' : undeclared identifier. It is defined in winuser.h, and I included the file (and windows.h). I just can't figure out why my program gives this error.

JOHan.
Avatar of johanhz

ASKER

Sorry,

Forgot to answer the purpose of the application...
We have to our PC a serial keyboard attached. I want this keyboard to behave like a standard AT keyboard, so I must send the (serial) keys to the topmost application that has the keyboard focus, so it receives the keys just as if they were comming from the at keyboard.

As I mentioned, with getforegroundwindow() this works only in 50% of the applcitions.

JOHan.
Avatar of johanhz

ASKER

Sorry,

Forgot to answer the purpose of the application...
We have to our PC a serial keyboard attached. I want this keyboard to behave like a standard AT keyboard, so I must send the (serial) keys to the topmost application that has the keyboard focus, so it receives the keys just as if they were comming from the at keyboard.

As I mentioned, with getforegroundwindow() this works only in 50% of the applcitions.

JOHan.
Avatar of johanhz

ASKER

OK, this does the JOB 100% correct

bla bla ..
GUITHREADINFO gui;

gui.cbSize = sizeof(GUITHREADINFO);
GetGUIThreadInfo(NULL,&gui); // get the foreground handle
hwndForeGround = gui.hwndFocus; // get the handle of the foregroundwindow that has the keyboard focus
::PostMessage(hwndForeGround,WM_CHAR,0x36,0x36); // just testing; in fact use WM_KEYDOWN, WM_CHAR,WM_KEYUP


Note : min requirements: WIN98 and WINNT SP3
You must install the SDK from microsoft, otherwise it wont compile!!

Thanks for your help, Alf.
Post me your comment And I will give you the points.

JOHan.
Sounds like you found an answer to your problem.

Yes, if you get the window that has the focus for the application it is - by definition - the one that is supposed to receive keyboard keys etc.

It is possible you can find it by searching through child windows and query if they have focus or not but why bother if there is a function that does it for you.

Only problem is that it appears it won't work for more modern systems such as WinXP so when you upgrade to those systems you probably have to use some other function to get it done.

I have no idea how you can do it on WinXP.

Alf
ASKER CERTIFIED SOLUTION
Avatar of Salte
Salte

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of johanhz

ASKER

Yep,

Tested on XP and 2000.
Works fine.

Thanks for your support.

JOHan.
Avatar of johanhz

ASKER

Your points ...