动态创建单个控件时没问题,但用数组创建多时,程序在执行到'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;
'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;
解决方案 »
- 按客户经理查询到的信息不能显示到TDBGridEh
- 如何使用TstringGrid实现这样的效果
- 怎么通过pop菜单删掉dbgrid里的数据?
- Dbchart的图例问题
- 那位可提供水晶报表阿
- 关于进度条的问题?请帮忙!
- 急用!!
- 用isapi(webbroker)程序生成页面的数据刷新问题?进来看看,应该很简单的。
- 一个多线程的处理问题,同时也是一个涵数调用问题,请高手们帮帮忙:) 谢谢我
- delphi5开发指南第七章的例子不能编译成功:file not found :cards.dcu?
- 如何快速判断一个字符串 是否在 一个字符串集合里 如 101a 是否在 集合{201a,101a,500b... }
- 关于返回指定单元格焦点的问题
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;
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;
再问个问题吧.请各位指教啊!
我动态创建按钮是因为想改公司原来的系统,原来的系统主界面按钮都是固定的.
我要改为根据用户权限,动态创建一些按钮,执行该用户所具有权限的程序.
现在动态创建完按钮后,用ONLICK加上它们的事件,但是事件内容要怎么处理,因为不同的按钮要执行不同的事件啊.
这个事件内容也不好事先事好吧.
有些明白要怎么处理了.
谢谢各位的指教.
我在FormClose中加入,关闭程序是还是会报错.
也不行
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'.请问是怎么回事啊.要怎么处理.
数组下标是从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);
弹出另一个Application Error错误:
Exception EAccessViolation in module Project1.exe at 00000000.
Accessviolation at address 00000000.read of address 00000000.
但用:Form1 := nil;就不会;
这两个有什么差别的地方呢???
经过这段时间对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)) 来判断该窗体是否已经创建在内存中
procedure TForm1.FormDestroy(Sender: TObject);
begin
Form1 := nil;
end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;