可能在使用VSTO技術對Office的相關程序進行操作時,會碰到用程序去控制一些快捷鍵的操作,可以對鍵盤進行掛鈎,此時使用P/Invoke函數實現。
原文鏈接:《VSTO應用程序中加入鍵盤鈎子》 http://www.cnblogs.com/2018/archive/2010/12/01/1893891.html
原文如下:
在VSTO應用程序中有時為了處理一些快捷按鍵操作等實現一些特殊的功能,此時需要對鍵盤進行掛鈎,此時使用P/Invoke函數實現,參考如下:
VSTO加載和卸載時進行鈎子的初始化和卸載
代碼 KeyboardHook hook; private void ThisAddIn_Startup(object sender, System.EventArgs e) { hook = new KeyboardHook(); hook.InitHook(); } private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { hook.UnHook(); } } //鈎子具體處理邏輯是: class KeyboardHook { #region (invokestuff) [DllImport("kernel32.dll")] static extern uint GetCurrentThreadId(); [DllImport("user32.dll")] static extern IntPtr SetWindowsHookEx(int code, HookProcKeyboard func, IntPtr hInstance, uint threadID); [DllImport("user32.dll")] static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll")] static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); #endregion #region constans private const int WH_KEYBOARD = 2; private const int HC_ACTION = 0; #endregion delegate int HookProcKeyboard(int code, IntPtr wParam, IntPtr lParam); private HookProcKeyboard KeyboardProcDelegate = null; private IntPtr khook; bool doing = false; public void InitHook() { uint id = GetCurrentThreadId(); //init the keyboard hook with the thread id of the Visual Studio IDE this.KeyboardProcDelegate = new HookProcKeyboard(this.KeyboardProc); khook = SetWindowsHookEx(WH_KEYBOARD, this.KeyboardProcDelegate, IntPtr.Zero, id); } public void UnHook() { if (khook != IntPtr.Zero) { UnhookWindowsHookEx(khook); } } private int KeyboardProc(int code, IntPtr wParam, IntPtr lParam) { try { if (code != HC_ACTION) { return CallNextHookEx(khook, code, wParam, lParam); } if ((int)wParam == (int)Keys.Z && ((int)lParam & (int)Keys.Alt) != 0) { if (!doing) { doing = true; MessageBox.Show("Captured"); doing = false; } } } catch { } return CallNextHookEx(khook, code, wParam, lParam); } }
注意對於命名空間的引入,在程序中Keys.Z,Keys.Alt可以改為你想要控制的按鍵鍵盤,可以是是單一按鍵也可以是組合鍵。當然,也可以捕獲復制、粘貼、撤銷等等組合快捷鍵。
對於鍵盤、鼠標鈎子的處理:《C#鼠標鍵盤鈎子》http://blog.csdn.net/wangyong0921/article/details/8262631
對於鍵盤鈎子的另一種處理:

