DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: chnifo
今日帖子: 54
在线用户: 18
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/23 18:54:42
标题:
呼叫lsuper,10.4.2 在win32平台下编译的程序,不能在win7 32位版本上正常运行。 浏览:1637
加入我的收藏
楼主: 程序都快写完了,结果发现编译的程序不能在windows 7 32位版本上正常运行,随便点几下就内存出错。但在win7 64位版本上能够正常运行。程序中使用了firedac、EhLib、fastreport、raize这些常用的第三方向组件。
恳请大师指点。
----------------------------------------------
-
作者:
男 moontowns (月光) ★☆☆☆☆ -
普通会员
2021/11/23 19:10:30
1楼: 用10.4.2社区版编译看看,如果还有问题就可以找Embarcadero的工程师了
----------------------------------------------
-
作者:
男 lsuper (lsuper) ★☆☆☆☆ -
盒子活跃会员
2021/11/23 20:27:16
2楼: 啥时候成 emb 客服了,[捂脸] [汗] ~

友情支持一下:安装 EurekaLog 控件,然后通过 ide 菜单激活你工程项目中,编译出 exe 环境再跑,看异常窗体堆栈信息
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/23 20:55:30
3楼: 谢谢大师。目前我退回到10.3.3编译,仍然还是同样错误。在64位上无比正常,在32位没办法跑。
估计是代码的问题,使用了动态创建TFrame并把它贴在panel上。其它都是用firedac进行的一些非常常规的数据库操作。
我估计10以上版本,可能都会有这个问题。
唉,现在是win7 32位版本很难找,只有另外一栋楼有,不能即改即调。
----------------------------------------------
-
作者:
男 moontowns (月光) ★☆☆☆☆ -
普通会员
2021/11/23 21:13:29
4楼: @lsuper 我装10.4.2社区版有问题,后来就是找Emb工程师解决的,他还顺便上报了一个安装的bug,我觉得我用的社区版是正版,所以可以名正言顺地找他们

请教下lsuper大侠,10.4.2非常不稳定,vcl拖控件写代码都经常崩溃,为了稳定我没有装任何第三方控件,windows也重装了,该打的3个补丁都打了,还是这样,不知道为什么
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/23 21:57:56
5楼: 请问 4 楼,该如何找?我用社区版,想做一个发布到 GOOGLE PLAY 的,各种问题。

我用 10.4.2. 做 FireMonkey 没有发现 IDE 崩溃的问题。没试过用它做 VCL。

试过 10.3.3 做 VCL,非常稳定。

另外,楼主,你测试 WIN7 32,装个虚拟机就好了,没必要跑另外一栋楼吧?

如果你跑另外一栋楼,那是在特定的电脑上测试,也许崩溃是那台电脑的问题而不是你的程序的问题。比如,检查一下那台电脑有没有装什么杀毒软件或者其它什么玩意。

所以,还是先自己装个虚拟机的系统用来测试比较好。
----------------------------------------------
-
作者:
男 moontowns (月光) ★☆☆☆☆ -
普通会员
2021/11/23 22:10:30
6楼: 申请社区版后会收到一个软件下载用户回访,我就直接回复提问题
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/23 22:40:46
7楼: 我已经试了跑到办公楼,找了10多台win7试,凡win7 32位必出错。所以肯定是不能在32位的win上跑。但win10肯定没问题的。
我估计问题肯定出在frame的处理上。
在delphi 10版本以前,如xe,我是把form建好后贴在panel上,然后在form里写子模块代码,实现模块化业务处理,免得把代码都写在主窗口。但这个办法在delphi 10以后各版本就不行了,会在窗口中出现焦点转移以及无效指针错误。
我现在是把frame贴在panel上,然后在frame写代码,实现模块化编程。但这个办法在 64位windows正常,在32位windows会出错。
----------------------------------------------
-
作者:
男 net1999 (net1999) ★☆☆☆☆ -
普通会员
2021/11/23 23:09:08
8楼: 减少代码,再测,会找到根源。
----------------------------------------------
-
作者:
男 lsuper (lsuper) ★☆☆☆☆ -
盒子活跃会员
2021/11/23 23:57:19
9楼: 1、还是推荐先试 EurekaLog,这玩意随用随知道啊
2、在 vmware 搭建 win7 32 测试环境,然后结合快照功能
3、如果有环境必现,现场装 ide 配环境也不是不可以的 ~
----------------------------------------------
-
作者:
男 nevergrief (孤独骑士) ★☆☆☆☆ -
盒子活跃会员
2021/11/24 2:52:03
10楼: 把form建好后贴在panel上——> 这种疯操作,你得深刻理解VCL才行,熟到VCL源码倒背如流。
----------------------------------------------
只有偏执狂才能生存!
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
注册会员
2021/11/24 5:47:16
11楼: you can found the All editions RAD Studio (Delphi / CBuilder) at:
wedelphi.com

