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

Вниз

Хук на окно   Найти похожие ветки 

 
alex134 ©   (2002-11-30 18:22) [0]

Пытаюсь поставить хук на создание окна. Ничего не получается...
Вот код:


library Hook;

uses
Windows, SysUtils;

{$R *.res}

const
WM_USER = $0400; // Скопировано из messages.pas
WM_KEYBHOOK = WM_USER + 346;

var
KeyboardHook: HHOOK;
f : TextFile;

function CBTProc(hCode: Integer; wParam: Longint; lParam: Longint): LRESULT; stdcall;
var
Wnd: THandle;
CreateWndStruct : ^tagCBT_CREATEWNDA;
cx,cy,x,y : integer;
name : string;
begin
if hCode = HCBT_CREATEWND then
begin
Wnd := FindWindow(nil, "freedomhook");
if Wnd > 0 then
begin
CreateWndStruct:=Ptr(lParam);
cx:=CreateWndStruct.lpcs.cx;
cy:=CreateWndStruct.lpcs.cy;
x:=CreateWndStruct.lpcs.x;
y:=CreateWndStruct.lpcs.y;
name:=CreateWndStruct.lpcs.lpszName;
Writeln(f, "name="+name+" cx="+IntToStr(cx)+" cy="+IntToStr(cy)+" x="+IntToStr(x)+" y="+IntToStr(y));
PostMessage(Wnd, WM_KEYBHOOK, wParam, lParam);
Result:=0;
end;
end;
Result := CallNextHookEx(KeyboardHook, hCode, wParam, lParam);
end;

function SetKeyboardHook: Boolean; stdcall; export;
begin
KeyboardHook := SetWindowsHookEx(WH_CBT, @CBTProc, HInstance, 0);
AssignFile(f, "d:\hook.txt");
Rewrite(f);
Result := KeyboardHook <> 0;
end;

function RemoveKeyboardHook: Boolean; stdcall; export;
begin
Result := UnhookWindowsHookEx(KeyboardHook);
CloseFile(f);
end;

exports SetKeyboardHook, RemoveKeyboardHook;

begin
end.

Использую WH_CBT вместо WH_SHELL т.к. надо знать кэпшн создаваемого окна.


 
Morfein ©   (2002-11-30 21:27) [1]

Скорее всего, тебе надо вынести функции SetKeyboardHook() и RemoveKeyboardHook() в отдельную прогу...
И тогда дописать в SetKeyboardHook() загрузку Hook.dll и получение адреса функции CBTProc().


 
alex134 ©   (2002-12-01 15:10) [2]

Я думаю, что проблема с name, но не знаю что не так :(


 
kostik78ua   (2002-12-01 17:41) [3]

> Использую WH_CBT вместо WH_SHELL т.к. надо знать кэпшн создаваемого окна.
Я все равно считаю, что надо испльзовать WH_SHELL. Именно ОН для этого предназначен. А кэпшн создаваемого окна можно узнать просто: GetWindowText.
> name:=CreateWndStruct.lpcs.lpszName
Для преобразования PChar в строку испльзуй SetString или StrPas


 
alex134 ©   (2002-12-01 18:18) [4]

Моя задача - написать программу, которая будет манипулировать некоторыми (в соотв. с заголовком) окнами (прятать, перемещать за пределы экрана или вообще убивать) так, чтобы этих окон не было заметно на экране. Т.е. чтобы окна даже не успели мелькнуть.
Пример: как только появляется окно с заголовком "TTTWindow" его надо
переместить в точку -1000, -1000.
--
Чем тут будет полезен WH_SHELL? Похоже, WH_CBT вообще нормально не пашет :(


 
alex134 ©   (2002-12-02 19:14) [5]

Есть люди, разобравшиеся с хуками CBT?


 
Snap ©   (2002-12-03 21:59) [6]

Основная проблема при написании хуков состоит в том что у процессов разные адресные простаранства. То есть все переменные объявленные в твоей ДЛЛ в разных процессах будут разныими, а в большинстве из них будут нулями, то есть просто проинициализованными переменными. Вынеси все переменные в прогу, которая будет устанавливать хук.


 
Bsl   (2002-12-04 08:07) [7]

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

Я делал именно так - в ответ на событие в чужом процессе я отправлял событие окну, установившему hook, а Handle и все параметры брал с помощью SharedMemory.
(в Delphi есть модуль как пользовать shared memory).


 
alex134 ©   (2002-12-04 19:28) [8]

Спасибо, попробую.


 
alex134 ©   (2002-12-06 20:27) [9]

Учел Ваши поправки и исправил код:
Код библиотеки с хуком:

library Hook;

uses
Windows, SysUtils;

{$R *.res}

const
WM_USER = $0400; //
WM_KEYBHOOK = WM_USER + 346;
MMFName: PChar = "MyMMF"; // имя объекта файлового отображения

type
PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = packed record
WindowName : ShortString; // имя окна
WindowH: HWND; // дескриптор окна
end;

var
KeyboardHook: HHOOK;
GlobalData: PGlobalDLLData;
MMFHandle: THandle;

function CBTProc(hCode: Integer; wParam: Longint; lParam: Longint): LRESULT; stdcall;
var
Wnd: THandle;
name : String;
WinH : THandle;
CBTStruct : PCBTCreateWnd;
begin
if hCode = HCBT_CREATEWND then
begin
MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalDLLData), MMFName);
if MMFHandle = 0 then
MessageBox(0, "Can""t open FileMapping", "Message from freedomhook", 0)
else begin
GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalDLLData));
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Can""t make MapViewOfFile", "Message from freedomhook", 0);
end
else
begin
CBTStruct:=Ptr(lParam);
name:=StrPas(CBTStruct^.lpcs.lpszName);
WinH :=wParam;
GlobalData^.WindowName:=name;
GlobalData^.WindowH:=WinH;
FlushViewOfFile(GlobalData, SizeOf(TGlobalDLLData));
wnd:=findwindow(nil, "freedomhook");
if wnd>0 then SendMessage(wnd,WM_KEYBHOOK, 0, 0);
end;
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
end;
Result := CallNextHookEx(KeyboardHook, hCode, wParam, lParam);
end;

