老问题,新技术,关于动态窗体的问题 ( 积分: 100 )

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
问题1:这个我是做的动态窗体,但是我觉得比较苯,是响应caption才创建窗体,我在数据库中有一列是FormName,是显示窗体的名字,例如:Usermanage,Authority...我想不用响应caption才创建窗体,要从数据库中直接调用FormName.请各位大侠帮帮小弟!!谢谢了!
我的数据表为:
ID AuthID data1 FormName
1 01 用户管理 Usermanage
1 02 权限管理 Authority

With Sender as TmenuItem do
begin
if caption='用户管理' then
with TUsermanage.Create(nil) do
try
ShowModal;
finally
Free;
end;
if caption='权限管理' then
with TAuthority.Create(nil) do
try
ShowModal;
finally
Free;
end;

主菜单表(Menu01) 子菜单表(Menuo2)
MainID data ID AuthID data1 FormName
1 系统管理 1 01 用户管理 Usermanage
2 B 1 02 权限管理 Authority
3 C 2 01 B1 Log
2 02 B2 Mian1

问题2:我的动态菜单是这样创建的,但是其中中间没有记录的时候,还是一样插进去,后面的依次这样,最后少了一个位置
看看能不能帮我改改这个变量 s ,请各位大侠帮帮小弟!!谢谢了!
procedure TMain.FormShow(Sender: TObject);
var
I,s:integer;
//将符合条件的记录(包括用户名,权限),添加到MainMenu的Item上。
begin
StatusBar1.Panels[0].Text := ' 用户名:'+Login.EdtUser.Text;
Login.QueryAuth.Close;
Login.QueryAuth.SQL.Clear;
//Login.QueryAuth.SQL.Add('select data from Menu01');
Login.QueryAuth.SQL.Add('select distinct data,MainId from User1 as a,Menu01 as b,Menu02 as c,authtable as d where a.UserId=d.authUser and c.authId=d.qxauthId and b.MainId=c.Id and d.qxID=b.MainId and UserId='''+Login.EdtUser.Text+''' and authority=''Y''');
Login.QueryAuth.SQL.Add('order by MainID');
Login.QueryAuth.Active:=true;
while not Login.QueryAuth.Eof do
begin
NewItem:=TmenuItem.Create(self);
NewItem.Caption:=Login.QueryAuth.FieldValues['data'];
MainMenu1.Items.Add(NewItem);
NewItem.AutoHotkeys:=maManual;
Login.QueryAuth.Next;
end;