here, you can see the Embarcadero Support for all Editions start in XE--Alexandria
https://wedelphi.com/t/422139/

//----------
REMEMBER:
--- A "FRAME" is as "FORM", include you can have a "CREATE" method for any necessity.

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  MyNewPanel: TPanel;
  MyNewFrame: TFrame;
  MyButton: TButton;
begin
  Button1.Enabled := false; // to avoid duplicate...
  //
  MyNewPanel        := TPanel.Create(Self { Form1 } );
  MyNewPanel.Name   := 'MyPanelNameXXXXX'; // very important for all object created
  MyNewPanel.Left   := 10;
  MyNewPanel.Top    := 10;
  MyNewPanel.Height := 200;
  MyNewPanel.Width  := 200;
  //
  MyNewPanel.Parent := Self;  // necessary to show it...
  //
  MyNewFrame      := TFrame.Create(MyNewPanel);
  MyNewFrame.Name := 'MyFrameZZZZZ';
  MyNewFrame.Left := 10;
  MyNewFrame.Top  := 10;
  //
  MyButton        := TButton.Create(MyNewFrame);
  MyButton.Name   := 'MyButtonYYYY';
  MyButton.Left   := 10;
  MyButton.Top    := 10;
  //
  MyButton.Parent := MyNewFrame;
  //
  MyNewFrame.Parent := MyNewPanel;  // at last, show the frame
end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/24 8:25:46
12楼: 用TFrame实现模块化编程是简易可行的方法。TForm有很多复杂的消息处理机制,把它当控件可能会有些深层次的问题,但TFrame要简单些。
我是这样考虑的:把Frame贴在主控窗口的Panel中,动态创建frame,这样一个主窗口背景panel上轮流创建Frame,实现业务处理模块化。
现在我可以肯定问题出在这段主控程序的代码
具体代码:
unit HndhMainFMUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, RzGroupBar, Vcl.ExtCtrls, RzPanel;

type
  THndhMainFM = class(TForm)
    RzPanel1: TRzPanel;
    Splitter1: TSplitter;
    RzPanelBk: TRzPanel;
    RzGroupBar1: TRzGroupBar;
    RzGroup1: TRzGroup;
    RzGroup2: TRzGroup;
    RzGroup3: TRzGroup;
    procedure FormCreate(Sender: TObject);
    procedure RzGroup1Items0Click(Sender: TObject);
    procedure RzGroup1Items1Click(Sender: TObject);
    procedure RzGroup3Items0Click(Sender: TObject);
    procedure RzGroup3Items1Click(Sender: TObject);
    procedure RzGroup2Items0Click(Sender: TObject);
    procedure RzGroup2Items1Click(Sender: TObject);
    procedure RzGroup3Items2Click(Sender: TObject);
    procedure RzGroup3Items3Click(Sender: TObject);
    procedure RzGroup3Items4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    Procedure FindOldFr(var OldFr:TComponent);
  end;

var
  HndhMainFM: THndhMainFM;

implementation

