在C#中使用全局热键捕获密钥#

问题描述:

我有一个在后台运行的应用程序,就像我可以将我的应用程序保留在系统托盘中一样。如果它保留在系统托盘中,我的应用程序将执行它的工作。每当用户按下F10或F9,一些作品就会完成。我想这:在C#中使用全局热键捕获密钥#

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

} 

,因为我用设置“this.ShowInTaskbar =假”这一行,如果我不设置此它的工作原理fine.For我的应用程序不work.but我必须使用此line.How我可以解决这个问题?

您需要订阅某些操作系统通过本机函数调用发送的消息,如RegisterHotKey()。当你调用这个函数时,通过指定窗口的Handle告诉操作系统哪个窗口发送消息,这可以被认为是一个地址。当您设置ShowInTaskbar = false时,句柄会发生变化,因此操作系统无法知道到达哪里。

见第一arugment:

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

要解决你的问题,你可以创建一个从NativeWindow其派生的类和“提供了一个窗口句柄的一个低级别的封装和窗口过程”。从该类中(或者至少根据您的实现使用该类的句柄),使用永不会更改的句柄注册热键。

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

据我所知,无论何时更改“ShowInTaskbar”状态,都需要重新注册热键。

其他人也有类似的问题;请参阅this thread