天天看点

C#使用SendMessage发送组合键lParam资讯

有时需要出发菜单功能,例如发送ALT + F打开应用程序的文件菜单,如何使用SendMessage实现呢?

使用用spy++截取的ALT+F的消息内容(如何使用spy++,请熟悉的高手指点下,我使用spy++ lite没有得到):

<00001> 000310DC P WM_SYSKEYDOWN nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:0 fAltDown:1 fRepeat:0 fUp:0

<00002> 000310DC P WM_SYSKEYDOWN nVirtKey:'F' cRepeat:1 ScanCode:21 fExtended:0 fAltDown:1 fRepeat:0 fUp:0

<00003> 000310DC P WM_SYSCHAR chCharCode:'102' (102) cRepeat:1 ScanCode:21 fExtended:0 fAltDown:1 fRepeat:0 fUp:0

<00004> 000310DC P WM_SYSKEYUP nVirtKey:'F' cRepeat:1 ScanCode:21 fExtended:0 fAltDown:1 fRepeat:1 fUp:1

<00005> 000310DC P WM_KEYUP nVirtKey:VK_MENU cRepeat:1 ScanCode:38 fExtended:0 fAltDown:0 fRepeat:1 fUp:1

转换为 SendMessage

[DllImport("user32.dll", EntryPoint = "SendMessage")]

public static extern int SendMessage(IntPtr hwnd, int wMsg, uint wParam, uint lParam);

SendMessage(hwnd, 0x0104, 0x00000012, 0x20380001);//(0x00000012 == VK_MENU(ALT键))

SendMessage(hwnd, 0x0104, 0x00000046, 0x20210001);//这一行可以省略(0x00000046 == 'F')

SendMessage(hwnd, 0x0106, 0x00000066, 0x20210001);//发送一个char 'f'

SendMessage(hwnd, 0x0105, 0x00000046, 0xE0210001);//这一行可以省略(0x00000046 == 'F')

SendMessage(hwnd, 0x0105, 0x00000012, 0xC0380001);//(0x00000012 == VK_MENU(ALT键))

过程是这样的: 

首先 发送了一个 ALT按下 //(WM_SYSKEYDOWN == 0x0104)

然后 发送了一个 'F'键      //这里省略可以实现同样功能 系统兼容性问题 建议发送这个键

然后 发送了一个 字符'f'    //(WM_SYSCHAR == 0x0106)

然后 抬起按键     'F'键     //这里省略可以实现同样功能 系统兼容性问题 建议发送这个键

最后 抬起按键     ALT键    //(WM_SYSKEYUP == 0x0105)

要实现类似功能 比如 ALT + a 可以这么写

SendMessage(hwnd, 0x0104, 0x00000012, 0x20380001);//0x00000012可以写成0x12

SendMessage(hwnd, 0x0104, 0x00000041, 0x201E0001);//0x00000041可以写成0x41

SendMessage(hwnd, 0x0106, (int)'a', 0x20210001);// (把char转换为 int 或者API声明时传递参数wParam为char) 

SendMessage(hwnd, 0x0105, 0x00000041, 0xE01E0001);//0x00000041 == 'A'

SendMessage(hwnd, 0x0105, 0x00000012, 0xC0380001);//

下面列举一下键盘按键对应值:

//Windows 使用的256个虚拟键码

public const int VK_LBUTTON = 0x1

public const int VK_RBUTTON = 0x2

public const int VK_CANCEL = 0x3

public const int VK_MBUTTON = 0x4

public const int VK_BACK = 0x8

public const int VK_TAB = 0x9

public const int VK_CLEAR = 0xC

public const int VK_RETURN = 0xD

public const int VK_SHIFT = 0x10

public const int VK_CONTROL = 0x11

public const int VK_MENU = 0x12

public const int VK_PAUSE = 0x13

public const int VK_CAPITAL = 0x14

public const int VK_ESCAPE = 0x1B

public const int VK_SPACE = 0x20

public const int VK_PRIOR = 0x21

public const int VK_NEXT = 0x22

public const int VK_END = 0x23

public const int VK_HOME = 0x24

public const int VK_LEFT = 0x25

public const int VK_UP = 0x26

public const int VK_RIGHT = 0x27

public const int VK_DOWN = 0x28

public const int VK_Select = 0x29

public const int VK_PRINT = 0x2A

public const int VK_EXECUTE = 0x2B

