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;