GETWINDOW在DLL和EXE中调用为何不同?(原问题已解决,散分) (100分)

  • 主题发起人 主题发起人 phyyun
  • 开始时间 开始时间
P

phyyun

Unregistered / Unconfirmed
GUEST, unregistred user!
原问题如下(新问题见回帖):<br>键盘钩子,HOOK总是断掉,请问如何解决?<br><br>这个程序是用来隐藏窗口的。包括一个EXE,一个DLL。<br>在列表框里加入想要隐藏的窗口标题,按 ALT+2,就会隐藏或显示设定的窗口。<br>我是在DLL中使用KeyboardHook来实现的。<br>每次在DLL里遍历窗口,然后和列表框里的比较,如果符合条件,就隐藏或显示。<br>但是现在程序有个问题,我怎么调试都找不到答案。就是每次启动程序,只有开始两次按ALT+2有效,后来就没响应了,不触发KeyboardHookHandler,我晕。<br>第一次使用HOOK,请教。源代码我贴下面。<br>*****************************<br>DLL PROJECT'HKTest.dpr'<br>*****************************<br>library HKTest;<br>uses<br>&nbsp; Sharemem,<br>&nbsp; forms,<br>&nbsp; HKProc in 'HKProc.PAS';<br>exports<br>EnableHotKeyHook,<br>DisableHotKeyHook,<br>Setform;<br><br>begin<br>hNextHookProc := 0;<br>HotKeyEnable := false;<br>procSaveExit := ExitProc;<br>ExitProc := @HotKeyHookExit;<br>end.<br>***********************<br>HKProc.PAS<br>***********************<br>unit HKProc;<br><br>interface<br><br>uses<br>Windows, &nbsp;dialogs, Messages, Classes, Forms, SysUtils;<br><br>var<br>hNextHookProc: HHook;<br>procSaveExit: Pointer;<br>FormStrings:TStringList;<br>FormStrings2:TStringList;<br>CustomStrings:TStringList;<br>HotKeyEnable: Boolean;<br><br>function KeyboardHookHandler(iCode: Integer;<br>wParam: WPARAM;<br>lParam: LPARAM): LRESULT; stdcall; export;<br>function EnableHotKeyHook: BOOL; export;<br>function DisableHotKeyHook: BOOL; export;<br>procedure HotKeyHookExit; far;<br>procedure Setform(formname, action: pchar; id: integer); export;<br><br>implementation<br><br>Function My_RefreshForm(MyStringList:TStringList; MyStringList2:TStringList):Boolean;<br>var<br>hCurrentWindow: HWnd;<br>szText: array[0..254] of char;<br>begin<br>MyStringList.Clear;<br>MyStringList2.Clear;<br>//hCurrentWindow := GetWindow(application.Handle, GW_HWNDFIRST);<br>hCurrentWindow := GetWindow(GetActiveWindow, GW_HWNDFIRST);<br>while hCurrentWindow &lt;&gt; 0 do<br>begin<br>if GetWindowText(hCurrentWindow, @szText, 255) &gt; 0 then<br>begin<br>&nbsp; MyStringList.Add(StrPas(@szText));<br>&nbsp; MyStringList2.Add(inttostr(hCurrentWindow));<br>end;<br>hCurrentWindow := GetWindow(hCurrentWindow, GW_HWNDNEXT);<br>end;<br>Result:=true;<br>end;<br><br>function KeyboardHookHandler(iCode: Integer;<br>wParam: WPARAM;<br>lParam: LPARAM): LRESULT; stdcall; export;<br>const<br>_KeyPressMask = $80000000;<br>var<br>&nbsp; i,j :integer;<br>&nbsp; ExeHandle : HWnd;<br>begin<br>Result := 0;<br>If iCode &lt; 0 Then<br>begin<br>Result := CallNextHookEx(hNextHookProc, iCode, wParam, lParam);<br>Exit;<br>end;<br>// 侦测 ALT + 2 组合键<br>if ((lParam and _KeyPressMask) = 0) and<br>&nbsp; (GetKeyState(VK_MENU) &lt; 0) and (wParam = Ord('2')) then<br>begin<br>&nbsp; Result := 1;<br>&nbsp; HotKeyEnable := not HotKeyEnable;<br>&nbsp; My_RefreshForm(FormStrings, FormStrings2);<br>&nbsp; &nbsp; for i:=0 to CustomStrings.count-1 do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; for j:=0 to FormStrings.count-1 do<br>&nbsp; &nbsp; &nbsp; if pos(CustomStrings, FormStrings[j])&gt;0 then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; ExeHandle := strtoint(FormStrings2[j]);<br>&nbsp; &nbsp; &nbsp; &nbsp; if ExeHandle &lt;&gt; 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if HotKeyEnable then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ShowWindow(ExeHandle,SW_hide)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ShowWindow(ExeHandle,SW_show);<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>end;<br>end;<br><br>function EnableHotKeyHook: BOOL; export;<br>begin<br>Result := False;<br>if hNextHookProc &lt;&gt; 0 then Exit;<br>FormStrings &nbsp;:= TStringList.Create;<br>FormStrings2 := TStringList.Create;<br>CustomStrings := TStringList.Create;<br>CustomStrings.clear;<br>// 挂上 WH_KEYBOARD 这型的 HOOK, 同时, 传回值必须保留下<br>// 来, 免得 HOOK 呼叫链结断掉<br>hNextHookProc := SetWindowsHookEx(WH_KEYBOARD,<br>KeyboardHookHandler,<br>HInstance,<br>0);<br>Result := hNextHookProc &lt;&gt; 0;<br>end;<br><br>function DisableHotKeyHook: BOOL; export;<br>begin<br>if hNextHookProc &lt;&gt; 0 then<br>begin<br>UnhookWindowshookEx(hNextHookProc); // 解除 Keyboard Hook<br>hNextHookProc := 0;<br>FormStrings.Free;<br>FormStrings2.Free;<br>CustomStrings.Free;<br>end;<br>Result := hNextHookProc = 0;<br>end;<br><br>procedure HotKeyHookExit;<br>begin<br>// 如果忘了解除 HOOK, 自动代理解除的动作<br>if hNextHookProc &lt;&gt; 0 then DisableHotKeyHook;<br>ExitProc := procSaveExit;<br>end;<br><br>procedure Setform(formname, action: pchar; id: integer); export;<br>var<br>&nbsp; name : string;<br>&nbsp; Saction : string;<br>begin<br>&nbsp; name := strpas(formname);<br>&nbsp; Saction := strpas(action);<br>&nbsp; if Saction = 'add' then<br>&nbsp; &nbsp; customstrings.add(name)<br>&nbsp; else<br>&nbsp; &nbsp; customstrings.delete(id);<br>end;<br>end.<br><br>*******************************<br>****************<br>Project1.dpr<br>****************<br>program Project1;<br><br>uses<br>&nbsp; Sharemem,<br>&nbsp; Forms,<br>&nbsp; Unit1 in 'Unit1.pas' {Form1};<br><br>{$R *.RES}<br><br>begin<br>&nbsp; Application.Initialize;<br>&nbsp; Application.CreateForm(TForm1, Form1);<br>&nbsp; Application.Run;<br>end.<br><br>********************<br>Unit1.pas<br>********************<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>&nbsp; StdCtrls, ComCtrls;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button3: TButton;<br>&nbsp; &nbsp; Button4: TButton;<br>&nbsp; &nbsp; Label1: TLabel;<br>&nbsp; &nbsp; ListBox1: TListBox;<br>&nbsp; &nbsp; Edit1: TEdit;<br>&nbsp; &nbsp; GroupBox1: TGroupBox;<br>&nbsp; &nbsp; Label2: TLabel;<br>&nbsp; &nbsp; Label3: TLabel;<br>&nbsp; &nbsp; procedure FormCreate(Sender: TObject);<br>&nbsp; &nbsp; procedure WMNCHitTest(var M:TWMNCHitTest);message wm_NCHitTest;<br>&nbsp; &nbsp; procedure ListBox1DblClick(Sender: TObject);<br>&nbsp; &nbsp; procedure Button3Click(Sender: TObject);<br>&nbsp; &nbsp; procedure Button4Click(Sender: TObject);<br>&nbsp; &nbsp; procedure FormDestroy(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>function EnableHotKeyHook: BOOL; external 'HKTEST.DLL';<br>function DisableHotKeyHook: BOOL; external 'HKTEST.DLL';<br>procedure Setform(formname, action: pchar; id: integer); external 'HKTEST.DLL';<br><br>{$R *.DFM}<br><br><br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>&nbsp; //总是置为最前<br> setWindowPos(Application.Handle, HWND_TOPMOST,<br>&nbsp; 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);<br>// &nbsp;ShowWindowAsync(application.Handle,sw_hide); {使用Ctrl+Del+Alt看不到此程序}<br><br>&nbsp; EnableHotKeyHook;<br><br>end;<br><br>procedure TForm1.WMNCHitTest(var M: TWMNCHitTest);<br>begin &nbsp;//可在窗口任意部分移動窗口<br>&nbsp; inherited;<br>&nbsp; if M.Result=htClient then<br>&nbsp; &nbsp; &nbsp;M.Result:=htCaption;<br>end;<br><br>procedure TForm1.ListBox1DblClick(Sender: TObject);<br>begin<br>&nbsp; ListBox1.DeleteSelected;<br>end;<br><br>procedure TForm1.Button3Click(Sender: TObject);<br>begin<br>&nbsp; if trim(edit1.text)&lt;&gt;'' then<br>&nbsp; begin<br>&nbsp; &nbsp; Setform(Pchar(trim(edit1.Text)), Pchar('add'), 0);<br>&nbsp; &nbsp; listbox1.Items.Add(trim(edit1.Text));<br>&nbsp; end;<br>end;<br><br>procedure TForm1.Button4Click(Sender: TObject);<br>begin<br>&nbsp; if (ListBox1.Count &gt; 0) and (ListBox1.ItemIndex &gt;= 0 ) then<br>&nbsp; begin<br>&nbsp; &nbsp; Setform(Pchar(ListBox1.Items.strings[ListBox1.ItemIndex]), Pchar('delete'), ListBox1.ItemIndex);<br>&nbsp; &nbsp; listbox1.DeleteSelected;<br>&nbsp; end;<br>end;<br><br>procedure TForm1.FormDestroy(Sender: TObject);<br>begin<br>&nbsp; DisableHotKeyHook;<br>end;<br><br>end.<br><br>unit1的FORM1是主窗口,很简单的,一个小FORM,窗口图片网址如下:http://www.djypanda.com/forum/UploadFile/20039316475963853.jpg<br>如果是DELPHI7的话,可以直接引用下面这个DFM文件:<br>object Form1: TForm1<br>&nbsp; Left = 257<br>&nbsp; Top = 194<br>&nbsp; Width = 369<br>&nbsp; Height = 289<br>&nbsp; Caption = #38544#34255#19987#23478#65288'phyyun'#65289<br>&nbsp; Color = clBtnFace<br>&nbsp; Font.Charset = DEFAULT_CHARSET<br>&nbsp; Font.Color = clWindowText<br>&nbsp; Font.Height = -11<br>&nbsp; Font.Name = 'MS Sans Serif'<br>&nbsp; Font.Style = []<br>&nbsp; OldCreateOrder = False<br>&nbsp; Position = poDesktopCenter<br>&nbsp; OnCreate = FormCreate<br>&nbsp; OnDestroy = FormDestroy<br>&nbsp; PixelsPerInch = 96<br>&nbsp; TextHeight = 13<br>&nbsp; object Label1: TLabel<br>&nbsp; &nbsp; Left = 8<br>&nbsp; &nbsp; Top = 8<br>&nbsp; &nbsp; Width = 329<br>&nbsp; &nbsp; Height = 13<br>&nbsp; &nbsp; AutoSize = False<br>&nbsp; &nbsp; Caption = #35831#36755#20837#35201#38544#34255#30340#31383#21475#26631#39064#25152#21253#21547#30340#25991#23383'('#27880#24847#22823#23567#20889')'<br>&nbsp; end<br>&nbsp; object Button3: TButton<br>&nbsp; &nbsp; Left = 224<br>&nbsp; &nbsp; Top = 64<br>&nbsp; &nbsp; Width = 57<br>&nbsp; &nbsp; Height = 25<br>&nbsp; &nbsp; Caption = #28155#21152<br>&nbsp; &nbsp; TabOrder = 0<br>&nbsp; &nbsp; OnClick = Button3Click<br>&nbsp; end<br>&nbsp; object Button4: TButton<br>&nbsp; &nbsp; Left = 224<br>&nbsp; &nbsp; Top = 112<br>&nbsp; &nbsp; Width = 57<br>&nbsp; &nbsp; Height = 25<br>&nbsp; &nbsp; Caption = #21024#38500<br>&nbsp; &nbsp; TabOrder = 1<br>&nbsp; &nbsp; OnClick = Button4Click<br>&nbsp; end<br>&nbsp; object ListBox1: TListBox<br>&nbsp; &nbsp; Left = 8<br>&nbsp; &nbsp; Top = 56<br>&nbsp; &nbsp; Width = 193<br>&nbsp; &nbsp; Height = 193<br>&nbsp; &nbsp; ItemHeight = 13<br>&nbsp; &nbsp; TabOrder = 2<br>&nbsp; &nbsp; OnDblClick = ListBox1DblClick<br>&nbsp; end<br>&nbsp; object Edit1: TEdit<br>&nbsp; &nbsp; Left = 8<br>&nbsp; &nbsp; Top = 32<br>&nbsp; &nbsp; Width = 193<br>&nbsp; &nbsp; Height = 21<br>&nbsp; &nbsp; TabOrder = 3<br>&nbsp; &nbsp; Text = #22823#23500#32705<br>&nbsp; end<br>&nbsp; object GroupBox1: TGroupBox<br>&nbsp; &nbsp; Left = 208<br>&nbsp; &nbsp; Top = 176<br>&nbsp; &nbsp; Width = 145<br>&nbsp; &nbsp; Height = 73<br>&nbsp; &nbsp; Caption = #28909#38190<br>&nbsp; &nbsp; TabOrder = 4<br>&nbsp; &nbsp; object Label2: TLabel<br>&nbsp; &nbsp; &nbsp; Left = 8<br>&nbsp; &nbsp; &nbsp; Top = 16<br>&nbsp; &nbsp; &nbsp; Width = 129<br>&nbsp; &nbsp; &nbsp; Height = 13<br>&nbsp; &nbsp; &nbsp; AutoSize = False<br>&nbsp; &nbsp; &nbsp; Caption = #38544#34255#25110#26174#31034#35774#23450#31383#21475<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; object Label3: TLabel<br>&nbsp; &nbsp; &nbsp; Left = 8<br>&nbsp; &nbsp; &nbsp; Top = 32<br>&nbsp; &nbsp; &nbsp; Width = 32<br>&nbsp; &nbsp; &nbsp; Height = 13<br>&nbsp; &nbsp; &nbsp; AutoSize = False<br>&nbsp; &nbsp; &nbsp; Caption = 'ALT+2'<br>&nbsp; &nbsp; end<br>&nbsp; end<br>end<br>
 