//将符合条件的记录(包括用户名,权限),添加到MainMenu子菜单栏上。
Login.QueryAuth.Close;
Login.QueryAuth.SQL.Clear;
Login.QueryAuth.SQL.Add('select * from User1 as a,Menu01 as b,Menu02 as c,authtable as d where a.UserId=d.authUser and c.authId=d.qxauthId and b.MainId=c.Id and d.qxid=b.mainID and UserId='''+Login.EdtUser.Text+''' and authority=''Y'' order by qxID,qxAuthID ');
Login.QueryAuth.Open;
Login.QueryAuth.Active:=true;

for i:=1 to Login.QueryAuth.RecordCount do
begin
Login.QueryAuth.Locate('data1',Trim(Login.QueryAuth.FieldValues['data1']),[]);
s:=Login.QueryAuth.FieldValues['ID'];
NewItem:=TMenuItem.Create(self);
NewItem.Caption:=Trim(Login.QueryAuth.FieldValues['data1']);
MainMenu1.Items[s-1].Add(NewItem);
NewItem.OnClick:=FrmNew;
Login.QueryAuth.Next;
end;
end;
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
问题1:这个我是做的动态窗体,但是我觉得比较苯,是响应caption才创建窗体,我在数据库中有一列是FormName,是显示窗体的名字,例如:Usermanage,Authority...我想不用响应caption才创建窗体,要从数据库中直接调用FormName.请各位大侠帮帮小弟!!谢谢了!
我的数据表为:
ID AuthID data1 FormName
1 01 用户管理 Usermanage
1 02 权限管理 Authority

With Sender as TmenuItem do
begin
if caption='用户管理' then
with TUsermanage.Create(nil) do
try
ShowModal;
finally
Free;
end;
if caption='权限管理' then
with TAuthority.Create(nil) do
try
ShowModal;
finally
Free;
end;

主菜单表(Menu01) 子菜单表(Menuo2)
MainID data ID AuthID data1 FormName
1 系统管理 1 01 用户管理 Usermanage
2 B 1 02 权限管理 Authority
3 C 2 01 B1 Log
2 02 B2 Mian1

问题2:我的动态菜单是这样创建的,但是其中中间没有记录的时候,还是一样插进去,后面的依次这样,最后少了一个位置
看看能不能帮我改改这个变量 s ,请各位大侠帮帮小弟!!谢谢了!
procedure TMain.FormShow(Sender: TObject);
var
I,s:integer;
//将符合条件的记录(包括用户名,权限),添加到MainMenu的Item上。
begin
StatusBar1.Panels[0].Text := ' 用户名:'+Login.EdtUser.Text;
Login.QueryAuth.Close;
Login.QueryAuth.SQL.Clear;
//Login.QueryAuth.SQL.Add('select data from Menu01');
Login.QueryAuth.SQL.Add('select distinct data,MainId from User1 as a,Menu01 as b,Menu02 as c,authtable as d where a.UserId=d.authUser and c.authId=d.qxauthId and b.MainId=c.Id and d.qxID=b.MainId and UserId='''+Login.EdtUser.Text+''' and authority=''Y''');
Login.QueryAuth.SQL.Add('order by MainID');
Login.QueryAuth.Active:=true;
while not Login.QueryAuth.Eof do
begin
NewItem:=TmenuItem.Create(self);
NewItem.Caption:=Login.QueryAuth.FieldValues['data'];
MainMenu1.Items.Add(NewItem);
NewItem.AutoHotkeys:=maManual;
Login.QueryAuth.Next;
end;


