建了三个Action, 一个右键菜单上三个菜单项分别对应了三个Action, 但是每个菜单项中间都一个分隔条, 故意让第二个Action不可见,
act1
-
act2
-
act3右键菜单第一次弹出
为
act1
-
-
act3
再弹一次就正确了
act1
-
act3(不要让我把分隔条也设上一个Action, 我不喜欢那样做)object Form1: TForm1
Left = 255
Top = 136
Width = 696
Height = 480
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PopupMenu = pm1
PixelsPerInch = 96
TextHeight = 13
object actlst1: TActionList
Left = 480
Top = 119
object act1: TAction
Caption = 'act1'
OnExecute = act1Execute
end
object act2: TAction
Caption = 'act2'
OnExecute = act2Execute
OnUpdate = act2Update
end
object act3: TAction
Caption = 'act3'
OnExecute = act3Execute
end
end
object pm1: TPopupMenu
Left = 188
Top = 95
object act21: TMenuItem
Action = act1
end
object N1: TMenuItem
Caption = '-'
end
object act22: TMenuItem
Action = act2
end
object N2: TMenuItem
Caption = '-'
end
object act31: TMenuItem
Action = act3
end
end
end
//---------
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ActnList, Menus;type
TForm1 = class(TForm)
actlst1: TActionList;
pm1: TPopupMenu;
act1: TAction;
act2: TAction;
act3: TAction;
act21: TMenuItem;
act22: TMenuItem;
act31: TMenuItem;
N1: TMenuItem;
N2: TMenuItem;
procedure act1Execute(Sender: TObject);
procedure act2Execute(Sender: TObject);
procedure act3Execute(Sender: TObject);
procedure act2Update(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.act1Execute(Sender: TObject);
begin
ShowMessage('1');
end;procedure TForm1.act2Execute(Sender: TObject);
begin
ShowMessage('2');
end;procedure TForm1.act3Execute(Sender: TObject);
begin
ShowMessage('3');
end;procedure TForm1.act2Update(Sender: TObject);
begin
with Sender as TAction do Visible := False;
end;end.
act1
-
act2
-
act3右键菜单第一次弹出
为
act1
-
-
act3
再弹一次就正确了
act1
-
act3(不要让我把分隔条也设上一个Action, 我不喜欢那样做)object Form1: TForm1
Left = 255
Top = 136
Width = 696
Height = 480
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PopupMenu = pm1
PixelsPerInch = 96
TextHeight = 13
object actlst1: TActionList
Left = 480
Top = 119
object act1: TAction
Caption = 'act1'
OnExecute = act1Execute
end
object act2: TAction
Caption = 'act2'
OnExecute = act2Execute
OnUpdate = act2Update
end
object act3: TAction
Caption = 'act3'
OnExecute = act3Execute
end
end
object pm1: TPopupMenu
Left = 188
Top = 95
object act21: TMenuItem
Action = act1
end
object N1: TMenuItem
Caption = '-'
end
object act22: TMenuItem
Action = act2
end
object N2: TMenuItem
Caption = '-'
end
object act31: TMenuItem
Action = act3
end
end
end
//---------
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ActnList, Menus;type
TForm1 = class(TForm)
actlst1: TActionList;
pm1: TPopupMenu;
act1: TAction;
act2: TAction;
act3: TAction;
act21: TMenuItem;
act22: TMenuItem;
act31: TMenuItem;
N1: TMenuItem;
N2: TMenuItem;
procedure act1Execute(Sender: TObject);
procedure act2Execute(Sender: TObject);
procedure act3Execute(Sender: TObject);
procedure act2Update(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.act1Execute(Sender: TObject);
begin
ShowMessage('1');
end;procedure TForm1.act2Execute(Sender: TObject);
begin
ShowMessage('2');
end;procedure TForm1.act3Execute(Sender: TObject);
begin
ShowMessage('3');
end;procedure TForm1.act2Update(Sender: TObject);
begin
with Sender as TAction do Visible := False;
end;end.
你应该放在PopupMenuPopup里面
我跟踪了一下Delphi的源码,其实问题不在Delphi,而在于你的代码。也就是说,问题在于TAction.Update事件到底什么时候激发的问题。在Delphi的内部,InternalRethinkLines方法被用来处理重复分隔条的显示问题。当上下文菜单被激活的时候,将会执行TMenu.Popup方法,在Popup方面内部,InternalRethinkLines被调用用来处理分隔条,请注意:
此时LZ的子菜单仍然Visible=True, 于是InternalRethinkLines方法什么也没做。然后Popup方法调用Win32API函数TrackPopupMenu执行菜单的绘制……绘制完毕在菜单显示前,Dephi做了一些手脚,于是调用了每个菜单的InitiateAction方法,最后调用了LZ的Action的Update方法。虽然LZ已经把Visible设置成False,但分隔条却并没有隐藏,于是还是显示了出来。下一次调用的时候,InternalRethinkLines方法注意到有两个重复的分隔条,于是隐藏了最下面的一个,菜单显示出来之后正常了。根据以上的流程,LZ要隐藏菜单条的显示,最好的办法是放到其它的方法中,最好的地方是Popup菜单的OnPopup事件中来处理。
procedure TFormMain.act2Update(Sender: TObject);
begin
with Sender as TAction do Visible := not Visible; pm1.Items.RethinkLines;
end;修改menus单元(拷贝到项目文件夹下)
function TMenuItem.RethinkLines: Boolean;
begin
Result := InternalRethinkLines(True);
if Result then
begin
RebuildHandle;
MenuChanged(True);
end;
end;