Крюк не работает с третьим приложением - PullRequest
0 голосов
/ 20 января 2020

Во-первых, извините за мой английский sh, но я сделаю все возможное. Я хотел бы получить уведомление BN_CLICKED, прикрепленное к определенной кнопке c, из третьего приложения. Я могу найти кнопку ручки на третьем приложении. Приведенный ниже код хорошо работает, когда я меняю идентификацию кнопки, чтобы найти с помощью кнопки в моем приложении, но не с другим приложением !!! Пожалуйста, скажи мне почему, потому что я собираюсь потерпеть крах. Заранее спасибо!

Это код DLL:

{ WINHOOK.dll }
library Winhook;
uses
  Windows, Messages, SysUtils, vcl.dialogs, tlhelp32;
type
  TPMsg = ^TCWPSTruct;
var
  NextHook: HHOOK;
  hbutton: hwnd;
//---------------------------------------------------------
//fonction de remplacement pour le traitement du message
function MsgFilterFunc(Code: Integer; MwParam: Wparam;
                    MlParam: Lparam): LRESULT; stdcall;
begin
Result := 0;
if TPMsg(MlParam)^.message = WM_COMMAND then
  //si le handle correspond au bouton a surveiller
  if TPMsg(mlParam)^.lParam = hbutton then
    if hiword(TPMsg(mlParam)^.wParam)=BN_clicked then
          showmessage('BN_CLICKED Activé');

Result := CallNextHookEx(NextHook, Code, MwParam
                            ,MlParam);
end;
//---------------------------------------------------------
//Mise en place du hook avec WH_CALLWNDPROC pour interception
//des messages WM_COMMAND
function SetHook(hbt: hwnd; th: integer; MsgToSend: Integer):
                   Boolean; stdcall;
begin
  Result := False;
  hbutton := hbt;
  //hook sur le thread donné par th
  NextHook := SetWindowsHookEx(WH_CALLWNDPROC,
            MsgFilterFunc, Hinstance,th);
  if NextHook <> 0 then Result := True;
end;
//---------------------------------------------------------
//Suppression du hook
function FreeHook: Boolean; stdcall;
begin
  Result := False;
  if UnHookWindowsHookEx(NextHook) then
    Result := true;
end;

exports
  SetHook ,
  FreeHook ;

begin
end.

Это код программы:

unit Uprogatester;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes,
  Graphics, Forms, Dialogs, StdCtrls, tlhelp32, ExtCtrls,
 Controls, ComCtrls;
const
  HookDemo = 'WINHOOK.dll';
const
  WM_HOOKCREATE = WM_USER + 300;
Type
  Pwindows = ^Twindows;
  Twindows = record
    windowhandle : hwnd;
    windowtext : string;
    windowclass : string;
   end;
Type
  TForm2 = class(TForm)
    Button2: TButton;
    BTNSETHook: TButton;
    BTNUNSETHook: TButton;
    Button1: TButton;
    procedure BTNSETHookClick(Sender: TObject);
    procedure BTNUNSETHookClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure IDHandle;
  private
    FHookSet: Boolean;
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;
var
  Form2: TForm2;
  IDProc: Tprocessentry32;
  IDThr: Tthreadentry32;
  processid,processhandle,threadid: cardinal;
  AWindows : PWindows;
  function SetHook(Hbt: hwnd; IDTh: integer; MsgToSend: Integer): Boolean;
                        stdcall; external HookDemo;
  function FreeHook: Boolean; stdcall; external HookDemo;
  function getclasstext(wnd:hwnd): boolean;
  function chercheboutonproc(wnd : hwnd;
                              Form : Tform2): bool;
                              {$ifdef win32} stdcall; {$endif}
  function enumwindowsproc(wnd : hwnd;
                        form : Tform2): bool;
                        {$ifdef win32} stdcall; {$endif}
implementation
{$R *.dfm}
//------------------------------------------------------
// recherche du bouton
function chercheboutonproc(wnd : hwnd;
                              Form : Tform2): bool;
                              {$ifdef win32} stdcall; {$endif}
