是这样的,我开发一个小程序,根据用户权限动态生成功能菜单。但我发现在一个奇怪的问题。如果我在一个静态的菜单里的OnClick里写 FrmMain.Caption := '你好'; 也就是说点击这个菜单,把主窗体的标题栏文字改变成 你好 二个字。执行以后,主窗体标题确实变成了 你好 二个字。但是如果我把动态生成的菜单的OnClick事件指向一个我自定义的过程时,也就是说点击动态生成的菜单的时候去执行我写的一个过程。这个过程里也只有一句句语 FrmMain.Caption := '你好'; 代码确实执行了,但窗体标题栏一点没变。我继续实验,把过程里的代码改成 FrmMain.Panel1.Visible := false; 希望执行后,窗体里的一个panel变为不可见。但代码确实执行了,可是那个Panel依然可见。不知道为什么。在静态菜单里执行这个代码全都好用,动态的就不行。谁知道是什么问题呢?代码如下://动态生成菜单
sMenuItem:= TMenuItem.Create(FrmMain);
sMenuItem.Name := 'MyMenu';
sMenuItem.Caption := '动态菜单';
sMenuItem.Tag := 1;
sMenuItem.OnClick := MyClick; //设置菜单的OnClick事件
MainMenu.Items.Add(sMenuItem);//MyClick过程
procedure TFrmMain.MyClick(Sender: Tobject);
begin
self.Caption := '你好';
end;
sMenuItem:= TMenuItem.Create(FrmMain);
sMenuItem.Name := 'MyMenu';
sMenuItem.Caption := '动态菜单';
sMenuItem.Tag := 1;
sMenuItem.OnClick := MyClick; //设置菜单的OnClick事件
MainMenu.Items.Add(sMenuItem);//MyClick过程
procedure TFrmMain.MyClick(Sender: Tobject);
begin
self.Caption := '你好';
end;
MainMenu.Items.Add(sMenuItem);
sMenuItem.OnClick := MyClick; //设置菜单的OnClick事件 两句调一下位置看看
begin
self.Caption := '你好';
end;//动态生成菜单
sMenuItem:= TMenuItem.Create(FrmMain);
sMenuItem.Name := 'MyMenu';
sMenuItem.Caption := '动态菜单';
sMenuItem.Tag := 1;
sMenuItem.OnClick := ActionFunctionMenuClickExecute; //设置菜单的OnClick事件
MainMenu.Items.Add(sMenuItem);
这样写也不行。ActionFunctionMenuClick 是我建立的一个action
而且我在 self.caption := '你好'; 后面又加了一句 showMessage(self.Caption); 弹出的Message竟然是 你好。
说明caption确实是改变了。但标题栏的文字就是没变化。
我用的是delphi7,你的是多少?
你在self.caption := '你好';后加一句FrmMain.Repaint;试试
//参数 MenuItem 指在哪个菜单上新增子菜单,如果是在MainMenu上新增,则传nil
function setUserFunctionMenuFromCache(MainMenu:TMainMenu; MenuItem: TMenuItem): Integer;
var
pMenuCaption : String; //当前父菜单名称
sMenuCaption : String; //当前子菜单名称
pMenuItem : TMenuItem; //当前父结点
sMenuItem : TMenuItem; //当前子结点
recordCount : Integer; //子结点个数
i: Integer; //临时循环变量
recordList:TList; //存放子结点的LIST
begin
recordList := TList.Create;
pMenuItem := MenuItem;
//判断是否指定了树根,如果没指定则取权限树的最底层根结点
if(pMenuItem = nil) then
begin
pMenuCaption := '-'; //没有指定树根
end
else
begin
pMenuCaption := pMenuItem.caption; //指定了树根
end; try
//取当前父结点的所有子结点,并存放到recordList里
For i:=0 To FrameConst.C_SYSFUNCTION_LIST_OF_CURRENT_USER.Count-1 do //FrameConst.C_SYSFUNCTION_LIST_OF_CURRENT_USER 这是一个List里面存放的是当前用户拥有的功能编号
begin
if(TSysFunctionVO(FrameConst.C_SYSFUNCTION_LIST_OF_CURRENT_USER[i]).getPFunctionName = pMenuCaption) then
begin
recordList.Add(FrameConst.C_SYSFUNCTION_LIST_OF_CURRENT_USER[i]);
end;
end;
recordCount := recordList.Count;
//把所有子结点添加到父结点上
if(recordCount > 0) then
begin
If(MenuItem <> nil) then //如果存在子菜单,则去掉父菜单的onclick事件
begin
MenuItem.OnClick := nil;
end; for i:=0 to recordCount-1 do
begin
sMenuCaption := TSysFunctionVO(recordList[i]).getFunctionName; //取子结点的名称
sMenuItem:= TMenuItem.Create(FrmMain);
sMenuItem.Name := TSysFunctionVO(recordList[i]).getFunctionCode;// DbKeyGenerator.getGuidString;
sMenuItem.Caption := sMenuCaption;
sMenuItem.Tag := 1;
If(MenuItem = nil) then
begin
MainMenu.Items.Add(sMenuItem);
end else begin
sMenuItem.ImageIndex := TSysFunctionVO(recordList[i]).getImgIndex16; //设置子结点的图标
sMenuItem.OnClick := FrmMain.FunctionMenuClick;//设置OnClick事件
MenuItem.Add(sMenuItem);
end;
//继续查找新添加上的子结点的再下一级的子结点 此处递归调用
setUserFunctionMenuFromCache(MainMenu, sMenuItem);
end;
end;
recordList.Free;
recordList := nil;
result := recordCount;
Except
on e:Exception do
Begin
TLogManager.saveToLog('function setUserMenuFunctionFromCache(MainMenu:TMainMenu; MenuItem: TMenuItem): Integer;',
TLogManager.LOG_LEVEL_DEBUG,
'从缓存中读取用户权限生成动态菜单时发生异常',
e.Message); raise Exception.Create(e.Message);
End;
End;
end;
//动态菜单OnClick调用的过程
procedure TFrmMain.FunctionMenuClick(Sender: Tobject);
begin
self.caption := '你好';
end;//在主窗体里调用动态生成菜单的方法
setUserFunctionMenuFromCache(self.MainMenu, nil);
FrmMain.Repaint试试
如果确定了,FrmMain.Caption 已经是 '你好'
Repaint一下应该就可以的
sMenuItem:= TMenuItem.Create(FrmMain);
sMenuItem.Name := 'MyMenu';
sMenuItem.Caption := '动态菜单';
sMenuItem.Tag := 1;
sMenuItem.OnClick := MyClick; //设置菜单的OnClick事件
self.MainMenu.Items.Add(sMenuItem); <-- 这里如果写成 FrmMain.MainMenu.Items.Add(sMenuItem); 就不会出现动态创建的菜单//MyClick过程
procedure TFrmMain.MyClick(Sender: Tobject);
begin
self.Caption := '你好';
end;
sMenuItem:= TMenuItem.Create(FrmMain);
sMenuItem.Name := 'MyMenu';
sMenuItem.Caption := '动态菜单';
sMenuItem.Tag := 1;
self.MainMenu.Items.Add(sMenuItem); <-- 这里如果写成 FrmMain.MainMenu.Items.Add(sMenuItem); 就不会出现动态创建的菜单 这里的self应该就是FrmMain,但是写 self.MainMenu.Items.Add(sMenuItem); 就可以显示出来动态创建的菜单,写成
FrmMain.MainMenu.Items.Add(sMenuItem); 就显示不出来。到底有什么不同呢?
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls;type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
Button1: TButton;
procedure ss(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementationuses unit2;{$R *.dfm}procedure TForm1.ss(Sender: TObject);
begin
showmessage('³É¹¦');
end;procedure TForm1.Button1Click(Sender: TObject);
begin
AddNewSM(self,MainMenu1,'adsf','fds',0);
end;end.unit Unit2;interfaceuses Windows, Forms, Menus, unit1; procedure AddNewSM(F: TForm1; P: TMainMenu; Mname: ShortString;MStr: ShortString; Mindex: SmallInt);implementation procedure AddNewSM(F: TForm1; P: TMainMenu; Mname: ShortString;MStr: ShortString; Mindex: SmallInt);
var
NMI: TMenuItem;
begin
NMI:= TMenuItem.Create(nil);
NMI.Name:= Mname;
NMI.Caption:= MStr;
NMI.OnClick:= F.ss;
P.Items.Add(NMI);
end;end.
我的试验:
procedure TFrmMain.test;
var
sMenuItem, sMenuItem2: TMenuItem;
begin
//动态生成菜单
sMenuItem:= TMenuItem.Create(FrmMain);
sMenuItem.Name := 'MyMenu';
sMenuItem.Caption := '动态菜单';
sMenuItem.Tag := 1;
frmMain.MainMenuMain.Items.Add(sMenuItem); //1
self.MainMenuMain.Items.Add(sMenuItem); //2
frmMain.MainMenuMain.Items.Add(sMenuItem); //3
end;procedure TFrmMain.FormShow(Sender: TObject);
begin
test;
end;
在我这里,注释1 不显示, 注释2和3都正常显示。到底怎么回事呢?
是我的不好,我检讨。我这句 Application.CreateForm(TFrmMain, FrmMain); 竟然写了二次。晕了。不好意思。