delphi 通过TMenuItem OnClick事件隐藏TMainMenu,自定义VCL样式处于活动状态

liwlm1x9  于 2023-05-06  发布在  其他
关注(0)|答案(2)|浏览(171)

将TMainMenu放在表单上,并将此处理程序附加到某个TMenuItem。它将隐藏主菜单,但如果自定义Vcl样式处于活动状态则不会。

procedure TForm1.HideMenuClick(Sender: TObject);
begin
  Menu := nil;
  { raised exception class $C0000005 with message 'access violation at 0x0038f397: read of address 0x00000008'. }
end;

这将工作,但只有当延迟足够大时:

procedure TForm1.HideMenuClick(Sender: TObject);
begin
  TThread.ForceQueue(nil, procedure   
  begin
    Menu := nil
  end,
  20);
end;

有没有一种干净可靠的方法来做到这一点?
(Note:问题仅与TMainMenu及其OnClick事件有关,与移除菜单或其他控件的其他方法无关。)

编辑:

使用鼠标重现问题。如果使用键盘打开菜单并激活项,则单击'ForceQueue(nil,procedure开始Menu:= nil;end)’将足以避免访问冲突错误。如果菜单项是用键盘快捷键激活的,那么即使是简单的“Menu:= nil”也可以工作。

wpcxdonn

wpcxdonn1#

没有任意超时,而且看起来没有错误,至少在 Delphi 中是这样。但我怀疑有人会把这称为一个干净的解决方案。

procedure TForm1.HideMenuClick(Sender: TObject);
begin
  TThread.ForceQueue(nil, procedure
  begin
    TThread.ForceQueue(nil, procedure
    begin
      Menu := nil;
    end);
  end);
end;
pvcm50d1

pvcm50d12#

这一个对我来说不使用计时器或线程:

type
  TForm150 = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    HideMenu1: TMenuItem;
    procedure HideMenu1Click(Sender: TObject);
  private
    { Private declarations }
    PROCEDURE   HideMenu(VAR Msg : TMsg); MESSAGE WM_USER+1;
  public
    { Public declarations }
  end;

var
  Form150: TForm150;

implementation

{$R *.dfm}

procedure TForm150.HideMenu(var Msg: TMsg);
begin
  Menu:=NIL
end;

procedure TForm150.HideMenu1Click(Sender: TObject);
begin
  PostMessage(Handle,WM_USER+1,0,0)
end;

PostMessage允许TMenuItem.OnClick事件在尝试隐藏TMainMenu之前完成。

相关问题