key capture using global hotkey in C#

﹥>﹥吖頭↗ 提交于 2019-12-10 15:15:31

问题


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????


回答1:


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



回答2:


As far as I know, you need to re-register the hotkey whenever you change the "ShowInTaskbar" state.

Someone else had a similar problem; see this thread.



来源:https://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!