如何突出显示特定的弹出菜单项?
How to HIGHLIGHT a specific popup menu item?
我有这个弹出菜单:
object pmTest: TPopupMenu
OnPopup = pmTestPopup
Left = 32
Top = 24
object mTest1: TMenuItem
Caption = 'Test 1'
OnClick = mTest1Click
end
object mTest2: TMenuItem
Caption = 'Test 2'
OnClick = mTest2Click
end
end
在使用 Popup
方法显示弹出菜单后,我需要以编程方式突出显示(而不是单击!)特定菜单项,所以我尝试了这个:
Winapi.Windows.HiliteMenuItem(pmTest.WindowHandle, pmTest.Handle, 1, MF_BYPOSITION or MF_HILITE);
但是不行。
如何以编程方式突出显示特定的弹出菜单项?
默认调用TPopupMenu.WindowHandle
property is set to the Application.Handle
window, not to the private HWND
that TPopupMenu
actually uses internally to actually dispatch its WM_COMMAND
messages to. That window is established when the TPopupMenu.Popup()
方法,不更新TPopupMenu.WindowHandle
属性.
尝试在 Vcl.Menus
单元中使用 TPopupList.Window
property instead of the TPopupMenu.WindowHandle
property for the HWND
to pass to HiliteMenuItem()
. There is a global PopupList
对象:
procedure TMyForm.pmTestPopup(Sender: TObject);
begin
Winapi.Windows.HiliteMenuItem({pmTest.WindowHandle}PopupList.Window, pmTest.Handle, 1, MF_BYPOSITION or MF_HILITE);
end;
如果仍然无效,请尝试使用 Win32 SetMenuItemInfo()
函数,该函数不需要 HWND
作为输入:
procedure TMyForm.pmTestPopup(Sender: TObject);
var
mii: MENUITEMINFO;
begin
ZeroMemory(@mii, sizeof(mii));
mii.cbSize := sizeof(mii);
mii.fMask := MIIM_STATE;
mii.fState := MFS_HILITE;
Winapi.Windows.SetMenuItemInfoW(pmTest.Handle, 1, True, mii);
end;
更新:经过进一步审查,TPopupMenu.OnPopup
事件在菜单可见之前触发,TPopupMenu
可能会在 [= 之后重新创建菜单30=] 已被调用,并且在菜单实际显示之前。因此,您最好的选择可能是 subclass the TPopupList
window so you can intercept the WM_ENTERMENULOOP
消息,然后自定义您的菜单项。例如:
type
TPopupListEx = class(TPopupList)
protected
procedure WndProc(var Message: TMessage); override;
end;
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
inherited;
if (Message.Msg = WM_ENTERMENULOOP) and (Message.WParam = 1) then
begin
// customize pmTest items as needed...
end;
end;
initialization
Popuplist.Free; //free the "default", "old" list
PopupList := TPopupListEx.Create; //create the new one
// The new PopupList will be freed by
// finalization section of Menus unit.
end.
我有这个弹出菜单:
object pmTest: TPopupMenu
OnPopup = pmTestPopup
Left = 32
Top = 24
object mTest1: TMenuItem
Caption = 'Test 1'
OnClick = mTest1Click
end
object mTest2: TMenuItem
Caption = 'Test 2'
OnClick = mTest2Click
end
end
在使用 Popup
方法显示弹出菜单后,我需要以编程方式突出显示(而不是单击!)特定菜单项,所以我尝试了这个:
Winapi.Windows.HiliteMenuItem(pmTest.WindowHandle, pmTest.Handle, 1, MF_BYPOSITION or MF_HILITE);
但是不行。
如何以编程方式突出显示特定的弹出菜单项?
默认调用TPopupMenu.WindowHandle
property is set to the Application.Handle
window, not to the private HWND
that TPopupMenu
actually uses internally to actually dispatch its WM_COMMAND
messages to. That window is established when the TPopupMenu.Popup()
方法,不更新TPopupMenu.WindowHandle
属性.
尝试在 Vcl.Menus
单元中使用 TPopupList.Window
property instead of the TPopupMenu.WindowHandle
property for the HWND
to pass to HiliteMenuItem()
. There is a global PopupList
对象:
procedure TMyForm.pmTestPopup(Sender: TObject);
begin
Winapi.Windows.HiliteMenuItem({pmTest.WindowHandle}PopupList.Window, pmTest.Handle, 1, MF_BYPOSITION or MF_HILITE);
end;
如果仍然无效,请尝试使用 Win32 SetMenuItemInfo()
函数,该函数不需要 HWND
作为输入:
procedure TMyForm.pmTestPopup(Sender: TObject);
var
mii: MENUITEMINFO;
begin
ZeroMemory(@mii, sizeof(mii));
mii.cbSize := sizeof(mii);
mii.fMask := MIIM_STATE;
mii.fState := MFS_HILITE;
Winapi.Windows.SetMenuItemInfoW(pmTest.Handle, 1, True, mii);
end;
更新:经过进一步审查,TPopupMenu.OnPopup
事件在菜单可见之前触发,TPopupMenu
可能会在 [= 之后重新创建菜单30=] 已被调用,并且在菜单实际显示之前。因此,您最好的选择可能是 subclass the TPopupList
window so you can intercept the WM_ENTERMENULOOP
消息,然后自定义您的菜单项。例如:
type
TPopupListEx = class(TPopupList)
protected
procedure WndProc(var Message: TMessage); override;
end;
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
inherited;
if (Message.Msg = WM_ENTERMENULOOP) and (Message.WParam = 1) then
begin
// customize pmTest items as needed...
end;
end;
initialization
Popuplist.Free; //free the "default", "old" list
PopupList := TPopupListEx.Create; //create the new one
// The new PopupList will be freed by
// finalization section of Menus unit.
end.