即使菜单项未启用,菜单项也可以接收OnClick事件吗?

时间:2013-08-07 13:11:34

标签: delphi event-handling controls mouseevent vcl

我正在尝试通过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事件,即使它们被禁用而其他菜单项也没有? 有没有办法让子菜单项也接收这些事件?

3 个答案:

答案 0 :(得分:4)

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

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

你想做的事情不容易做到。我能看到你这么做的唯一方法是处理原始的鼠标和键盘事件。就个人而言,我不打算这样做。

答案 1 :(得分:2)

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

我的建议是使用树控件创建一个专用的菜单编辑窗口,该控件在运行时根据实际的菜单布局一般填充其项目,然后为树节点提供启用/禁用反映相应的菜单项。然后你可以保存/加载menuitem列表等。这应该更清晰,更容易,然后潜入VCL的阴暗深处,并弄清楚(和重写)事件如何从'真实'控件传播到名为{{的设计时表示1}}Š...

答案 2 :(得分:0)

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

解决问题的简单方法是覆盖OnDrawItem()的{​​{1}}方法,将其显示为已禁用,并替代处理TMenuItem事件。

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

编辑:

根据Delphi帮助使用.OwnerDraw事件使其更容易,因为它提供了关于menuitem本身的信息。