我试图拥有一个功能,用户可以通过单击表单上的现有按钮来创建新按钮。现在,我试图通过创建自己的类,称为 mybutton
,其中 tbutton
作为祖先类。
我遇到的问题是,单击现有按钮后,新按钮未显示在表单上。
我尝试使用属性设置所需的值,并使用我的班级中所述的过程,但我总是会遇到相同的三个错误。
这是我创建的类:
unit clsButton;
interface
uses
vcl.StdCtrls, System.Classes;
type
myButton = class(TButton)
private
fTop, fLeft, fWidth, fHeight: Integer;
fCaption: String;
published
property top: Integer read fTop write fTop;
property left: Integer read fLeft write fLeft;
property width: Integer read fwidth write fWidth;
property height: Integer read fheight write fHeight;
property caption: String read fCaption write fCaption;
public
procedure setTop(value: Integer);
procedure setLeft(value: Integer);
procedure setWidth(value: Integer);
procedure setHeight(value: Integer);
procedure setCaption(value: String);
constructor Create();
end;
implementation
constructor myButton.Create;
begin
inherited Create(Self);
end;
procedure myButton.setTop(value: Integer);
begin
fTop := value;
end;
procedure myButton.setleft(value: Integer);
begin
fLeft := value;
end;
procedure myButton.setWidth(value: Integer);
begin
fWidth := value;
end;
procedure myButton.setHeight(value: Integer);
begin
fHeight := value;
end;
procedure myButton.setCaption(value: String);
begin
fCaption := value;
end;
end.
这是 onclick
过程的主要单元,以创建一个新按钮:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, clsButton;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
btn: myButton;
begin
btn := myButton.Create();
with btn do
begin
//top := 25;
//left := 25;
//height := 45;
//width := 50;
//caption := 'MyButton';
parent := self;
settop(25);
setLeft(25);
setheight(45);
setwidth(50);
setcaption('MyButton');
show;
end;
end;
end.
这是我运行程序后遇到的错误:
现在,如果我去了已经创建 clsbutton
并评论所有内容的类最初在主单元中对此进行了评论),新按钮在我的表单上显示了我分配的标题值...但是,所有其他值不是我给出的值(顶部,左,宽度和高度)。这些是 form1
具有的值。
我的猜测是我在构造函数中的某个地方误解,但我无法弄清楚。
update :我正在根据@Remy在他的coment中建议的内容添加我创建的类:
unit clsButton;
interface
uses
System.Types, Vcl.StdCtrls, VCl.Forms, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Dialogs;
type
myButton = class(Tbutton)
private
procedure setBounds(ALeft, ATop, AHeight, AWidth: Integer); override;
public
constructor Create(aOwner: TComponent); override;
end;
implementation
constructor myButton.Create;
begin
inherited create(AOwner);
end;
procedure myButton.setBounds(ALeft, ATop, AHeight, AWidth: Integer);
begin
inherited;
left := aLeft;
top := ATop;
height := AHeight;
width := AWidth;
end;
end.
这也是 onttonClick
事件,应该创建一个新按钮:
procedure TForm1.Button1Click(Sender: TObject);
var
p: myButton;
begin
p := mybutton.Create(self);
with p do
begin
parent := form1;
caption := 'MyButton';
setbounds(50, 85, 78, 92);
end;
end;
我仍然得到同样的错误...
I am trying to have a functionality where a user will be able create a new button by clicking on the existing one on the form. Now, I am trying to achieve that by creating my own class called MyButton
that has a TButton
as an ancestor class.
The problem that I am having is that the new button is not showing on the Form after the existing button is clicked.
I have tried using the properties to set the needed values, as well as using the procedures that are stated in my class, but I always get the same three errors.
Here is the class that I have created:
unit clsButton;
interface
uses
vcl.StdCtrls, System.Classes;
type
myButton = class(TButton)
private
fTop, fLeft, fWidth, fHeight: Integer;
fCaption: String;
published
property top: Integer read fTop write fTop;
property left: Integer read fLeft write fLeft;
property width: Integer read fwidth write fWidth;
property height: Integer read fheight write fHeight;
property caption: String read fCaption write fCaption;
public
procedure setTop(value: Integer);
procedure setLeft(value: Integer);
procedure setWidth(value: Integer);
procedure setHeight(value: Integer);
procedure setCaption(value: String);
constructor Create();
end;
implementation
constructor myButton.Create;
begin
inherited Create(Self);
end;
procedure myButton.setTop(value: Integer);
begin
fTop := value;
end;
procedure myButton.setleft(value: Integer);
begin
fLeft := value;
end;
procedure myButton.setWidth(value: Integer);
begin
fWidth := value;
end;
procedure myButton.setHeight(value: Integer);
begin
fHeight := value;
end;
procedure myButton.setCaption(value: String);
begin
fCaption := value;
end;
end.
Here is the main unit where the OnClick
procedure is called in order to create a new button:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, clsButton;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
btn: myButton;
begin
btn := myButton.Create();
with btn do
begin
//top := 25;
//left := 25;
//height := 45;
//width := 50;
//caption := 'MyButton';
parent := self;
settop(25);
setLeft(25);
setheight(45);
setwidth(50);
setcaption('MyButton');
show;
end;
end;
end.
And here are the errors that I get after running the program:
Now, if I go to the class that I have created clsButton
and comment everything and then, in my main unit set the values of the properties by not using the setter methods (the block of code that is initially commented in the main unit), the new button shows on my Form having the caption value that I assigned... but, all other values are not the ones that I have given (top, left, width and height). Those are the values that Form1
has.
My guess is that I am mistaking somewhere in the constructor, but I can not figure it out.
UPDATE: I am adding the class I created based on what @Remy suggested in his coment:
unit clsButton;
interface
uses
System.Types, Vcl.StdCtrls, VCl.Forms, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Dialogs;
type
myButton = class(Tbutton)
private
procedure setBounds(ALeft, ATop, AHeight, AWidth: Integer); override;
public
constructor Create(aOwner: TComponent); override;
end;
implementation
constructor myButton.Create;
begin
inherited create(AOwner);
end;
procedure myButton.setBounds(ALeft, ATop, AHeight, AWidth: Integer);
begin
inherited;
left := aLeft;
top := ATop;
height := AHeight;
width := AWidth;
end;
end.
This is also the OnButtonClick
event that should create a new button:
procedure TForm1.Button1Click(Sender: TObject);
var
p: myButton;
begin
p := mybutton.Create(self);
with p do
begin
parent := form1;
caption := 'MyButton';
setbounds(50, 85, 78, 92);
end;
end;
I still get the same errors....
发布评论
评论(2)
您为什么要介绍自己的
左
/top
/width
/height
/字幕>字幕
mybutton
中的功能?您没有为从tbutton
继承的相同名称的现有属性分配任何值。您确实应该使用现有属性,如果要对这些属性的更改做出反应,则可以覆盖虚拟setBounds()
方法,然后处理cm_textchanged
消息,根据需要。另外,为什么
mybutton
在其构造函数中将自己设置为自己的所有者
?这是完全错误的,这可能就是为什么您会在运行时遇到“堆栈溢出”错误的原因,这会导致您的按钮构造函数中止。试试看:
然后您需要修复
tform1.button1click()
以使用正确的构造函数和属性,例如:Why are you introducing your own
left
/top
/width
/height
/caption
functionality inmyButton
? You are not assigning any values to the existing properties of the same names that are inherited fromTButton
. You really should be using the existing properties, and if you want your button to react to changes to those properties then you can override the virtualSetBounds()
method, and handle theCM_TEXTCHANGED
message, as needed.Also, why is
myButton
setting itself as its ownOwner
in its constructor? That is just plain wrong, and is likely why you are getting "stack overflow" errors at runtime, which will cause your button constructor to abort.Try this instead:
And then you need to fix
TForm1.Button1Click()
to use the correct constructor and properties, eg:因此,在@Remy的帮助下,这是我使用的代码,并解决了我的问题。
这是
onClick
,它创建一个新按钮So, with the help from @Remy, here is the code that I used and that solved my issue.
And here is the
OnClick
that creates a new button