动态创建单个控件时没问题,但用数组创建多时,程序在执行到'btn[i] := TButton.Create(Form1);'就报错了:
'Access violation at address 004A1736 in module 'Project1.exe'.请大侠指教了.创建别的类型的控件也是这样.procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
begin
  for i := 1 to 5 do
  begin
    btn[i] := TButton.Create(Form1);
    btn[i].Parent := Form1;
    btn[i].Height := 30;
    btn[i].Width := 75;
    btn[i].Visible := True;
    btn[i].top := Self.Top + 50 * i;
    btn[i].Left := Self.Left + 50 * i;
    btn[i].Caption := '动态控件';
  end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
    btn := TButton.Create(Form1);
    btn.Parent := Form1;
    btn.Height := 30;
    btn.Width := 75;
    btn.Visible := True;
    btn.top := Self.Top + 50 * i;
    btn.Left := Self.Left + 50 * i;
    btn.Caption := '动态控件';
end;

解决方案 »

  1.   

    var 
      i: integer;
      btn:array[1..5] of TButton;
    begin
      for i:= 1 to 5 do
      begin
        btn[i]:= TButton.Create(Form1);
        btn[i].Parent:= Form1;
        btn[i].Height:= 30;
        btn[i].Width:= 75;
        btn[i].Visible:= True;
        btn[i].top:=Self.Top+50*i;
        btn[i].Left:=Self.Left+50*i;
        btn[i].Caption:='动态控件';
      end;
    end;
      

  2.   

    var
      i: integer;
      btn:array of TButton;
      count:Integer;
    begin
      count:=10;//创建10个
      setlength(btn,count);
      for i:= 0 to count-1 do
      begin
        btn[i]:= TButton.Create(Form1);
        btn[i].Parent:= Form1;
        btn[i].Height:= 30;
        btn[i].Width:= 75;
        btn[i].Visible:= True;
        btn[i].top:=Self.Top+50*i;
        btn[i].Left:=Self.Left+50*i;
        btn[i].Caption:='动态控件';
      end;
    end;
      

  3.   

    一天后才可以结贴啊!
    再问个问题吧.请各位指教啊!
    我动态创建按钮是因为想改公司原来的系统,原来的系统主界面按钮都是固定的.
    我要改为根据用户权限,动态创建一些按钮,执行该用户所具有权限的程序.
    现在动态创建完按钮后,用ONLICK加上它们的事件,但是事件内容要怎么处理,因为不同的按钮要执行不同的事件啊.
    这个事件内容也不好事先事好吧.
      

  4.   

    看了这一贴:http://topic.csdn.net/u/20071218/08/c515fc87-6a79-4040-9af2-92f8e522d411.html
    有些明白要怎么处理了.
    谢谢各位的指教.
      

  5.   

    请问是用btn:=nil释放资源吗?
    我在FormClose中加入,关闭程序是还是会报错.
      

  6.   

    SetLength(Btn, 0);
    也不行
      

  7.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, DB, ADODB, StdCtrls, Buttons, QButtons;type
      TForm1 = class(TForm)
        Button1: TButton;
        Cnn: TADOConnection;
        DST: TADODataSet;
        Edit1: TEdit;
        procedure Button1Click(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private declarations }
        BitBtnArry: array of TButton;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormDestroy(Sender: TObject);
    begin
      SetLength(BitBtnArry, 0);
    //  BitBtnArry := nil;
      Form1 := nil;
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      SetLength(BitBtnArry, 0);
      Action := caFree;
    //  BitBtnArry := nil;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      i: integer;
    begin
      DST.Close;
      DST.CommandText := 'select * from t_Modules';
      DST.Open;
      DST.First;
      if not DST.Eof then
      begin
        i := 1;
        SetLength(BitBtnArry, DST.RecordCount);
        while i <= DST.RecordCount do
        begin
          BitBtnArry[i] := TButton.Create(Form1);
          BitBtnArry[i].Parent := Form1;
          BitBtnArry[i].Caption := vartostr(DST['FName']);
          BitBtnArry[i].Left := Trunc((i mod 5) * 110) + 20;
          BitBtnArry[i].Top := Trunc(i / 5) * 40 + 50;
          BitBtnArry[i].Width := 100;
          BitBtnArry[i].Height := 30;
          BitBtnArry[i].Visible := True;
          DST.Next;
          inc(i);
        end;
      end;
    end;
    运行程序,创建按钮,关闭时出现:'Access   violation   at   address   00401D42   in   module   'Project1.exe'.Write of address 0042bdf8'.请问是怎么回事啊.要怎么处理.
      

  8.   

    数组越界了!
    数组下标是从0开始的:
        DST.First; 
        if   not   DST.Eof   then 
        begin 
            i   :=  0;   //把1改成0
            SetLength(BitBtnArry,   DST.RecordCount); 
            while   i   <=   DST.RecordCount -1   do // 这里给DST.RecordCount - 1
            begin 
             .......
            end; 
        end; 释放的时候:
    在Form1.Destroy中写一个:SetLength(BitBtnArry, 0);就可以了,其他的去掉。
      Form1 := nil;//不要这么写,如果要动态释放窗体并赋为nil,可以用FreeAndNil(Form1);
      

  9.   

    按你说的改了,刚才的错误处理好。
    弹出另一个Application Error错误:
    Exception EAccessViolation in module Project1.exe at 00000000.
    Accessviolation at address 00000000.read of address 00000000.
      

  10.   

    发现用:FreeAndNil(Form1);会出现上面的错误;
    但用:Form1 := nil;就不会;
    这两个有什么差别的地方呢???
      

  11.   

    从别的地方(http://www.cnitblog.com/flyinggoal/archive/2006/09/28/17448.aspx)copy来下面这一段,请哪位帮忙补充说明一下吧。delphi中关于资源释放(Free/release/freeAndNil)的一点体会 
    经过这段时间对delphi中free 和 release 的仔细学习,先总结如下:
    1。form.free直接释放资源后,调用OnDestroy事件,但是没有将form指针改为nil
    2。form.release 等待资源不再使用后释放资源,同样不修改form指针为nil,所以在destroy中最好使用    release进行资源释放操作。
    3。局部变量释放资源时,可以考虑用freeandnil()释放资源,这样效率会高些,能提高内存的利用率
    4。在对窗体操作时,单纯通过assigned(form1)判断窗体是否已经创建是不够的,因为如果窗体通过free   /release进行资源释放的话,form1指向的是一个未知地址,而非nil,所以需要用(not    Assigned(ShowForm)) and (not (ShowForm is  TForm2)) 来判断该窗体是否已经创建在内存中 
      

  12.   

    在我的系统里面,以前程序员都是用下面来释放资源,不知道对不对??
    procedure   TForm1.FormDestroy(Sender:   TObject); 
    begin 
        Form1   :=   nil; 
    end; procedure   TForm1.FormClose(Sender:   TObject;   var   Action:   TCloseAction); 
    begin 
        Action   :=   caFree; 
    end;