public const int VK_SNAPSHOT = 0x2C

public const int VK_Insert = 0x2D

public const int VK_Delete = 0x2E

public const int VK_HELP = 0x2F

public const int VK_0 = 0x30

public const int VK_1 = 0x31

public const int VK_2 = 0x32

public const int VK_3 = 0x33

public const int VK_4 = 0x34

public const int VK_5 = 0x35

public const int VK_6 = 0x36

public const int VK_7 = 0x37

public const int VK_8 = 0x38

public const int VK_9 = 0x39

public const int VK_A = 0x41

public const int VK_B = 0x42

public const int VK_C = 0x43

public const int VK_D = 0x44

public const int VK_E = 0x45

public const int VK_F = 0x46

public const int VK_G = 0x47

public const int VK_H = 0x48

public const int VK_I = 0x49

public const int VK_J = 0x4A

public const int VK_K = 0x4B

public const int VK_L = 0x4C

public const int VK_M = 0x4D

public const int VK_N = 0x4E

public const int VK_O = 0x4F

public const int VK_P = 0x50

public const int VK_Q = 0x51

public const int VK_R = 0x52

public const int VK_S = 0x53

public const int VK_T = 0x54

public const int VK_U = 0x55

public const int VK_V = 0x56

public const int VK_W = 0x57

public const int VK_X = 0x58

public const int VK_Y = 0x59

public const int VK_Z = 0x5A

public const int VK_STARTKEY = 0x5B

public const int VK_CONTEXTKEY = 0x5D

public const int VK_NUMPAD0 = 0x60

public const int VK_NUMPAD1 = 0x61

public const int VK_NUMPAD2 = 0x62

public const int VK_NUMPAD3 = 0x63

public const int VK_NUMPAD4 = 0x64

public const int VK_NUMPAD5 = 0x65

public const int VK_NUMPAD6 = 0x66

public const int VK_NUMPAD7 = 0x67

public const int VK_NUMPAD8 = 0x68

public const int VK_NUMPAD9 = 0x69

public const int VK_MULTIPLY = 0x6A

public const int VK_ADD = 0x6B

public const int VK_SEPARATOR = 0x6C

public const int VK_SUBTRACT = 0x6D

public const int VK_DECIMAL = 0x6E

public const int VK_DIVIDE = 0x6F

public const int VK_F1 = 0x70

public const int VK_F2 = 0x71

public const int VK_F3 = 0x72

public const int VK_F4 = 0x73

public const int VK_F5 = 0x74

public const int VK_F6 = 0x75

public const int VK_F7 = 0x76

public const int VK_F8 = 0x77

public const int VK_F9 = 0x78

public const int VK_F10 = 0x79

public const int VK_F11 = 0x7A

public const int VK_F12 = 0x7B

public const int VK_F13 = 0x7C

public const int VK_F14 = 0x7D

public const int VK_F15 = 0x7E

public const int VK_F16 = 0x7F

public const int VK_F17 = 0x80

public const int VK_F18 = 0x81

public const int VK_F19 = 0x82

public const int VK_F20 = 0x83

public const int VK_F21 = 0x84

public const int VK_F22 = 0x85

public const int VK_F23 = 0x86

public const int VK_F24 = 0x87

public const int VK_NUMLOCK = 0x90

public const int VK_OEM_SCROLL = 0x91

public const int VK_OEM_1 = 0xBA

public const int VK_OEM_PLUS = 0xBB

public const int VK_OEM_COMMA = 0xBC

public const int VK_OEM_MINUS = 0xBD

public const int VK_OEM_PERIOD = 0xBE

public const int VK_OEM_2 = 0xBF

public const int VK_OEM_3 = 0xC0

public const int VK_OEM_4 = 0xDB

public const int VK_OEM_5 = 0xDC

public const int VK_OEM_6 = 0xDD

public const int VK_OEM_7 = 0xDE

public const int VK_OEM_8 = 0xDF

public const int VK_ICO_F17 = 0xE0

public const int VK_ICO_F18 = 0xE1

public const int VK_OEM102 = 0xE2

public const int VK_ICO_HELP = 0xE3

public const int VK_ICO_00 = 0xE4

public const int VK_ICO_CLEAR = 0xE6

public const int VK_OEM_RESET = 0xE9

public const int VK_OEM_JUMP = 0xEA

public const int VK_OEM_PA1 = 0xEB

