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

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大侠,我把动态生成菜单也是用您的
里面的代码比较容易懂,但是这句
QueryDetail.Filter:=format('ID=%d',QueryMain.FieldByName('MainID').AsInteger);
我不太懂,而且我运行的时候出错
错误为:
[Error] MMain.pas(208): There is no overloaded version of 'Format' that can be called with these arguments

我的主菜单有唯一的索引就是MainID

我想值得提出的是,我的子菜单没有唯一的索引
需要把字段 ID 和 AuthID(与权限表相关连) 才能确定子菜单中的 data1

您的菜单中我没有看见子菜单插在主菜单是那个位置
这句话的功能是不是把MainID 和ID 中相同的记录屏蔽
QueryDetail.Filter:=format('ID=%d',[QueryMain.FieldByName('MainID').AsInteger]);
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
不好意思,要加中括号:
QueryDetail.Filter:=format('ID=%d',[QueryMain.FieldByName('MainID').AsInteger]);
相当于
QueryDetail.Filter:='ID='+QueryMain.FieldByName('MainID').AsString);

只是传参数的一种方式,如果参数多的话比较方便
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
那你就在下面改改,我不知道你具体的数据结构,只是大概写了个意思:
Qy_detail.Close;
Qy_detail.SQL.Text:=format('select * from Menu02 a inner join [登录用户权限表] b on(a.XX=b.XX and a.XX=b.XX……) where userID=''%s'' order by ID,AhtuID',[登录用户ID]);
Qy_detail.Open;
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
plenilune168大侠,这样比较直接
这个是我写的动态菜单,而且要动态弹出窗体的代码
等下我把我所以的数据表发给你
unit MMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, DB, ADODB, Menus, ComCtrls, MLogin, MUserManage,
MAuthority, MLog, MDM_Main;

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

TFunLoadObject=class(TObject)
FormName:String;
Fun:TFunLOad;
end;


TMain = class(TForm)
StatusBar1: TStatusBar;
MainMenu1: TMainMenu;
QueryMenu: TADOQuery;
QueryMenu1: TADOQuery;
Timer1: TTimer;
QueryMain: TADOQuery;
QueryDetail: TADOQuery;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject
var Action: TCloseAction);
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
FormShowFunArr:TStrings
//调用方法数组
procedure Form_Show_Usermanage
//用户管理
procedure Form_Show_Authority
//权限管理
procedure Form_Add(FormName:string
Fun:TFunLoad);//增加窗体调用方法
// procedure Form_Load(FormName:string)
overload
//根据FormName调用模块
procedure Form_Load(Index:integer)
//根据序号调用模块
procedure Form_Clear;
procedure DoMenuClick(Sender: TObject)
//清除窗体调用方法

// procedure FrmNew(Sender:TObject);
{ Public declarations }
end;

var
Main: TMain;
NewParItem,NewChildItem: TMenuItem;
J,K:String;

implementation

{$R *.dfm}


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

end;

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

end;

procedure TMain.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 Tmain.Form_Load(Index:integer);
var FunLoadObject:TFunLoadObject;
begin //根据序号调用模块
FunLoadObject:=TFunLoadObject(FormShowFunArr.Objects[Index]);
if Assigned(FunLoadObject.Fun) then FunLoadObject.Fun();
end;


{procedure TMain.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 TMain.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 TMain.DoMenuClick(Sender:TObject);
var
I:integer;
begin
I:=TMenuItem(Sender).Tag;
Form_Load(I);
end;




{procedure TMain.FrmNew(Sender: TObject);
//单击主菜单中的某个子菜单,弹出相应的子菜单
begin
QueryMain.Close;
QueryMain.SQL.Clear;
QueryMain.SQL.Add('select data1,formName 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 ');
QueryMain.Open;
QueryMain.Active:=true;
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;
if caption='查询日志' then
with TLog.Create(nil) do
try
ShowModal;
finally
Free;
end;
if caption='系统退出' then
try
application.Terminate;
finally
end;

end;
end;
}


procedure TMain.FormShow(Sender: TObject);
var
I,s:integer;
//将符合条件的记录(包括用户名,权限),添加到MainMenu的Item上。
begin
//调出全部主菜单
StatusBar1.Panels[0].Text := ' 用户名:'+Login.EdtUser.Text;
QueryMain.Close;
QueryMain.SQL.Clear;
QueryMain.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''');
QueryMain.Active:=true;

//调出全部子菜单
QueryDetail.Close;
QueryDetail.SQL.Clear;
QueryDetail.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 ');
QueryDetail.Active:=true;

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

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

//循环增加子菜单
QueryDetail.First;
while not QueryDetail.Eof do
begin
NewChildItem:=TMenuItem.Create(self);
NewChildItem.Caption:=QueryDetail.FieldByName('data1').AsString;
NewChildItem.Add(NewChildItem);
NewChildItem.Tag:=FormShowFunArr.IndexOf(QueryDetail.fieldByName('FormName').AsString);
NewChildItem.OnClick:=DoMenuClick;
QueryDetail.Next;
end;
QueryMain.Next;

end;
// end;

{
QueryMain.Close;
QueryMain.SQL.Clear;
//Login.QueryAuth.SQL.Add('select data from Menu01');
QueryMain.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''');
QueryMain.SQL.Add('order by MainID');
QueryMain.Active:=true;
while not QueryMain.Eof do
begin
NewItem:=TmenuItem.Create(self);
NewItem.Caption:=QueryMain.FieldValues['data'];
MainMenu1.Items.Add(NewItem);
NewItem.AutoHotkeys:=maManual;
QueryMain.Next;
end;


