您的位置:程序门 -> delphi -> windows sdk/api



dll菜鸟高分求教,键盘钩子退出时会导致explorer.exe进程死掉


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


dll菜鸟高分求教,键盘钩子退出时会导致explorer.exe进程死掉[已结贴,结贴人:myth_2002]
发表于:2007-11-26 16:53:29 楼主
程序的功能目的很简单,如果程序窗口被其他程序挡住,按ctrl+z能把程序窗口切换到最前面来(成为当前窗口)。
实现的方式是:用一个键盘钩子监视ctrl+z,当这两个键被按下时,把程序窗口最大化,并置为topmost窗口。
出现问题的地方是,有时候切换几次后,再把程序关掉,会出现explorer.exe出错的提示,点确定后桌面消失,过一会儿才会出来。

键盘钩子写在一个dll里,代码是改自网上找来的一个键盘钩子的代码
dll代码:
library   hook;

uses
    hookunit   in   'hookunit.pas';

exports
enablehotkeyhook,
disablehotkeyhook;

{$r   *.res}
begin
hnexthookproc   :=   0;  
procsaveexit   :=   exitproc;
exitproc   :=   @hotkeyhookexit;
end.

hookunit.pas代码:
unit   hookunit;
interface
uses
windows,   messages,dialogs,sysutils,inifiles,forms;
var
hnexthookproc:   hhook;//保存setwindowshookex的返回值
procsaveexit:   pointer;
function   keyboardhookhandler(icode:   integer;wparam:   wparam;lparam:   lparam):   lresult;   stdcall;   export;
function   enablehotkeyhook:   bool;   export;//安装钩子
function   disablehotkeyhook:   bool;   export;//卸载钩子
procedure   hotkeyhookexit;   far;
implementation
function   keyboardhookhandler(icode:   integer;wparam:   wparam;lparam:   lparam):   lresult;   stdcall;   export;
const
_keypressmask=$80000000;//键盘掩码常量
var
      myhandle,otherhandle:cardinal;
    ini:tinifile;
    s:string;
    scr_w,scr_h:integer;
begin
result:=0;
if   icode   <   0   then   //根据sdk说明,若icode小于0,调用callnexthookex并返回
begin
result:=callnexthookex(hnexthookproc,   icode,   wparam,   lparam);
exit;
end;
//   监测是否按下了ctrl+z,
if   ((lparam   and   _keypressmask)   =   0)   and(getkeystate(vk_control)   <0)
and   ((wparam   =   ord('z'))   )then
begin
//以下是我自己改的部分
      scr_h:=getdevicecaps(getwindowdc(getdesktopwindow),vertres);//高
      scr_w:=getdevicecaps(getwindowdc(getdesktopwindow),horzres);//宽
      s:=extractfilepath(application.exename)+'pic\button.ini';
      ini:=tinifile.create(s);
    //从配置文件中读取程序的标题名
      s:=ini.readstring('buttons','title','');
      //找到程序窗口的句柄
      myhandle:=findwindow(nil,pchar(s));
      //最大化窗口
      postmessage(myhandle,wm_syscommand,sc_maximize,0);
      //设置为topmost窗口
      setwindowpos(myhandle,hwnd_topmost,0,   0,scr_w,scr_h,   swp_nosize);
//修改结束
      result:=1;
      exit;
end;
end;
function   enablehotkeyhook:   bool;   export;
begin
result   :=   false;//初始化返回值
if   hnexthookproc <> 0   then//如果已经注册,直接退出
exit;  
//挂上键盘钩子,同时传回值必须保留下来,免得hook呼叫链结断掉
hnexthookproc:=setwindowshookex(wh_keyboard,keyboardhookhandler,hinstance,0);
//注册hook
result:=hnexthookproc   <>   0;//通过返回值确定是否注册成功
end;
function   disablehotkeyhook:   bool;   export;
begin
if   hnexthookproc <> 0   then
begin
unhookwindowshookex(hnexthookproc);//解除keyboard   hook
hnexthookproc:=0;//恢复标志
end;
result:=hnexthookproc=0;//返回是否注销成功  
end;
procedure   hotkeyhookexit;
begin
if   hnexthookproc <> 0   then   disablehotkeyhook;//如果忘了解除hook,自动代理解除动作
exitproc:=procsaveexit;
end;
end.

在主程序里调用这个钩子
在主窗体的onformcreate事件中调用loadhook加载钩子
procedure   tform1.loadhook;
var
    path:string;

begin
  if   hookhandle=0   then
      begin
          path:=extractfilepath(application.exename)+'hook.dll';
          hookhandle:=loadlibrary(pchar(path));
          if   hookhandle> 0   then
              begin
                  @enablehook:=getprocaddress(hookhandle,'enablehotkeyhook');
                  @disablehook:=getprocaddress(hookhandle,'disablehotkeyhook');
                  if   @enablehook <> nil   then
                        enablehook;
              end;
      end;
 
end;
在主窗体的onclose事件中调用unloadhook卸载钩子
procedure   tform1.unloadhook;
begin
    if   @disablehook <> nil   then
        begin
            disablehook;
            //if   disablehook   then
              //   showmessage('注销钩子成功');
        end;
    if   hookhandle <> 0   then
        begin
            freelibrary(hookhandle);
        end;
end;


请各位大哥帮我看看,有哪里写得不好导致程序不稳定
发表于:2007-11-26 16:55:591楼 得分:100
registerhotkey不行么,干嘛要用键盘钩子?
发表于:2007-11-26 16:56:322楼 得分:0
被这个bug折磨很久了,请大家来帮帮忙,是不是有其他方法可以实现的
发表于:2007-11-26 17:02:163楼 得分:0
registerhotkey?我找找,老大有demo代码否?
发表于:2007-11-26 17:13:114楼 得分:0
bool   registerhotkey(
hwnd   hwnd,   //   window   to   receive   hot-key   notification
int   id,   //   identifier   of   hot   key
uint   fsmodifiers,   //   key-modifier   flags
uint   vk   //   virtual-key   code);
参数   id为你自己定义的一个id值,对一个线程来讲其值必需在0x0000   -   0xbfff范围之内,对dll来讲其值必需在0xc000   -   0xffff   范围之内,在同一进程内该值必须唯一
参数   fsmodifiers指明与热键联合使用按键,可取值为:mod_alt   mod_control   mod_win   mod_shift
参数   vk指明热键的虚拟键码  


弱弱地问一下   'z'   的virtual-key   code有没有?
发表于:2007-11-26 17:37:435楼 得分:0
找到了'z'是$5a
多谢老大,马上给分


快速检索

最新资讯
热门点击