С поиском окна которое надо отслеживать проблем нет, пусть для примера это будет блокнот, он есть в каждой винде.
Загружаю dll, вешаю обработчик, а дальше начинаются странности. Какие-то окна сообщают об активации, а какие-то нет, закономерности я не заметил. После перезапуска винды те программы, что не сообщали об активации, начинают сообщать, зато перестают работать другие, вот такая любопытнота. ЧЯНТД?
Код программы
- Код: Выделить всё
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, windows, LConvEncoding, RegExpr,
ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
private
WM_WORKER_CHECK: DWORD;
HookHandle: HWND;
HLib: HWND;
CheckWnd: HWND;
public
procedure WndProc(var TheMessage: TMessage); override;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
WND: qword;
Buf: array[0..127] of char;
x: Boolean;
Capt: string;
RE: TRegExpr;
begin
// Почтовый голубь для dll
WM_WORKER_CHECK := RegisterWindowMessage('WorkerCheckMessage');
// Загрузка библиотеки и установка хука
HLib := LoadLibrary('workcheckhook.dll');
HookHandle := SetWindowsHookEx(WH_CBT,HOOKPROC(GetProcAddress(HLib,'WndHook')),HLib,0);
// Регулярка для поиска окна по кусочку имени
RE := TRegExpr.Create('.+ Блокнот$');
WND:=GetWindow(Handle, GW_HWNDFIRST);
while (WND <> 0) do begin
if (WND <> Handle) and IsWindowVisible(WND) and (GetWindowText(WND,Buf,SizeOf(Buf)) <> 0) then begin
GetWindowText(WND,Buf,SizeOf(Buf));
Capt := ConvertEncodingToUTF8(Buf,'cp1251',x);
RE.InputString:=Capt;
if RE.Exec(1) then begin
Memo1.Append(Capt);
CheckWnd:=WND; // Окно найдено
break;
end;
end;
WND:=GetWindow(WND, GW_HWNDNEXT);
end;
end;
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
UnhookWindowsHookEx(HookHandle);
FreeLibrary(HLib);
end;
procedure TForm1.WndProc(var TheMessage: TMessage);
begin
inherited WndProc(TheMessage);
if TheMessage.msg = WM_WORKER_CHECK then begin
// Запись данных, полученных от dll об активации окна
if TheMessage.wParam <> Handle then
Memo1.Append(IntToStr(TheMessage.wParam)+' - '+IntToStr(TheMessage.lParam)+' - '+inttostr(CheckWnd));
// Сравнение активированного окна с нужным
if TheMessage.wParam = CheckWnd then begin
Memo1.Append('Активировано целевое окно.');
end;
end;
end;
end.
Код dll
- Код: Выделить всё
library workcheckhook;
{$mode objfpc}{$H+}
uses
Classes, windows;
var
WM_WORKER_CHECK: DWORD;
function WndHook(Code: integer; wParam: WPARAM; lParam: LPARAM): Int64;stdcall;export;
begin
Result := CallNextHookEx(0, Code, wParam, lParam);
if Code = HCBT_ACTIVATE then PostMessage(FindWindow(nil,'Form1'),WM_WORKER_CHECK,wParam,lParam);
end;
exports WndHook;
begin
WM_WORKER_CHECK := RegisterWindowMessage('WorkerCheckMessage');
end.