Delphi SetWindowsHookEx钩子中未处理消息

Delphi SetWindowsHookEx钩子中未处理消息,delphi,hook,message-queue,delphi-xe,Delphi,Hook,Message Queue,Delphi Xe,我想创建一个DLL,当加载到进程中时,它会在应用程序菜单中添加一个“始终在顶部”项。我创建了一个钩子,尝试了SetWindowsHookEx(WH_CALLWNDPROC,…)和SetWindowsHookEx(WM_GETMESSAGE,…),然后从那里添加菜单并检查WM_u消息中的点击事件。WM_SYSCOMMAND被触发,但没有我插入的菜单项ID(始终\u ONTOP)。为什么我的菜单项没有被处理(或者,为什么我不能捕获插入的菜单项单击事件) 库dlltest; 使用 窗口、消息、系统工具

我想创建一个DLL,当加载到进程中时,它会在应用程序菜单中添加一个“始终在顶部”项。我创建了一个钩子,尝试了
SetWindowsHookEx(WH_CALLWNDPROC,…)
SetWindowsHookEx(WM_GETMESSAGE,…)
,然后从那里添加菜单并检查WM_u消息中的点击事件。WM_SYSCOMMAND被触发,但没有我插入的菜单项ID(始终\u ONTOP)。为什么我的菜单项没有被处理(或者,为什么我不能捕获插入的菜单项单击事件)

库dlltest;
使用
窗口、消息、系统工具;
变量
钩子:HHOOK;
启用:布尔值;
常数
始终p=100;
函数GetMessageCallback(代码:整数;wParam:wParam;lParam:lParam):LRESULT;stdcall;
变量
uMsg:TMSG;
汉努:唐德尔;
开始
如果(代码=HC\U动作),则
开始
//--
//--插入菜单项
如果(Enabled=False),则
开始
humenu:=GetSystemMenu(umsg.hwnd,FALSE);
如果(hMenu 0)那么
开始
{Enabled:=}附加菜单(menu,MF_分隔符,0,”);
已启用:=附录菜单(hMenu、MF_字符串、始终在顶部、“始终在顶部”);
End//Else writetext('hMenu=0!');
结束;
//--
//--处理消息
uMsg:=PMSG(lParam)^;
案例(uMsg.消息)
WM_SYSCOMMAND:
开始
案例loword(uMsg.信息)
始终坚持:
开始
//切换复选标记
MessageBoxA(0,'你好世界','测试',0);
结束;
结束//案例
结束//WM_SYSCOMMAND:
WM_初始化菜单:
开始
//GetSystemMenu返回0?,嗯
//writetext('WM_INITMENU');
结束//WM_初始化菜单:
结束//案例uMsg
结束//如果(HC_行动)
结果:=CallNextHookEx(Hook、Code、wParam、lParam);
结束;
开始
已启用:=假;
Hook:=SetWindowsHookEx(WH_GETMESSAGE{WH_CALLWNDPROC},@GetMessageCallback{@WndProcCallback},0,GetCurrentThreadId());
如果(Hook=0),则
开始
消息框(0,'无挂钩','失败',0);
结束;
结束。

旁注:我的WndProcCallback()与GetMessageCallback()基本相同,只是我根据MSDN将lParam强制转换为PCWPStruct。

嗯,刚刚意识到我的标题有误导性,我如何更改它?阅读帮助,点击标签下面的链接(在本例中,就在
delphi
hook
之间)。。请仅使用适用于您的问题的标签。Delphi不是Pascal。泛型Pascal标记用于传统Pascal语言。Delphi可能起源于turbopascal,但它已经演变成自己的语言。谢谢。为什么在测试
时总是使用
loword(uMsg.message)
?至此,您已经知道
uMsg.message
本身就是
WM\u SYSCOMMAND
。它的位中不包含
始终\u ONTOP
值。您应该测试
uMsg.wParam和$FFF0
。话虽如此,您是否考虑过使用
WH\u CBT
hook?尝试在
HCBT_CREATEWND
HCBT_ACTIVATE
HCBT_SETFOCUS
通知中添加菜单项,然后在
HCBT_SYSCOMMAND
通知中处理菜单项。
WM_SYSCOMMAND
保留
wParam
的低位4位供内部使用(这就是为什么在测试值时必须使用
wParam和$FFF0
)。二进制中的100是
01100100
,而二进制中的96是
01100000
。看起来很熟悉吗?96是100,其低位4位设置为0(在本例中,100-4=96).So 100作为菜单项ID与
WM\u SYSCOMMAND
不兼容。请使用不使用低位4位的其他值,或与现有
SC\u…
定义的ID冲突。
library dlltest;
uses
  Windows, messages, sysutils;

var
  Hook    : HHOOK;
  Enabled : boolean;
Const
  ALWAYS_ONTOP = 100;

Function  GetMessageCallback(code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
Var
  uMsg  : TMSG;
  hMenu : Thandle;
Begin
  IF(Code = HC_ACTION)Then
  Begin
//--
//-- Insert Menu Item
    IF (Enabled = False) then
    Begin
      hMenu := GetSystemMenu(umsg.hwnd, FALSE);
      IF (hMenu <> 0) Then
      Begin
       {Enabled :=}AppendMenu(hMenu, MF_SEPARATOR, 0, '');
        Enabled := AppendMenu(hMenu, MF_STRING, ALWAYS_ONTOP, 'Always On Top');
      End //Else writetext('hMenu=0!');
    End;
//--
//-- Process message(s)
    uMsg := PMSG(lParam)^;
    case (uMsg.message) of

      WM_SYSCOMMAND:
        Begin
          case loword(uMsg.message) of
            ALWAYS_ONTOP:
              Begin
                //toggle checkmark
                MessageBoxA(0, 'Hello World', 'test', 0);
              End;
          End;//Case
        End;//WM_SYSCOMMAND:

      WM_INITMENU:
        Begin
          //GetSystemMenu returns 0?, hmm
          //writetext('WM_INITMENU');
        End;//WM_INITMENU:

    end;//case uMsg
  end;//IF (HC_ACTION)
  Result := CallNextHookEx(Hook, Code, wParam, lParam);
End;

begin
  enabled := False;
  Hook    := SetWindowsHookEx(WH_GETMESSAGE{WH_CALLWNDPROC}, @GetMessageCallback {@WndProcCallback}, 0, GetCurrentThreadId());
  IF(Hook = 0)Then
  Begin
    messagebox(0, 'no hook', 'fail', 0);
  End;
end.