begin
result := true;
if getclasstext(wnd) then
  if awindows^.windowclass = 'TButton'  then
  begin
    if awindows^.windowtext = 'Bouton a Tester' then
    begin
    result := false;
    end;
  end;
end;
//------------------------------------------------------
// recherche de la fenetre PARENT
function enumwindowsproc(wnd : hwnd;
                        form : Tform2): bool;
                        {$ifdef win32} stdcall; {$endif}
begin
result := true;
if getclasstext(wnd) then
  if awindows^.windowclass = 'TForm2'   then
  begin
    if awindows^.windowtext = 'Programme a tester' then
    begin
    enumchildwindows(wnd,@chercheboutonproc,0);
    result := false;
    end;
  end;
end;
//------------------------------------------------------
//Bouton Hook
procedure TForm2.BTNSETHookClick(Sender: TObject);
begin
  enumwindows(@enumwindowsproc,longint(self));
  idhandle;
  showmessage(awindows^.WindowText+' / ' + awindows^.windowclass);
  FHookSet := LongBool(SetHook(awindows^.windowhandle,
                      threadID, WM_HOOKCREATE));
  if FHookSet then
  begin
    BTNSETHook.Enabled   := false;
    BTNUNSETHook.Enabled := true;
  end;
end;
//------------------------------------------------------
//Bouton UNHook
procedure TForm2.BTNUNSETHookClick(Sender: TObject);
begin
  FHookSet := FreeHook;
  if FHookSet then
  begin
    BTNSETHook.Enabled   := true;
    BTNUNSETHook.Enabled := false;
  end;
end;
//------------------------------------------------------
//Recherche handle ID processus et thread
procedure TForm2.IDHandle;
var shothdl: Thandle;
begin
//pour trouver une numero d'id d'un processus
IDProc.dwSize := sizeof(IDProc);
shothdl := createtoolhelp32snapshot(TH32CS_SNAPPROCESS, 0);
try
  if shothdl=-1 then exit;
  if process32first(shothdl,IDProc) then
  begin
    while process32next(shothdl,IDProc) do
    begin
      if (ansisametext(IDProc.szExeFile,'winhook.dll')) then
      begin
        processid := IDProc.th32ProcessID;
      end;
    end;
  end;
finally closehandle(shothdl);
end;
//pour trouver le numero d'id du thread correspondant
IDThr.dwSize := sizeof(IDThr);
shothdl := createtoolhelp32snapshot(TH32CS_SNAPTHREAD, 0);
try
  if shothdl=-1 then exit;
  if thread32first(shothdl,IDThr) then
  begin
    while thread32next(shothdl,IDThr) do
    begin
      if IDThr.th32OwnerProcessID=processid then
      begin
        threadid := IDThr.th32ThreadID;
      end;
    end;
  end;
finally closehandle(shothdl);
end;
end;
//------------------------------------------------------
procedure TForm2.FormCreate(Sender: TObject);
begin
FHookSet := false;
btnsethook.Enabled := true;
btnunsethook.Enabled := false;
end;
//------------------------------------------------------
procedure TForm2.FormDestroy(Sender: TObject);
begin
  BTNUNSETHook.Click;
end;
//------------------------------------------------------
//recupération a chaque enumérartion
function getclasstext(wnd:hwnd): boolean;
var
  buffer : array[0..99] of char;
  nomclass : array[0..255] of char;
begin
result := true;
getclassname(wnd,nomclass,256);
getwindowtext(wnd,buffer,100);
new(awindows);
awindows^.windowhandle := wnd;
awindows^.windowtext := strpas(buffer);
awindows^.windowclass := strpas(nomclass);
end;

end.

проблема при выполнении с третьим применение

1 Ответ

0 голосов
/ 21 января 2020

Вы пытаетесь установить кнопку на себя, но документация говорит, что WM_COMMAND отправляется на родительский кнопки. Таким образом, вы должны установить крюк на родителя.

...