{$R *.dfm}

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.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutdown := True;
  MainDataMd.FDConnection1.LoginPrompt := True;
  MainDataMd.FDConnection1.Connected := True;

  Application.HintColor:=clBlue;
  Application.HintHidePause:=5*1000;

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);

   FrTotalRep:=TFrTotalRep.Create(self);
   FrTotalRep.Name:='FrTotalRep';
   FrTotalRep.Parent:=RzPanelBk;
   FrTotalRep.Align:=alclient;
   FrTotalRep.SetFocus;
   FrTotalRep.Show;
end;


//基本参数设置
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;

end.
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2021/11/24 8:39:43
12楼: 我也用了TFrame贴在Panel上的技术,Delphi 10.3.3 一直在64位下开发调试, 在虚拟机的Windows 7 sp1 32bit下编译测试,发布.没有问题.
----------------------------------------------
UniKeeper V10.00 -- 您最贴心的个人数据管理助手
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/24 8:43:21
13楼: 楼上是怎么做的呢?可以指导下吗?
----------------------------------------------
-
作者:
男 doersoft (XMG-ZY) ★☆☆☆☆ -
普通会员
2021/11/24 8:44:57
13楼: 多半代码问题,不一定IDE问题~~~
----------------------------------------------
delphi Flutter&Vue|golang rhinoslink
作者:
男 bluestorm8 (bluestorm) ▲▲△△△ -
注册会员
2021/11/24 9:09:53
14楼: 你可以用排除法查找原因:把程序逐步删减,直到问题不再出现,这时你就应该能从最后一步分析出为什么这个问题会出现了。
这个问题大概率不是delphi的问题,而是你的程序里面生成Frame的时间顺序问题。
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/24 9:16:18
15楼: 楼上,已经定位错误是这里:
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;

也就是这样用frame,在win32上不行,win64可以
----------------------------------------------
-
作者:
男 hardnut (麦轲数据管家) ★☆☆☆☆ -
普通会员
2021/11/24 9:18:38
14楼: 其实都差不多: 
{{TXXXFrame.InstFrame
实例化Frame
AParent: 即是新frame的parent也是owner, 常常是TPanel或TTabSheet对象


}
class function TXXXFrame.InstFrame(AParent: TWinControl): TFrame;
begin

  Result:=self.NewInstance as TFrame;
  Result.Create(AParent);
  Result.Parent:=AParent;  //耗时
  Result.Align:=alClient;
  Result.Visible:=True;

end;

TXXXFrame在设计时Visible设为False
----------------------------------------------
UniKeeper V10.00 -- 您最贴心的个人数据管理助手
作者:
男 bluestorm8 (bluestorm) ▲▲△△△ -
注册会员
2021/11/24 9:27:30
16楼: 你把
  FrSetDw.SetFocus;
改为
  Winapi.Windows.SetFocus(FrSetDw.Handle)
试试看

或者把FrSetDw.SetFocus;放在FrSetDw.Show;的后面试试
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/24 10:20:04
17楼: 楼上,估计不行,问题应该出现对TFrame的销毁上。因为这里也是出错:

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);
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/24 10:41:16
18楼: @麦轲数据管家
您只讲了怎样创建frame,但没有讲怎样销毁frame。
实际上,做程序里,内存可能存在Frame,如果不销毁,那么肯定会有内存泄漏,因为frame都是动态创建的,必须手动销毁。
怎样销毁已经创建的frame?
有二种方法:
一是定义一个TFrame全局变量,让它接纳每个动态创建的Tframe,然后用freeandnil删除;
二是从内存中找到frame实例,然后freeandnil。
第一种方法出错,第二种方法在win32上出错
----------------------------------------------
-
作者:
男 bluestorm8 (bluestorm) ▲▲△△△ -
注册会员
2021/11/24 10:43:34
18楼: 那就看看OldFr虽然不是nil,但它对应的Frame是否真的存在。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/24 10:47:24
17楼: 在一个 Panel 上摆放 Frame 和在一个 Panel 上摆放 Form 一样。

我以前喜欢在 Panel 上面摆 Form。

