我想创建一个DLL,当加载到进程中时,会向应用程序Sysmenu添加“Always on top”项。我创建了一个试用SetWindowsHookEx(WH_CALLWNDPROC,...)
和SetWindowsHookEx(WM_GETMESSAGE,...)
的钩子,然后添加菜单并检查单击事件的WM_消息。 WM_SYSCOMMAND被触发,但没有我插入的菜单项ID(ALWAYS_ONTOP)。为什么我的菜单项没有被处理(或者,为什么我不能捕获我插入的菜单项点击事件)?
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.
旁注:我的WndProcCallback()与GetMessageCallback()基本相同,只不过我按照MSDN将lParam转换为PCWPStruct。