![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как отловить нажатие кнопки в окне чужого приложения? [Win2k]
Ana © (2004-12-02 14:03:00)Здравствуйте! Подскажите, пожалуйста, как мне отловить событие нажатия кнопки (TButton), которая находится в окне чужого приложения.
Заранее спасибо!
Leonid Troyanovsky (2004-12-03 08:52:00) [1]
> 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.
Leonid Troyanovsky (2004-12-02 22:20:00) [2]
> 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.
Piter (2004-12-02 22:14:00) [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.
Тебе дальше надо?
Ana (2004-12-02 14:48:00) [4]Уважаемый LVT!
Не могли ли Вы примерчик продемонстрировать, а то я так не совсем поняла, как это сделать.
Заранее огромное спасибо!
Leonid Troyanovsky (2004-12-02 14:18:00) [5]
> Ana © (02.12.04 14:03)
> Здравствуйте! Подскажите, пожалуйста, как мне отловить событие
> нажатия кнопки (TButton), которая находится в окне чужого
> приложения.
А откуда уверенность, что это TButton?
Ну, а вообще-то, нужно подменить оконную процедуру
(SetWindowLong) ее парента (Windows.GetParent) на предмет
WM_COMMAND c идентификатором оной кнопки (GetDlgCtrlID).
Только делать это надо из системного (dll) хука
(SetWindowsHookEx with WH_GETMESSAGE на целевой поток).
Т.е., установить его можно путем PostThreadMessage
условленного сообщения.
А при снятиии хука нужно вернуть старую оконную процедуру
на место.
--
С уважением, LVT.