如何修复 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.