Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Хук на смену активного окна


Автор: TechnoMag 19.9.2013, 18:46
Пробовал: WH_MSGFILTER, WH_SYSMSGFILTER, WH_SHELL

Код

SetWindowsHookEx(WH_SYSMSGFILTER, @ShellProc, HInstance, 0);

function ShellProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT;  stdcall;
begin
  Result := CallNextHookEx(ShellHooker1.ShellHook, nCode, WParam, LParam); // программа даже не попадает на эту строку.
  // ....
end;


Хук создается в оконном приложении в основном потоке. Никаких Dll.

Автор: Illusion Dolphin 19.9.2013, 19:17
Цитата

SetWindowsHookEx(WH_SYSMSGFILTER, @ShellProc, HInstance, 0);


If the function succeeds, the return value is the handle to the hook procedure.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.

1) Надо бы сохранять оригинальный указатель
2) Надо бы посмотреть что не так если его нету

Автор: TechnoMag 20.9.2013, 10:29
GetLastError возвращает код ошибки 1428.

А так, ShellProc реагирует, если активным становится окно собственного процесса.
Код

 ShellHook := SetWindowsHookEx(WH_SHELL, @ShellProc, GetModuleHandle(nil), GetCurrentThreadId());



Автор: Illusion Dolphin 20.9.2013, 10:58
Цитата

GetLastError возвращает код ошибки 1428.

Ну конечно посмотреть что такое 1428 было очень сложно:
ERROR_HOOK_NEEDS_HMOD
    1428 (0x594)
    Cannot set nonlocal hook without a module handle.

http://stackoverflow.com/questions/12357705/setwindowshookex-fails-with-error-1428

Т.е. надо указывать нужный модуль, а не текущий вроде как

Автор: TechnoMag 20.9.2013, 11:41
Какой модуль? DLL? Ведь хук я создаю в основном процессе, а не в DLL.

Автор: Illusion Dolphin 20.9.2013, 11:47
Цитата

Ведь хук я создаю в основном процессе, а не в DLL.

Чтобы ловить другие приложения нужно DLL

Автор: TechnoMag 20.9.2013, 12:36
Хм. Почему для хука на мышь и клавиатуру не нужно Dll?
По крайней мере не обязательно. Проверял на Win7 и Xp - работают.

Автор: Illusion Dolphin 20.9.2013, 13:08
Цитата

Хм. Почему для хука на мышь и клавиатуру не нужно Dll?

Может это в MSDN объясняет:
For a specified hook type, thread hooks are called first, then global hooks. Be aware that the WH_MOUSE, WH_KEYBOARD, WH_JOURNAL*, WH_SHELL, and low-level hooks can be called on the thread that installed the hook rather than the thread processing the hook.

Автор: TechnoMag 20.9.2013, 14:55
Попробовал сделать в DLL.
Опять же, реагирует только на саму себя.
Почему-то постепенно валит все приложения в системе, включая службы.


Код

library ShellHook;
uses
  System.SysUtils,
  System.Classes,
  Windows;

{$R *.res}

type
  TGlobalDLLData=packed record
    SysHook:HHOOK; //дескриптор установленной ловушки
    MyAppWnd:HWND; //дескриптор нашего приложения
  end;

var
  GlobalData:TGlobalDLLData;
  MMFHandle:THandle;
  WM_MYSHELLHOOK:Cardinal;

function ShellProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT;  stdcall;
var
  AppWnd:HWND;
begin
  if nCode < 0 then
  begin
    Result:=CallNextHookEx(GlobalData.SysHook,nCode,wParam,lParam);
    Exit;
  end;
    SendMessage(GlobalData.MyAppWnd, WM_MYSHELLHOOK, wParam, lParam);
    CallNextHookEx(GlobalData.SysHook,nCode,wParam,lParam);
  Result:= 0;
end;


procedure hook(switch: boolean; hMainProg: HWND) export; stdcall;
var
  mm: MINIMIZEDMETRICS;
begin
  if switch=true then
  begin
  {Устанавливаем HOOK, если не установлен (switch=true). }
  mm.cbSize:=sizeof(MINIMIZEDMETRICS);
  mm.iArrange:=ARW_HIDE or ARW_BOTTOMRIGHT;
  mm.iWidth := 32;
  mm.iHorzGap := 14;
  mm.iVertGap := 14;
 {
  Вообще не пойму смысла этого, но взял отсюда: http://www.vsokovikov.narod.ru/New_MSDN_API/Hook/wh_shell.htm
 }
  SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), @mm, SPIF_SENDCHANGE);
  

    GlobalData.SysHook := SetWindowsHookEx(WH_SHELL, @ShellProc, HInstance, 0);
    GlobalData.MyAppWnd := hMainProg;
  end
  else
    UnhookWindowsHookEx(GlobalData.SysHook);
end;

procedure OpenGlobalData();
begin
  {регестрируем свой тип сообщения в системе}
  WM_MYSHELLHOOK := RegisterWindowMessage('WM_MYSHELLHOOK');
end;

procedure CloseGlobalData();
begin
end;

exports hook;

procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
  case dwReason of
    DLL_PROCESS_ATTACH: OpenGlobalData;
    DLL_PROCESS_DETACH: CloseGlobalData;
  end;
end;

begin
  DLLProc:= @DLLEntryPoint;
  {вызываем назнаxенную процедуру для отражения факта присоединения данной
  библиотеки к процессу}
  DLLEntryPoint(DLL_PROCESS_ATTACH);
end.


Код

 TForm1 = class(TForm)
 private
    { Private declarations }
    hDLL: THandle; // дескриптор загружаемой библиотеки
    WM_MYSHELLHOOK: DWORD; // мо? сообщение
  public
    { Public declarations }
    procedure WndProc(var Msg: TMessage); override;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Hook: procedure (switch : Boolean; hMainProg: HWND) stdcall;
begin
  @hook:= nil; // инициализируем переменную hook
  hDLL:=LoadLibrary(PChar('shellhook.dll')); { загрузка DLL }
  if hDLL > HINSTANCE_ERROR then
  begin { если вс? без ошибок, то }
      WM_MYSHELLHOOK := RegisterWindowMessage('WM_MYSHELLHOOK');
      @hook:=GetProcAddress(Hdll, 'hook'); { полу?аем указатель на необходимую процедуру}
      StatusBar1.SimpleText:= 'Status: DLL loaded...';
      hook(true, Form1.Handle);
  end
  else
      StatusBar1.SimpleText:= 'Status: DLL not loaded...';
end;

procedure TForm1.WndProc(var Msg: TMessage);
begin
 inherited;
 if Msg.Msg = WM_MYSHELLHOOK then
    Memo1.Lines.Add('Смена окна');
end;


Автор: TechnoMag 20.9.2013, 21:37
http://www.free-notes.ru/?p=200

Цитата

Windows вызывает этот хук, когда диалоговое окно, информационное окно, полоса прокрутки или меню получают сообщение, либо когда пользователь нажимает комбинацию клавиш ALT+TAB (или ALT+ESC) при активном приложении, установившем этот хук. Данный хук устанавливается для конкретного потока, поэтому его безопасно размещать как в самом приложении, так и в DLL.


Пробовал и WH_MGSFILTER. Причем не в DLL, не в самом приложении не работает. 

Автор: TechnoMag 21.9.2013, 18:38
http://www.delphisources.ru/pages/sources/system/2008-year/shell-hook.html

На Win 7 64 почему-то реагирует не на все окна.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)