//将符合条件的记录(包括用户名,权限),添加到MainMenu子菜单栏上。
Login.QueryAuth.Close;
Login.QueryAuth.SQL.Clear;
Login.QueryAuth.SQL.Add('select * from User1 as a,Menu01 as b,Menu02 as c,authtable as d where a.UserId=d.authUser and c.authId=d.qxauthId and b.MainId=c.Id and d.qxid=b.mainID and UserId='''+Login.EdtUser.Text+''' and authority=''Y'' order by qxID,qxAuthID ');
Login.QueryAuth.Open;
Login.QueryAuth.Active:=true;

for i:=1 to Login.QueryAuth.RecordCount do
begin
Login.QueryAuth.Locate('data1',Trim(Login.QueryAuth.FieldValues['data1']),[]);
s:=Login.QueryAuth.FieldValues['ID'];
NewItem:=TMenuItem.Create(self);
NewItem.Caption:=Trim(Login.QueryAuth.FieldValues['data1']);
MainMenu1.Items[s-1].Add(NewItem);
NewItem.OnClick:=FrmNew;
Login.QueryAuth.Next;
end;
end;
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
建立一个对象数组,用于存储各模块调用方法的指针

Type
TMainForm=class(TForm)
……
public
FormShowFunArr:TStrings
//调用方法数组
procedure Form_Show_Usermanage
//用户管理
procedure Form_Show_Authority
//权限管理
……
procedure Form_Load(FormName:string)
overload
//根据FormName调用模块
procedure Form_Load(Index:integer)
overload
//根据序号调用模块
end;
……

procedure TMainForm.Form_Show_Usermanage;
begin //调用方法:用户管理
with TUsermanage.Create(nil) do
try
ShowModal;
finally
Free;
end

end;

procedure TMainForm.Form_Show_Authority

begin //调用方法:权限管理
with TAuthority.Create(nil) do
try
ShowModal;
finally
Free;
end

end;

……

procedure TMainForm.Form_Load(FormName:string)

type TMyFun=procedure of Object;
var MyFun:TMyFun;
i:integer;
begin //根据FormName调用模块
i:=FormShowFunArr.IndexOf(FormName);
if i>=0 then
begin
MyFun:=TMyFun(FormShowFunArr.Objects);
if Assigned(MyFun) then MyFun();
end;
end;

procedure TMainForm.Form_Load(Index:integer)

type TMyFun=procedure of Object;
var MyFun:TMyFun;
begin //根据序号调用模块
MyFun:=TMyFun(FormShowFunArr.Objects[Index]);
if Assigned(MyFun) then MyFun();
end;

procedure TMainForm.FormCreate(Sender:TObject)

begin //窗体初始化
FormShowFunArr:=TStringList.Create
//建立调用方法数组

//把调用方法及其FormName入到调用方法数组
FormShowFunArr.AddObject('Usermanage',Self.Form_Show_Usermanage)
//用户管理
FormShowFunArr.AddObject('Authority',Self.Form_Show_Authority)
//权限管理
……
end;

procedure TMainForm.FormClose(Sender:TObject
Action:……)

begin //窗体释放
FreeAndNil(FormShowFunArr)
//释放调用方法数组
end;

---------------------------------------------------------------------
则以上可以利用 Form_Load 分别通过 FormName 或者 Index 调用模块

(1)菜单项MenuItem动态建立的时候,可以把对应调用方法的数组Index存在对应的MenuItem的Tag属性中,所有动态生成的MenuItem的OnClick事件公用一个方法,里面根据Tag属性值调出对应的方法

//动态生成MenuItem中增加代码
FormName:=Query.FieldByName('XXX').AsString;
i:=FormShowFunArr.IndexOf(FormName);
MenuItem.Tag:=i;
MenuItem.onClick=DoMenuClick;

//MenuItem公共Click事件
procedure TMainForm.DoMenuClick(Sender:TObject);
var i:integer;
begin
i:=TMenuItem(Sender).Tag;
Form_Load(i)

end;

(2)或者生成的MenuItem就以FormName命名,点击事件根据MenuItem的名称调用对应方法

//动态生成MenuItem中增加代码
FormName:=Query.FieldByName('XXX').AsString;
MenuItem.Name:='MI_'+FormName;
MenuItem.onClick=DoMenuClick;

//MenuItem公共Click事件
procedure TMainForm.DoMenuClick(Sender:TObject);
var FormName:string;
begin
FormName:=TMenuItem(Sender).Name;
Delete(FormName,1,3)
//删除前面的MI_
Form_Load(FormName)

end;
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢plenilune168给我的回答,我先把程序写上去运行看看!
我还想请问plenilune168大侠
由于我是初学者
代码
FormName:=Query.FieldByName('XXX').AsString;
中的XXX是代表什么
是不是代表 列名:FormName
 
B

bbscom

Unregistered / Unconfirmed
GUEST, unregistred user!
這樣做用戶權限管理不太方便,我常用自定義數據結構為變量;然後將數據放入,打開的時候再對這個變量判斷即可。
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
对阿,你数据库存储FormName的字段。如果从数据库生成MenuItem你自己写,只要插入我上面写的一段

以上程序直接写的,没有调试过,看懂意思你自己调试
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢plenilune168对我的帮助。
请问下FormCreate 和FormShow 是不是在一般情况下可以等价使用?

我想请问下bbscom,您说定义数据结构,您所说的是线性表、堆栈或者还是队列???
能否象plenilune168一样送我些源代码,毕竟我学习delphi才2个月。
 
B

Beyondbill

Unregistered / Unconfirmed
GUEST, unregistred user!
FormCreate事件在FormShow事件之前发生,一般情况下对于一些初始对象的创建还有一些变量的初始化最好是放在FormCreate,而对于组件的排列或者状态刷新之类的代码放在FormShow
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
实例化也就是执行 Create 后马上触发 FormCreate
调用show/showmodel,开始显示之前,触发 FormShow

如果你实例化窗体后马上执行show,或者是说窗体设计期 Visible=true,或者是MDI子窗体,一般 FormCreate 和 FormShow 事件是差不多的。

注意,FormShow 事件的时候窗体还没有真正show出来的
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
plenilune168让你久等了,刚刚经理叫我们拟订年度计划

首先您说
如果从数据库生成MenuItem你自己写,只要插入我上面写的一段。

从数据库生成MenuItem是我自己写的,也是仿照别人的写的,我已经看懂了人家的意思,应该现在是属于我的东西了,但是您写的东西我有点看不懂

//动态生成MenuItem中增加代码
FormName:=Query.FieldByName('XXX').AsString;
i:=FormShowFunArr.IndexOf(FormName);
MenuItem.Tag:=i;
MenuItem.onClick=DoMenuClick;

//MenuItem公共Click事件
procedure TMainForm.DoMenuClick(Sender:TObject);
var i:integer;
begin
i:=TMenuItem(Sender).Tag;
Form_Load(i)

end;
你的程序有2段。我就想自己生成的时候按照我的条件生成

我的程序是这样
//将符合条件的记录(包括用户名,权限),添加到MainMenu子菜单栏上。
Login.QueryAuth.Close;
Login.QueryAuth.SQL.Clear;
Login.QueryAuth.SQL.Add('select * from User1 as a,Menu01 as b,Menu02 as c,authtable as d where a.UserId=d.authUser and c.authId=d.qxauthId and b.MainId=c.Id and d.qxid=b.mainID and UserId='''+Login.EdtUser.Text+''' and authority=''Y'' order by qxID,qxAuthID ');
Login.QueryAuth.Open;
Login.QueryAuth.Active:=true;

for i:=1 to Login.QueryAuth.RecordCount do
begin
Login.QueryAuth.Locate('data1',Trim(Login.QueryAuth.FieldValues['data1']),[]);
s:=Login.QueryAuth.FieldValues['ID'];
NewItem:=TMenuItem.Create(self);
NewItem.Caption:=Trim(Login.QueryAuth.FieldValues['data1']);
MainMenu1.Items[s-1].Add(NewItem);
NewItem.OnClick:=FrmNew;
Login.QueryAuth.Next;
end;
我认为里面的这个S,肯定有问题,S是插入在主菜单中位置,当我的第主菜单2个位置没有的时候,系统还是把第3个位置默认为第2个位置,后面的依此类推,到最后就少了一个位置。


当我把生成主菜单的条件改为:
Login.QueryAuth.SQL.Add('select data from Menu01');
Login.QueryAuth.SQL.Add('select distinct data,MainId from User1 as a,Menu01 as b,Menu02 as c,authtable as d where a.UserId=d.authUser and c.authId=d.qxauthId and b.MainId=c.Id and d.qxID=b.MainId and UserId='''+Login.EdtUser.Text+''' and authority=''Y''');
的时候就能满足我的功能
但是我不想看到的第2个位置在上面。
您看能怎样把我的第2个位置的内容去掉,而且不影响后面的位置。

