科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件深入VCL源码研究DELPHI窗体的创建和关闭

深入VCL源码研究DELPHI窗体的创建和关闭

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

从VCL源码中看窗体的创建和关闭。

作者:简单就是美 来源:CSDN 2008年3月21日

关键字: 窗体 源码 C++ C Linux

  • 评论
  • 分享微博
  • 分享邮件

一、窗体的建立

       在DELPHI中,我们通常使用Application.CreateForm(TForm2, Form2)和TForm.create来创建窗体,我们几乎无法区别这两种方法差异,更何况,我们更多的时候都是在使用TForm.create来生成子窗体。

       不过,仔细观察VCL源码,你会发现,其实两者区别很大。

procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
  Instance: TComponent;
begin
  Instance :
= TComponent(InstanceClass.NewInstance);
  TComponent(Reference) :
= Instance;
  
try
    Instance.Create(Self);
  except
    TComponent(Reference) :
= nil;
    raise;
  end;
  
if (FMainForm = nil) and (Instance is TForm) then
  begin
    TForm(Instance).HandleNeeded;
    FMainForm :
= TForm(Instance);
  end;
end;


constructor TCustomForm.Create(AOwner: TComponent);
begin
  GlobalNameSpace.BeginWrite;
  
try
    CreateNew(AOwner);
    
if (ClassType <> TForm) and not (csDesigning in ComponentState) then
    begin
      Include(FFormState, fsCreating);
      
try
        
if not InitInheritedComponent(Self, TForm) then
          raise EResNotFound.CreateFmt(SResNotFound, [ClassName]);
      
finally
        Exclude(FFormState, fsCreating);
      end;
      
if OldCreateOrder then DoCreate;
    end;
  
finally
    GlobalNameSpace.EndWrite;
  end;
end; 


       Form1 := TForm1.Create(Application); 是先调用TForm1的Create方法, 然后赋值 给Form1变量。而Application.CreateForm(TForm1, Form1);  他会先得到一个Instance的指针, 把这个指针赋值给Form1, 然后是Form1.Create(Application). 这Tform1.create的区别在于, 在TForm1的OnCreate事件中, 我们可以使用Form1这个变量。

        千万不要小瞧这点区别。例如你的程序有多个窗体,各个子窗体都是在需要的时候通过Tform1.create动态生成的,你想在FormOnCreate事件中对窗体上的edit1赋值text属性,那么你不能直接使用Form1.edit1.text := 'wudi_1982',你可以使用self.edit1.text 或者直接使用edit1.text。此时,你可能会想,可以直接用edit1.text,我为什么要多写form1.edit1.text呢?这里除了了解两者的区别,更重要的在于,如果你的程序中有一个函数,函数并非写在窗体类中,此函数调用了form上的信息,而在初始化的时候,你又必须调用它,如果不明白此中道理,可能就这个问题,就要让你调试好长时间,关于这方面的例子我就不写了。在DELPHI的DEMO程序中,又一个关于ListView的,其中就有类似的情况,只不过那个DEMO程序只有一个窗体,用不到Tform.create,如果有兴趣,你可以把那个例程添加到一个已存在的工程中,然后用两种不同的方法生成,你就会发现问题了。

二、窗体的关闭

       通常情况下,我们对于程序中子窗体的关闭,大多是使用close方法或者直接点击窗体右上角的关闭按钮。那么对于VCL的窗体,它真的“关闭”了吗?在默认情况下,答案是否定的。观察VCL源码,你会发现,那个关闭只能算做隐藏。至于怎么测试,我想你知道。
       要彻底关闭窗体并释放资源,就要调用他的free方法(模式窗体的常用办法),或者在onclose事件中,设置Action := caFree(无模式窗体的常用办法),如果窗体还要通过并且将自身赋值为nil。关于为什么手动做form1 := nil的操作,我这里就不多说了,

TCloseAction = (caNone, caHide, caFree, caMinimize);

procedure TCustomForm.Close;
var
  CloseAction: TCloseAction;
begin
  
if fsModal in FFormState then
    ModalResult :
= mrCancel
  
else
    
if CloseQuery then
    begin
      
if FormStyle = fsMDIChild then
        
if biMinimize in BorderIcons then
          CloseAction :
= caMinimize else
          CloseAction :
= caNone
      
else
        CloseAction :
= caHide;
      DoClose(CloseAction);
      
if CloseAction <> caNone then
        
if Application.MainForm = Self then Application.Terminate
        
else if CloseAction = caHide then Hide
        
else if CloseAction = caMinimize then WindowState := wsMinimized
        
else Release;
    end;
end;


 

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章