如何释放根据窗体名称找到的窗体对象呢? FreeAndNil(TForm(form1)); //不报错
FreeAndNil(TForm(FindGlobalComponent(strName)))); //报错,strName为窗体名称目的是,是根据用户操作取得窗体名称,然后释放该窗体。因为窗体是动态创建的,所以只能根据窗体名称来释放窗体var
strName:string;
begin
strName:=...;//根据用户操作来取得窗体的名称(窗体为动态创建的)
Tfrom(FindGlobalComponent(strName))).free;
Tfrom(FindGlobalComponent(strName))):=nil; //这句报错 left side cannot be assigned to
使用如下方法,可不报错,但是,当再次创建窗体时就报错,因为上次关闭时并没有使得窗体对象置为nil。var
f:TForm;
begin
f:=TForm(FindGlobalComponent(strName));
freeandnil(f);
FreeAndNil(TForm(FindGlobalComponent(strName)))); //报错,strName为窗体名称目的是,是根据用户操作取得窗体名称,然后释放该窗体。因为窗体是动态创建的,所以只能根据窗体名称来释放窗体var
strName:string;
begin
strName:=...;//根据用户操作来取得窗体的名称(窗体为动态创建的)
Tfrom(FindGlobalComponent(strName))).free;
Tfrom(FindGlobalComponent(strName))):=nil; //这句报错 left side cannot be assigned to
使用如下方法,可不报错,但是,当再次创建窗体时就报错,因为上次关闭时并没有使得窗体对象置为nil。var
f:TForm;
begin
f:=TForm(FindGlobalComponent(strName));
freeandnil(f);
窗体名.free
窗体名.close
或者直接写 close
2)特殊情况如下:
如果窗体中是静态加载DLL的话,就在关闭窗体之前,先释放掉那个DLL
再close
即可
3)我上面说的那种情况,假设窗体中设置与数据库控件关联时,必须点周“保存”
这个按扭时,才能关闭窗体时,当然这个方面是为了将信息在保存时后的最后一个
“确认保存”功能的,否则最后一条记录是不会保存到数据库中........
比如实例的地址是123,而Form1的地址是456(它指向的值是123);把FindGlobalComponent的结果置为nil,就是mov [123],0,而不是想要的mov [456],0。 解决办法很简单,自己保存一个List,存入字符串Form1和Form1的地址即可。like this:List := TStringList.Create;
List.AddObject('Form1', TObject(@Form1));//保存TObject(PDWORD(List.Objects[List.IndexOf('Form1')])^).Free;//Form1.Free
PDWORD(List.Objects[List.IndexOf('Form1')])^ := 0;//Form1 := nil
然后调用frmx.show;
然后在单击主窗体的关闭按钮时释放frmx, FreeAndNil(TForm(FindGlobalComponent(strname)));
这时就会报错,
当然,可以在TFrmx的onclose事件中释放,但是我的工程不允许这么做,只能在主窗体中释放他所创建并调用的窗体。
的想法:
1)根据窗体名称找到窗体上的对象
清空信息值
初始化参数
2)在“单元2”中引用“单元1”的中窗体中的控件,就是必须
在“单元2”中引用一下“单元1”的名称后,使用其值即可如下:
uses 单元1;
if 单元1.edit1.text='abc' then
ShowMessage('信息为:'+(单元1.edit1.text));
这样好像是是不行的
当下次创建窗体时,form1依然不等于nil
但是有个BUG呀,你可以在“进程”看一下,窗体是关闭了,但是“进程”中还有呀
没有
CLOSE直接在将窗体和进程一块“关闭”的
但是有个BUG呀,你可以在“进程”看一下,窗体是关闭了,但是“进程”中还有呀
我现在主要要解决的是,如何使得窗体的name来找到窗体对象的变量变为nil。
窗的为NIL值就可以吗,这样进程中不是还有一个“程序体”吗
那程序在“结束”时,你也应该“考虑”这个问题的,否则会
“浪费资源”的
先free然后nil
free是没有问题的,问题是free后,如何nil呢(注意:是根据name找到的窗体对象,所以不能直接使用对象的变量名,即不能nFrom:=nil);
不过这种NIL空值,一般情况都是针对“图片”控件(image1)的
代码如下:
Image1.Picture.Assign(nil);
Image1.Picture.Graphic.Free;
这窗体中的Image1中的图片就会清空的
“窗体值必须先以NIL(就是空值)赋值,才能再free(释放)”这种说法是不正确的。
我的意思是如何实现以下语句要实现的功能:
FreeAndNil(TForm(FindGlobalComponent(strName)))); //报错,strName为窗体名称
根据你的这个理解的话,既然窗体被FREE后,就从内存就消失了呀
不能再接受任意值的呀NIL???
我平时管理对象的时候 喜欢用自己写的一个hashtable来管理。
只要你做到 你所有对象名称 别名不重复 你可以把你程序中所有的对象放到这个hashtable中来,对象的查找速度是非常快的。
type
TInitComponent= procedure (Compent:TComponent);
type
PPHashItem = ^PHashItem;
PHashItem = ^THashItem;
THashItem = record
Next: PHashItem;
Key: String;
Value: TObject;
end;
THXHashTable = class
private
Buckets: array of PHashItem;
function GetValue(key: String): Tobject;
procedure SetValue(key: String; const Value: Tobject);
protected
function Find(const Key: String): PPHashItem;
function HashOf(const Key: String): Cardinal; virtual;
public
constructor Create(Size: Integer = 256);
destructor Destroy; override;
procedure Add(const Key: String; Value: Tobject);
procedure Clear;
procedure InitCompentValues(funcP:TInitComponent);
procedure Delete(const Key: String);
property ValueOf[key:String]: Tobject read GetValue write SetValue;
end;{ THXHashTable }procedure THXHashTable.Add(const Key: String; Value: tobject);
var
Hash: Integer;
Bucket: PHashItem;
begin
Hash := HashOf(Key) mod Cardinal(Length(Buckets));
// Bucket := Find(key)^;
// if Bucket = nil then
New(Bucket);
Bucket^.Key := Key;
Bucket^.Value := Value;
Bucket^.Next := Buckets[Hash];
Buckets[Hash] := Bucket;
end;procedure THXHashTable.Clear;
var
I: Integer;
P, N: PHashItem;
begin
for I := 0 to Length(Buckets) - 1 do
begin
P := Buckets[I];
while P <> nil do
begin
N := P^.Next;
Dispose(P);
P := N;
end;
Buckets[I] := nil;
end;
end;constructor THXHashTable.Create(Size: Integer);
begin
inherited Create;
SetLength(Buckets, Size);
end;destructor THXHashTable.Destroy;
begin
Clear;
inherited;
end;function THXHashTable.Find(const Key: String): PPHashItem;
var
Hash: Integer;
begin
Hash := HashOf(Key) mod Cardinal(Length(Buckets));
Result := @Buckets[Hash];
while Result^ <> nil do
begin
if Result^.Key = Key then
Exit
else
Result := @Result^.Next;
end;
end;function THXHashTable.HashOf(const Key: String): Cardinal;
var
I: Integer;
begin
Result := 0;
for I := 1 to Length(Key) do
Result := ((Result shl 2) or (Result shr (SizeOf(Result) * 8 - 2))) xor
Ord(Key[I]);
end;function THXHashTable.GetValue(key: String): Tobject;
var
P: PHashItem;
begin
P := Find(Key)^;
if P <> nil then
Result := P^.Value else
Result := nil;
end;procedure THXHashTable.SetValue(key: String; const Value: Tobject);
var
P: PHashItem;
begin
P := Find(Key)^;
if P <> nil then
P^.Value := Value;
end;procedure THXHashTable.Delete(const Key: String);
var
P: PHashItem;
Prev: PPHashItem;
begin
Prev := Find(Key);
P := Prev^;
if P <> nil then
begin
Prev^ := P^.Next;
Dispose(P);
end;
end;
procedure THXHashTable.InitCompentValues(funcP:TInitComponent);
var
I: Integer;
P, N: PHashItem;begin
for I := 0 to Length(Buckets) - 1 do
begin
P := Buckets[I];
while P <> nil do
begin
N := P^.Next;
funcP(TComponent(P^.value));
P := N;
end;
end;end;上面的InitCompentValues 是将你自己定义 的一个对控件操作的函数传入进行处理的一个函数。
你家的地址是XXX路XXX街XXX号,你家是违章建筑被强拆了,难道就不能再在你家的这个地方重新建楼房?再或者是有关部门不能把你家的地址都注销掉?有木有? 有木有?? 有木有???!!!
解决办法就是采用TList来管理你的所有窗体,在Close时,让TList中对应实例的地址为0即可(即nil)
下面是例子:...
private
procedure ShowForm(frm:TForm;Pfrm:TFormClass);
procedure MdiFormClose(Sender: TObject; var Action: TCloseAction);
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
FList: TStringList;implementationuses unit2,unit3;{$R *.dfm}procedure TForm1.MdiFormClose(Sender: TObject; var Action: TCloseAction);
var
frmIndex: Integer;
begin
Action:=caFree;
if Sender is TForm then
begin
frmIndex := FList.IndexOf(TForm(Sender).Name);
if frmIndex >= 0 then
begin
PWord(FList.Objects[frmIndex])^:=0;
FList.Delete(frmIndex);
end;
end;
end;procedure TForm1.ShowForm(frm:TForm;Pfrm:TFormClass);
begin
if not AsSigned(frm)then
begin
frm:=Pfrm.Create(self);
frm.OnClose:=MdiFormClose;
FList.AddObject(frm.Name, @frm);
end;
frm.Show;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
ShowForm(Form2,TForm2);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
ShowForm(Form3,TForm3);
end;initialization
FList := TStringList.Create;
finalization
FList.Free;end.
kaikai_kk
(KAIKAI)
的总结,我再研究研究这个问题
strName:string;
Mycomp : TComponent;
begin
strName:=...;//根据用户操作来取得窗体的名称(窗体为动态创建的)
Mycomp := FindGlobalComponent(strName);
Tfrom(Mycomp).free;
Tfrom(Mycomp):=nil; //这句报错 left side cannot be assigned to
kuangning在33楼系统深入地讲述了使用哈希表解决管理对象的方法。
kaikai_kk在36楼写出了完整的demo,方法与8楼一致。
-------------------------------------------------
再次感谢所有关注问题的朋友!