如何修复 C# 控制台应用程序中的错误 KeyEventHandler?
How to fix error KeyEventHandler in c# console application?
我有一个问题,在我的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 wParam, 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 wParam, 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;
谁能帮帮我,非常感谢!
鉴于您发布的代码和含糊不清的 “我收到一条错误消息”(这不是实际问题,也不是有用的问题陈述……总是 specific),您似乎没有引用 System.Windows.Forms.dll
。另一方面,如果您没有引用 Winforms 程序集,则不清楚为什么在使用 KeyEventArgs
时也不会出现错误,因为它是在同一个程序集中定义的。
就是说,假设您在使用 KeyEventHandler
时遇到的错误仅仅是因为它没有定义,您可以定义相同的类型供您自己使用:
public delegate void KeyEventHandler(object sender, KeyEventArgs e);
即,只需复制 the documentation 中的委托类型声明。
现在,所有 都说过,如果您没有引用 Winforms 程序集,并且您也会收到 KeyEventArgs
类型的错误消息,正如预期的那样,您可能想要考虑不复制此方法的 Winforms 实现,而只是使用您自己的事件处理程序声明您自己的事件参数类型。您返回的唯一内容是虚拟键码,因此您不妨为此定义自己的类型:
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 对象。
请注意,您的 event-raising 实施不是 thread-safe。在 C# 中使用 null-conditional 运算符会更安全、更惯用,例如:
if (wParam == (IntPtr)WM_KEYDOWN)
{
KeyDown?.Invoke(this, new KeyboardHookEventArgs(kbStruct.VirtualKeyCode));
}
您还应该为 sender
传递正确的值,即 this
,如上所示。如果您希望事件没有发送者,那么它(以及 class 的其余部分)应该只是 static
.
我有一个问题,在我的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 wParam, 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 wParam, 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;
谁能帮帮我,非常感谢!
鉴于您发布的代码和含糊不清的 “我收到一条错误消息”(这不是实际问题,也不是有用的问题陈述……总是 specific),您似乎没有引用 System.Windows.Forms.dll
。另一方面,如果您没有引用 Winforms 程序集,则不清楚为什么在使用 KeyEventArgs
时也不会出现错误,因为它是在同一个程序集中定义的。
就是说,假设您在使用 KeyEventHandler
时遇到的错误仅仅是因为它没有定义,您可以定义相同的类型供您自己使用:
public delegate void KeyEventHandler(object sender, KeyEventArgs e);
即,只需复制 the documentation 中的委托类型声明。
现在,所有 都说过,如果您没有引用 Winforms 程序集,并且您也会收到 KeyEventArgs
类型的错误消息,正如预期的那样,您可能想要考虑不复制此方法的 Winforms 实现,而只是使用您自己的事件处理程序声明您自己的事件参数类型。您返回的唯一内容是虚拟键码,因此您不妨为此定义自己的类型:
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 对象。
请注意,您的 event-raising 实施不是 thread-safe。在 C# 中使用 null-conditional 运算符会更安全、更惯用,例如:
if (wParam == (IntPtr)WM_KEYDOWN)
{
KeyDown?.Invoke(this, new KeyboardHookEventArgs(kbStruct.VirtualKeyCode));
}
您还应该为 sender
传递正确的值,即 this
,如上所示。如果您希望事件没有发送者,那么它(以及 class 的其余部分)应该只是 static
.