Delphi MDI多文档架构几个问题解决

来源:互联网 发布:如何成立软件工作室 编辑:程序博客网 时间:2024/06/06 17:41

1.关于登录窗口(Login):

很多时候我们在做开发delphi的MDIform时,常常因为要做进去Login一个正常的登录窗口,平常做Login的project代码如下:
只有Login登录成功了时候,才会建立起frm_Main窗体,这是正常不用MDI框架的正常登录与主窗体切换。

Application.CreateForm(Tfrm_Login, frm_Login);    if frm_Login.ShowModal = mrOK then //登录窗体关闭时返回了mrOK值,说明登录成功    begin      Application.CreateForm(Tfrm_Main, frm_Main);      frm_Main.ShowModal;    end;

现在问题是frm_Main是MDI主窗体,而delphi会把第一个CreateForm认定为MDI主窗体,而frm_Login的FormsTyle是fsNormal正常窗体。

如果按上面的代码的话,将导致“Cannot create form.No MDI forms are currently active."

解决方案:

既然delphi会把第一个CreateForm认定为MDI主窗体,那我们就把Application.CreateForm(Tfrm_Main,frm_Main);放在最前,project代码如下:

  Application.CreateForm(Tfrm_Main, frm_Main);  Application.CreateForm(Tfrm_Login, frm_Login);
这样的话执行后的第一个窗口不是Login 而是Main窗体,这时我们需要再Main窗体OnCreate事件中加进如下代码:
procedure Tfrm_Main.FormCreate(Sender: TObject);begin  with Tfrm_Login.Create(Self) do ShowModal;end;

加上这句后的,执行后的第一个窗口就是Login,第一个问题解决。


2.关于MDI子窗体最小化,与窗体恢复:

在做MDI窗体的时候,点击菜单按钮呼出第一个MDI子窗体。对MDI子窗体最小化后,我们会看到窗体在主窗体的左下角。

而当我们往往再次点击菜单那个按钮不是再次重新建立一个窗体,而是对原有窗体进行呼出选择并显示。(比如MDI子窗体最小化了,而我们点击菜单该子窗体按钮时,该子窗体应重新Restrore到中央)

一开始,我试着对frm_UserDefine(我的一个MDI子窗体)进行控制。包括以下:

showwindow(frm_UserDefine.handle, sw_restore);   // 显示子窗口

SendMessage(frm_UserDefine.Handle,MY_SETSTATE_MSG,0,0);// 发送消息到子窗口 触发消息进行Restore

都不管用,甚至以下代码,都会报内存错误

procedure Tfrm_Main.N9Click(Sender: TObject);var  frm_UserDefine: Tfrm_UserDefine;begin  if not isInclude(Tfrm_UserDefine) then  begin    frm_UserDefine := Tfrm_UserDefine.Create(Application);    frm_UserDefine.Show;  end  else  begin    frm_UserDefine.Show;  end;end;
当重新点击时 判断了frm_UserDefine已建立,重新show时就报错,最后跟踪查了下frm_UserDefine找不到,我也不太清楚什么原因。

解决方案:

我在判断子窗体是否存在时,若存在就对其进行Restore,就把这个功能实现了,代码如下:

function Tfrm_Main.isInclude(Formclass: TFormClass): Boolean;var  i: Integer;  Form: TObject;begin  Result := false;  for i := 0 to frm_Main.MDIChildCount do  begin    Form := frm_Main.MDIChildren[i];    if Form is Formclass then    begin      Result := true;      SendMessage(MDIChildren[i].Handle, WM_SYSCOMMAND, SC_RESTORE, 0); //在这里对MDI窗口进行管理恢复      MDIChildren[i].Enabled:=true;      MDIChildren[i].Show;      MDIChildren[i].SetFocus;    end;  end;end;
procedure Tfrm_Main.N9Click(Sender: TObject);var  frm_UserDefine: Tfrm_UserDefine;begin  if not isInclude(Tfrm_UserDefine) then  begin    frm_UserDefine := Tfrm_UserDefine.Create(Application);    frm_UserDefine.Show;  end;end;

这样就实现了重新点击就能使子窗体重新恢复的功能。不过大家有什么更好的解决方法也可以跟我留言。


3.关于MDI子窗体被主窗体控件遮挡问题

因为要在主窗体插入Falsh或者Webbrower控件,panel控件做总体导航时,因为MDI子窗体挡在后面而头疼。(Image控件刚好没有遮挡MDI子窗体,所以一般开发就是在MDI主窗体背后放个Image做背景),OK,现在问题是如何解决主窗体的控件不遮挡MDI子窗体,而且躲在底层还能点击。

解决方案:

这里我是把子窗体的父类指向MDI主窗体,代码如下:

procedure Tfrm_Main.N9Click(Sender: TObject);var  frm_UserDefine: Tfrm_UserDefine;begin  if not isInclude(Tfrm_UserDefine) then  begin    frm_UserDefine := Tfrm_UserDefine.Create(Application);    Winapi.Windows.SetParent(frm_UserDefine.Handle,frm_Main.Handle);    frm_UserDefine.Show;  end;end;
 这时呼出来的 子窗体界面就在控件前面了,还有个小Bug,就是对子窗体最小化后看不到子窗体,这时关闭窗体会报内存错误。

其实最小化后是隐藏起来,鼠标还是可以点击到的。(这里怎么会隐藏起来,可能还需要研究,如果大神知道原因的话,可以留言告诉我,我觉得可能改变了框架导致MDI错乱了吧)

这里可以在子窗体在最小化时show一下,且子窗体需要有控件(例如:panel)存在(没控件存在的form也会最小化隐藏),以下为子窗体代码

procedure Tfrm_UserDefine.FormCanResize(Sender: TObject; var NewWidth,  NewHeight: Integer; var Resize: Boolean);begin  case WindowState of    wsMinimized: Self.Show;  end;end;

问题解决!

以上代码是泡泡航在Delphi XE5的开发,虽然微软说明多文档界面MDI存在问题,但是现在以MDI窗体作为系统开发的还是蛮多的。如果大家有什么更好的办法或者建议,可以多多留言交流。


0 0
原创粉丝点击