public const int VK_OEM_PA2 = 0xEC

public const int VK_OEM_PA3 = 0xED

public const int VK_OEM_WSCTRL = 0xEE

public const int VK_OEM_CUSEL = 0xEF

public const int VK_OEM_ATTN = 0xF0

public const int VK_OEM_FINNISH = 0xF1

public const int VK_OEM_COPY = 0xF2

public const int VK_OEM_AUTO = 0xF3

public const int VK_OEM_ENLW = 0xF4

public const int VK_OEM_BACKTAB = 0xF5

public const int VK_ATTN = 0xF6

public const int VK_CRSEL = 0xF7

public const int VK_EXSEL = 0xF8

public const int VK_EREOF = 0xF9

public const int VK_PLAY = 0xFA

public const int VK_ZOOM = 0xFB

public const int VK_NONAME = 0xFC

public const int VK_PA1 = 0xFD

public const int VK_OEM_CLEAR = 0xFE

按照以上对照表 写快捷键 CTRL + F :

SendMessage(hwnd, 0x0104, 0x11, 0x20380001);//0x11 == VK_CONTROL == ALT键

SendMessage(hwnd, 0x0104, (int)'F', 0x20210001);//

SendMessage(hwnd, 0x0106, (int)'f', 0x20210001);// 

SendMessage(hwnd, 0x0105, (int)'F', 0xE0210001);//

SendMessage(hwnd, 0x0105, 0x11, 0xC0380001);//

忘记说了 关于参数 lParam 是这么说的:

Parameters

nVirtKey 
Value of wParam. Specifies the virtual-key code of the key being pressed. 
lKeyData 
Value of lParam. Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table. 
Value Description
0–15 Specifies the repeat count for the current message. The value is the number of times the keystroke is auto-repeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative.
16–23 Specifies the scan code. The value depends on the original equipment manufacturer (OEM).
24 Specifies whether the key is an extended key, such as the right-hand alt and ctrl keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
25–28 Reserved; do not use.
29 Specifies the context code. The value is 1 if the ALT key is down while the key is pressed; it is 0 if the WM_SYSKEYDOWN message is posted to the active window because no window has the keyboard focus.
30 Specifies the previous key state. The value is 1 if the key is down before the message is sent, or it is 0 if the key is up.
31 Specifies the transition state. The value is always 0 for a WM_SYSKEYDOWN message.

0-15位:指定当前消息的重复次数。其值就是用户按下该键后自动重复的次数,但是重复次数不累积

16-23位:指定其扫描码,其值依赖于OEM厂商

24位:指定该按键是否为扩展按键,所谓扩展按键就是Ctrl,Alt之类的,如果是扩展按键,其值为1,否则为0 

25-28位:保留字段,暂时不可用 

29位:指定按键时的上下文,其值为1时表示在按键时Alt键被按下,其值为0表示WM_SYSKEYDOWN消息因没有任何窗口有键盘焦点而被发送到当前活动窗口。 

30位:指定该按键之前的状态,其值为1时表示该消息发送前,该按键是被按下的,其值为0表示该消息发送前该按键是抬起的。 

31位:指定其转换状态,对WM_SYSKEYDOWN消息而言,其值总为0。

具体可以参考 

http://msdn.microsoft.com/zh-cn/library/ms646286(en-us,VS.85).aspx

如果你想知道这些参数的含义 你可以直接输入1 就可以了表示按键的次数

lParam资讯

C#使用SendMessage发送组合键lParam资讯

  在四个按键讯息(WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN和WM_SYSKEYUP)中,wParam讯息参数含有上面所讨论的虚拟键码,而lParam讯息参数则含有对了解按键非常有用的其他资讯。lParam的32位分为6个栏位,如图所示。

  在Win 3.x中,WPARAM是16位的,而LPARAM是32位的,两者有明显的区别。因为地址通常是32位的,所以LPARAM被用来传递地址,这个习惯在Win32 API中仍然能够看到。在Win32 API中,WPARAM和LPARAM都是32位,所以没有什么本质的区别。Windows的消息必须参考帮助文件才能知道具体的含义。如果是你定义的消息,愿意怎么使这两个参数都行。但是习惯上,我们愿意使用LPARAM传递地址,而WPARAM传递其他参数。

以上方法可以打开主菜单上的第一层菜单如文件(F),但是文件下面的二级菜单采用此方法无效果,请熟悉的高手指点。

继续阅读