问题描述
我有一个问题,当在我的winform应用程序中执行此代码时,它可以正常运行,但是在控制台上运行时会收到错误消息,看来KeyEventHandler仅在winform中使用,可以在控制台中替换应用。这是我的钩子函数:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
namespace Websevice_Core_Console
{
class Y2KeyboardHook
{
#region Win32 API Functions and Constants
[DllImport("user32.dll",SetLastError = true)]
private static extern IntPtr SetwindowsHookEx(int idHook,KeyboardHookDelegate lpfn,IntPtr hMod,int dwThreadId);
[DllImport("user32.dll",SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll",SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk,int nCode,IntPtr wParam,IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x101;
#endregion
private KeyboardHookDelegate _hookProc;
private IntPtr _hookHandle = IntPtr.Zero;
public delegate IntPtr KeyboardHookDelegate(int nCode,IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
public struct KeyboardHookStruct
{
public int VirtualKeyCode;
public int ScanCode;
public int Flags;
public int Time;
public int ExtraInfo;
}
#region Keyboard Events
public event KeyEventHandler KeyDown;
public event KeyEventHandler KeyUp;
#endregion
// destructor
~Y2KeyboardHook()
{
Uninstall();
}
public void Install()
{
_hookProc = KeyboardHookProc;
_hookHandle = SetupHook(_hookProc);
if (_hookHandle == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
private IntPtr SetupHook(KeyboardHookDelegate hookProc)
{
IntPtr hInstance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);
return SetwindowsHookEx(WH_KEYBOARD_LL,hookProc,hInstance,0);
}
private IntPtr KeyboardHookProc(int nCode,IntPtr lParam)
{
if (nCode >= 0)
{
KeyboardHookStruct kbStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam,typeof(KeyboardHookStruct));
if (wParam == (IntPtr)WM_KEYDOWN)
{
if (KeyDown != null)
KeyDown(null,new KeyEventArgs((Keys)kbStruct.VirtualKeyCode));
}
else if (wParam == (IntPtr)WM_KEYUP)
{
if (KeyUp != null)
KeyUp(null,new KeyEventArgs((Keys)kbStruct.VirtualKeyCode));
}
}
return CallNextHookEx(_hookHandle,nCode,wParam,lParam);
}
public void Uninstall()
{
UnhookWindowsHookEx(_hookHandle);
}
}
}
这是我的用法:
_y2KeyboardHook.KeyDown += (sender,e) =>// ghi nhan thong tin tu ban phim
{
if (e.KeyCode.ToString() != "")
{
Console.WriteLine("Hello "+KeyCode);
}
}
我在2行上收到一条错误消息
public event KeyEventHandler KeyDown;
public event KeyEventHandler KeyUp;
谁能帮助我,非常感谢!
解决方法
考虑到您发布的代码和模糊的“我收到了错误消息” (这不是一个实际的问题,也不是有用的问题说明,...总是特定于 ),您似乎没有引用System.Windows.Forms.dll
。另一方面,如果您未引用Winforms程序集,则不清楚为什么在使用KeyEventArgs
时也不会出现错误,因为它是在同一程序集中定义的。
也就是说,假设使用KeyEventHandler
时遇到的错误只是未定义,您可以定义相同的类型以供自己使用:
public delegate void KeyEventHandler(object sender,KeyEventArgs e);
也就是说,只需复制the documentation中的委托类型声明即可。
现在,所有 都说过,如果您未引用Winforms程序集,并且也会像预期的那样收到KeyEventArgs
类型的错误消息,您可能要考虑不复制此方法的Winforms实现,而只是使用自己的事件处理程序声明自己的事件args类型。您唯一要返回的是虚拟密钥代码,因此您最好为此定义自己的类型:
class KeyboardHookEventArgs : EventArgs
{
public int VirtualKeyCode { get; }
public KeyboardHookEventArgs(int virtualKeyCode)
{
VirtualKeyCode = virtualKeyCode;
}
}
…然后发生事件:
public event EventHandler<KeyboardHookEventArgs> KeyDown;
public event EventHandler<KeyboardHookEventArgs> KeyUp;
在其中创建new KeyboardHookEventArgs(kbStruct.VirtualKeyCode)
之类的args对象的地方。
请注意,您的事件引发实现不是线程安全的。使用空条件运算符(例如:
)在C#中更安全,更习惯。if (wParam == (IntPtr)WM_KEYDOWN)
{
KeyDown?.Invoke(this,new KeyboardHookEventArgs(kbStruct.VirtualKeyCode));
}
您还应该为sender
传递正确的值,即我上面显示的this
。如果您希望该事件没有发送者,则该事件(以及课程的其余部分)应该仅为static
。