我是这样想的,您看可以不,首先判断是否要不要第2个位置上面的内容,如果不存在的话,我的S不变,如果存在我的S就S:=S+1;
我试过了,好象不行,请plenilune168您给再给我些意见。
谢谢了!

最后我还想说的,我的位置不一定是第2个,很可能是多个中的某个,或者是多个中的多个
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
“如果从数据库生成MenuItem你自己写,只要插入我上面写的一段。”指的是:

for i:=1 to Login.QueryAuth.RecordCount do
begin
Login.QueryAuth.Locate('data1',Trim(Login.QueryAuth.FieldValues['data1']),[]);
s:=Login.QueryAuth.FieldValues['ID'];
NewItem:=TMenuItem.Create(self);
NewItem.Caption:=Trim(Login.QueryAuth.FieldValues['data1']);
MainMenu1.Items[s-1].Add(NewItem);
//NewItem.OnClick:=FrmNew
去掉,用下面的

//加在这里:Begin
NewItem.Tag:=FormShowFunArr.IndexOf(Login.QueryAuth.FieldValues['FormName'])
//把MenuItem对应的菜单数组的序号记录下来
NewItem.onClick=DoMenuClick;
//加在这里:End

Login.QueryAuth.Next;
end;

//采用这个MenuItem公共Click事件
procedure TMainForm.DoMenuClick(Sender:TObject);
var i:integer;
begin
i:=TMenuItem(Sender).Tag;
Form_Load(i)

