Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.01.23;
Скачать: CL | DM;

Вниз

Как отловить нажатие кнопки в окне чужого приложения?   Найти похожие ветки 

 
Ana ©   (2004-12-02 14:03) [0]

Здравствуйте! Подскажите, пожалуйста, как мне отловить событие нажатия кнопки (TButton), которая находится в окне чужого приложения.
Заранее спасибо!


 
Leonid Troyanovsky   (2004-12-02 14:18) [1]


> Ana ©   (02.12.04 14:03)  
> Здравствуйте! Подскажите, пожалуйста, как мне отловить событие
> нажатия кнопки (TButton), которая находится в окне чужого
> приложения.


А откуда уверенность, что это TButton?

Ну, а вообще-то, нужно подменить оконную процедуру  
(SetWindowLong) ее парента (Windows.GetParent) на предмет
WM_COMMAND c идентификатором оной кнопки (GetDlgCtrlID).
Только делать это надо из системного (dll) хука
(SetWindowsHookEx with WH_GETMESSAGE на целевой поток).
Т.е., установить его можно путем PostThreadMessage
условленного сообщения.
А при снятиии хука нужно вернуть старую оконную процедуру
на место.

--
С уважением, LVT.


 
Ana ©   (2004-12-02 14:48) [2]

Уважаемый LVT!
Не могли ли Вы примерчик продемонстрировать, а то я так не совсем поняла, как это сделать.
Заранее огромное спасибо!


 
Piter ©   (2004-12-02 22:14) [3]

Ana ©   (02.12.04 14:03)

уверен, что это сложно для твоего уровня квалификации. Вот пример DLL, которая внедряется в чужое ВАП:

library piter_hook;

uses
 Windows;

const
 cMMFileName = "piter-hook_{E891D15B-DD53-4BC8-81F4-E0BF8A5573B6}";

type
 PGlobalData = ^TGlobalData;
 TGlobalData = packed record
   HookProcessId: DWORD;
   HookHandle: HHOOK;
   WindowHandle: THandle;
   idMsg: LongWord;
 end;

var
 GlobalData: PGlobalData ;
 MapHandle: THandle;

function DeleteHook(CheckProcess: boolean): boolean;
begin
 Result := false;
 if GlobalData <> nil then
   with GlobalData^ do
     if HookHandle<>0 then
       if (not CheckProcess) or (GetCurrentProcessId = HookProcessId) then
         begin
           Result := UnHookWindowsHookEx(HookHandle) ;
           if Result then
             HookHandle := 0;
         end;
end;

function RemoveShellHook: boolean; stdcall;
begin
 Result := DeleteHook(True);
end;

function ShellProc(nCode: integer; wParam: LongWord;
   lParam: LongWord): integer; stdcall;
begin
 Result := 0;
 if GlobalData <> nil then
   with GlobalData^ do
   begin
     if IsWindow(WindowHandle) then
       SendMessage(WindowHandle, idMsg, wParam, nCode)
     else
       DeleteHook(False);
     CallNextHookEx(HookHandle, nCode, wParam, lParam);
   end;
end;

function SetShellHook(CallbackWindow: THandle;
   idCallBackMessage: LongWord): boolean; stdcall;
begin
 Result := false;
 if GlobalData <> nil then
   with GlobalData^ do
     if ( HookHandle = 0 ) and ( IsWindow(CallbackWindow) ) then
       begin
         HookHandle := SetWindowsHookEx(WH_SHELL, @ShellProc, HInstance, 0);
         Result := HookHandle <> 0;
         if Result then
           begin
             HookProcessId := GetCurrentProcessId ;
             WindowHandle := CallbackWindow ;
             idMsg :=  idCallBackMessage ;
             Result := true;
           end;
       end;
end;

procedure OpenSharedData;
var
 Size: integer;
begin
 Size := SizeOf(TGlobalData);
 MapHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE,
     0, Size, cMMFileName);
 if MapHandle = 0 then exit;
 GlobalData := MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);
end;

procedure CloseSharedData;
begin
 UnmapViewOfFile(GlobalData);
 CloseHandle(MapHandle);
end;

procedure DLLEntryProc(dwReason: DWord);
begin
 case dwReason of
   DLL_PROCESS_ATTACH: OpenSharedData;
   DLL_PROCESS_DETACH:
     begin
       RemoveShellHook ;
       CloseSharedData;
     end;
 end;
end;

exports
 SetShellHook, RemoveShellHook;

begin
 DLLProc := @DLLEntryProc;
 DLLEntryProc(DLL_PROCESS_ATTACH);
end.


