0

可能重复:
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++ 日志的输出:

<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 行发送了额外的消息。这可能是无法正常工作的原因吗?

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

谢谢,

4

2 回答 2

2

另一种解决方案。您似乎没有为 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);
于 2012-12-02T06:50:15.097 回答
1

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

自从我不得不编写这样的代码以来已经有一段时间了,但我相信文档建议 VK_MENU 是“alt”键的代码。

于 2012-12-02T06:41:54.150 回答