- UID
- 390967
- 帖子
- 1592
- 主題
- 821
- 精華
- 0
- 積分
- 854
- 楓幣
- 10961
- 威望
- 395
- 存款
- 10100
- 贊助金額
- 1800
- 推廣
- 0
- GP
- 2677
- 閱讀權限
- 150
- 在線時間
- 189 小時
- 註冊時間
- 2023-5-18
- 最後登入
- 2024-11-21
|
當焦點不在程式上時,用程式加入監控按下鍵盤事件是無法捕抓到相關鍵盤消息!
這時就要用HOOK監聽系統整體的消息發送
先創一個專門監聽功能的類別,這裡命名空間 SystemHook- using System;using System.Collections.Generic;
- using System.Text;
- using System.Runtime.InteropServices;
- using System.windows.Forms;
- using System.Reflection;
- namespace SystemHook
- {
- class KeyboardHook
- {
- public event KeyEventHandler KeyDownEvent;
- public event KeyPressEventHandler KeyPressEvent;
- public event KeyEventHandler KeyUpEvent;
- public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
- static int hKeyboardHook = 0;
- public const int WH_KEYBOARD_LL = 13;
- HookProc KeyboardHookProcedure;
- //鍵盤鉤子結構
- [StructLayout(LayoutKind.Sequential)]
- public class KeyboardHookStruct
- {
- public int vkCode;
- public int scanCode;
- public int flags;
- public int time;
- public int dwExtraInfo;
- }
- // 裝載鉤子
- [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
- public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
- // 卸載鉤子
- [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
- public static extern bool UnhookWindowsHookEx(int idHook);
- // 呼叫下一個鉤子
- [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
- public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
- // 取得當前執行緒編號
- [DllImport("kernel32.dll")]
- static extern int GetCurrentThreadId();
- // 使用WINDOWS API函數取代取得目前執行個體的函數,防止鉤子失效
- [DllImport("kernel32.dll")]
- public static extern IntPtr GetModuleHandle(string name);
- public void Start()
- {
- // 裝載鍵盤鉤子
- if (hKeyboardHook == 0)
- {
- KeyboardHookProcedure = new HookProc(KeyboardHookProc);
- hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 0);
- if (hKeyboardHook == 0)
- {
- Stop();
- throw new Exception("裝載鍵盤鉤子失敗");
- }
- }
- }
- public void Stop()
- {
- bool retKeyboard = true;
- if (hKeyboardHook != 0)
- {
- retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
- hKeyboardHook = 0;
- }
- if (!(retKeyboard)) throw new Exception("卸載鉤子失敗!");
- }
- // ToAscii 轉換指定的虛擬鍵碼和鍵盤狀態的對應字元或字元
- [DllImport("user32")]
- public static extern int ToAscii(int uVirtKey,
- int uScanCode,
- byte[] lpbKeyState,
- byte[] lpwTransKey,
- int fuState);
- // 取得按鍵的狀態
- [DllImport("user32")]
- public static extern int GetKeyboardState(byte[] pbKeyState);
- [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
- private static extern short GetKeyState(int vKey);
- private const int WM_KEYDOWN = 0x100;
- private const int WM_KEYUP = 0x101;
- private const int WM_SYSKEYDOWN = 0x104;
- private const int WM_SYSKEYUP = 0x105;
- private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
- {
- // 監聽鍵盤事件
- if ((nCode >= 0) && (KeyDownEvent != null || KeyUpEvent != null || KeyPressEvent != null))
- {
- KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
- if (KeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
- {
- Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
- KeyEventArgs e = new KeyEventArgs(keyData);
- KeyDownEvent(this, e);
- }
- // 按下鍵盤
- if (KeyPressEvent != null && wParam == WM_KEYDOWN)
- {
- byte[] keyState = new byte[256];
- GetKeyboardState(keyState);
- byte[] inBuffer = new byte[2];
- if (ToAscii(MyKeyboardHookStruct.vkCode, MyKeyboardHookStruct.scanCode, keyState, inBuffer, MyKeyboardHookStruct.flags) == 1)
- {
- KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]);
- KeyPressEvent(this, e);
- }
- }
- // 放開鍵盤
- if (KeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
- {
- Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
- KeyEventArgs e = new KeyEventArgs(keyData);
- KeyUpEvent(this, e);
- }
- }
- // 如果返回1,則結束訊息,這個訊息到此為止,不再傳遞。
- // 如果回傳0或呼叫CallNextHookEx函數,則訊息離開這個鉤子繼續往下傳遞,也就是傳給訊息真正的接受者
- return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
- }
- ~KeyboardHook()
- {
- Stop();
- }
- }
- }
複製代碼 實作上把就是訂閱KeyboardHook類別的KeyDownEvent事件再回調自己設定的事件處理器函數
這裡舉例一個按下Alt+A就彈出訊息提示- using System.Runtime.InteropServices;
- using Microsoft.Win32;
- KeyboardHook kb_hook = new KeyboardHook();
- kb_hook.KeyDownEvent += new KeyEventHandler(hook_KeyDown);//鉤住鍵按下
- kb_hook.Start();
- private void hook_KeyDown(object sender, KeyEventArgs e)
- {
- //判斷按下的按鍵(Alt + A)
- if (e.KeyValue == (int)Keys.A && (int)Control.ModifierKeys == (int)Keys.Alt)
- {
- System.Windows.Forms.MessageBox.Show(“按下了指定快捷键组合”);
- }
- }
複製代碼 若要再多組合幾個按鍵就把判斷條件再拓展就可以了
|
[發帖際遇]: whitefox 為了避免被「就讀腐大的咬蚊子」嗆「多讀點書」,因此購買大量書籍,花費 1 楓幣 |
幸運榜 / 衰神榜 |
|