end;
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
我另外写了一个动态生成菜单的代码

var NewParItem,NewChildItem:TMenuItem;
begin
//调出全部主菜单
Qy_main.Close;
Qy_main.SQL.Text:='select * from Menu01 order by MainID')
//如果有别的条件自己在这里加
Qy_main.Open;

//调出全部子菜单
Qy_detail.Close;
Qy_detail.SQL.Text:='select * from Menu02 order by ID,AhtuID'
//如果有别的条件自己在这里加
Qy_detail.Open;

while not Qy_main.Eof do
begin
//增加主菜单
NewParItem:=TMenuItem.Create(self);
NewParItem.Caption:=Qy_main.FieldByName('data').AsString;
MainMenu1.Items.Add(NewParItem);

//过滤出对应当前主菜单的子菜单项
Qy_detail.Filtered:=false;
Qy_detail.Filter:=format('ID=%d',Qy_main.FieldByName('MainID').AsInteger);
Qy_detail.Filtered:=true;

//循环增加子菜单
Qy_detail.First;
while not Qy_detail.Eof do
begin
NewChildItem:=TMenuItem.Create(self);
NewChild.Caption:=Qy_main.FieldByName('data').AsString;
NewParItem.Add(NewChildItem);
NewChildItem.Tag:=FormShowFunArr.IndexOf(Qy_detail.FieldByName('FormName').AsString)

NewChildItem.onClick=DoMenuClick;

Qy_detail.Next

end;

Qy_main.Next

end;
end;
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
plenilune168大侠,我用的是你的第2个方案。但是代码
procedure TMain.Form_Load(FormName:String);
type TMyFun=procedure of Object;
var
I:Integer;
MyFun:TMyFun;
begin
I:=FormShowFunArr.IndexOf(FormName);
if I>=0 then
begin
MyFun:=TMyFun(FormShowFunArr.Objects);
if Assigned(MyFun) then
MyFun();
end;
end;
中的 MyFun:=TMyFun(FormShowFunArr.Objects);这行错误
提示:[Error] MMain.pas(77): Invalid typecast
[Fatal Error] MMain.pas(7): Could not compile used unit 'MMain'
您看这是什么原因?
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
重新写了一个完整的例子,可以运行的

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
//窗体调用对象
TFunLoad=procedure of Object;

TFunLoadObject=class(TObject)
FormName:string;
Fun:TFunLoad;
end;

TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject
var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
FormShowFunArr:TStrings
//调用方法数组
procedure A;
procedure B;
procedure Form_Add(FormName:string
Fun:TFunLoad)
//增加窗体调用方法
procedure Form_Load(FormName:string)
overload
//根据FormName调用模块
procedure Form_Load(Index:integer)
overload
//根据序号调用模块
procedure Form_Clear
//清除窗体调用方法
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.A;
begin
showmessage('a');
end;

procedure TForm1.B;
begin
showmessage('b');
end;

procedure TForm1.Form_Add(FormName:string
Fun:TFunLoad);
var FunLoadObject:TFunLoadObject;
begin //增加窗体调用方法
FunLoadObject:=TFunLoadObject.Create;
FunLoadObject.FormName:=FormName;
FunLoadObject.Fun:=Fun;
FormShowFunArr.AddObject(FormName,FunLoadObject);
end;