function SetKeyboardHook: Boolean; stdcall; export;
begin
KeyboardHook := SetWindowsHookEx(WH_CBT, @CBTProc, HInstance, 0);
Result := KeyboardHook <> 0;
end;

function RemoveKeyboardHook: Boolean; stdcall; export;
begin
Result := UnhookWindowsHookEx(KeyboardHook);
end;

exports SetKeyboardHook, RemoveKeyboardHook;

begin
end.


Код главной программы (пустая форма с Memo):

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Hook;

const
WM_USER = $0400; //
WM_KEYBHOOK = WM_USER + 346;
MMFName: PChar = "MyMMF"; // имя объекта файлового отображения

type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
procedure WMKEYBHOOK(var Msg: TMessage); message WM_KEYBHOOK;
public
{ Public declarations }
end;

type

PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = packed record
WindowName : ShortString; // имя окна
WindowH: HWND; // дескриптор окна
end;

var
Form1: TForm1;
GlobalData: PGlobalDLLData;
MMFHandle: THandle;

implementation

{$R *.dfm}

procedure TForm1.WMKEYBHOOK(var Msg: TMessage);
begin
Memo1.Lines.Add(GlobalData^.WindowName+" "+IntToStr(GlobalData^.WindowH));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
if not SetKeyboardHook then Application.Terminate;
GlobalData:=nil;
MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalDLLData), MMFName);
if MMFHandle = 0 then
MessageBox(0, "Can""t create FileMapping", "Message from freedomhook", 0)
else begin
GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalDLLData));
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Can""t make MapViewOfFile", "Message from freedomhook", 0);
end;
end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
RemoveKeyboardHook;
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;

end.

Программа отслеживает создание окон в системе, и передает заголовок и handle создавшегося окна главной программе.
В большинстве случаев имя заголовка пустое, однако, при создании интересующих меня окон оно содержит название окна - т.е. с этим проблем нет. Однако, работает все "не гладко" как хотелось бы - некоторые окна не открываются, похоже подвисают.
Например, при запуске ACDSee ее окно не показывается и программа продолжает "висеть" в памяти.
Один раз шелл заглючил. В чем ошибка мастера?



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

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

Наверх




Память: 0.51 MB
Время: 0.013 c
3-72144
rule
2002-12-21 13:02
2003.01.23
Как задать хитрый SQL запрос


4-72612
Egor
2002-12-07 16:48
2003.01.23
Как определить геометрию жесткого диска...


1-72221
zolotov
2003-01-14 12:35
2003.01.23
F1Book


3-72058
Picco
2003-01-05 13:09
2003.01.23
форматы Access 97,2000,2002


4-72597
Cosmic
2002-12-07 23:29
2003.01.23
Процесс, который невозможно удалить