Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

key capture using global hotkey in C#

I have a application that runs in the background like i may keep my app in the system tray.If it remains on system tray my app will do it's job. Whenever a user press F10 or F9 some works will be done. i tried this:

public partial class Form1 : Form
{
    public int a = 1;

    [DllImport("user32.dll")]
    public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
    [DllImport("user32.dll")]
    public static extern bool UnregisterHotKey(IntPtr hWnd, int id);


    [DllImport("User32.dll")]
    private static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);
    [DllImport("User32.dll")]
    private static extern short GetAsyncKeyState(System.Int32 vKey);

    const int MYACTION_HOTKEY_ID = 1;

    public Form1()
    {
        InitializeComponent();
        RegisterHotKey(this.Handle, MYACTION_HOTKEY_ID, 0, (int) Keys.F9);
        RegisterHotKey(this.Handle, MYACTION_HOTKEY_ID, 0, (int)Keys.F10);

        this.ShowInTaskbar = false;
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x0312 && m.WParam.ToInt32() == MYACTION_HOTKEY_ID && (GetAsyncKeyState(Keys.F9) == -32767))
        {
            if ((a % 2) != 0)
            {
                a++;
                MessageBox.Show(a.ToString()+"not equal F9");
                label1.Text = "not equal F9";
            }

            if ((a % 2) == 0)
            {
                a++;
                MessageBox.Show(a.ToString()+"equal F9");
                label1.Text = " equal F9";
            }

        }

        else if (m.Msg == 0x0312 && m.WParam.ToInt32() == MYACTION_HOTKEY_ID && (GetAsyncKeyState(Keys.F10) == -32767))
        {
            if ((a % 2) != 0)
            {
                a++;
                MessageBox.Show(a.ToString() + "not equal F10");
                label1.Text = "not equal F10";
            }

            if ((a % 2) == 0)
            {
                a++;
                MessageBox.Show(a.ToString() + "equal F10");
                label1.Text = " equal F10";
            }

        }
        base.WndProc(ref m);
    }

}

As i use set "this.ShowInTaskbar = false" this line it doesn't work.But if i don't set this it works fine.For my app i have to use this line.How can i solve this????

like image 710
ImonBayazid Avatar asked Mar 15 '13 14:03

ImonBayazid


1 Answers

You need to subscribe to certain messages that the operating system sends by means of a native function call like RegisterHotKey(). When you call this function You tell the operating system which window to send the messages to by specifying the Handle of the window, this can be considered an address. When you set ShowInTaskbar = false the handle changes so the operating system will not know where to reach you.

See the first arugment:

RegisterHotKey(this.Handle, MYACTION_HOTKEY_ID, 0, (int) Keys.F9);

To resolve your issue you can create a class that derives from NativeWindow which "Provides a low-level encapsulation of a window handle and a window procedure." and from within that class (or at least using that class's handle depending on your implementation), register the hotkeys using a handle that will never change.

public sealed class HotkeyManager : NativeWindow, IDisposable
{
    public HotkeyManager()
    {
        CreateHandle(new CreateParams());
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == Constants.WM_HOTKEY)
        {
             //handle hotkey message
        }
        base.WndProc(ref m);
    }

    public void Dispose()
    {
        DestroyHandle();
    }
}
like image 122
User 12345678 Avatar answered Oct 29 '22 14:10

User 12345678