CongSyIT
CongSyIT

Reputation: 61

How to fix error KeyEventHandler in c# console application?

I have a problem that when executing this code in my winform application, it runs normally but when running on the console it gets an error message, it seems that KeyEventHandler is only used in winform, yes What can be replaced in the console application. Here is my hook function:

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);
    }
}
}

Here is how I use it:

 _y2KeyboardHook.KeyDown += (sender, e) =>// ghi nhan thong tin tu ban phim
        {
            if (e.KeyCode.ToString() != "")
            {
               Console.WriteLine("Hello "+KeyCode);
            }

      }

I got an error message on 2 lines

    public event KeyEventHandler KeyDown;
    public event KeyEventHandler KeyUp;

Can anyone help me, thanks a lot!

Upvotes: 1

Views: 364

Answers (1)

Peter Duniho
Peter Duniho

Reputation: 70652

Given the code you posted and the vague "I got an error message" (which is not an actual question nor a useful problem statement…always be specific), it seems likely you are not referencing System.Windows.Forms.dll. On the other hand, if you aren't referencing the Winforms assembly, it's not clear why you don't also get an error where you use KeyEventArgs, since that's defined in the same assembly.

That said, assuming the error you're getting for your use of KeyEventHandler is simply that it's not defined, you can define the same type for your own use:

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

I.e., just copy the delegate type declaration from the documentation.

Now, all that said, if you aren't referencing the Winforms assembly, and you are getting an error message as expected with the KeyEventArgs type as well, as would be expected, you might want to consider not copying the Winforms implementation of this approach, and just declaring your own event args type with your own event handler. The only thing you're returning is the virtual key code, so you might as well define your own types for that:

class KeyboardHookEventArgs : EventArgs
{
    public int VirtualKeyCode { get; }

    public KeyboardHookEventArgs(int virtualKeyCode)
    {
        VirtualKeyCode = virtualKeyCode;
    }
}

…then the events:

public event EventHandler<KeyboardHookEventArgs> KeyDown;
public event EventHandler<KeyboardHookEventArgs> KeyUp;

Where you create the args object like new KeyboardHookEventArgs(kbStruct.VirtualKeyCode) instead.

Note that your event-raising implementation is not thread-safe. It would be more safe, and more idiomatic in C#, to use the null-conditional operator, e.g.:

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

You should also pass a correct value for sender, i.e. this as I've shown above. If you want for the event to have no sender, then it (and the rest of the class) should just be static.

Upvotes: 1

Related Questions