🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Newbie's Newbie Trying to get KeyEventArgs in C# to Work

Started by
12 comments, last by Shaarigan 4 years, 10 months ago

A very good day to you Sir,

I hope you are doing Great Sir,

I am trying to get the C# GetKeyPress Function to work 

Please kindly see my C# Code attached 

Can someone please kindly help me out

Thank you very much for your time and kind help

Kind Regards as Always

 


using System;
public class Program
{
	public static void Main()
	{
		KeyEventArgs GetKeys;

            	if (GetKeys.KeyCode == Keys.Enter)
            	{
                	System.Windows.Forms.MessageBox.Show("Enter Key Pressed");
            	}
			
	}
}

 

 

 

Advertisement

If you want to see if the Enter key has been pressed you just do this by using KeyUp which fires after the key has been released:


using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.KeyUp += new KeyEventHandler(this.Form1_KeyUp);
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                MessageBox.Show("'Enter' Key Pressed");
            }
        }
    }
}

 

Programmer and 3D Artist

To obtain key events from a C' application, you need to connect to the OS message loop. This is usually a set of functions that query and signal the messages that the OS is passing to every UI related process. For example if you move the mouse over a window or a button should be redrawn by the OS UI API is all some kind of message the underlaying handler tells your process. In other languages like C++, you would have to query this by your own but fortunately C# offers some ways to do this for you.

You could create a Windows Form as @Rutin showed above, you can use WPF or go deeper into API programming and either use System Hooks or the query functions from the OS API directly.

However, Winforms and WPF provide events; multicast delegates you can attach a function to. Those events will be fired from the .NET Framework behind so you won't need to do anything else and simply can handle the input event in your code

Thank you everyone for replying to my Newbie's questions

The reason I need this is because I am using the Jitbit Macro Recorder 

I am not able to get the Jitbit Macro Recorder to use 3 Keyboard Keys for the Trigger macro

E.G. I use these 3 Keys - Down Arrow + Left Arrow + A

But the Jitbit Macro Recorder does have a small C# Functionality

It is able to handle simple C# programs from within the Macro Engine

And the Jitbit Macro C# Engine must use these C# Procedure calls


public class Program
{
	public static void Main()
	{
	}
}

I am not sure how I can get the Jitbit Macro Engine to accept the Binding of 3 Keys for the Macro

Thank you and kind regards

On that matter

I was wondering if any kind soul knows of a Game Macro Engine that can be bound to more then 1 Key

Hope to hear from you soon

Thank you and kind regards

My Logitech Mouse is able to simulate complex Macro Keys but to answer your question, it is quite difficult to grab OS keys without the message loop. Your only option is using Hooks for example in Windows. It can be done like so


using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class InterceptKeys
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private static LowLevelKeyboardProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;

    public static void Main()
    {
        _hookID = SetHook(_proc);
        Application.Run();
        UnhookWindowsHookEx(_hookID);
    }

    private static IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);
            Console.WriteLine((Keys)vkCode);
        }

        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
}

(From this StackOverflow question)

And the author also has written an article you should read

Thank you extremely much for all your time and kind help

I really appreciate it very much

I hope you have a great week ahead Sir

Kind Regards as Always

May I please kindly ask I need to merge all my .CS Files into 1 big .CS Main File in order for everything to work

I have the following code which I found on the Internet

I guess that this First Section of Code is for the .CS File -  LowLevelKeyboardHook.CS


using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class LowLevelKeyboardHook
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_SYSKEYDOWN = 0x0104;
    private const int WM_KEYUP = 0x101;
    private const int WM_SYSKEYUP = 0x105;

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    public event EventHandler<Keys> OnKeyPressed;
    public event EventHandler<Keys> OnKeyUnpressed;

    private LowLevelKeyboardProc _proc;
    private IntPtr _hookID = IntPtr.Zero;

    public LowLevelKeyboardHook()
    {
        _proc = HookCallback;
    }

    public void HookKeyboard()
    {
        _hookID = SetHook(_proc);
    }

    public void UnHookKeyboard()
    {
        UnhookWindowsHookEx(_hookID);
    }

    private IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);

            OnKeyPressed.Invoke(this, ((Keys)vkCode));
        }
        else if(nCode >= 0 && wParam == (IntPtr)WM_KEYUP ||wParam == (IntPtr)WM_SYSKEYUP)
        {
            int vkCode = Marshal.ReadInt32(lParam);

            OnKeyUnpressed.Invoke(this, ((Keys)vkCode));
        }

        return CallNextHookEx(_hookID, nCode, wParam, lParam);            
    }
}

 

