【问题标题】:Is possible for a menu item to receive an OnClick event even when it's not enabled?即使未启用菜单项也可以接收 OnClick 事件吗?
【发布时间】:2013-08-07 13:11:33
【问题描述】:

我正在尝试让管理员通过 Ctrl+单击来启用/禁用我的应用程序主菜单中的菜单项。为此,我在主窗体中注入了带有自定义版本的 TMenuItem 类,并重写了 Click 虚拟方法,如下所示:

uses
  Forms, Menus;

type
  TMenuItem = class(Menus.TMenuItem)
  public
    ControlActivationState: Boolean;
    procedure Click; override;
  end;

  TMyMainForm = class(TForm)

...

procedure TMenuItem.Click;
begin
  if ControlActivationState and IsKeyPressed(VK_CONTROL) then
    Self.Enabled := not Self.Enabled
  else
    inherited;
end;

它有效,但仅适用于顶级菜单。 为什么顶级菜单项即使在禁用时也会收到 OnClick 事件,而其他菜单项却没有? 有没有办法让子菜单项也接收这些事件?

【问题讨论】:

    标签: delphi event-handling controls mouseevent vcl


    【解决方案1】:

    顶级OnClick 事件由收到WM_INITMENUPOPUP 消息触发。即使顶级项目被禁用,也会发送该消息。我不确定为什么在那种情况下发送它,但确实如此。对于有子项的子项也是如此。

    但是,对于没有子项的子项,OnClickWM_COMMAND 消息触发。但是如果菜单项被禁用,系统甚至不会发送消息。

    你试图做的事情并不容易做到。我能看到你这样做的唯一方法是处理原始的鼠标和键盘事件。就个人而言,我不会考虑这样做。

    【讨论】:

    • 我有点怀疑为禁用的顶部菜单发送 WM_INITMENUPOPUP 的原因,因为该菜单实际上并没有弹出。但我没有更好的解释..
    • @SertacAkyuz 文档说:在下拉菜单或子菜单即将激活时发送。这允许应用程序在菜单显示之前对其进行修改,而无需更改整个菜单。
    • 与文档相反,即使下拉列表要为禁用的顶部项目激活,也会发送消息。
    • @SertacAkyuz 我不这样做。
    • @SertacAkyuz 哦,好吧。我们只能推测。
    【解决方案2】:

    TMenuItem 是一个 TComponent,即它不是一个窗口控件并且它没有经典事件。相反,发生在真实窗口控件上的单击事件被委托给 TMenuItem 实例。我不知道哪个窗口控件是事件的 real 主机,但即使我知道,我认为很难确定哪个 TMenuItem 对应于实际的点击点。

    我的建议是使用树控件创建一个用于菜单编辑的专用窗口,该树控件通常在运行时根据实际菜单布局填充其项目,然后为 树节点 提供启用/禁用反映相应的菜单项。然后,您可以保存/加载 menuitem 列表等。这应该更清晰、更容易,然后深入 VCL 的阴暗深处并弄清楚(并覆盖)事件如何从“真实”控件传播到称为 @987654321 的设计时表示@s...

    【讨论】:

    • 你的第一段没有意义。有关如何生成菜单项点击的信息,请参阅 David 的回答。
    • 我的意思是,您无法单独检测给定 TMenuItem 实例的点击,因为它是一个 TComponent 并且它不直接接收 Windows 消息。
    【解决方案3】:

    事实上,你正在努力做到这一点......

    解决问题的简单方法是覆盖 TMenuItemOnDrawItem() 方法,使其像被禁用一样显示,并交替处理 OnClick 事件。

    (不要忘记设置菜单的.OwnerDraw 属性以使此解决方案有效。)

    编辑:

    根据 Delphi 帮助,使用 OnAdvancedDrawItem 事件会更容易,因为它提供了有关菜单项本身的信息。

    【讨论】:

    • 绘制一个准确的主题控件再难了
    • 更难。如果您想捕获禁用菜单项的消息,您必须检索 Windows 菜单项的句柄并覆盖其功能。如果要绘制非活动菜单项,则必须将Canvas.Font.Color 设置为 clInactiveCaption。
    • 绘制一个主题准确的菜单项很难。如果这很容易,那么 Emba 将能够正确地做到这一点。这就是为什么我的应用程序不使用有缺陷的 Emba 代码并让系统绘制主题菜单的原因。系统做对了。
    • 作为一种折衷方案,可以在管理员模式下使用此技巧。 IE。只有管​​理员才能看到丑陋的非标准项目。
    • 这就是@Uri 的计划
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 2021-04-18
    • 1970-01-01
    相关资源
    最近更新 更多