Форум: "WinAPI";
Текущий архив: 2005.01.23;
Скачать: [xml.tar.bz2];
ВнизКак отловить нажатие кнопки в окне чужого приложения? Найти похожие ветки
← →
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 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.01.23;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.041 c