2009-07-24 101 views
1

我使用下面的代碼來禁用Alt + Tab,Alt + Esc,Ctrl + Esc和Windows Key,但不知何故它不工作。請幫我糾正它。使用C阻止快捷鍵#

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

     private delegate int LowLevelKeyboardProcDelegate(int nCode, int 
      wParam, ref KBDLLHOOKSTRUCT lParam); 

     [DllImport("user32.dll", EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi)] 
     private static extern int SetWindowsHookEx(
      int idHook, 
      LowLevelKeyboardProcDelegate lpfn, 
      int hMod, 
      int dwThreadId); 

     [DllImport("user32.dll")] 
     private static extern int UnhookWindowsHookEx(int hHook); 

     [DllImport("user32.dll", EntryPoint = "CallNextHookEx", CharSet = CharSet.Ansi)] 
     private static extern int CallNextHookEx(
      int hHook, int nCode, 
      int wParam, ref KBDLLHOOKSTRUCT lParam); 

     const int WH_KEYBOARD_LL = 13; 
     private int intLLKey; 
     private KBDLLHOOKSTRUCT lParam; 

     private struct KBDLLHOOKSTRUCT 
     { 
      public int vkCode; 
      int scanCode; 
      public int flags; 
      int time; 
      int dwExtraInfo; 
     } 

     private int LowLevelKeyboardProc(
      int nCode, int wParam, 
      ref KBDLLHOOKSTRUCT lParam) 
     { 
      bool blnEat = false; 
      switch (wParam) 
      { 
       case 256: 
       case 257: 
       case 260: 
       case 261: 
        //Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key 
        if (((lParam.vkCode == 9) && (lParam.flags == 32)) || 
        ((lParam.vkCode == 27) && (lParam.flags == 32)) || ((lParam.vkCode == 
        27) && (lParam.flags == 0)) || ((lParam.vkCode == 91) && (lParam.flags 
        == 1)) || ((lParam.vkCode == 92) && (lParam.flags == 1)) || ((true) && 
        (lParam.flags == 32))) 
        { 
         blnEat = true; 
        } 
        break; 
      } 

      if (blnEat) 
       return 1; 
      else return CallNextHookEx(0, nCode, wParam, ref lParam); 

     } 

     private void KeyboardHook(object sender, EventArgs e) 
     { 
      intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL,new LowLevelKeyboardProcDelegate(LowLevelKeyboardProc), 
         System.Runtime.InteropServices.Marshal.GetHINSTANCE(
         System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0); 
     } 

     private void ReleaseKeyboardHook() 
     { 
      intLLKey = UnhookWindowsHookEx(intLLKey); 
     } 

     private void checkBox1_CheckedChanged(object sender, EventArgs e) 
     { 
      if (checkBox1.Checked) 
       KeyboardHook(this, e); 
      else 
       ReleaseKeyboardHook(); 
     } 
    } 
} 
+0

@湯姆·裏特,究竟是什麼在代碼編輯以上。謝謝。 – Anuya 2009-07-24 04:17:07

回答

6

該代碼一般工作得很好。您目睹的效果可能源於在Visual Studio調試器下運行,這通常意味着您在 Visual Studio Hosting Process (vshost.exe)中運行。

這意味着在您的KeyboardHook()函數中調用System.Reflection.Assembly.GetExecutingAssembly()將返回vshost.exe而不是您的可執行文件,因此無法實現爲可執行文件安裝掛鉤的預期效果。

所以看你的代碼實際上你必須執行以下操作之一:通過菜單

  • 來看,它的Visual Studio之外
  • 在Visual Studio中運行它,但「Debug'- >「開始不調試」
  • 禁用的Visual Studio宿主進程,請參見下面

注意可以disable the Visual Studio Hosting Process,但請注意潛在的副作用,引證:

當宿主進程被禁用, 幾個調試功能 不可用或經驗減小 性能。欲瞭解更多信息,請參閱 Debugging and the Hosting Process

1

您可以通過here查看我對有關問題的回答。 注意RegisterLowLevelHook方法的差異(您稱爲您的KeyboardHook,因此您知道要比較哪些內容)。即使從VS進行調試,我也沒有遇到任何問題。 基本上,正如其他人所說,不要使用GetExecutingAssembly方法,而是我在其他答案中列出的。

這裏是你感興趣的一個函數摘錄:

private IntPtr RegisterLowLevelHook(LowLevelKeyboardProc hook) 
{ 
    IntPtr handle = IntPtr.Zero; 

    using (Process currentProcess = Process.GetCurrentProcess()) 
    using (ProcessModule currentModule = currentProcess.MainModule) 
    { 
     IntPtr module = Kernel32.GetModuleHandle(currentModule.ModuleName); 
     handle = User32.SetWindowsHookEx(HookType.KEYBOARD_LL, hook, module, 0); 
    } 

    return handle; 
}