键盘钩子问题:程序失去焦点后就不起作用了.

海宏AA 2007-11-10 06:45:38
{源码如下.用到了钩子和热键,热键没问题}

unit Unit1;

interface

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

type
TForm1 = class(TForm)
cmd_Start: TBitBtn;
cmd_Stop: TBitBtn;
cmd_Config: TBitBtn;
txt_Info: TMemo;
procedure FormCreate(Sender: TObject);
procedure cmd_StartClick(Sender: TObject);
procedure cmd_StopClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
procedure hotKey(var msg:TMessage); message wm_HotKey;
procedure processDeactive(var msg:TMessage); message WM_ACTIVATE;
procedure processMinimize(var msg:TMessage); message wm_windowPosChanging;
procedure processLostFocus(var msg:TMessage); message wm_killFocus;
{WM_ACTIVATE WM_GETMINMAXINFO wm_Active WM_WINDOWPOSCHANGED WM_GETMINMAXINFO
WM_KILLFOCUS WM_SETFOCUS}
public
//application处理消息
procedure onAppMessage(var Msg: tagMSG; var Handled: Boolean);
end;

Const _KeyPressMask=$8000000;
//处理
function processKey(Key:integer):boolean; stdCall;
//钩子
function enableHook:Boolean; stdCall;
function disableHook:Boolean; stdCall;
function keyBoardHook(Code:Integer; WParam:WPARAM; lParam:LPARAM):Integer; Stdcall; //键盘钩子

type
_keys=record //注册热键
nKeyCode: integer; //按键码
wAtom : word; //globalAddAtom原子
end;
var
Form1 : TForm1;
HookHandle : HHook=0; //当前钩子句柄,CallNextHook用
AppHandle : THandle=0; //程序句柄
vKeys: array [0..7] of _keys;
implementation

{$R *.dfm}


//处理
function processKey(Key:integer):boolean;
begin
with form1 do begin
txt_Info.Lines.Add( char(Key) );
end;
end;
//键盘钩子主处理
function keyBoardHook(Code:Integer; WParam:WPARAM; lParam:LPARAM):Integer;
var msg:TEventMsg; L:Boolean;
begin
result:=1;
if code<0 then begin //不需要处理的,必须执行下一个钩子
result:=CallNextHookEx(hookHandle, code, wParam, lParam);
exit;
end;
//HC_ACTION msg:=PEventMsg(lParam)^;
if true then begin //msg.message=wm_KeyDown
//发送给程序消息 //processKey(wParam); form1.Perform application.OnMessage(msg, L);
//sendMessage(appHandle, wm_KeyDown, wParam, lParam);
PostMessageW(appHandle, wm_KeyDown, wParam, lParam);
end;
//处理下一个钩子
//result:=CallNextHookEx(hookHandle, code, wParam, lParam);
end;
//禁止钩子
function disableHook:Boolean;
begin
result:=hookHandle<1; if result then exit;
UnhookWindowsHookEx(hookHandle);
result:=true;
hookHandle:=0;
end;
//启用钩子Hinstance
function enableHook:Boolean;
begin
result:=HookHandle>0; if result then exit;
hookHandle:=SetWindowsHookEx(wh_KeyBoard, @keyBoardHook, Hinstance, 0); //wh_hardWare wh_KeyBoard wh_Debug
result:=hookHandle>0;
end;
//
procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
begin
appHandle:=application.Handle;
application.OnMessage:=onAppMessage; //接收到程序消息
//注册热键
for i:=low(vKeys) to high(vKeys) do vKeys[i].wAtom:=0;
vKeys[0].wAtom:=GlobalAddAtom('1VeryBad');
vKeys[1].wAtom:=GlobalAddAtom('2Bad');
RegisterHotKey(handle, vKeys[0].wAtom, 0, vk_f10); //参数3可以用MOD_ALT, mod_control之类
RegisterHotKey(handle, vKeys[1].wAtom, 0, vk_f11); //参数3可以用MOD_ALT, mod_control之类
//
txt_Info.Clear;
end;
//热键
procedure TForm1.hotKey(var msg:TMessage);
begin
if msg.LParamHi=vk_f10 then
self.Hide
else if msg.LParamHi=vk_f11 then
self.Show;
end;
//
procedure processMessageIns(var msg:TMessage);
begin
form1.txt_Info.lines.add('message:'+ intToStr(msg.Msg));
msg.Result:=1;
end;
procedure TForm1.processDeactive(var msg:TMessage);
begin
processMessageIns(msg);
end;
procedure TForm1.processMinimize(var msg:TMessage);
begin
processMessageIns(msg);
end;
procedure TForm1.processLostFocus(var msg:TMessage);
begin
processMessageIns(msg);
end;
//application处理消息
procedure TForm1.onAppMessage(var Msg: tagMSG; var Handled: Boolean);
var key:char; n:cardinal;
begin
inherited; n:=msg.message;
if (n=wm_keyDown) then begin //or (msg.message=wm_keyUp) or (msg.message=wm_SysKeyDown)then begin
key:=char(msg.wParam);
processKey( ord( key ) ); //调用处理
end
else if (n=WM_ACTIVATEAPP) or (n=WM_ACTIVATE) or
(n=WM_KILLFOCUS) or (n=WM_SETFOCUS) then begin
//上面这些消息是窗口失去焦点和获得焦点的屏蔽
//msg.message:=0;
end;
//将窗口消息传递给Windows处理
//Result:=CallWindowProc(OldProc,Hwnd,Msg,wParam,lParam);
end;
//
procedure TForm1.cmd_StartClick(Sender: TObject);
begin
enableHook;
end;

procedure TForm1.cmd_StopClick(Sender: TObject);
begin
disableHook;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var i:integer;
begin
disableHook;
//删除热键注册
for i:=low(vKeys) to high(vKeys) do if vKeys[i].wAtom<>0 then globalDeleteatom(vKeys[i].wAtom);
end;

end.
...全文
299 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Bear_hx 2007-11-15
  • 打赏
  • 举报
回复
其实就是内存映射,盒子上有一个完整的内存映射和钩子的例子,你去看看.
海宏AA 2007-11-15
  • 打赏
  • 举报
回复
to寒萧: 我在DLL时用sendMessage截获消息作的,DLL内存共享确实是个问题啊,有例子没?
海宏AA 2007-11-15
  • 打赏
  • 举报
回复
本来是用DLL作的没问题,提问的目的是“希望不用DLL也可以”。

问题已经解决了。换了钩子类型jure那个,也想法屏蔽了ctrl+esc按键。

感谢各位参与。
AsheBin 2007-11-13
  • 打赏
  • 举报
回复
楼上两位大侠都说对了,只有把钩子写到DLL里面才能实现全局钩子。
如果不写到DLL里面,下面这句:
hookHandle:=SetWindowsHookEx(wh_KeyBoard, @keyBoardHook, Hinstance, 0); //wh_hardWare
作用就不大了,因为失去焦点以后,你就钩不住消息了,所以只能钩住当前EXE的消息,也就是说实质上还是个局部钩子,不是全局钩子。
Bear_hx 2007-11-10
  • 打赏
  • 举报
回复
楼主你的钩子要写在Dll中,而且要用共享内存的形式存储数据,这样才能获得全局钩子.你写在exe程序中,别的程序是调不到的.
internetroot 2007-11-10
  • 打赏
  • 举报
回复
必须写道动态链接库里,最好还把动态链接库注入explorer.exe中,那样即使你关闭你的程序也可以监控。

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