使用User32。dll发送消息发送带有ALT修饰符的键[duplicate]

时间:2022-02-11 07:29:26

Possible Duplicate:
C# and SendMessage (keys) is not working

可能的重复:c#和SendMessage(键)不工作

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.

我正在编写一个应用程序,使用user32.dll中定义的SendMessage函数向另一个应用程序发送击键。我已经知道如何发送一个击键,但我在尝试发送击键和ALT键时遇到了困难。

For the purposes of my question I will focus on sending F1, and ALT + F1.

对于我的问题,我将主要关注发送F1和ALT + F1。

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:

如上所述,我可以发送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);

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:

值得注意的是,尽管上面的代码可以将F1键发送到目标应用程序,但与我看到的使用Spy++的代码不同。在监视目标应用程序时,当我在监视目标应用程序时,这里是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

Note that there are two messages sent, WM_KEYDOWN and WM_KEYUP.

注意,有两个消息发送,WM_KEYDOWN和WM_KEYUP。

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?

我的第一个问题是,当Spy++ +告诉我WM_KEYDOWN + WM_KEYUP是正确的消息序列时,为什么我成功地使用WM_SYSKEYDOWN发送F1 ?

Moving on to my next challenge of trying to send ALT + F1.

下一个挑战是发射ALT + F1。

I have used Spy++ to monitor the messages passed when pressing ALT + F1 on my keyboard and this is what I see:

我用间谍+ +监控信息通过按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

Given the above Spy++ message capture I tried to send the exact message sequence using the following code (simplified):

考虑到上面的间谍++消息捕获,我尝试使用以下代码(简化)发送准确的消息序列:

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);

This did not work.

这并不工作。

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?

这就引出了我的下一个问题。还有什么我可以尝试的,或者我在这里做错了什么?

Whenever I captured the output of my program using Spy++ here is what was logged:

每当我使用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

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?

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

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 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 function, which I have set to zero in all cases.)

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

Thank you,

谢谢你!

Jan

1月

2 个解决方案

#1


0  

Another solution. It doesn't appear you are passing anything for the lparam of the WM_SYSKEYDOWN. Yet the docs, clearly suggest that bit 29 of the lparam needs to be set to indicate the ALT key was pressed.

另一个解决方案。它不显示您正在为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);

#2


1  

I don't think SendMessage and WM_SYSKEYDOWN is what you want to use. Instead, use the SendInput function. If I recall, you'll likely pass four inputs for every keystroke you want to simulate. One for the "down" event of the alt key. Another down event for the corresponding key. Then two up events for each.

我不认为SendMessage和WM_SYSKEYDOWN是您想要使用的。相反,使用SendInput函数。如果我记得的话,您可能会为您想要模拟的每个击键传递4个输入。一个用于alt键的“向下”事件。对应键的另一个下拉事件。然后为每一个人准备两件事。

It's been a while since I've had to write code like this, but I believe the docs suggest that VK_MENU is the code for the "alt" key.

我已经有一段时间不需要像这样写代码了,但是我相信文档中建议VK_MENU是“alt”键的代码。

#1


0  

Another solution. It doesn't appear you are passing anything for the lparam of the WM_SYSKEYDOWN. Yet the docs, clearly suggest that bit 29 of the lparam needs to be set to indicate the ALT key was pressed.

另一个解决方案。它不显示您正在为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);

#2


1  

I don't think SendMessage and WM_SYSKEYDOWN is what you want to use. Instead, use the SendInput function. If I recall, you'll likely pass four inputs for every keystroke you want to simulate. One for the "down" event of the alt key. Another down event for the corresponding key. Then two up events for each.

我不认为SendMessage和WM_SYSKEYDOWN是您想要使用的。相反,使用SendInput函数。如果我记得的话,您可能会为您想要模拟的每个击键传递4个输入。一个用于alt键的“向下”事件。对应键的另一个下拉事件。然后为每一个人准备两件事。

It's been a while since I've had to write code like this, but I believe the docs suggest that VK_MENU is the code for the "alt" key.

我已经有一段时间不需要像这样写代码了,但是我相信文档中建议VK_MENU是“alt”键的代码。