using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
using Microsoft.Win32;
using System.Windows.Forms;
namespace PrintScreen
{
public class KeyboardHook
{
private const int WH_KEYBOARD_LL = 13; //鍵盤
//鍵盤處理事件委託 ,當捕獲鍵盤輸入時調用定義該委託的方法.
private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);
//客戶端鍵盤處理事件
public delegate void ProcessKeyHandle(HookStruct param, out bool handle);
//接收SetWindowsHookEx返回值
private static int hHookValue = 0;
//勾子程序處理事件
private HookHandle KeyBoardHookProcedure;
//Hook結構
[StructLayout(LayoutKind.Sequential)]
public class HookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
//設置鉤子
[DllImport("user32.dll")]
private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int threadId);
//取消鉤子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
//調用下一個鉤子
[DllImport("user32.dll")]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
////獲取當前線程ID
//[DllImport("kernel32.dll")]
//private static extern int GetCurrentThreadId();
//Gets the main module for the associated process.
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string name);
private IntPtr hookWindowPtr = IntPtr.Zero;
//構造器
public KeyboardHook() { }
//外部調用的鍵盤處理事件
private static ProcessKeyHandle _clientMethod = null;
/// <summary>
/// 安裝勾子
/// </summary>
/// <param name="hookProcess">外部調用的鍵盤處理事件</param>
public void InstallHook(ProcessKeyHandle clientMethod)
{
_clientMethod = clientMethod;
// 安裝鍵盤鉤子
if (hHookValue == 0)
{
KeyBoardHookProcedure = new HookHandle(OnHookProc);
hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
hHookValue = SetWindowsHookEx(
WH_KEYBOARD_LL,
KeyBoardHookProcedure,
hookWindowPtr,
0);
//如果設置鉤子失敗.
if (hHookValue == 0) UninstallHook();
}
}
//取消鉤子事件
public void UninstallHook()
{
if (hHookValue != 0)
{
bool ret = UnhookWindowsHookEx(hHookValue);
if (ret) hHookValue = 0;
}
}
//鉤子事件內部調用,調用_clientMethod方法轉發到客戶端應用。
// 0x101 keyup
private static int OnHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == 0x0100)
{
//轉換結構
HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));
if (_clientMethod != null)
{
bool handle = false;
//調用客戶提供的事件處理程序。
_clientMethod(hookStruct, out handle);
if (handle) return 1; //1:表示攔截鍵盤,return 退出
}
}
return CallNextHookEx(hHookValue, nCode, wParam, lParam);
}
}
}
使用方法:
private KeyboardHook _keyboardHook = null;
private void SetKeyBoardHook()
{
_keyboardHook = new KeyboardHook();
_keyboardHook.InstallHook(this.OnKeyPress);
}
private void UnhookKeyBoard()
{
if (_keyboardHook != null) _keyboardHook.UninstallHook();
}
private void OnKeyPress(KeyboardHook.HookStruct hookStruct, out bool handle)
{
handle = false;
if (!isKeyDown)
{
//截獲control+alt+x
if (hookStruct.vkCode == (int)Keys.C && (int)Control.ModifierKeys == (int)Keys.Alt + (int)Keys.Control)
{
StartApp("SnapShot.exe");
isKeyDown = true;
}
}
}
load之後調用SetKeyBoardHook();即可;
下面是啓動外部exe
private static bool ifExit;
private static bool isKeyDown;
/// <summary>
/// 啓動外部程序,通過事件監視其退出
/// </summary>
public void StartApp(string appName)
{
// 啓動外部程序
Process proc = Process.Start(appName);
ifExit = false;
if (proc != null)
{
// 監視進程退出
proc.EnableRaisingEvents = true;
// 指定退出事件方法
proc.Exited += new EventHandler(proc_Exited);
}
}
/// <summary>
/// 啓動外部程序退出事件
/// </summary>
private void proc_Exited(object sender, EventArgs e)
{
ifExit = true;
isKeyDown = false;
}