Delphi动态创建窗口可能出现的问题

      程序中经常会用到动态创建的窗口,而这其中用得最多的应该还是调用DLL封装的窗口,代码网上是一大堆了,所以在这里说说动态创建窗口后可能遇到的麻烦。

 

      创建的窗口分模式和非模式窗口两种,第一种是对话框式的窗口,焦点是封装的,只有关闭后才能激活主窗口,而第二种是可以与主窗口进行焦点切换。模式窗口创建时通常不会出现什么问题,因为用的是showModal(),并直接用了try finally进行的显示、关闭、释放,程序顺序执行,所以创建消毁都很正常。非模式窗口用的是show(),所以需要手动释放窗口,而麻烦也经常会出现在这里。释放窗口有3种方法,一般都会写在窗口的close事件里:

 

1. formName.free;formName:=nil;

 

光是Free是不行的,因为只是这样的话引用窗口实例的指针还是存在的,那样你就没法在第二次动态调用窗口时显示窗口了,因为你在调用时肯定需要判断窗口是否已经调用并创建,否则一定会出问题,而且如果在调用显示窗口后直接关闭整个程序也是很有可能报错的。

 

2. freeAndNil(formName)

 

这个是上面代码的合集,更方便。

 

3. Action:=caFree;FormName:=nil;

 

这个是在窗口关闭时同步释放,然后销毁。

 

      如果是直接创建普通的窗口,那是没有任何问题的,就算你动态调用了窗口,然后直接关闭主窗口也能顺利结束程序,可是如果在窗口中使用了第三方控件的话可就不一定能顺利关闭了。像我使用FlashPlayerControl控件时就遇到了动态调用窗口后直接关闭主程序的报错,要么就是runtime error 216 ,要么就是内存读取错误,经过调试才发现是第三方控件引起的,用过前两种方法都不行,然后发现,只要先关闭动态调用的窗口再关闭主程序就没问题,没办法,所以在退出主程序之前调用了Findwindow(nil,FormName)来找出调用的窗口并向窗口发送关闭的消息,可就算是这样窗口也不能同步释放,依然报错,所以才用了第三种,这样的调用才算是完成了真正意义上的“动态”调用。

 

      接下来还碰到了更加有趣的问题,在Delphi2010里,我发现如果动态调用上面创建的这样一个非模式窗口,并且将窗口风格设置为无边框标题栏时,用消息来控制拖动窗口是无效的,而且在窗口里使用ApplicationEvent控件也是没任何反应,可窗口标题栏的功能是正常的,能拖动,于是试着调用显示了窗口句柄,发现读取窗口句柄会出错,所以我想这问题应该是出在窗口句柄上了,但查了很多资料都没找到答案,大概是动态调用无标题栏非模式窗口的人不多,不过我也不打算在这样的问题上多花脑力,也许更多人愿意用多线程去开这样的非模式窗口,但我离用这样强大功能的时候还很远,希望有知道答案的能说说。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DELPHI动态创建删除FRAME unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,FM; type TForm2 = class(TForm) Panel1: TPanel; Button2: TButton; ScrollBox1: TScrollBox; procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; type TFM = Array Of TFrame1; var Form2: TForm2; aFM: TFM; procedure DeleteArrItem(var arr: TFM ; Index: Integer);stdcall; implementation {$R *.dfm} procedure DeleteArrItem(var arr: TFM ; Index: Integer); var Count: Cardinal; i:integer; begin Count := Length(arr); if (Count = 0) or (Index = Count) then Exit; Move(arr[Index+1], arr[Index], (Count-Index)* SizeOf(arr[0])); SetLength(arr, Count - 1); for I := 0 to Length(arr) - 1 do begin arr[i].Label1.Caption:=inttostr(i); end; end; procedure TForm2.Button2Click(Sender: TObject); var fram:TFrame1; begin SetLength(aFM,length(aFM)+1); aFM[length(aFM)-1] :=TFrame1.Create(nil) ; fram:=aFM[length(aFM)-1]; fram.Label1.Caption:=inttostr(length(aFM)-1); fram.Parent:=ScrollBox1; end; end. unit fm; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFrame1 = class(TFrame) GroupBox1: TGroupBox; Label1: TLabel; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; implementation uses unit2; {$R *.dfm} procedure TFrame1.Button1Click(Sender: TObject); begin DeleteArrItem(aFM,strtoint(label1.Caption)); ( Sender as Tbutton ).Parent.Parent.Destroy; end; end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值