Тебе дальше надо?


 
Leonid Troyanovsky   (2004-12-02 22:20) [4]


> Ana ©   (02.12.04 14:48) [2]

> Не могли ли Вы примерчик продемонстрировать, а то я так
> не совсем поняла, как это сделать.


К сожалению, готового примера у меня нет.
Но, для начала, можно воспользоваться установкой хука в
ответ на сообщение:

http://rsdn.ru/Forum/?mid=305498

И сабклассировать (в хуковой процедуре) парент кнопки,
т.е. получить адрес "старой" оконной процедуры:

olpwndproc := GetWindowLong(hBtnParent, GWL_WNDPROC);

Затем описать (в dll) новую:

function NewWndProc(h: HWND; Msg: UINT; aWParam: WPARAM; aLPARAM: LPARAM): LResult; stdcall;
begin
 if (Msg = WM_COMMAND) and (LoWord(AWParam)= idButton)  then
   {сработала наша кнопка};
 Result := CallWindowProc(oldwndproc, h, Msg, AWParam, ALParam);
end;

а установить ее путем SetWindowLong(hbtnParent, GWL_WNDPROC);
(опять же, из хуковой процедуры).

Ну, и, конечно, следует сказать, что пишу это я прямо
здесь, т.е., воспринимать все оное нужно через призму
компилятора, а еще лучше - сверяясь c msdn.
А если возникнут проблемы, то их, при наличии конкретного кода,
надеюсь,  можно будет последовательно разрешить.

--
С уважением, LVT.


 
Leonid Troyanovsky   (2004-12-03 08:52) [5]


> Leonid Troyanovsky   (02.12.04 22:20) [4]

> Но, для начала, можно воспользоваться установкой хука в
> ответ на сообщение:
>
> http://rsdn.ru/Forum/?mid=305498


Мдя, немного перемудрил на ночь глядя.
Если цель лишь в отслеживании нажатия (не пытаясь отменять),
то достаточно установки SetWindowsHookEx with WH_CALLWNDPROC
or WH_CALLWNPROCRET.

Например, вот так можно предотвращать появление диалога
About.. для Notepad :

----------lib0.dpr------------

library lib0;

uses
 windows, messages;

var
 hhk: HHook;
 hcaller: HWND; // окно, получающее извещения

function GetMsgProc(code: Longint; awparam: WParam; alparam: Lparam):LResult;stdcall;
var
 msg: PCWPRETSTRUCT;
begin
 Result := 0;
 msg := PCWPRETSTRUCT(alparam);
 case msg.message of
   WM_NULL:
     begin
       hcaller := msg.wParam;
       hhk := msg.lParam;
     end;
   WM_INITDIALOG: // при инициализации диалога извещаем caller
     PostMessage(hcaller, WM_USER, 0, msg.hwnd);
 end;
 if hhk <> 0 then
   Result := CallNextHookEx(hhk, code, awparam, alparam);
end;

exports
 GetMsgProc;

begin

end.

----------EOF lib0.dpr------------

Так оную библиотеку используем (блокнот запущен предварительно)


type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   { Private declarations }
   procedure WMUser(var msg: TMessage); message WM_USER;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

var
 hhk: HHook;

procedure TForm1.WMUser;
var
 h : HWND;
begin
 h := FindWindowEx(msg.LParam, 0, "Button", "OK");
 PostMessage(h, BM_CLICK, 0, 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 h: HWND;
 tid: DWord;
 mh: THandle;
 p: Pointer;
begin
 h := FindWindow("Notepad", nil);
 tid := GetWindowThreadProcessId(h, nil);
 mh := LoadLibrary("Lib0.dll");
 p := GetProcAddress(mh, "GetMsgProc");
 Win32Check(p <> nil);
 hhk := SetWindowsHookEx(WH_CALLWNDPROCRET, p, mh, tid);
 FreeLibrary(mh);
 SendMessage(h, 0, Handle, hhk); // передаем параметры dll
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 UnhookWindowsHookEx(hhk);
end;


--
С уважением, LVT.



Страницы: 1 вся ветка

Текущий архив: 2005.01.23;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.027 c
1-1105523884
mariya_mezenceva
2005-01-12 12:58
2005.01.23
ole-объект 1с


1-1105502786
TankMan
2005-01-12 07:06
2005.01.23
Писал кто-нибудь видеопроигрыватель?


1-1105283066
Kolyan
2005-01-09 18:04
2005.01.23
Файловые функции


9-1097422358
Evgenius
2004-10-10 19:32
2005.01.23
Проблема с кривыми...


10-1081225251
Djon1111
2004-04-06 08:20
2005.01.23
Изменение размеров страницы в Excell