本帖最后由 haiou327 于 2013-02-22 14:17:18 编辑

解决方案 »

  1.   

    已知控件名称(注意, 不是控件对象)和控件类型
    就要用到proc1的方法
      

  2.   

    用Pro2是可以的,但AProgressBar必须申明为全局变量,或者声明到Private或Public里面。
      

  3.   

    对于aProgressBar声明为局部变量只能用Proc1方法
      

  4.   

    请问在AProgressBar作用域是全局的条件下,Proc1和proc2方法是不是等价的,或者说有区别的?
      

  5.   

    就你这段代码来说,Proc1和Proc2是没区别的
      

  6.   

    csdn还真是快,效率还是真是高
    还有其它的看法吗
      

  7.   


    以下两种情况, 不像外部传递对象的情况下;
    已知存在一个名叫progress的TProgressBar类型控件, 此时要得到这个对象怎么办?
    1 : 用proc1;
    2 : 遍历self的控件进行匹配
    var
    AProgressBar:TProgressBar;
    begin
    AProgressBar := TProgressBar.Create(self);    
        with AProgressBar do  
        begin  
          Name := 'Progress';  
          Parent := from1;  
          Max := Form1.Tag;
          Step := 1;  
          Top := 95;  
          Left := 8;  
          Width := Form1.ClientWidth - 16;  
        end;
    end;//////////////////
    begin
      with TProgressBar.Create(self)do  
        begin  
          Name := 'Progress';  
          Parent := from1;  
          Max := Form1.Tag;
          Step := 1;  
          Top := 95;  
          Left := 8;  
          Width := Form1.ClientWidth - 16;  
        end;
    end;
      

  8.   

    既然是已知的,又不是外部程序,直接控件名.xxx来赋值不是比遍历来得更直接
      

  9.   


    FindComponent就是遍历Self的所有控件。
      

  10.   


    所以定义为全局变量或者Private和Public下好,创建后要Free掉也好控制。要养成习惯,Create就要Free。
      

  11.   

    begin
      with TProgressBar.Create(self)do  
        begin  
          Name := 'Progress';  
          Parent := from1;  
          Max := Form1.Tag;
          Step := 1;  
          Top := 95;  
          Left := 8;  
          Width := Form1.ClientWidth - 16;  
        end;
    end;
    这种情况就只能用Proc1方法,没有可操作指针引用
      

  12.   


    感谢你的提醒,原文是有Try...Fanlly Free,我只是引用其中一段代码
      

  13.   

    begin
      with TButton.Create(self)do
        begin
          Name:='bt1';
          Parent := Self;
          Left:=20;
          top:=60;
          Width:=90;
        end;
    end;var
      BT:TButton;
    begin
      BT:=TButton(FindComponent('bt1'));
      ShowMessage(BT.Caption);
      FreeAndNil(BT); 
    end;[/code]
    这种情况就只能用Proc1了,我们无法用Bt1.xxx来直接操作。
    还有一点疑问,在这里如果没有这里显示FREE掉,bt1内存释放交给谁了,由他的Onwer关闭后会自动Free吗
      

  14.   

    begin
      with TButton.Create(self)do
        begin
          Name:='bt1';
          Parent := Self;
          Left:=20;
          top:=60;
          Width:=90;
        end;
    end;var
      BT:TButton;
    begin
      BT:=TButton(FindComponent('bt1'));
      ShowMessage(BT.Caption);
      FreeAndNil(BT); 
    end;
    这种情况就只能用Proc1了,我们无法用Bt1.xxx来直接操作。
    还有一点疑问,在这里如果没有这里显示FREE掉,bt1内存释放交给谁了,他的Onwer关闭后会自动Free吗
      

  15.   

    简单的应用场景:
    在form中动态创建N个Button.
    -----------------------------
    不能定一堆全局变量吧!
    用其它容器存放变量? 那就和form的Components属性重复了!
    另:
    创建控件拥有者不为nil时, 这个控件的生命周期就有拥有者接管了, 不需要特殊处理
      

  16.   


    这种控件的Create内存是分配在堆区,理论上是要程式自己控制释放的,若程序员不释放,程序结束时可能由OS回收。
      

  17.   

    感谢simonhehe  feiba7288的释疑
    下面写了一段代码自动创建多个Button
    用的两种方法,一个是用数组变量存放checkbox,另一个是按simonhehe的方法没有传递外部对象的方法来创建button
    看一下哪种方法更优化或者说更合理{method1******************************************}
    procedure Tform1.butClick(sender: Tobject);
    var
      i: integer;
      Tb: TButton;
    begin
      for i := 1 to 5 do
      //TB:=TButton(FindComponent('btn'+inttostr(i)));
        if ((sender as TButton).Caption) = 'btn' + inttostr(i) then
          ShowMessage('btn' + inttostr(i));
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      i: Integer;
    begin
      Button1.Tag := 20;
      for i := 1 to 5 do
        with TButton.Create(self) do
        begin
          Caption := 'btn' + inttostr(i);
          Name := 'btn' + inttostr(i);
          Button1.tag := Button1.Tag + 60;
          top := Button1.Tag;
          Left := 40;
          Width := 80;
          Parent := Self;
          OnClick := butClick;
        end;
    end;
    {method1******************************************}
    var
    isNo:boolean;
    ChB: array[1..5] of Tcheckbox;
    procedure Tform1.checkonClick(sender: TObject);
    begin
      if (sender as TCheckBox).Checked then
        ShowMessage((sender as TCheckBox).Caption + '  已选中');
    end;procedure TForm1.Button1Click(Sender: TObject);
      var
      i,High: integer;
    begin
      if isNo then
      begin                           //防止多次实例化
        begin
          High := 20;
          for i := 1 to 5 do
          begin
            High := High + 20;
            ChB[i] := TCheckBox.Create(self);
            ChB[i].Caption := 'chkb' + Inttostr(i);
            ChB[i].Top := High;
            ChB[i].Left := 56;
            ChB[i].Width := 100;
            ChB[i].Parent := Grp1;
            ChB[i].OnClick := checkonClick;
          end;
        end;
        isNo := False;
      end
      else
        begin
        for i := 5 DownTo 1 do
          FreeAndNil(ChB[i]);
          isNo:=True;
        end;
    end;var
    isNo:boolean;
    ChB: array[1..5] of Tcheckbox;
    procedure Tform1.checkonClick(sender: TObject);
    begin
      if (sender as TCheckBox).Checked then
        ShowMessage((sender as TCheckBox).Caption + '  已选中');
    end;procedure TForm1.Button1Click(Sender: TObject);
      var
      i,High: integer;
    begin
      if isNo then
      begin                           //防止多次实例化
        begin
          High := 20;
          for i := 1 to 5 do
          begin
            High := High + 20;
            ChB[i] := TCheckBox.Create(self);
            ChB[i].Caption := 'chkb' + Inttostr(i);
            ChB[i].Top := High;
            ChB[i].Left := 56;
            ChB[i].Width := 100;
            ChB[i].Parent := Grp1;
            ChB[i].OnClick := checkonClick;
          end;
        end;
        isNo := False;
      end
      else
        begin
        for i := 5 DownTo 1 do
          FreeAndNil(ChB[i]);
          isNo:=True;
        end;
    end;
      

  18.   

    一不小心就复制重复了{method1*******************************************************}
    procedure Tform1.butClick(sender: Tobject);
    var
      i: integer;
      Tb: TButton;
    begin
      for i := 1 to 5 do
      //TB:=TButton(FindComponent('btn'+inttostr(i)));
        if ((sender as TButton).Caption) = 'btn' + inttostr(i) then
          ShowMessage('btn' + inttostr(i));
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      i: Integer;
    begin
      Button1.Tag := 20;
      for i := 1 to 5 do
        with TButton.Create(self) do
        begin
          Caption := 'btn' + inttostr(i);
          Name := 'btn' + inttostr(i);
          Button1.tag := Button1.Tag + 60;
          top := Button1.Tag;
          Left := 40;
          Width := 80;
          Parent := Self;
          OnClick := butClick;
        end;
    end;
    {method2***********************************************************}
    var
    isNo:boolean;
    ChB: array[1..5] of Tcheckbox;
    procedure Tform1.checkonClick(sender: TObject);
    begin
      if (sender as TCheckBox).Checked then
        ShowMessage((sender as TCheckBox).Caption + '  已选中');
    end;procedure TForm1.Button1Click(Sender: TObject);
      var
      i,High: integer;
    begin
      if isNo then
      begin                           //防止多次实例化
        begin
          High := 20;
          for i := 1 to 5 do
          begin
            High := High + 20;
            ChB[i] := TCheckBox.Create(self);
            ChB[i].Caption := 'chkb' + Inttostr(i);
            ChB[i].Top := High;
            ChB[i].Left := 56;
            ChB[i].Width := 100;
            ChB[i].Parent := Grp1;
            ChB[i].OnClick := checkonClick;
          end;
        end;
        isNo := False;
      end
      else
        begin
        for i := 5 DownTo 1 do
          FreeAndNil(ChB[i]);
          isNo:=True;
        end;
    end;
      

  19.   


    你可以用simonhehe的方法,处理控制上更简洁些,但最好在创建的时候加个判断
    for i := 1 to 5 do
      if not Assigned(FindComponent('btn' + inttostr(i))) then
        with TButton.Create(self) do
        begin
          Caption := 'btn' + inttostr(i);
          Name := 'btn' + inttostr(i);
          Button1.tag := Button1.Tag + 60;
          top := Button1.Tag;
          Left := 40;
          Width := 80;
          Parent := Self;
          OnClick := butClick;
        end;同时在FormDestroy时将这些创建的控件一个个Free掉
    var
      aBtn: TButton;
    for i := 1 to 5 do
    begin
      aBtn := TButton(FindComponent('btn' + inttostr(i)));
      if Assigned(aBtn) then
        FreeAndNil(aBtn);
    end;
         
      

  20.   

    TCheckBox.Create(self);
    这样一创建, chkbox就在self的子列表中了
    建立容器存放特定对象, 需要处理时简洁点儿(比如容器内存放的都是同类型的对象, self就无法保证)
      

  21.   


    var
      aBtn: TButton;
    begin
      if not Assigned(aBtn) then
      begin
        aBtn := TButton.Create(self);
        aBtn.Top := 10;
        aBtn.Left := 20;
        aBtn.Width := 80;
        aBtn.Name:='tb1';
        aBtn.Parent := Form1;
      end;
    end;Assigned用在这里无效
    Assigned(Form1)有效
      

  22.   

    ok了,又是变量声明
    把aBtn改为全程变量begin
      if (not Assigned(aBtn)) then
      begin
        aBtn := TButton.Create(self);
        aBtn.Top := 10;
        aBtn.Left := 20;
        aBtn.Width := 80;
        aBtn.Name:='tb1';
        aBtn.Parent := Form1;
      end;
    end;