我正在编写一个应用程序,使用 user32.dll 中定义的SendMessage函数将键击发送到另一个应用程序。我已经想出了如何发送一次击键,但我很难尝试发送击键和ALT键。
就我的问题而言,我将专注于发送F1和ALT + F1。
如上所述,我能够发送F1键没问题。这是我的代码片段,它发送F1键:
// DLL Imports
//Set the active window
[DllImport("user32.dll")]
public static extern IntPtr SetActiveWindow(IntPtr hWnd);
//sends a windows message to the specified window
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);
// ...
// Some constants
#define WM_SYSKEYDOWN 260
#define WM_SYSKEYUP 261
#define WM_CHAR 258
#define WM_KEYDOWN 256
#define WM_KEYUP 257
// ...
// activate the window and send F1
SetActiveWindow(hWnd);
ushort action = (ushort)WM_SYSKEYDOWN;
ushort key = (ushort)System.Windows.Forms.Keys.F1;
SendMessage(hWnd, action, key, 0);
一个有趣的旁注是,尽管上面的代码在将F1键发送到目标应用程序时起作用,但它与我使用Spy ++看到的不同。每当我在监控目标应用程序时点击F1键,这是Spy ++日志的输出:
<00001> 00050412 P WM_KEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00002> 00050412 P WM_KEYUP nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:0 fRepeat:1 fUp:1
请注意,发送了两条消息,WM_KEYDOWN和WM_KEYUP。
我的第一个问题是,当Spy ++告诉我WM_KEYDOWN + WM_KEYUP是正确的消息序列时,为什么我成功使用WM_SYSKEYDOWN发送F1?
接下来我尝试发送ALT + F1的下一个挑战。
我使用Spy ++来监控键盘上按ALT + F1时传递的消息,这就是我所看到的:
<00001> 00050412 P WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:1 fAltDown:1 fRepeat:0 fUp:0
<00002> 00050412 P WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:0 fUp:0
<00003> 00050412 P WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:1 fUp:1
<00004> 00050412 P WM_KEYUP nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:1 fAltDown:0 fRepeat:1 fUp:1
鉴于上述Spy ++消息捕获,我尝试使用以下代码(简化)发送确切的消息序列:
SetActiveWindow(hWnd);
SendMessage(hWnd, (ushort)WM_SYSKEYDOWN, (ushort)System.Windows.Forms.Keys.Menu, 0);
SendMessage(hWnd, (ushort)WM_SYSKEYDOWN, (ushort)System.Windows.Forms.Keys.F1, 0);
SendMessage(hWnd, (ushort)WM_SYSKEYUP, (ushort)System.Windows.Forms.Keys.F1, 0);
SendMessage(hWnd, (ushort)WM_KEYUP, (ushort)System.Windows.Forms.Keys.Menu, 0);
这不起作用。
所以这引出了我的下一个问题。 还有什么我可以尝试的,或者我在这里做错了什么?
每当我使用Spy ++捕获我的程序输出时,记录的是
<00001> 00050412 S WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00002> 00050412 R WM_SYSKEYDOWN
<00003> 00050412 S WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00004> 00050412 R WM_SYSKEYDOWN
<00005> 00050412 S WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00006> 00050412 R WM_SYSKEYUP
<00007> 00050412 S WM_KEYUP nVirtKey:VK_MENU cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00008> 00050412 R WM_KEYUP
请注意,在第2,4,6和8行发送了额外的消息。这可能是事情不起作用的原因吗?
关于从实际键盘输入捕获的消息与使用我的应用程序捕获的消息之间的区别,我有一个最后的问题。请注意 cRepeat , ScanCode , fExtended 等参数。它们在消息中不为零 使用我的键盘作为输入捕获它们在我的应用程序发送的消息中都是零。 这可能是我的代码无效的原因吗? 如果是这样,我该如何修改这些值?(我假设它们来自SendMessage的第4个参数 函数,我在所有情况下都设置为零。)
谢谢,
扬
答案 0 :(得分:1)
我认为SendMessage和WM_SYSKEYDOWN不是您想要使用的。而是使用SendInput功能。如果我记得,你可能会为你想要模拟的每次击键传递四个输入。一个用于alt键的“down”事件。相应键的另一个向下事件。然后为每个事件分两个事件。
已经有一段时间了,因为我不得不编写这样的代码,但我相信文档建议VK_MENU是“alt”键的代码。
答案 1 :(得分:0)
另一种解决方案。你似乎没有为WM_SYSKEYDOWN的lparam传递任何东西。然而the docs,清楚地表明需要设置lparam的第29位以指示ALT键被按下。
ushort action = (ushort)WM_SYSKEYDOWN;
ushort key = (ushort)System.Windows.Forms.Keys.F1;
uint lparam = (0x01 << 28);
SendMessage(hWnd, action, key, lparam);