最近是做 Frame 摆到 Panel 上面。

楼主的问题没有碰到过。当然最近也没遇到过 WIN7 32bit.一般都是 64bit 的了。

另外,楼上说的 “或者把FrSetDw.SetFocus;放在FrSetDw.Show;的后面试试”,

这个从逻辑上,肯定应该是先 show 出来,再 SetFocus 啊。
----------------------------------------------
-
作者:
男 hawke2e (hawke2e) ▲▲▲▲▲ -
注册会员
2021/11/24 10:48:56
19楼: FrSetDw:=TFrSetDw.Create(self);  改为:FrSetDw:=TFrSetDw.Create(nil);
因为你是手动销毁。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/24 10:48:57
19楼: 用frame创建后贴在panel,可以很好地实现业务模块化编程。但做起来还是有一些小问题,例如编译的代码在win32上不能运行,如果解决不了,就得放弃这个简洁易行的方法。
这个应该是delphi的问题,我的功力不够,恳请技术大佬想想办法。
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/24 10:52:42
20楼: 另外,tframe没有创建和销毁事件,但可以覆盖这两个事件,让frame具备接近form的功能:
 procedure AfterConstruction; override;   //类似OnCreate事件
 procedure BeforeDestruction; override; //类似OnDestroy事件
----------------------------------------------
-
作者:
男 hawke2e (hawke2e) ▲▲▲▲▲ -
注册会员
2021/11/24 10:54:01
20楼: 另外,你在贴frame时,主窗体要先禁止绘画界面,贴完再恢复,防止界面闪烁。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 744840146 (744840146) ▲▲▲▲△ -
注册会员
2021/11/24 11:00:09
14楼: 这一套代码支持 D7 D10 D10.4没出过问题
此帖子包含附件:744840146_202111241109.zip 大小:8.0K
----------------------------------------------
-
作者:
男 bluestorm8 (bluestorm) ▲▲△△△ -
注册会员
2021/11/24 11:13:20
21楼: 对于TFrame,可以定义constructor和destructor,来代替OnCreate和OnDestroy
----------------------------------------------
-
作者:
男 flcop (flcop) ▲▲▲△△ -
注册会员
2021/11/24 11:27:39
22楼: 你这代码写的不严谨而且啰嗦,比如就看FindOldFr,函数里面如果没有找到,那么你传入的局部变量就是个随机值,你去释放它,只能听天由命了。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/24 11:27:44
22楼: 错误信息究竟是什么?

啥信息都不提供,别人只能猜。
----------------------------------------------
-
作者:
男 lsuper (lsuper) ★☆☆☆☆ -
盒子活跃会员
2021/11/24 11:33:05
22楼: 用 frame 管理组织 ui 控件确实比较方便,也便于组织协同开发;但基于 frame 开发确实有很多潜规则,如设置 parent 时机,这和 windows 消息机制相关,如会导致 listview/treeview 等一些 windows 控件诡异的事件。

确实如 @evergrief (孤独骑士) 的感受:“这种疯操作,你得深刻理解VCL才行,熟到VCL源码倒背如流。”

基于 frame 开发需要有开发规范,如统一 baseframe,规范 initui 时机(初始化界面、数据程序等),独立成 virtual 方法,在 parent 之后调用等
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/24 11:37:37
23楼: 目前我一个比较大的 VCL 是基于 Frame 开发的。也没特别注意什么,暂时没发现有什么问题。

一个 FMX 程序也是基于 Frame 开发的,除了主 Form,其它界面都是 Frame。在 WINDOWS 和 ANDROID 底下也暂时没发现有什么问题。

如果 Frame 有问题,在 VCL 底下,可以用多个 Form 来做界面。最后呈现的时候,如果只想出现一个 Form,就把其它的 Form.Parent := MyPanel 这样的方式来呈现就好了。这样用 Form 的模式,N 多年前 D7 时代我用得很多,也没发现过什么问题。
----------------------------------------------
-
作者:
男 dbyoung (dbyoung) ★☆☆☆☆ -
普通会员
2021/11/24 13:12:20
24楼: 我印象中 Raize 控件自带的示例用的是 TFrame 技术。
可以去看看。参考参考。

