微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何修复C#控制台应用程序中的错误KeyEventHandler?

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。