Форум: "WinAPI";
Текущий архив: 2006.03.12;
Скачать: [xml.tar.bz2];
ВнизПроблема с Hook om Найти похожие ветки
← →
Igor_thief (2005-12-17 13:54) [0]Почему хук миши не срабатует тогда, когда клик происходит по заголовку окна?
Почему хук перестает работать, когда выйти из прилодения, которое установило хук?
Вот код:library Hook;
uses
SysUtils, Classes, Messages, WinTypes, WinProcs;
var
HookHandle: HHOOK;
IsHooked: Boolean;
DesktopWin: HWND;
function HookProc(Code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if wParam = WM_LBUTTONDOWN then
Beep(100, 100);
Result := CallNextHookEx(HookHandle, Code, wParam, lParam);
end;
function SetHook: Boolean; stdcall;
begin
Result := false;
if IsHooked then
Exit;
DesktopWin := GetDesktopWindow;
HookHandle := SetWindowsHookEx(WH_MOUSE, HookProc, HInstance, 0);
Result := HookHandle <> 0;
end;
function RemoveHook: Boolean; stdcall;
begin
Result := false;
if (not IsHooked) and (HookHandle <> 0) then
Result := UnhookWindowsHookEx(HookHandle);
IsHooked := false;
end;
exports
SetHook name "SetHook",
RemoveHook name "RemoveHook",
HookProc name "HookProc";
{$R *.res}
begin
IsHooked := false;
end.
Исользуюющая программа:unit frmMainU;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TfrmMain = class(TForm)
btnHook: TButton;
btnUnhook: TButton;
procedure btnUnhookClick(Sender: TObject);
procedure btnHookClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
function SetHook: Boolean; stdcall;
function RemoveHook: Boolean; stdcall;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
function SetHook; external "Hook.dll" name "SetHook";
function RemoveHook; external "Hook.dll" name "RemoveHook";
procedure TfrmMain.btnHookClick(Sender: TObject);
begin
if SetHook then
ShowMessage("Global Hook is setted!")
else
ShowMessage("Error!");
end;
procedure TfrmMain.btnUnhookClick(Sender: TObject);
begin
if RemoveHook then
ShowMessage("Global Hook is removed!")
else
ShowMessage("Error!");
end;
end.
← →
Lamer@fools.ua © (2005-12-17 14:20) [1]>Почему хук миши не срабатует тогда, когда клик происходит по заголовку окна?
Потому что там приходит другое сообщение. Не WM_LBUTTONDOWN, а WM_NCLBUTTONDOWN, если не ошибаюсь.
>Почему хук перестает работать, когда выйти из прилодения, которое установило хук?
Спросите у Microsoft"а.
← →
Igor_thief (2005-12-17 14:54) [2]Lamer@fools.ua © (17.12.05 14:20) [1]
Потому что там приходит другое сообщение. Не WM_LBUTTONDOWN, а WM_NCLBUTTONDOWN, если не ошибаюсь.
Проверю.
Lamer@fools.ua © (17.12.05 14:20) [1]
Спросите у Microsoft"а.
:))
← →
Lamer@fools.ua © (2005-12-17 21:06) [3]Смех смехом, а Рихтера всё-таки почитайте:
http://www.podgoretsky.com/ftp/Docs/Classics/Richter/
← →
Se (2005-12-18 09:24) [4]Igor_thief ты не один такой. Я тоже мучаюсь с этим вопросом (посмотри "Форма не обрабатывает сообщения, когда неактивна").
← →
Igor_thief (2005-12-18 12:57) [5]Lamer@fools.ua © (17.12.05 14:20) [1]
Потому что там приходит другое сообщение. Не WM_LBUTTONDOWN, а WM_NCLBUTTONDOWN, если не ошибаюсь.
The WM_NCLBUTTONDOWN message is posted when the user presses the left mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.
и
The WM_LBUTTONDOWN message is posted when the user presses the left mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
Следовательно сделал такие изменения:function HookProc(Code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if wParam = WM_NCLBUTTONDOWN then
Beep(100, 100);
if wParam = WM_LBUTTONDOWN then
Beep(100, 100);
Result := CallNextHookEx(HookHandle, Code, wParam, lParam);
end;
← →
Igor_thief (2005-12-18 19:58) [6]Теперь появилась новая проблема. Надо чтобы когда срабатывал хук мыши (на нажатие левой кнопки), мое приложение обрабатывало это событие.
Сразу в голове возникло два варианта решения проблемы. Первый - CallBack функция, второй - зарегистрировать уникальное сообщение (RegisterWindowMessage).
Для начала решил пойти вторым путем. Вроде работает нормально, но все же есть один нюанс! Помогите решить, плиз. Суть нюанаса -BroadcastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE, @Recepients, UserMsg, 0, 0);
вот так работает правильно, если не клацать в форме окна, которое зарегистрировало хук. Теоретически, для чтобы обойти это и сделать так, чтобы работало даже если клик происходит в окне, чей процесс зарегистровал хук, надо всего лишь убрать параметр BSF_IGNORECURRENTTASK. Как только я это делаю, приложение просто увеивает машину (загрузка проца - 100%).
Далее привожу полный код хука и решистрируещего приложения:library Hook;
uses
SysUtils, Classes, Messages, WinTypes, WinProcs;
var
HookHandle: HHOOK;
IsHooked: Boolean;
DesktopWin: HWND;
UserMsg: UINT;
Recepients: DWORD;
function HookProc(Code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if (wParam = WM_NCLBUTTONDOWN) or (wParam = WM_LBUTTONDOWN) then
BroadcastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE, @Recepients, UserMsg, 0, 0);
Result := CallNextHookEx(HookHandle, Code, wParam, lParam);
end;
function SetHook: Boolean; stdcall;
begin
Result := false;
if IsHooked then
Exit;
DesktopWin := GetDesktopWindow;
HookHandle := SetWindowsHookEx(WH_MOUSE, HookProc, HInstance, 0);
Result := HookHandle <> 0;
end;
function RemoveHook: Boolean; stdcall;
begin
Result := false;
if (not IsHooked) and (HookHandle <> 0) then
Result := UnhookWindowsHookEx(HookHandle);
IsHooked := false;
end;
exports
SetHook name "SetHook",
RemoveHook name "RemoveHook",
HookProc name "HookProc";
{$R *.res}
begin
IsHooked := false;
Recepients := BSM_APPLICATIONS;
UserMsg := RegisterWindowMessage("{FF4B9248-40A7-4062-9CA3-CF08E2031306}");
end.
Программа которая обрабатывает сообщение:
unit frmMainU;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TfrmMain = class(TForm)
btnHook: TButton;
btnUnhook: TButton;
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btnUnhookClick(Sender: TObject);
procedure btnHookClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
function SetHook: Boolean; stdcall;
function RemoveHook: Boolean; stdcall;
function NewWindowProc(TheWindow: HWND; Msg: Integer; wParam: WPARAM;
lParam: LPARAM): Longint; stdcall;
var
frmMain: TfrmMain;
UserMsg: UINT;
OldWindowProc: TFNWndProc;
implementation
{$R *.dfm}
function SetHook; external "Hook.dll" name "SetHook";
function RemoveHook; external "Hook.dll" name "RemoveHook";
procedure TfrmMain.btnHookClick(Sender: TObject);
begin
if SetHook then
ShowMessage("Global Hook is setted!")
else
ShowMessage("Error!");
end;
procedure TfrmMain.btnUnhookClick(Sender: TObject);
begin
if RemoveHook then
ShowMessage("Global Hook is removed!")
else
ShowMessage("Error!");
end;
function NewWindowProc(TheWindow: HWND; Msg: Integer; wParam: WPARAM; lParam: LPARAM): Longint;
begin
if Msg = UserMsg then
begin
frmMain.Tag := frmMain.Tag + 1;
frmMain.Caption := frmMain.Caption + IntToStr(frmMain.Tag);
// Application.ProcessMessages;
{the message was handled, so return a one}
Result := 1;
end
else
{any other message must be passed to the previous window procedure}
Result := CallWindowProc(OldWindowProc, TheWindow, Msg, wParam, lParam);
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
UserMsg := RegisterWindowMessage("{FF4B9248-40A7-4062-9CA3-CF08E2031306}");
OldWindowProc := TFNWndProc(SetWindowLong(frmMain.Handle, GWL_WNDPROC,
Longint(@NewWindowProc)));
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
SetWindowLong(frmMain.Handle, GWL_WNDPROC, Longint(OldWindowProc));
end;
end.
← →
Igor_thief (2005-12-19 17:26) [7]Удалено модератором
Примечание: Создание пустых сообщений
← →
ANB © (2005-12-20 11:27) [8]
> Igor_thief (18.12.05 19:58) [6]
C CallBack можешь даже не начинать, т.к. хуковый фильтр/процедура в DLL будет работать в АП чужого процесса, для которого адрес твоей CallBack функции - бессмысленный набор цифр.
Рассылка броадкастом вообще то избыточна. Можно заранее при установке хука передать хендл окна, которое будет обрабатывать служебные сообщения, в DLL, а там сохранить ее в MMF, чтобы хендл стал доступен всем экземплярам DLL. В MMF можно еще много чего полезного напихать. Регистрять отдельное сообщение и его же передавать тоже будет не круто, т.к. у тебя в него не влезет вся нужная информация (ссылки через WM_USER передавать бессмысленно). Хотя можно опять таки использовать MMF, но тут возникнет куча проблем с синхронизацией доступа. Короче - я использую помеченную WM_COPYDATA. Работает шустро и не сбоит.
← →
Igor_thief (2005-12-20 20:24) [9]Сделал используя MMF.
← →
grisme © (2005-12-21 11:32) [10]
> Почему хук миши не срабатует тогда, когда клик происходит
> по заголовку окна?
Потому что необходимо обрабатывать не WM_LBUTTONDOWN, а WM_NCHITTEST (вроде так - в хелпе посмотри!)
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2006.03.12;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.015 c