弄个开发环境在 Win7X86 上,分分钟不就找到问题了吗,何必这么纠结。
----------------------------------------------
武汉天气不好
作者:
男 vkow (vkow) ★☆☆☆☆ -
普通会员
2021/11/24 13:46:41
25楼: 对于这种莫名其妙的问题。

EurekaLog 控件是个神器。还是老老实实的先用个找到问题点再说吧。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/24 16:33:15
26楼: 老实写个最简单的程序,只有一个 Frame,加2个按钮,只测试这个 Frame 的创建释放。看看问题是不是创建或者释放导致。

如果确定就是那几行,
每一行加个 try..except Memo1.Lines.Add('这句话出错了')end;

另外,这个 Frame 的实例,为啥要先释放再创建?原来的那个创建好的实例不能直接使用?
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/24 17:04:19
27楼: 楼上大师,现在已经确定是Frame的释放导致的问题
如果不先释放再创建,重复点击会产生多个frame对象,产生内存泄漏。
现在的问题是,frame不能简单地freeandnil,不知道为什么,但在frame里面,却可以通过freeandnil(self)释放,而且无论在win32/64上都能跑。
现在可以这样,避免重复创建:
 if  FindComponent('FrSetDw')=nil then begin
     FrSetDw:=TFrSetDw.Create(self);
     FrSetDw.Name:='FrSetDw';
     FrSetDw.Parent:=RzPanelBk;
     FrSetDw.Align:=alclient;
     FrSetDw.SetFocus;
     FrSetDw.Show;
   end;
然后在TFrSetDw里写这个:
procedure TFrSetDw.N6Click(Sender: TObject);
begin
   FreeAndNil(self);
end;
实现对FrSetDw实例的销毁。
但现在仍有个小问题:如果用户没有点击N6,则仍无法销毁FrSetDw。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/24 17:11:57
28楼: 1. 既然能找到一个已经创建好的 Frame 实例,为啥不能直接用它?还要另外创建一个?

2. 确定是 Frame 释放导致的问题?是一个空白的 Frame 还是有很多代码和控件的 Frame ?  如果做了一个简单没有任何代码的程序,仅仅是放一个空白的 Frame 进去,然后发现有问题,才能确定是释放 Frame 导致。
----------------------------------------------
-
作者:
男 hawke2e (hawke2e) ▲▲▲▲▲ -
注册会员
2021/11/25 9:45:54
29楼: 印象里,楼主在论坛已经好多年,这么简单的问题1天都找不到原因?
Create(self)就是把创建出来的对象交给self来释放,那就不要手动释放,你不知道?
在self的模块里,调用FreeAndNil(self)? 你是不是走偏了
你不会写个测试程序,不手动释放,看会不会这样。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/25 10:54:35
30楼: 楼上的老师傅,你讲的也不对。凡是动态创建的堆对象,应当手动收回,而对于那些owner 为nil的,必须的手动收回,否则在程序结束前,这些内存都是不可用的。这个是delphi帮助文件里讲的。
现在问题已经解决了,确实是我的代码有问题,不过这种错误很奇怪,在win64上系统居然放了他一马,而win32却嫉恶如仇,根本不给他机会,直接AV或闪退。

其实,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。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/25 11:41:31
31楼: 用户反复点击按钮,你就要释放了再次去创建?

你不会判断对象是否存在,存在就直接用这个对象,而不是释放了重新创建一个?
----------------------------------------------
-
作者:
男 hawke2e (hawke2e) ▲▲▲▲▲ -
注册会员
2021/11/25 12:21:43
32楼: for i :=0 to RzPanelBk.ControlCount-1 do
       TFrame(RzPanelBk.Controls[0]).Free;

