首页 > 解决方案 > 如何修复 C# 控制台应用程序中的错误 KeyEventHandler?

问题描述

我有一个问题,在我的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;

谁能帮帮我,非常感谢!

标签: c#hookmousekeyhook

解决方案


鉴于您发布的代码和模糊的“我收到一条错误消息”(这不是一个实际问题,也不是一个有用的问题陈述……总是要具体),您似乎没有引用System.Windows.Forms.dll. 另一方面,如果您没有引用 Winforms 程序集,则不清楚为什么您在使用的地方也没有收到错误KeyEventArgs,因为这是在同一个程序集中定义的。

也就是说,假设您使用的错误KeyEventHandler只是没有定义,您可以定义相同的类型供您自己使用:

public delegate void KeyEventHandler(object sender, KeyEventArgs e);

即,只需从文档中复制委托类型声明。

现在,说了这么多,如果您没有引用 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 对象。

请注意,您的事件引发实现不是线程安全的。在 C# 中使用空条件运算符会更安全,也更惯用,例如:

if (wParam == (IntPtr)WM_KEYDOWN)
{
    KeyDown?.Invoke(this, new KeyboardHookEventArgs(kbStruct.VirtualKeyCode));
}

您还应该为 传递一个正确的值sender,即this如上所示。如果您希望事件没有发件人,那么它(和班级的其他人)应该只是static.


推荐阅读