EDN Admin
Well-known member
I am writing an application that sends keystrokes to another application using the SendMessage function defined in *user32.dll*. I have figured out how to send a single keystroke but I am stumped trying to send the keystroke along with the ALT key.<br/>
<br/>
For the purposes of my question I will focus on sending F1, and ALT + F1.<br/>
<br/>
As stated above, I am able to send the F1 key no problem. Here is a snippet of my code that sends the F1 key:<br/>
<br/>
// DLL Imports<br/>
<br/>
//Set the active window<br/>
[DllImport("user32.dll")]<br/>
public static extern IntPtr SetActiveWindow(IntPtr hWnd);<br/>
<br/>
//sends a windows message to the specified window<br/>
[DllImport("user32.dll")]<br/>
public static extern int SendMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);<br/>
<br/>
// ...<br/>
<br/>
// Some constants<br/>
#define WM_SYSKEYDOWN 260<br/>
#define WM_SYSKEYUP 261<br/>
#define WM_CHAR 258<br/>
#define WM_KEYDOWN 256<br/>
#define WM_KEYUP 257<br/>
<br/>
// ...<br/>
<br/>
// activate the window and send F1<br/>
SetActiveWindow(hWnd);<br/>
ushort action = (ushort)WM_SYSKEYDOWN;<br/>
ushort key = (ushort)System.Windows.Forms.Keys.F1;<br/>
SendMessage(hWnd, action, key, 0);<br/>
<br/>
One interesting side note is that even though the above code works in sending the F1 key to the target application it is not the same as what I see using Spy++. Here is the output of the Spy++ log whenever I hit the F1 key while monitoring the target application:<br/>
<br/>
<00001> 00050412 P WM_KEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00002> 00050412 P WM_KEYUP nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:0 fRepeat:1 fUp:1<br/>
<br/>
Note that there are two messages sent, WM_KEYDOWN and WM_KEYUP. <br/>
<br/>
*My first question would be, why am I succesful sending F1 using WM_SYSKEYDOWN when Spy++ tells me that WM_KEYDOWN/WM_KEYUP is the proper message sequence?*<br/>
<br/>
Moving on to my next challenge of trying to send ALT + F1. <br/>
<br/>
I have used Spy++ to monitor the messages passed when pressing ALT + F1 on my keyboard and this is what I see:<br/>
<br/>
<00001> 00050412 P WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:1 fAltDown:1 fRepeat:0 fUp:0<br/>
<00002> 00050412 P WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:0 fUp:0<br/>
<00003> 00050412 P WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:1 fUp:1<br/>
<00004> 00050412 P WM_KEYUP nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:1 fAltDown:0 fRepeat:1 fUp:1<br/>
<br/>
Given the above Spy++ message capture I tried to send the exact message sequence using the following code (simplified):<br/>
<br/>
SetActiveWindow(hWnd); <br/>
SendMessage(hWnd, (ushort)WM_SYSKEYDOWN, (ushort)System.Windows.Forms.Keys.Menu, 0);<br/>
SendMessage(hWnd, (ushort)WM_SYSKEYDOWN, (ushort)System.Windows.Forms.Keys.F1, 0);<br/>
SendMessage(hWnd, (ushort)WM_SYSKEYUP, (ushort)System.Windows.Forms.Keys.F1, 0);<br/>
SendMessage(hWnd, (ushort)WM_KEYUP, (ushort)System.Windows.Forms.Keys.Menu, 0);<br/>
<br/>
This did not work.<br/>
<br/>
*And so this leads to my next question. Is there anything else I can try or is there something that I am doing wrong here?*<br/>
<br/>
Whenever I captured the output of my program using Spy++ here is what was logged:<br/>
<br/>
<00001> 00050412 S WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00002> 00050412 R WM_SYSKEYDOWN<br/>
<00003> 00050412 S WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00004> 00050412 R WM_SYSKEYDOWN<br/>
<00005> 00050412 S WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00006> 00050412 R WM_SYSKEYUP<br/>
<00007> 00050412 S WM_KEYUP nVirtKey:VK_MENU cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00008> 00050412 R WM_KEYUP<br/>
<br/>
Notice that there are *extra* messages being sent at lines 2, 4, 6, and 8. *Could this be the reason why things are not working?*<br/>
<br/>
I have one final question regarding the difference between the messages captured from actual keyboard input and those captured using my application. Notice the *cRepeat*, *ScanCode*, *fExtended*, etc. *arguments*. They are non-zero in the messages that were<br/>
captured using my keyboard as the input and they are all zero in the messages sent by my application. *Could this be the reason why my code is not working?* *If so, how do I modify these values?* (I am assuming they come from the 4th argument to the SendMessage<br/>
function, which I have set to zero in all cases.)<br/>
<br/>
Thank you
View the full article
<br/>
For the purposes of my question I will focus on sending F1, and ALT + F1.<br/>
<br/>
As stated above, I am able to send the F1 key no problem. Here is a snippet of my code that sends the F1 key:<br/>
<br/>
// DLL Imports<br/>
<br/>
//Set the active window<br/>
[DllImport("user32.dll")]<br/>
public static extern IntPtr SetActiveWindow(IntPtr hWnd);<br/>
<br/>
//sends a windows message to the specified window<br/>
[DllImport("user32.dll")]<br/>
public static extern int SendMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);<br/>
<br/>
// ...<br/>
<br/>
// Some constants<br/>
#define WM_SYSKEYDOWN 260<br/>
#define WM_SYSKEYUP 261<br/>
#define WM_CHAR 258<br/>
#define WM_KEYDOWN 256<br/>
#define WM_KEYUP 257<br/>
<br/>
// ...<br/>
<br/>
// activate the window and send F1<br/>
SetActiveWindow(hWnd);<br/>
ushort action = (ushort)WM_SYSKEYDOWN;<br/>
ushort key = (ushort)System.Windows.Forms.Keys.F1;<br/>
SendMessage(hWnd, action, key, 0);<br/>
<br/>
One interesting side note is that even though the above code works in sending the F1 key to the target application it is not the same as what I see using Spy++. Here is the output of the Spy++ log whenever I hit the F1 key while monitoring the target application:<br/>
<br/>
<00001> 00050412 P WM_KEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00002> 00050412 P WM_KEYUP nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:0 fRepeat:1 fUp:1<br/>
<br/>
Note that there are two messages sent, WM_KEYDOWN and WM_KEYUP. <br/>
<br/>
*My first question would be, why am I succesful sending F1 using WM_SYSKEYDOWN when Spy++ tells me that WM_KEYDOWN/WM_KEYUP is the proper message sequence?*<br/>
<br/>
Moving on to my next challenge of trying to send ALT + F1. <br/>
<br/>
I have used Spy++ to monitor the messages passed when pressing ALT + F1 on my keyboard and this is what I see:<br/>
<br/>
<00001> 00050412 P WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:1 fAltDown:1 fRepeat:0 fUp:0<br/>
<00002> 00050412 P WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:0 fUp:0<br/>
<00003> 00050412 P WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:1 fUp:1<br/>
<00004> 00050412 P WM_KEYUP nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:1 fAltDown:0 fRepeat:1 fUp:1<br/>
<br/>
Given the above Spy++ message capture I tried to send the exact message sequence using the following code (simplified):<br/>
<br/>
SetActiveWindow(hWnd); <br/>
SendMessage(hWnd, (ushort)WM_SYSKEYDOWN, (ushort)System.Windows.Forms.Keys.Menu, 0);<br/>
SendMessage(hWnd, (ushort)WM_SYSKEYDOWN, (ushort)System.Windows.Forms.Keys.F1, 0);<br/>
SendMessage(hWnd, (ushort)WM_SYSKEYUP, (ushort)System.Windows.Forms.Keys.F1, 0);<br/>
SendMessage(hWnd, (ushort)WM_KEYUP, (ushort)System.Windows.Forms.Keys.Menu, 0);<br/>
<br/>
This did not work.<br/>
<br/>
*And so this leads to my next question. Is there anything else I can try or is there something that I am doing wrong here?*<br/>
<br/>
Whenever I captured the output of my program using Spy++ here is what was logged:<br/>
<br/>
<00001> 00050412 S WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00002> 00050412 R WM_SYSKEYDOWN<br/>
<00003> 00050412 S WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00004> 00050412 R WM_SYSKEYDOWN<br/>
<00005> 00050412 S WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00006> 00050412 R WM_SYSKEYUP<br/>
<00007> 00050412 S WM_KEYUP nVirtKey:VK_MENU cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0<br/>
<00008> 00050412 R WM_KEYUP<br/>
<br/>
Notice that there are *extra* messages being sent at lines 2, 4, 6, and 8. *Could this be the reason why things are not working?*<br/>
<br/>
I have one final question regarding the difference between the messages captured from actual keyboard input and those captured using my application. Notice the *cRepeat*, *ScanCode*, *fExtended*, etc. *arguments*. They are non-zero in the messages that were<br/>
captured using my keyboard as the input and they are all zero in the messages sent by my application. *Could this be the reason why my code is not working?* *If so, how do I modify these values?* (I am assuming they come from the 4th argument to the SendMessage<br/>
function, which I have set to zero in all cases.)<br/>
<br/>
Thank you
View the full article