[0] 你确定以上代码没问题?
----------
你的意思是前面 用TFrame.Create(RzPanelBk)    后面就TFrame(RzPanelBk.Controls[i]).Free() ;
你确定Free() 后  RzPanelBk能收到它管理的TFrame的释放消息?

我的意思是用 aa:=TFrame.Create(Nil) ;  不要用RzPanelBk的ComponentCount和ControlCount了。
到时你就 aa.Free() ;来释放就可以了
你还没搞清楚原因呀
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 hawke2e (hawke2e) ▲▲▲▲▲ -
注册会员
2021/11/25 12:26:26
33楼: 还有,你想制造单文档的效果,好处就是每个Frame都是新的,系统会稳定一些。
那你得手动管理Frame的创建和释放,即使在释放某个Frame时发生错误异常,都不能影响其它Frame的创建。
明白我的意思吗?你要尽可能不依赖VCL的机制来实现“Frame的创建和释放”,这样系统就稳定了。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/25 12:43:15
34楼: 对的,我现在要的是单文档模式,这也是当今桌面应用比较推荐的形式,MDI已经过时了。所以我应该即用即建,用完即删。
for i :=0 to RzPanelBk.ControlCount-1 do
     if RzPanelBk.Controls[0] is  TFrame then 
        RzPanelBk.Controls[0].Free;
这样好些,反正Free会自动调用 TFrame的析构函数,强制应该是多余的。
我对delphi的内部工作机制并不熟悉,好在用delphi并不需要很熟悉底层的东西,让我能够把精力花在业务逻辑上。
----------------------------------------------
-
作者:
男 hawke2e (hawke2e) ▲▲▲▲▲ -
注册会员
2021/11/25 12:49:21
35楼: 怪不得你搞了这么多年delphi都不熟悉。
用python和PHP更符合你的需要
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 dbyoung (dbyoung) ★☆☆☆☆ -
普通会员
2021/11/25 13:02:58
36楼: 不就是个单文档吗,哪里需要循环。
定义一个成员变量就可以了。FActiveFrame:TFrame;
(hawke2e 大侠说的是这个意思吧)

反复点击为何会创建多次?
说明你在释放时肯定没有 FActiveFrame := nil。
----------------------------------------------
武汉天气不好
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/25 14:19:44
37楼: delphi10以上版本也不知道咋回事,如果定义一个TFrame的全局变量用来承接每次创建的不同Tframe,则用freeandnil时每次销毁时必出错:无效指针。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2021/11/25 16:05:35
38楼: alpha control 给的代码例子里面就是用的Frame。
主窗体里面有个当前frame的指针。
然后不断的销毁创建。
达到主界面展示不同页面的效果。
可以参考,不过为了各种效果,它确实写得很复杂。

类似的,我用的Form,一堆监控Form创建出来显示或不显示在主Form上。
也没啥问题(当然最近些年都没试过32位windows)

只是我用List来存这些Form的指针,而不是用容器的Controls[i]。
刷新时每次从List里面,手动Free掉这些子Form,再创建新的一批。
但是主Form的FormDestroy()里面,别再手动释放每个子Form。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 dbyoung (dbyoung) ★☆☆☆☆ -
普通会员
2021/11/25 16:14:10
39楼: Delphi11 Windows10X64 下开发。
测试 TFrame 的动态创建和销毁。

WIN7X86、WIN7X64 虚拟机下测试通过。
WIN10X64 下真实环境下测试通过。
此帖子包含附件:dbyoung_2021112516146.zip 大小:2.02M
----------------------------------------------
武汉天气不好
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/25 16:32:09
39楼: 因为你可能有多个 TFrame 的子类,即便每个子类只需要一个对象实例,那你也有多个 TFrame 的对象实例,怎么能够拿一个全局的 TFrame 的全局变量来对应这么多的实例?

如果这个全局变量是 AFrame,那么,你做一个 FreeAndNil(AFrame) 究竟是释放了哪个 TFrame 的实例?

我怀疑你是否明白 TFrame 一个类,和一个 TFrame 的实例对象,这两者的区别是什么。