//将符合条件的记录(包括用户名,权限),添加到MainMenu子菜单栏上。
QueryMain.Close;
QueryMain.SQL.Clear;
QueryMain.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 ');
QueryMain.Open;
QueryMain.Active:=true;

for i:=1 to QueryMain.RecordCount do
begin
QueryMain.Locate('data1',Trim(QueryMain.FieldValues['data1']),[]);
s:=QueryMain.FieldValues['ID'];
NewItem:=TMenuItem.Create(self);
NewItem.Caption:=Trim(QueryMain.FieldValues['data1']);
MainMenu1.Items[s-1].Add(NewItem);
//NewItem.OnClick:=FrmNew;
NewItem.Tag:=FormShowFunArr.IndexOf(QueryMain.FieldValues['FormName']);
NewItem.OnClick:=DoMenuClick;
QueryMain.Next;
end;}
end;

procedure TMain.FormClose(Sender: TObject
var Action: TCloseAction);
begin
application.Terminate;
end;

procedure TMain.Timer1Timer(Sender: TObject);
begin
StatusBar1.Panels[1].Text:=' 时间:'+timetostr(time);
end;

procedure TMain.FormCreate(Sender: TObject);
begin
FormShowFunArr:=TStringList.Create
//建立调用方法数组

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

end.
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
用户表(User1) 主菜单表(Menu01)
UserID Password MainID data
abc 123 1 A
mis 456 2 B
3 C
子菜单表(Menu02)
ID AuthID data1 FormName
1 01 A1 Usermanage
1 02 A2 Auheority
2 01 B1 dddd
2 02 B2 ddddd
3 01 C1 ddddddd
3 02 C2 ddddddddd
3 03 C3 ddddddddddd

权限表(AuthTable)
qxID qxAuthID AuthUser Authority
1 01 abc y
1 02 abc y
3 02 abc y

我的任务是:不同的用户在根据权限表的Authority,动态的在主窗体中生成相应的菜单,当单击菜单的时候,弹出相应的菜单窗体.

您所说的
QueryDetail.Filter:=format('ID=%d',[QueryMain.FieldByName('MainID').AsInteger]);
是不是下面这句话中的MainID='''+Edit1.text+'''
Query.sql.add('select * from Menu01 as a,Menu02 as b where a.MainID=b.ID and MainID='''+Edit1.text+'''');
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
您的菜单中我没有看见子菜单插在主菜单是那个位置
这句话的功能是不是把MainID 和ID 中相同的记录屏蔽
QueryDetail.Filter:=format('ID=%d',[QueryMain.FieldByName('MainID').AsInteger]);
--------------------------
filter是本地过滤,过滤出当前对应主数据集main的子数据集detail的记录,也就是说循环主数据集,然后里面嵌套循环子数据集,每循环一个主数据集(主菜单),就建议一个主菜单,然后根据id过滤出所有对应该主菜单记录的子菜单记录,循环这些子菜单记录同时建立对应主菜单的子菜单

上面的SQL查询应该一次性调用所有满足用户权限的所有的主菜单记录和子菜单记录,然后在本地循环过滤记录动态生成菜单,不用多次对调用数据库,提高效率
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
根据你的数据结构写的动态生成菜单的代码,可能表之间的关系不是很正确,你再看看吧:

附:表authtable中其实已经有userID(即authUser)了,子菜单的查询SQL就不用连接表User1了。

var NewParItem,NewChildItem:TMenuItem;
begin
//调出全部主菜单
Qy_main.Close;
Qy_main.SQL.Text:='select * from Menu01'

Qy_main.Open;

//调出全部子菜单
Qy_detail.Close;
Qy_detail.SQL.Text:=format('select distinct a.* from Menu02 a inner join AuthTable b on(a.AuthID=b.qxAuthID) where b.AuthUser=''%s'' and b.authority=''Y'' order by ID,AhtuID',[Login.EdtUser.Text]);
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_detail.FieldByName('data1').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大侠您对我的提示~~~~我再试试!!~~~[:)]
这是您添加子菜单的代码
NewParItem.Add(NewChildItem);
这个好象没有说明插在那个位置(因为是二级菜单)
老是出错
NewParItem.Items.add(NewChildItem);
这样好象又不可以
您看有什么好办法?
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
plenilune168大侠,我终于把动态菜单搞出来了!真的非常感谢您![:)]
不过我现在朝动态窗体进军。
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
你现在不是动态窗体么?
你现在的窗体都是要在设计期事先做好的,根本就没有动态的意义。除非是所有窗体都是同一个窗体类,根据参数设定生成不同界面的窗体实例才算时动态,或者说你每个模块都是通过动态增加一个DLL来实现,新设计一个模块不用重新编译主Exe。
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
NewParItem.Add(NewChildItem);
应该是
NewParItem.Items.Add(NewChildItem);
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
plenilune168大侠,你说的这个问题我也考虑过,您所说的
你每个模块都是通过动态增加一个DLL来实现,新设计一个模块不用重新编译主Exe。
关于dll我还不懂,您可以介绍相关的知识或者网站吗?谢谢了!
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
这个涉及的东西就比较麻烦了,你先巩固目前的把,那种方式也是比较大型的系统才会考虑的,发布也没有那么方便,处理不好有些不太稳定。

网上搜索应该有很多相关资料的。
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
plenilune168大侠:
好的,我准备把这个问题截止您看可以吗?
您可以留给我您的邮箱号码吗?我们公司不准备上QQ,
以后我还有很读问题向您请教!!!~[:)][:)][:)]
我的邮箱号码是yi_1121@163.com[:)][:)][:)]
 
P

plenilune168

Unregistered / Unconfirmed
GUEST, unregistred user!
可以阿

我的邮箱 jason@windy.net.cn
 

雨竹

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢您了!~~~
 
顶部