none
利用hook监控到全局,得到的键盘numlock状态与实际情况不同。 RRS feed

  • 问题

  • form1上有一个Label1控件
    //这是Hook类:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Windows .Forms ;
    using System.Diagnostics;
    using System.Threading;
    namespace 键盘灯
    {
       public class 键盘监控   {
         [DllImport("user32.dll")]
       
           private static extern IntPtr  SetWindowsHookEx( HookType code, HookProc func, IntPtr instance, int threadID);
         [DllImport("kernel32.dll")]
         private static extern int GetModuleHandle(string lpModuleName);
           [DllImport("user32.dll")]

            private static extern int UnhookWindowsHookEx(IntPtr hook);

            [DllImport("user32.dll")]
           private static extern int CallNextHookEx(
               IntPtr hook, int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);

           private delegate int HookProc(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);

         public delegate void HookEventHandler(object sender, HookEventArgs e);
            public event HookEventHandler KeyDown;
           public event HookEventHandler KeyUp;

    //因为要接收的是键盘的消息所以要定义一些消息,和我们要接收的结构。
        public class HookEventArgs : EventArgs
       {
          // using Windows.Forms.Keys instead of Input.Key since the Forms.Keys maps
          // to the Win32 KBDLLHOOKSTRUCT virtual key member, where Input.Key does not
           public Keys Key;
            public bool Alt;
           public bool Control;
           public bool Shift;
         
           public HookEventArgs(UInt32 keyCode)
           {
             
               // detect what modifier keys are pressed, using
                // Windows.Forms.Control.ModifierKeys instead of Keyboard.Modifiers
               // since Keyboard.Modifiers does not correctly get the state of the
              // modifier keys when the application does not have focus
               this.Key = (Keys)keyCode;
               this.Alt = (System.Windows.Forms.Control.ModifierKeys & Keys.Alt) != 0;
              this.Control = (System.Windows.Forms.Control.ModifierKeys & Keys.Control) != 0;
                this.Shift = (System.Windows.Forms.Control.ModifierKeys & Keys.Shift) != 0;
             
            }

           public HookEventArgs()
           {
              
           }
        }

            private enum HookType : int
            {
               WH_JOURNALRECORD = 0,
                 WH_JOURNALPLAYBACK = 1,
                WH_KEYBOARD = 2,
                WH_GETMESSAGE = 3,
                WH_CALLWNDPROC = 4,
              WH_CBT = 5,
             WH_SYSMSGFILTER = 6,
               WH_MOUSE = 7,
                WH_HARDWARE = 8,
                WH_DEBUG = 9,
                WH_SHELL = 10,
                WH_FOREGROUNDIDLE = 11,
                 WH_CALLWNDPROCRET = 12,
                WH_KEYBOARD_LL = 13,
                 WH_MOUSE_LL = 14
            }
     
             public struct KBDLLHOOKSTRUCT
            {
               public UInt32 vkCode;
               public UInt32 scanCode;
                public UInt32 flags;
                 public UInt32 time;
                public IntPtr extraInfo;
             }
    //关键的在这里 注册Hook
             public IntPtr  _hookHandle;
        public  void Install()
            {
             
                HookProc _hookFunction = new HookProc(HookCallback);
                if (_hookHandle != IntPtr.Zero)
                   return;
     
               using (Process curProcess = Process.GetCurrentProcess())
                {
                    using (ProcessModule curModule = curProcess.MainModule)
                        _hookHandle = SetWindowsHookEx(_hookType, _hookFunction, (IntPtr)GetModuleHandle(curModule.ModuleName), 0);
                }
        }
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetKeyState(int nVirtKey);
        HookType _hookType = HookType.WH_KEYBOARD_LL;
           //因为要截获键盘消息
    //还有
       
    //其实最关键的是Marshal.GetHINSTANCE(list[0])得到当前程序的instance,这样这个Hook就是全局的Hook,这个位置也可以是null,这样就不是全局Hook。
    //有个很奇怪的现象就是这个函数,在调试状态执行不能成功,而做成Release以后运行成功,所以你在做程序时,不要因为调试失败而对这个函数有怀疑,编一个Release版本的程序,独立运行再试一下。我使用的环境是VS2005 + Vista。

    //接收消息的函数.
     
        public enum KeyboardEvents
        {
            KeyDown = 0x0100,
            KeyUp = 0x0101,
            SystemKeyDown = 0x0104,
            SystemKeyUp = 0x0105
        }

     


          private int HookCallback(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
          {
             
              if (code < 0)
                   return CallNextHookEx(_hookHandle, code, wParam, ref lParam);

           if ((lParam.flags & 0x80) != 0 && this.KeyUp != null)
          
              {
                 // Thread.Sleep(200);
                  this.KeyUp(this, new HookEventArgs(lParam.vkCode));
              }
         
          if ((lParam.flags & 0x80) == 0 && this.KeyDown != null)
                   {
                  this.KeyDown(this, new HookEventArgs(lParam.vkCode));
     }
               if (lParam.vkCode == 44)
                         {
                            return 1;
                          }
              // Thread.Sleep(200);
          return CallNextHookEx(_hookHandle, code, wParam, ref lParam);
           }
    //这里会区分KeyUp和KeyDown,注意一定要调用CallNextHookEx,这样会将这个消息在系统中继续传递,这很重要。除非你想阻止这个消息,也不希望其他程序再处理这个消息。

    //下面最后的操作,释放注册。
     public  void Uninstall()
          {
              if (_hookHandle != IntPtr.Zero)
               {
                    UnhookWindowsHookEx(_hookHandle);
                   _hookHandle = IntPtr.Zero;
                }
            }
     

    }
    }
    //hook结束。

    //在form中创类。
     键盘灯.键盘监控 myKeyboard = new 键盘监控();

            private void Form1_Load(object sender, EventArgs e)
            {

      myKeyboard.Install();

             myKeyboard.KeyUp  +=new 键盘监控.HookEventHandler(myKeyboard_KeyUp);
    }

    //全局的keydown事件。
      private void myKeyboard_KeyUp(object sender, 键盘监控.HookEventArgs  e) {
                if (e.Key ==  Keys.Capital|| e.Key ==Keys .NumLock || e.Key ==Keys .Scroll )
                {
     String Str消息 = "";
                String Str大写 = "";
                String Str数字 = "";
                String Str滚动锁 = "";
          Boolean 大写 =Control .IsKeyLocked(Keys.Capital);
                Boolean 滚动锁 = Control .IsKeyLocked(Keys.Scroll );
                Boolean 数字 = Control .IsKeyLocked(Keys.NumLock );
     if (数字) { Str数字 = "数字锁 开"; } else { Str数字 = "数字锁 关"; }
                if (大写) { Str大写 = "大写 开"; } else { Str大写 = "大写 关"; }
                if (滚动锁) {  Str滚动锁 = "滚动锁 开"; } else { Str滚动锁 = "滚动锁 关"; }
          Str消息 = Str数字 + "|" + Str大写 + "|" + Str滚动锁;
    //窗体上有一个Label1 控件。
                this.Label1.Text=Str消息 ;
                             }

    • 已移动 邹俊才Moderator 2011年3月4日 15:41 (发件人:2011微软MSDN论坛线下活动互动讨论区(挨踢人士甘苦讨论区))
    2009年10月30日 7:25