首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

怎么释放根据窗体名称找到的窗体对象呢

2012-05-03 
如何释放根据窗体名称找到的窗体对象呢?如何释放根据窗体名称找到的窗体对象呢?Delphi(Pascal) codeFreeAn

如何释放根据窗体名称找到的窗体对象呢?
如何释放根据窗体名称找到的窗体对象呢?

Delphi(Pascal) code
   FreeAndNil(TForm(form1));                                  //不报错   FreeAndNil(TForm(FindGlobalComponent(strName))));       //报错,strName为窗体名称

目的是,是根据用户操作取得窗体名称,然后释放该窗体。因为窗体是动态创建的,所以只能根据窗体名称来释放窗体
Delphi(Pascal) code
var  strName:string;begin  strName:=...;//根据用户操作来取得窗体的名称(窗体为动态创建的)  Tfrom(FindGlobalComponent(strName))).free;  Tfrom(FindGlobalComponent(strName))):=nil;  //这句报错 left side cannot be assigned to


使用如下方法,可不报错,但是,当再次创建窗体时就报错,因为上次关闭时并没有使得窗体对象置为nil。
Delphi(Pascal) code
var  f:TForm;begin  f:=TForm(FindGlobalComponent(strName));  freeandnil(f);  


[解决办法]
FindGlobalComponent找到的是实例的地址,而不是指向实例的指针的地址(比如Form1),所以不能置为nil。
比如实例的地址是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
[解决办法]
自己创建的对象 自己管理不就得了。
我平时管理对象的时候 喜欢用自己写的一个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 是将你自己定义 的一个对控件操作的函数传入进行处理的一个函数。
[解决办法]
答案就在8#, 还有什么好讨论的...

正常做法是在各个窗体的Close或Destroy事件,让窗体为nil,麻烦就是每个窗体都要这么写
解决办法就是采用TList来管理你的所有窗体,在Close时,让TList中对应实例的地址为0即可(即nil)
下面是例子:

Delphi(Pascal) code
...  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. 

热点排行