读书人

键盘勾子程序!高手帮忙!解决办法

发布时间: 2012-06-02 14:16:14 作者: rapoo

键盘勾子程序!高手帮忙!
我要编写一程序在后台运行,程序要求当键盘按下ESC键或者像(CTRL+ALT+S)这样的自定义组合键时运行特定的功能。不是不是捕获WindowsForm里面的按键操作,是系统的键盘操作哦,怎么实现?


[解决办法]
Imports System.Runtime.InteropServices
Public Class KeyCallBackHook
'callbackhandle ,callback
Private m_iKeyHandle As Integer = 0
Private m_clsHookCallback As HookCallBack
'virtual-key code
Private Const HC_ACTION As Integer = 0
'key code
Private Const VK_KEY_ENTER As Integer = &HD
Private Const VK_LWin As Integer = &H5B
Private Const VK_RWin As Integer = &H5C
'hookid
Private Const WH_KEYBOARD_LL = 13
'wPawam
Private Const WM_KEYDOWN As Integer = &H100
Private Const WM_KeyUP As Integer = &H101
Private Const WM_SYSKEYDOWN As Integer = &H104
Private Const WM_SYSKEYUP As Integer = &H105
'callbackfunction
Private fix_COCD As HookCallBack '定义引用变量防止CallbackOnCollectedDelegate错误的产生
'callback
Private Delegate Function HookCallBack(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
'api
Private Declare Function GetModuleHandle Lib "kernel32.dll" Alias "GetModuleHandleA" (ByVal ModuleName As String) As IntPtr
Private Declare Function GetLastError Lib "kernel32" Alias "GetLastError" () As Integer
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
Private Overloads Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal HookProc As HookCallBack, ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
End Function
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
Private Overloads Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean
End Function

Public Event KeyDown As System.Windows.Forms.KeyEventHandler
Public Event KeyUp As System.Windows.Forms.KeyEventHandler

'structure
Private Structure KeyboardHookStruct
' Specifies a virtual-key code. The code must be a value in the range 1 to 254.
Public vkCode As Integer
'Specifies a hardware scan code for the key.
Public scanCode As Integer
'Specifies the extended-key flag, event-injected flag, context code, and transition-state flag.
Public flags As Integer
'Specifies the time stamp for this message.
Public time As Integer
'Specifies extra information associated with the message.
Public dwExtraInfo As Integer
End Structure
Private _RWinNoCallNext As Boolean = False
Private _LWinNoCallNext As Boolean = False
Public Property RWinNoCallNext() As Boolean
Get
Return _RWinNoCallNext
End Get
Set(ByVal value As Boolean)
_RWinNoCallNext = value
End Set
End Property

Public Property LWinNoCallNext() As Boolean
Get
Return _LWinNoCallNext
End Get
Set(ByVal value As Boolean)
_LWinNoCallNext = value
End Set
End Property

Private Function KeyBoardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Dim newPtr As KeyboardHookStruct = CType(Marshal.PtrToStructure(lParam, newPtr.GetType()), KeyboardHookStruct)
'Debug.Print(nCode)


If (nCode = HC_ACTION) Then
If wParam.ToInt32 = WM_KeyUP Or wParam.ToInt32 = WM_SYSKEYUP Then
If newPtr.vkCode = VK_KEY_ENTER Then
RaiseEvent KeyUp(Me, New Windows.Forms.KeyEventArgs(CType(newPtr.vkCode, Windows.Forms.Keys)))
End If
ElseIf wParam.ToInt32 = WM_KEYDOWN Or wParam.ToInt32 = WM_SYSKEYDOWN Then
If newPtr.vkCode = VK_KEY_ENTER Then
RaiseEvent KeyDown(Me, New Windows.Forms.KeyEventArgs(CType(newPtr.vkCode, Windows.Forms.Keys)))
End If
End If
End If
Return CallNextHookEx(m_iKeyHandle, nCode, wParam, lParam)
End Function

Public Sub SetHook()
fix_COCD = New HookCallBack(AddressOf KeyBoardProc)
m_iKeyHandle = SetWindowsHookEx(WH_KEYBOARD_LL, fix_COCD, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0)
If m_iKeyHandle = 0 Then
Throw New System.Exception("SetWindowsHookEx 函数失败!GetLastError 返回代码: " & GetLastError)
Else
End If
End Sub

Public Sub UnHook()
If (m_iKeyHandle <> 0) Then UnhookWindowsHookEx(m_iKeyHandle)
End Sub

Protected Overrides Sub Finalize()
UnHook()
MyBase.Finalize()
End Sub
End Class


[解决办法]
代码供参考
// 安装钩子
[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();

public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);

static int hKeyboardHook = 0;
static int hMouseHook = 0;

HookProc KeyboardHookProcedure;
HookProc MouseHookProcedure;

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 const int WH_MOUSE_LL = 14; //mouse hook constant
public const int WH_KEYBOARD_LL = 13; //keyboard hook constant


private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if (nCode >= 0)
{
switch(wParam)
{
case WM_KEYDOWN:
textBox1.Text = "KeyDown";
break;
case WM_KEYUP:
textBox1.Text = "KeyUp";
break;
}
}
return CallNextHookEx(hKeyboardHook,nCode,wParam,lParam);
}

private const int move = 0x200;
private const int leftButtonDown = 0x201;
private const int RightButtonDown = 0x204;
private const int leftButtonUp = 0x202;
private const int RightButtonUp = 0x205;
private const int MouseWheel1 = 0x020A;

private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if (nCode >= 0)


{
switch (wParam)
{
case move:
textBox1.Text = "move";
break;
case leftButtonDown:
textBox1.Text = "leftButtonDown";
break;
case RightButtonDown:
textBox1.Text = "RightButtonDown";
break;
case MouseWheel1:
textBox1.Text = "MouseWheel";
break;
}
}
return CallNextHookEx(hKeyboardHook,nCode,wParam,lParam);
}

//安装钩子
public void HookStart()
{
try
{
if (hKeyboardHook == 0)
{
// 创建HookProc实例
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
// 设置线程钩子
hKeyboardHook = SetWindowsHookEx(13,KeyboardHookProcedure,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
// 如果设置钩子失败
if (hKeyboardHook == 0)
{
HookStop();
throw new Exception("SetWindowsHookEx failed.");
}
}

if (hMouseHook == 0)
{
MouseHookProcedure = new HookProc(MouseHookProc);

hMouseHook = SetWindowsHookEx(14,MouseHookProcedure,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
if (hMouseHook == 0)
{
HookStop();
throw new Exception("SetWindowsHookEx failed.");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

// 卸载钩子
public void HookStop()
{
bool retKeyboard = true;
if (hKeyboardHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
hKeyboardHook = 0;
}
if (hMouseHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hMouseHook);
hMouseHook = 0;
}
if (!(retKeyboard && retKeyboard)) throw new Exception("UnhookWindowsHookEx failed.");
}

读书人网 >VB Dotnet

热点推荐