使用User32.dll SendMessage使用ALT修改器发送密钥

可能重复:
C#和SendMessage(键)无法正常工作

我正在编写一个应用程序,使用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 ++日志的输出:

  00050412 P WM_KEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:0 fRepeat:0 fUp:0  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时传递的消息,这就是我所看到的:

  00050412 P WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:1 fAltDown:1 fRepeat:0 fUp:0  00050412 P WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:0 fUp:0  00050412 P WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:1 ScanCode:3B fExtended:0 fAltDown:1 fRepeat:1 fUp:1  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 ++捕获我的程序输出时,记录的是:

  00050412 S WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0  00050412 R WM_SYSKEYDOWN  00050412 S WM_SYSKEYDOWN nVirtKey:VK_F1 cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0  00050412 R WM_SYSKEYDOWN  00050412 S WM_SYSKEYUP nVirtKey:VK_F1 cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0  00050412 R WM_SYSKEYUP  00050412 S WM_KEYUP nVirtKey:VK_MENU cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0  00050412 R WM_KEYUP 

请注意,在第2,4,6和8行发送了额外的消息。这可能是事情不起作用的原因吗?

关于从实际键盘输入捕获的消息与使用我的应用程序捕获的消息之间的区别,我有一个最后的问题。 请注意cRepeatScanCodefExtended参数 。 它们在使用键盘作为输入捕获的消息中不为零,并且在我的应用程序发送的消息中它们全为零。 这可能是我的代码无效的原因吗? 如果是这样,我该如何修改这些值? (我假设它们来自SendMessage函数的第4个参数,我在所有情况下都设置为零。)

谢谢,

一月

另一解决方案 你似乎没有为WM_SYSKEYDOWN的lparam传递任何东西。 然而,文档清楚地表明,需要设置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); 

我不认为SendMessage和WM_SYSKEYDOWN是您想要使用的。 而是使用SendInput函数。 如果我记得,你可能会为你想要模拟的每次击键传递四个输入。 一个用于alt键的“down”事件。 相应键的另一个向下事件。 然后每个两个上升事件。

已经有一段时间了,因为我必须编写这样的代码,但我相信文档建议VK_MENU是“alt”键的代码。