using System;using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; namespace ICS.Common { /// <summary> /// 這個類可以讓你得到一個在運行中程序的所有鍵盤或鼠標事件 /// 並且引發一個帶KeyEventArgs參數的.NET事件以便你很容易使用這些信息 /// </summary> public class KeyBordHook { private const int WM_KEYDOWN = 0x100; private const int WM_KEYUP = 0x101; private const int WM_SYSKEYDOWN = 0x104; private const int WM_SYSKEYUP = 0x105; //全局的事件 public event KeyEventHandler OnKeyDownEvent; public event KeyEventHandler OnKeyUpEvent; public event KeyPressEventHandler OnKeyPressEvent; static int hKeyboardHook = 0; //鍵盤鈎子句柄 //鼠標常量 public const int WH_KEYBOARD_LL = 13; //keyboard hook constant HookProc KeyboardHookProcedure; //聲明鍵盤鈎子事件類型. //聲明鍵盤鈎子的封送結構類型 [StructLayout(LayoutKind.Sequential)] public class KeyboardHookStruct { public int vkCode; //表示一個在1到254間的虛似鍵盤碼 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("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); public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); /// <summary> /// 墨認的構造函數構造當前類的實例並自動的運行起來. /// </summary> public KeyBordHook() { Start(); } //析構函數. ~KeyBordHook() { Stop(); } public void Start() { //安裝鍵盤鈎子 if (hKeyboardHook == 0) { KeyboardHookProcedure = new HookProc(KeyboardHookProc); hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().ManifestModule), 0); if (hKeyboardHook == 0) { Stop(); throw new Exception("SetWindowsHookEx ist failed. "); } } } public void Stop() { bool retKeyboard = true; if (hKeyboardHook != 0) { retKeyboard = UnhookWindowsHookEx(hKeyboardHook); hKeyboardHook = 0; } //如果卸下鈎子失敗 if (!(retKeyboard)) throw new Exception("UnhookWindowsHookEx failed. "); } private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) { if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null)) { KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); //引發OnKeyDownEvent if (OnKeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) { Keys keyData = (Keys)MyKeyboardHookStruct.vkCode; KeyEventArgs e = new KeyEventArgs(keyData); OnKeyDownEvent(this, e); } //引發OnKeyPressEvent if (OnKeyPressEvent != 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]); OnKeyPressEvent(this, e); } } //引發OnKeyUpEvent if (OnKeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)) { Keys keyData = (Keys)MyKeyboardHookStruct.vkCode; KeyEventArgs e = new KeyEventArgs(keyData); OnKeyUpEvent(this, e); } } return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); } }
對於鼠標鈎子的處理:
using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; namespace PowerPointTest { /// <summary> /// 這個類可以讓你得到一個在運行中程序的所有鼠標事件 /// 並且引發一個帶MouseEventArgs參數的.NET鼠標事件以便你很容易使用這些信息 /// </summary> public class MouseHook { private const int WM_MOUSEMOVE = 0x200; private const int WM_LBUTTONDOWN = 0x201; private const int WM_RBUTTONDOWN = 0x204; private const int WM_MBUTTONDOWN = 0x207; private const int WM_LBUTTONUP = 0x202; private const int WM_RBUTTONUP = 0x205; private const int WM_MBUTTONUP = 0x208; private const int WM_LBUTTONDBLCLK = 0x203; private const int WM_RBUTTONDBLCLK = 0x206; private const int WM_MBUTTONDBLCLK = 0x209; //全局的事件 public event MouseEventHandler OnMouseActivity; static int hMouseHook = 0; //鼠標鈎子句柄 //鼠標常量 public const int WH_MOUSE_LL = 14; //mouse hook constant HookProc MouseHookProcedure; //聲明鼠標鈎子事件類型. //聲明一個Point的封送類型 [StructLayout(LayoutKind.Sequential)] public class POINT { public int x; public int y; } //聲明鼠標鈎子的封送結構類型 [StructLayout(LayoutKind.Sequential)] public class MouseHookStruct { public POINT pt; public int hWnd; public int wHitTestCode; 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); public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); /// <summary> /// 墨認的構造函數構造當前類的實例. /// </summary> public MouseHook() { //Start(); } //析構函數. ~MouseHook() { Stop(); } public void Start() { //安裝鼠標鈎子 if (hMouseHook == 0) { //生成一個HookProc的實例. MouseHookProcedure = new HookProc(MouseHookProc); hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0); //如果裝置失敗停止鈎子 if (hMouseHook == 0) { Stop(); throw new Exception("SetWindowsHookEx failed. "); } } } public void Stop() { bool retMouse = true; if (hMouseHook != 0) { retMouse = UnhookWindowsHookEx(hMouseHook); hMouseHook = 0; } //如果卸下鈎子失敗 if (!(retMouse)) throw new Exception("UnhookWindowsHookEx failed. "); } private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam) { //如果正常運行並且用戶要監聽鼠標的消息 if ((nCode >= 0) && (OnMouseActivity != null)) { MouseButtons button = MouseButtons.None; int clickCount = 0; switch (wParam) { case WM_LBUTTONDOWN: button = MouseButtons.Left; clickCount = 1; break; case WM_LBUTTONUP: button = MouseButtons.Left; clickCount = 1; break; case WM_LBUTTONDBLCLK: button = MouseButtons.Left; clickCount = 2; break; case WM_RBUTTONDOWN: button = MouseButtons.Right; clickCount = 1; break; case WM_RBUTTONUP: button = MouseButtons.Right; clickCount = 1; break; case WM_RBUTTONDBLCLK: button = MouseButtons.Right; clickCount = 2; break; } //從回調函數中得到鼠標的信息 MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct)); MouseEventArgs e = new MouseEventArgs(button, clickCount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, 0); OnMouseActivity(this, e); } return CallNextHookEx(hMouseHook, nCode, wParam, lParam); } } }