zoukankan      html  css  js  c++  java
  • 深入VCL源码研究Delphi窗体的创建和关闭

    http://edu.codepub.com/2010/0519/22813.php

    一、窗体的建立

    一、窗体的建立

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

  • 相关阅读:
    matplotlib数据可视化之柱形图
    xpath排坑记
    Leetcode 100. 相同的树
    Leetcode 173. 二叉搜索树迭代器
    Leetcode 199. 二叉树的右视图
    Leetcode 102. 二叉树的层次遍历
    Leetcode 96. 不同的二叉搜索树
    Leetcode 700. 二叉搜索树中的搜索
    Leetcode 2. Add Two Numbers
    Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
  • 原文地址:https://www.cnblogs.com/chulia20002001/p/1837473.html
Copyright © 2011-2022 走看看