我觉得,可能和遍历窗口(My_RefreshForm)时调用的GetWindow,或者和<br>在KeyboardHookHandler事件里调用ShowWindow(ExeHandle,SW_hide), ShowWindow(ExeHandle,SW_show) 有关。<br>但不知如何解决。<br>我想过,把遍历窗口的实现部分放到EXE里,这样HOOK就不会断了。但是要在DLL里通知主程序实现功能,我试着用<br>发送消息通知,可惜不成功。
 
该问题我已解决。<br>我把遍历窗口的实现部分放到EXE里,这样HOOK就不会断了。然后在DLL里通知主程序实现功能,用发送消息给MAINFORM通知。<br>原先不成功是因为发送的HANDLE有问题,查了离线资料解决了,用内存映象。<br><br>既然都发了分在这里,那么换个问题,回帖的都给分!<br>遍历窗口的代码如下:<br>Function My_RefreshForm(MyStringList:TStringList; MyStringList2:TStringList):Boolean;<br>var<br>hCurrentWindow: HWnd;<br>szText: array[0..254] of char;<br>begin<br>MyStringList.Clear;<br>MyStringList2.Clear;<br>//hCurrentWindow := GetWindow(application.Handle, GW_HWNDFIRST);<br>hCurrentWindow := GetWindow(GetActiveWindow, GW_HWNDFIRST);<br>while hCurrentWindow &lt;&gt; 0 do<br>begin<br>if GetWindowText(hCurrentWindow, @szText, 255) &gt; 0 then<br>begin<br>&nbsp;MyStringList.Add(StrPas(@szText));<br>&nbsp;MyStringList2.Add(inttostr(hCurrentWindow));<br>end;<br>hCurrentWindow := GetWindow(hCurrentWindow, GW_HWNDNEXT);<br>end;<br>Result:=true;<br>end;<br>我在DLL中使用这句代码才有效<br>hCurrentWindow := GetWindow(GetActiveWindow, GW_HWNDFIRST);<br>而在exe中必须这样:<br>hCurrentWindow := GetWindow(application.Handle, GW_HWNDFIRST);<br>否则在DLL中HOOK就会断。在EXE中hCurrentWindow 会返回0。<br>请问什么原因。
 
晕什么啊。哪位帮忙解释一下GETWINDOW,谢谢
 
在DELPHI工程里面,真正的顶级窗口是Application对象,GetActiveWindow得到的只是你工程中当前的窗口,不会得到顶级窗口的<br><br>在任务栏上按右键,选择平铺,会发现DELPHI写出来的程序无法正常平铺,也是这个原因,还有任务栏上按钮的右键菜单少了几项....
 
取得窗口句柄<br>HWND GetWindow(<br><br>&nbsp; &nbsp; HWND hWnd, // 窗口句柄<br>&nbsp; &nbsp; UINT uCmd // 标志 &nbsp; <br>); <br><br>uCmd:<br>&nbsp;<br>GW_CHILD当前窗口的子窗口<br>GW_HWNDFIRST最顶层窗口<br>GW_HWNDLAST最末层窗口<br>GW_HWNDNEXT当前窗口的下一个窗口<br>GW_HWNDPREV当前窗口的上一个窗口
 
to ysai这两者确实是有区别的。只是不知道为什么HOOK会断掉。<br>其实枚举遍历窗口用EnumWindows+GetWindowLong 实现更好。<br>现在这个方法是借鉴别人的代码。
 
新年到了。结帖吧。
 
后退
顶部