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

谁能帮我,非常感谢!

彼得·杜尼奥

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

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

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

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

现在,所有这些都说明了,如果您没有引用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;

在类似的地方创建args对象new KeyboardHookEventArgs(kbStruct.VirtualKeyCode)

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

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

您还应该为传递正确的值sender,即this如上所述。如果您希望该事件没有发送者,则该事件(以及该类的其余部分)应该为static

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何从C#中的控制台应用程序运行Web应用程序

在C#中的控制台应用程序异步?

控制台应用程序 c# 中的 PrintDialog

错误,C#控制台应用程序中的正则表达式无效

如果用户在C#程序中打印“ x”,如何使控制台应用程序退出?

如何在C#控制台应用程序中捕获ctrl-c(SIGINT)

如何在C#的控制台应用程序中设置启动对象?

如何在控制台应用程序C#中访问SolidBrush

如何从C#控制台应用程序写入Azure WebJobs中的日志?

如何使用 C# 在控制台应用程序中执行命令或进程

如何在控制台应用程序C#中打印值

如何在控制台应用程序中同时写多个位置?C#

C# 如何在控制台应用程序中制作水平条形图

如何在C#控制台应用程序中过滤文件类型,例如.exe

如何使用C#在内存中执行.NET控制台应用程序?

如何使用 C# 控制台应用程序中的方法更新表?

如何在 C# 控制台应用程序中显示模型列表

尝试在控制台应用程序中创建枚举时如何修复“}预期”?

控制台应用程序中的Unity Config错误

控制台应用程序 c# 舍入

VS 2017 控制台应用程序 (C#)

河内C#塔控制台应用程序。

C#控制台应用程序即服务

C# 控制台应用程序安全

从其他C#控制台应用程序运行C#控制台应用程序

C#控制台应用程序错误-无法识别/正确评估返回的int

显示/隐藏C#控制台应用程序的控制台窗口

如何使用命令中的开关在 C# 控制台应用程序中运行命令?

如何停止控制台应用程序中的闪烁?