其实就一个 TFrame 的问题,非常简单,居然搞得如此复杂。

另外,假设 RaPanel 对于它要管理的对象的管理方式有问题会导致释放有问题,最简单的就是不让它管理,也就是 19楼 说的:【FrSetDw:=TFrSetDw.Create(self);  改为:FrSetDw:=TFrSetDw.Create(nil);】

我看到你反驳 19 楼道说法,似乎根本没去试。
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/25 18:43:23
40楼: 楼上大师,难度你不明白父类兼容子类,而反过来就不行?FreeAndNil会自动调用Free
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/25 18:51:47
41楼: 1. 什么叫父类兼容子类?

2. FreeAndNil 的源代码本身就是两行,一行是 Free,一行是设置变量为 Nil,这个有什么好说的?不调用这个函数,自己写,也没两行代码。你的问题根本不是 FreeAndNil 的问题。

我打字那么多,你就一句话,也不知道你在说什么。看来给你提建议没什么用。
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/25 18:56:21
42楼: 我没用freeandnil
for i :=0 to RzPanelBk.ControlCount-1 do
     if RzPanelBk.Controls[0] is  TFrame then 
        RzPanelBk.Controls[0].Free;
反正问题解决了。
----------------------------------------------
-
作者:
男 bluestorm8 (bluestorm) ▲▲△△△ -
注册会员
2021/11/25 19:38:31
43楼: for i :=0 to RzPanelBk.ControlCount-1 do
     if RzPanelBk.Controls[0] is  TFrame then 
        RzPanelBk.Controls[0].Free;

i在循环里面完全没有利用到,这个明显有问题
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/25 20:18:30
44楼: 楼上,每删除一个子组件,ControlCount就会少一个
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
注册会员
2021/11/25 20:58:00
45楼: YOU CAN NOT USE "FOR" in all cases

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!
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2021/11/25 21:19:56
46楼: 是的,楼上说得对,循环中删[0],count就会减少,for的条件就会每次变化。
我隐约记得试过,这样确实会少循环一半。

除了楼上说的while,
还可以直接改成for i:=RzPanelBk.ControlCount-1 downto 0。
虽然有点怪,但是count的变化就不会影响循环了。

呃,那岂不是没释放完……
还是说LZ的情况永远只有一个,所以不出错?
----------------------------------------------
Bye bye DDRFAN...
作者:
男 bluestorm8 (bluestorm) ▲▲△△△ -
注册会员
2021/11/25 22:04:41
47楼: n := RzPanelBk.ControlCount;
for i := n-1 downto 0 do
begin
  if RzPanelBk.Controls[i] is  TFrame then 
        RzPanelBk.Controls[i].Free;
end;

你原来的写法,只有RzPanelBk.Controls全部都是TFrame才成立,一旦有一个Control不是TFrame,后面的不管是不是TFrame全部删不掉
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/25 22:11:21
47楼: 感谢 emailx45 (emailx45)
 while  RzPanelBk.ControlCount>0 do
  if RzPanelBk.Controls[0] is TFrame then     
    TFrame(RzPanelBk.Controls[0]).Free;
是正确的,RzPanelBk上面没有别的控件
----------------------------------------------
-
作者:
男 flcop (flcop) ▲▲▲△△ -
注册会员
2021/11/26 12:02:01
48楼: 1. 循环删[0],虽然在某些情况下能工作,但不是好的设计,特别是后面又想要扩展成可以过滤控件的情况,所以用Downto来删除是正确的选择。
2. 另外,认为控件上没有别的控件的想法是错误的,比如在FMX下, 控件一般都是其他控件组合起来的,它的初始ControlCount很可能不为零,强行删除会破坏父控件的完整性,所以一个原则是显式的只删除你想要删除的控件。
----------------------------------------------
-
作者:
男 crystalmoon (crystalmoon) ★☆☆☆☆ -
盒子活跃会员
2021/11/26 12:08:56
48楼: FreeAndNil,10.4.2有更严格的定义了,所以,10.3能搞的,10.4不一定能用。。
详见:https://en.delphipraxis.net/topic/3075-freeandnil-104-vs-1031-and-pointers/
----------------------------------------------
-
作者:
男 lsz100 (lsz) ★☆☆☆☆ -
盒子活跃会员
2021/11/26 13:36:18
49楼:    FindOldFr(OldFr);
    if Assigned(OldFr) then FreeAndNil(OldFr);
   FrManageBill:=TFrManageBill.Create(nil);
   FrManageBill.Name:='FrManageBill';
   FrManageBill.Parent:=RzPanelBk;
   FrManageBill.Align:=alclient;
   FrManageBill.Show;
   FrManageBill.SetFocus;
