天天看点

Hook 底层键盘钩子

声明底层键盘钩子消息数据 结构:

//Delphi中没有定义KBDLLHOOKSTRUCT结构,自己定义一个
type
  PKBDLLHOOKSTRUCT=^KBDLLHOOKSTRUCT;
  KBDLLHOOKSTRUCT=record
    vkCode:DWORD;
    scanCode:DWORD;
    flags:DWORD;
    time:DWORD;
    dwExtraInfo:DWORD;
  end;

const
  WH_KEYBOARD_LL = 13;
           

安装卸载钩子:

var
  MyHook: HHook;
  
function InstallKeyboardListener: Boolean; stdcall;
begin
  MyHook:= SetWindowsHookEx(WH_KEYBOARD_LL, AA, HInstance, 0);
  Result:= MyHook <> 0;
end;

function UninstallKeyboardListener: Boolean; stdcall;
begin
  if MyHook<>0 then
    Result:= UnhookWindowsHookEx(MyHook);
end;
           

钩子子程:

function AA(nCode: Integer; wParam: WPARAM; lParam: LPARAM):LRESULT; stdcall;
var
  p: PKBDLLHOOKSTRUCT;
  KeyInfo, sChar: string;
  BCtrl, BShift, BAlt, BCapsLk: Boolean;
begin
  if wParam= WM_KEYDOWN then
  if nCode = HC_Action then
  begin
    BCtrl:= GetKeyState(VK_CONTROL)<0;
    if BCtrl then
      KeyInfo:= KeyInfo+ 'Ctrl=1'#9
    else
      KeyInfo:= KeyInfo+ 'Ctrl=0'#9;

    BShift:= GetKeyState(VK_SHIFT)<0;
    if BShift then
      KeyInfo:= KeyInfo+ 'Shift=1'#9
    else
      KeyInfo:= KeyInfo+ 'Shift=0'#9;

    BAlt:= GetKeyState(VK_MENU)<0;
    if BAlt then
      KeyInfo:= KeyInfo+ 'Alt=1'#9
    else
      KeyInfo:= KeyInfo+ 'Alt=0'#9;

    BCapsLk:= GetKeyState(VK_CAPITAL)and 1 = 1;
    if BCapsLk then
      KeyInfo:= KeyInfo+ 'CapsLk=1'#9
    else
      KeyInfo:= KeyInfo+ 'CapsLk=0'#9;

    p:= PKBDLLHOOKSTRUCT(lParam);

    case p^.vkCode of
      65..90:      // A..Z
      begin
        if BCapsLk xor BShift then
          sChar:= chr(p^.vkCode)        //大写
        else
          sChar:= chr(p^.vkCode+32);    //小写
      end;
      48..57:      //0..9
      begin  
        if not BShift then  //Shift没按下
          sChar:= chr(p^.vkCode)
        else
          case p^.vkCode of
            48: sChar:= chr(41);  //0
            49: sChar:= chr(33);  //1
            50: sChar:= chr(64);  //2
            51: sChar:= chr(35);  //3
            52: sChar:= chr(36);  //4
            53: sChar:= chr(37);  //5
            54: sChar:= chr(94);  //6
            55: sChar:= chr(38);  //7
            56: sChar:= chr(42);  //8
            57: sChar:= chr(40);  //9
          end;
      end;  
      186:   //;(分号)
      begin    
        if not BShift then  //Shift没按下
          sChar:= chr(59)
        else       
          sChar:= chr(58);
      end;
      187:   //=键
      begin  
        if not BShift then  //Shift没按下
          sChar:= chr(61)
        else       
          sChar:= chr(43);
      end;
      188:   //,键(逗号)
      begin
        if not BShift then  //Shift没按下
          sChar:= chr(44)
        else       
          sChar:= chr(60);
      end;
      189:   //-键(减号)
      begin  
        if not BShift then  //Shift没按下
          sChar:= chr(45)
        else
          sChar:= chr(95);
      end;
      190:   //.键(句号)
      begin 
        if not BShift then  //Shift没按下
          sChar:= chr(46)
        else       
          sChar:= chr(62);
      end;
      191:   ///键
      begin    
        if not BShift then  //Shift没按下
          sChar:= chr(47)
        else       
          sChar:= chr(63);
      end;
      192:   //`键(Esc下面)
      begin  
        if not BShift then  //Shift没按下
          sChar:= chr(96)
        else       
          sChar:= chr(126);
      end;
      219:   //[键
      begin          
        if not BShift then  //Shift没按下
          sChar:= chr(91)
        else       
          sChar:= chr(123);
      end;
      220:   //\键
      begin   
        if not BShift then  //Shift没按下
          sChar:= chr(92)
        else       
          sChar:= chr(124);
      end;
      221:   //]键
      begin   
        if not BShift then  //Shift没按下
          sChar:= chr(93)
        else
          sChar:= chr(125);
      end;
      222:   //'键(引号)
      begin  
        if not BShift then  //Shift没按下
          sChar:= chr(39)
        else       
          sChar:= chr(34);
      end;

      //以下是不可见字符
      1..47:
        sChar:= ArrVKs1[p^.vkCode];
      91..135:
        sChar:= ArrVKs2[p^.vkCode];
      144:
        sChar:= 'VK_NUMLOCK';
      145:    
        sChar:= 'VK_SCROLL';
      160..165:
        sChar:= ArrVKs3[p^.vkCode];
      229:     
        sChar:= 'VK_PROCESSKEY';
      246..254: 
        sChar:= ArrVKs4[p^.vkCode];
    end;

    if p^.vkCode in [65..90,48..57,186..192,219..222] then
      sChar:= sChar+#9;

    KeyInfo:= 'Key='+ sChar+ #9 + 'VK='+ IntToStr(p^.vkCode)+#9 + KeyInfo;

    AddLog(KeyInfo, DllPath+ FormatDateTime('yyyyMMdd',Date)+ '.txt');
  end;

  Result:= CallNextHookEx(MyHook, nCode, wParam, lParam);
end;
           

Messages.pas单元键盘的动作类型:

{$EXTERNALSYM WM_KEYFIRST}
  WM_KEYFIRST         = $0100;
  {$EXTERNALSYM WM_KEYDOWN}
  WM_KEYDOWN          = $0100;
  {$EXTERNALSYM WM_KEYUP}
  WM_KEYUP            = $0101;
  {$EXTERNALSYM WM_CHAR}
  WM_CHAR             = $0102;
  {$EXTERNALSYM WM_DEADCHAR}
  WM_DEADCHAR         = $0103;
  {$EXTERNALSYM WM_SYSKEYDOWN}
  WM_SYSKEYDOWN       = $0104;
  {$EXTERNALSYM WM_SYSKEYUP}
  WM_SYSKEYUP         = $0105;
  {$EXTERNALSYM WM_SYSCHAR}
  WM_SYSCHAR          = $0106;
  {$EXTERNALSYM WM_SYSDEADCHAR}
  WM_SYSDEADCHAR      = $0107;
  {$EXTERNALSYM WM_KEYLAST}
  WM_KEYLAST          = $0108;
           

GetKeyState

下一篇: API HOOK 原理

继续阅读