Now these Code are for the Main.CS File


kbh = new LowLevelKeyboardHook();
kbh.OnKeyPressed += kbh_OnKeyPressed;
kbh.OnKeyUnpressed += kbh_OnKeyUnpressed;
kbh.HookKeyboard();

 

I suspect the following Code could be found in the HookCallBack in the - LowLevelKeyboardHook.CS File


bool lctrlKeyPressed;
bool f1KeyPressed;

void kbh_OnKeyPressed(object sender, Keys e)
{
    if (e == Keys.LControlKey)
    {
        lctrlKeyPressed = true;
    }
    else if (e == Keys.F1)
    {
        f1KeyPressed= true;
    }
    CheckKeyCombo();
}

void kbh_OnKeyUnPressed(object sender, Keys e)
{
    if (e == Keys.LControlKey)
    {
        lctrlKeyPressed = false;
    }
    else if (e == Keys.F1)
    {
        f1KeyPressed= false;
    }
}

void CheckKeyCombo()
{
    if (lctrlKeyPressed && f1KeyPressed)
    {
        //Open Form
    }
}

 

And Finally Here is the Code for the Main.CS File


[STAThread]
static void Main()
{

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    LowLevelKeyboardHook kbh = new LowLevelKeyboardHook();
    kbh.OnKeyPressed += kbh_OnKeyPressed;
    kbh.OnKeyUnpressed += kbh_OnKeyUnpressed;
    kbh.HookKeyboard();

    Application.Run();

    kbh.UnHookKeyboard();

}

 

What I would like to know is - How can I combine all These Codes into 1 Main Big .CS File ?

E.G. How do I combine everything in the File - LowLevelKeyboardHook.CS into the Main.CS File ?

Hope to hear from you soon

Thank you very much for your time and kind help

Kind Regards as Always Sir

 

 

 

 

Just copy/paste it!? ?

If you know a little about C#, you also know that it dosen't matter where something is defined, as long as it is defined due to the C# grammar. SO if you have everything in an own namespace, just copy paste it. If you have same namespace, just copy paste the code from inside the namespace.

You need to merge the using directives in the header of the file because C# dosen't allow to have multiple using blocks spread arround in your code so copy paste any using directive from the files and add it to the destination files header first before any code.

Thats it, dosen't sound to complicated hu?

Dear Sir,

Thank you for coming back to this Thread and taking a look at my Code 

I really appreciate it very much

I have done my best and please kindly see the code below for what I have combined so far

The code does not work for some reason - The Error Message is - 

Line 14 - The name "kbh_OnKeyPressed" does not exist in the current context

Line 15 - The name "Kbh_OnKeyUnpressed" does not exist in the current context

May I please kindly ask how can I resolve this issue

Hope to hear from you soon - Thank you and kind regards as always Sir


using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class Program
{
    public static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        LowLevelKeyboardHook kbh = new LowLevelKeyboardHook();
        kbh.OnKeyPressed += kbh_OnKeyPressed;
        kbh.OnKeyUnpressed += kbh_OnKeyUnpressed;
        kbh.HookKeyboard();

        Application.Run();

        kbh.UnHookKeyboard();
    }
}

public class LowLevelKeyboardHook
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_SYSKEYDOWN = 0x0104;
    private const int WM_KEYUP = 0x101;
    private const int WM_SYSKEYUP = 0x105;

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    public event EventHandler<Keys> OnKeyPressed;
    public event EventHandler<Keys> OnKeyUnpressed;

    private LowLevelKeyboardProc _proc;
    private IntPtr _hookID = IntPtr.Zero;

    public LowLevelKeyboardHook()
    {
        _proc = HookCallback;
    }

    public void HookKeyboard()
    {
        _hookID = SetHook(_proc);
    }

    public void UnHookKeyboard()
    {
        UnhookWindowsHookEx(_hookID);
    }

    private IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);

            OnKeyPressed.Invoke(this, ((Keys)vkCode));
        }
        else if(nCode >= 0 && wParam == (IntPtr)WM_KEYUP ||wParam == (IntPtr)WM_SYSKEYUP)
        {
            int vkCode = Marshal.ReadInt32(lParam);

            OnKeyUnpressed.Invoke(this, ((Keys)vkCode));
        }

        return CallNextHookEx(_hookID, nCode, wParam, lParam);            
    }
}

 

 

 

This topic is closed to new replies.

Advertisement