C#中使用 SendMessage 向非頂端表單發送按鍵組合

來源:互聯網
上載者:User
開門見山,不廢話了, 直接舉例說明一下:

比如發送ALT + F

以下是 用spy++截取的訊息內容

<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資訊  在四個按鍵訊息(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傳遞其他參數。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.