gpt4 book ai didi

delphi - 在弹出菜单的禁用菜单项上显示工具提示提示

转载 作者:行者123 更新时间:2023-12-03 14:59:13 27 4
gpt4 key购买 nike

所以我有一个 TMenuItem 附加到 TDBGrid 的 TPopupMenu 上的 TAction(实际上是第 3 方,但你明白了)。根据网格中选定的行,启用或禁用 TAction。我想要的是能够向用户显示提示,解释为什么该项目被禁用。

至于为什么我想要有关禁用菜单项的提示,我们可以说我是 in agreement with Joel .

所有 TMenuItem 都有一个提示属性,但据我所知,它们仅使用 TApplicationEvent.OnHint 事件处理程序将提示粘贴到 TStatusBar 或其他一些特殊处理中。我found an article关于如何为 TMainMenu 的 TMenuItems 创建自己的偶数窗口,但它不适用于 TPopupMenu 的 TMenuItem。它通过处理 WM_MENUSELECT 消息来工作,据我所知,该消息不是在 TPopupMenu 上发送的。

最佳答案

WM_MENUSELECT 确实也针对弹出菜单中的菜单项进行处理,但不是由包含(弹出)菜单的窗体的 windows 过程处理,而是由 Menus.PopupList 创建的不可见帮助程序窗口处理。幸运的是,您可以(至少在 Delphi 5 下)通过 Menus.PopupList.Window 获取此 HWND。

现在您可以使用老式的方法对窗口进行子类化,如本 CodeGear article 中所述。 ,也可以处理弹出菜单的 WM_MENUSELECT。 HWND 从第一个 TPopupMenu 创建后到最后一个 TPopupMenu 对象被销毁之前有效。

使用问题中链接文章中的演示应用程序进行快速测试应该可以揭示这是否有效。

编辑:它确实有效。我改变了the linked example也显示弹出菜单的提示。步骤如下:

将 OnDestroy 的处理程序、旧窗口过程的成员变量和新窗口过程的方法添加到表单中:

TForm1 = class(TForm)
...
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ApplicationEvents1Hint(Sender: TObject);
private
miHint : TMenuItemHint;
fOldWndProc: TFarProc;
procedure WMMenuSelect(var Msg: TWMMenuSelect); message WM_MENUSELECT;
procedure PopupListWndProc(var AMsg: TMessage);
end;

更改窗体的OnCreate处理程序以子类化隐藏的PopupList窗口,并在OnDestroy处理程序中实现窗口过程的正确恢复:

procedure TForm1.FormCreate(Sender: TObject);
var
NewWndProc: TFarProc;
begin
miHint := TMenuItemHint.Create(self);

NewWndProc := MakeObjectInstance(PopupListWndProc);
fOldWndProc := TFarProc(SetWindowLong(Menus.PopupList.Window, GWL_WNDPROC,
integer(NewWndProc)));
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
NewWndProc: TFarProc;
begin
NewWndProc := TFarProc(SetWindowLong(Menus.PopupList.Window, GWL_WNDPROC,
integer(fOldWndProc)));
FreeObjectInstance(NewWndProc);
end;

实现子类化窗口过程:

procedure TForm1.PopupListWndProc(var AMsg: TMessage);

function FindItemForCommand(APopupMenu: TPopupMenu;
const AMenuMsg: TWMMenuSelect): TMenuItem;
var
SubMenu: HMENU;
begin
Assert(APopupMenu <> nil);
// menuitem
Result := APopupMenu.FindItem(AMenuMsg.IDItem, fkCommand);
if Result = nil then begin
// submenu
SubMenu := GetSubMenu(AMenuMsg.Menu, AMenuMsg.IDItem);
if SubMenu <> 0 then
Result := APopupMenu.FindItem(SubMenu, fkHandle);
end;
end;

var
Msg: TWMMenuSelect;
menuItem: TMenuItem;
MenuIndex: integer;
begin
AMsg.Result := CallWindowProc(fOldWndProc, Menus.PopupList.Window,
AMsg.Msg, AMsg.WParam, AMsg.LParam);
if AMsg.Msg = WM_MENUSELECT then begin
menuItem := nil;
Msg := TWMMenuSelect(AMsg);
if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then begin
for MenuIndex := 0 to PopupList.Count - 1 do begin
menuItem := FindItemForCommand(PopupList.Items[MenuIndex], Msg);
if menuItem <> nil then
break;
end;
end;
miHint.DoActivateHint(menuItem);
end;
end;

循环中的所有弹出菜单都会执行此操作,直到找到第一个匹配的项目或子菜单。

关于delphi - 在弹出菜单的禁用菜单项上显示工具提示提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/470696/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com