procedure TForm1.Form_Clear;
var FunLoadObject:TFunLoadObject;
i:integer;
begin //清除窗体调用方法
for i:=0 to FormShowFunArr.Count-1 do
begin
FunLoadObject:=TFunLoadObject(FormShowFunArr.Objects);
FreeAndNil(FunLoadObject);
end;
FormShowFunArr.Clear;
end;

procedure TForm1.Form_Load(FormName:string);
var FunLoadObject:TFunLoadObject;
i:integer;
begin //根据FormName调用模块
i:=FormShowFunArr.IndexOf(FormName);
if i>=0 then
begin
FunLoadObject:=TFunLoadObject(FormShowFunArr.Objects);
if Assigned(FunLoadObject.Fun) then FunLoadObject.Fun();
end;
end;

procedure TForm1.Form_Load(Index:integer);
var FunLoadObject:TFunLoadObject;
begin //根据序号调用模块
FunLoadObject:=TFunLoadObject(FormShowFunArr.Objects[Index]);
if Assigned(FunLoadObject.Fun) then FunLoadObject.Fun();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin //窗体初始化
FormShowFunArr:=TStringList.Create
//建立调用方法数组

//把调用方法及其FormName入到调用方法数组
Form_Add('A',Self.A);
Form_Add('B',Self.B);
end;

procedure TForm1.FormClose(Sender: TObject
var Action: TCloseAction);
begin //窗体释放
Form_Clear;
FreeAndNil(FormShowFunArr);
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
Form_Load('a');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Form_Load('b');
end;

end.
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢plenilune168您对我的帮助!![:)]
我已经把你的程调式而且能够运行了,我看能不能实现我的功能。
 

雾锁长河

Unregistered / Unconfirmed
GUEST, unregistred user!
可不可以这样:
1.先在设计环境中创建所有菜单项。将所有需要权限控制的菜单项的visible设为false.
2.调用权限表,根据表中的相应权限设置对应的菜单visible为true.
3.上述的调用及显示过程放在form的onshow事件中。
我就是这样处理的。代码比较简单。菜单项的分隔可以根据某组菜单的某一项是否显示决定其是否显示。
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
雾锁长河:你好,你那样的设计我觉得不怎么好,因为
数据库设计范式
关系数据库设计之时是要遵守一定的规则的。尤其是数据库设计范式 现简单介绍1NF(第一范式),2NF(第二范式),3NF(第三范式)和BCNF,另有第四范式和第五范式留到以后再介绍。 在你设计数据库之时,若能符合这几个范式,你就是数据库设计的高手。
不知道大家同意不?
http://www.phpe.net/print.php?aid=340
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
plenilune168大侠:
不好意思,还要麻烦您
我单独运行你的程序可以
但是加上DoMenuClick这个的单击过程就出现问题
问题出现在Form_Load(I);
错误是:[Error] MMain.pas(120): There is no overloaded version of 'Form_Load' that can be called with these arguments
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
以下两个如果你只保留一个的话,定义部分后面的 Overload 关键字去掉

实际上你用第2个就可以了

procedure TForm1.Form_Load(FormName:string);
var FunLoadObject:TFunLoadObject;
i:integer;
begin //根据FormName调用模块
i:=FormShowFunArr.IndexOf(FormName);
if i>=0 then
begin
FunLoadObject:=TFunLoadObject(FormShowFunArr.Objects);
if Assigned(FunLoadObject.Fun) then FunLoadObject.Fun();
end;
end;

procedure TForm1.Form_Load(Index:integer);
var FunLoadObject:TFunLoadObject;
begin //根据序号调用模块
FunLoadObject:=TFunLoadObject(FormShowFunArr.Objects[Index]);
if Assigned(FunLoadObject.Fun) then FunLoadObject.Fun();
end;
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
非常感谢您对我的答复,我先去试试!
能运行了,但是还有错误,是我菜单的错误,您看是不是把是生成菜单是代码全部换成您的代码?
 
顶部