Search code examples
delphisetwindowshookex

Hook WH_GETMESSAGE and filter WM_SETTEXT only


Using the Microsoft Spy++ I see that Notepad++ receives a WM_SETTEXT message, when you open/create a new document. I need to hook title changes on Windows, so I'm trying doing WH_GETMESSAGE hook, and filtering only WM_SETTEXT. But so far I'm unsuccessful. Here's my DLL:

uses
  System.SysUtils,
  Windows,
  Messages,
  System.Classes;

var
  CurrentHook: HHOOK;

{$R *.res}

function GetMessageHookProc(Code: Integer; iWParam: WPARAM; iLParam: LPARAM): LRESULT; stdcall;
begin
  Result:= CallNextHookEx(CurrentHook, Code, iWParam, iLParam);
  if (Code = HC_ACTION) and (PMSG(iLParam).message = wm_settext) then
  begin
    MessageBox(0, 'WM_SETTEXT', 'WM_SETTEXT', MB_OK);

    //this code below is just a prototype to what I will try when this works:
    if IntToStr(PMSG(iLParam).lParam) = 'new - Notepad++' then
      MessageBox(0, 'Notepad++', 'Notepad++', MB_OK);

  end;
end;

procedure SetHook; stdcall;
begin
  CurrentHook:= SetWindowsHookEx(WH_GETMESSAGE, @GetMessageHookProc, HInstance, 0);
  if CurrentHook <> 0 then
    MessageBox(0, 'HOOKED', 'HOOKED', MB_OK);
end;

procedure UnsetHook; stdcall;
begin
  UnhookWindowsHookEx(CurrentHook);
end;

exports
  SetHook,
  UnsetHook;

begin

end.

I get the 'HOOKED' message box, indicating that the hook was settled, but I never get the 'WM_SETTEXT' message box inside the if of the callback procedure. How can I filter only this kind of message, and check the string of the message?

Thank you!


Solution

  • WM_SETTEXT is a sent message, not a posted message. A WH_GETMESSAGE hook only sees messages that are posted to the target thread's message queue, so it will never see WM_SETTEXT messages. To hook messages that are sent directly to a window without going through the message queue, you need to use a WH_CALLWNDPROC or WH_CALLWNDPROCRET hook instead.