这样改就不会有问题了 可以试一下  SELF时是系统FREE  有可能系能已FREE但指针没收会 就会出现 能找到指针但对像已FREE 但是NIL时就必需你自己FREEANDNIL
----------------------------------------------
我为人人为我
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/26 21:09:40
50楼: 我已经把代码改好了,现在无论32/64都没问题了。
建frame没问题,关键是删除frame
现在这样就可以了
while  RzPanelBk.ControlCount>0 do
  if RzPanelBk.Controls[0] is TFrame then     
    TFrame(RzPanelBk.Controls[0]).Free;
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/26 21:22:43
51楼: @pcplayer (pcplayer)
用户反复点击按钮,你就要释放了再次去创建?

你不会判断对象是否存在,存在就直接用这个对象,而不是释放了重新创建一个?
//----------
系统里设计了多个TFrame的子类,每个子类代表不同的业务封装和界面窗体。
用户肯定不只点击一个创建frame的按钮,他可能会点分别创建TFrame的多个子类的按钮,这个时候内存里就的Tfrmae1、Tfrmae2、Tfrmae3.....等多个Tframe的实例,这些实例都贴在panel上,如果不删除这些实例,很可能导致程序出现一些错误的操作。
可见每次创建新的Tfrmae前,删除内存中已经创建的Tfrmae无用的实例,不仅是必须的,而且是非常重要的。
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/26 21:34:09
52楼: 最近搞个东西要用到发短信功能,就用了IDHttp向服务器提交json数据。也就半天时间从不会到实现发送短信和接收返回信息。电信工程师问我用什么工具,我说delphi,总共23行代码,现在把它封装成函数后放在datasnap rest服务器上供客户端调用。他说跟他们接洽的有java/C#/php/C++,你用delphi是最快的了。
向伟大的delphi致敬。
----------------------------------------------
-
作者:
男 nevergrief (孤独骑士) ★☆☆☆☆ -
盒子活跃会员
2021/11/27 3:49:56
53楼: to 步惊云
帖子太长,我也没自己测试。既然解决了,我就想问一下,之前32 / 64为什么会不一致?
----------------------------------------------
只有偏执狂才能生存!
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
2021/11/27 11:08:05
54楼: 自己写的东西对Windows兼容有问题,也找到lsuper头上,好像天生欠的似的
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
男 dbyoung (dbyoung) ★☆☆☆☆ -
普通会员
2021/11/27 11:43:35
55楼: 武哥生气了,后果很严重。 --- 天下无贼
做人怎么能无耻到如此地步。 ---- 一个馒头引发的血案
如此浪费公共资源,合适吗? ---- 西虹市首富

哈哈哈。
----------------------------------------------
武汉天气不好
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2021/11/27 16:55:53
56楼: 讨论,是让便多的人学习和思考,有何不可?
----------------------------------------------
-
作者:
男 bdl1 (bdl1) ▲▲▲▲△ -
注册会员
2021/11/28 22:37:16
57楼: 感谢super!
----------------------------------------------
-我的新浪博客
作者:
男 hz_2009 (盒子) ▲▲▲▲▲ -
注册会员
2021/12/22 16:23:59
58楼: 一般是内存使用错误,或溢出,等等
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v2.1 版权所有 页面执行62.5毫秒 RSS