uses MainDataMdUnit, FrManageBillUnit, FrAccoundBookUnit, FMSysSetUnit, FrSetdwUnit, FrBJCountUnit, FrTotalRepUnit, SetCodeUnit, FrDataProcUnit, FMDataProcUnit, FMHelpUnit; //用引用传值的方式找到已经创建的Frame procedure THndhMainFM.FindOldFr(var OldFr: TComponent); begin if FindComponent('FrManageBill')<>nil then OldFr:=FindComponent('FrManageBill'); if FindComponent('FrAccountbook')<>nil then OldFr:=FindComponent('FrAccountbook'); if FindComponent('FrSetDw')<>nil then OldFr:=FindComponent('FrSetDw'); if FindComponent('FrBJCount')<>nil then OldFr:=FindComponent('FrBJCount'); if FindComponent('FrTotalRep')<>nil then OldFr:=FindComponent('FrTotalRep'); if FindComponent('FrDataProc')<>nil then OldFr:=FindComponent('FrDataProc');
end; //凭证单据处理 procedure THndhMainFM.RzGroup1Items0Click(Sender: TObject); var FrManageBill:TFrManageBill; OldFr:TComponent; begin
FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr); FrManageBill:=TFrManageBill.Create(self); FrManageBill.Name:='FrManageBill'; FrManageBill.Parent:=RzPanelBk; FrManageBill.Align:=alclient; FrManageBill.SetFocus; FrManageBill.Show;
end; //账册管理 procedure THndhMainFM.RzGroup1Items1Click(Sender: TObject); var FrAccountbook:TFrAccountbook; OldFr:TComponent; begin FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr);
FrAccountbook:=TFrAccountbook.Create(self); FrAccountbook.Name:='FrAccountbook'; FrAccountbook.Parent:=RzPanelBk; FrAccountbook.Align:=alclient; FrAccountbook.SetFocus; FrAccountbook.Show; end; //本级统计 procedure THndhMainFM.RzGroup2Items0Click(Sender: TObject); var FrBJCount:TFrBJCount; OldFr:TComponent; begin FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr);
FrBJCount:=TFrBJCount.Create(self); FrBJCount.Name:='FrBJCount'; FrBJCount.Parent:=RzPanelBk; FrBJCount.Align:=alclient; FrBJCount.SetFocus; FrBJCount.Show; end; procedure THndhMainFM.RzGroup2Items1Click(Sender: TObject); var FrTotalRep:TFrTotalRep; OldFr:TComponent; begin FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr);
//基本参数设置 procedure THndhMainFM.RzGroup3Items0Click(Sender: TObject); var FMSysSet: TFMSysSet; OldFr:TComponent; begin FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr); FMSysSet:= TFMSysSet.Create(self); FMSysSet.ShowModal; end; //上报报表单位、党费上交单位设置 procedure THndhMainFM.RzGroup3Items1Click(Sender: TObject); var FrSetDw:TFrSetDw; OldFr:TComponent; begin FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr); FrSetDw:=TFrSetDw.Create(self); FrSetDw.Name:='FrSetDw'; FrSetDw.Parent:=RzPanelBk; FrSetDw.Align:=alclient; FrSetDw.SetFocus; FrSetDw.Show;
end; procedure THndhMainFM.RzGroup3Items2Click(Sender: TObject); var SetCodeForm: TSetCodeForm; OldFr:TComponent; begin FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr); SetCodeForm:= TSetCodeForm.Create(self); SetCodeForm.ShowModal; end;
procedure THndhMainFM.RzGroup3Items3Click(Sender: TObject); var FMDataProc: TFMDataProc; OldFr:TComponent; begin FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr); FMDataProc:= TFMDataProc.Create(self); FMDataProc.ShowModal; end;
procedure THndhMainFM.RzGroup3Items4Click(Sender: TObject); var FMHelp: TFMHelp; begin FMHelp:= TFMHelp.Create(self); //这段代码不会出错 FMHelp.GTitle:='怎样开始'; FMHelp.ShowModal; FreeAndNil(FMHelp); end;
procedure THndhMainFM.RzGroup3Items3Click(Sender: TObject); var FMDataProc: TFMDataProc; OldFr:TComponent; begin FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr); FMDataProc:= TFMDataProc.Create(self); FMDataProc.ShowModal; end; 问题应该出在对内存中的TFrame的销毁。 FindOldFr(OldFr); if Assigned(OldFr) then FreeAndNil(OldFr);
----------------------------------------------
-
其实,TFrame完全可以放心地实现业务模块化编程,只是释放时稍微注意一下。 现在我是这样释放的: for i :=0 to RzPanelBk.ControlCount-1 do TFrame(RzPanelBk.Controls[0]).Free; 把所有建在panel上的Tframe释放掉。 为何在创建farme前必须删除已经创建的frame?因为在主控模块里用户可能会反复点击创建和个frame子模块的按钮,在创建前释放掉frame,可以确保内存里只有一份工作的frame。 现在,无论你在frame写多么复杂的业务代码,多复杂的界面,在win32/64里都能健康奔跑了。 再次证明,如果系统有错误,99.99%是你的责任,0.001%怪delphi。
----------------------------------------------
-
对的,我现在要的是单文档模式,这也是当今桌面应用比较推荐的形式,MDI已经过时了。所以我应该即用即建,用完即删。 for i :=0 to RzPanelBk.ControlCount-1 do if RzPanelBk.Controls[0] is TFrame then RzPanelBk.Controls[0].Free; 这样好些,反正Free会自动调用 TFrame的析构函数,强制应该是多余的。 我对delphi的内部工作机制并不熟悉,好在用delphi并不需要很熟悉底层的东西,让我能够把精力花在业务逻辑上。
----------------------------------------------
-
我没用freeandnil for i :=0 to RzPanelBk.ControlCount-1 do if RzPanelBk.Controls[0] is TFrame then RzPanelBk.Controls[0].Free; 反正问题解决了。
----------------------------------------------
-
1) "FOR" always works with "i=1.... <=i= LAST ITEM"
YOU SHOULD USE "WHILE", why?
1) "WHILE" always works with " IF item-exists-on-memory... then DO IT"
so...
RAD 11 Alexandria in test:
procedure TForm1.Button2Click(Sender: TObject); var i : integer; MyControl: TControl; begin
// if Panel1.ContainsControl( YOUR-CONTROL-TO-TRY) then // ... delete control x
i := 0; while (Panel1.ControlCount > 0) do // if you dont know how much "Controls" exist into Panel1 begin MyControl := Panel1.Controls[ 0 ]; // FIXED to "FREE" !!!!!! [ i ] to test not using "FREE" // ShowMessage(MyControl.Name); // if (MyControl.GetEnumerator = nil) then // trying in case the "control have another components" ShowMessage('hello world'); // MyControl.Free; // here "decrement automatically" the "ControlCount" above" dont needs "EXIT" below // // if not using "FREE" //if (i >= Panel1.ControlCount) then // exit; end; end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
感谢 emailx45 (emailx45) while RzPanelBk.ControlCount>0 do if RzPanelBk.Controls[0] is TFrame then TFrame(RzPanelBk.Controls[0]).Free; 是正确的,RzPanelBk上面没有别的控件
----------------------------------------------
-
我已经把代码改好了,现在无论32/64都没问题了。 建frame没问题,关键是删除frame 现在这样就可以了 while RzPanelBk.ControlCount>0 do if RzPanelBk.Controls[0] is TFrame then TFrame(RzPanelBk.Controls[0]).Free;
----------------------------------------------
-