自定义tbutton未显示在表单上

发布于 2025-01-22 09:35:05 字数 3763 浏览 0 评论 0 原文

我试图拥有一个功能,用户可以通过单击表单上的现有按钮来创建新按钮。现在,我试图通过创建自己的类,称为 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:

image

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....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

羁绊已千年 2025-01-29 09:35:05

您为什么要介绍自己的/ top / width / height /字幕>字幕 mybutton 中的功能?您没有为从 tbutton 继承的相同名称的现有属性分配任何值。您确实应该使用现有属性,如果要对这些属性的更改做出反应,则可以覆盖虚拟 setBounds()方法,然后处理 cm_textchanged 消息,根据需要。

另外,为什么 mybutton 在其构造函数中将自己设置为自己的所有者?这是完全错误的,这可能就是为什么您会在运行时遇到“堆栈溢出”错误的原因,这会导致您的按钮构造函数中止。

试试看:

type
  myButton = class(TButton)
  protected
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  end;

procedure myButton.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;
  // do something...
end;

procedure myButton.CMTextChanged(var Message: TMessage);
begin
  inherited;
  // do something...
end;

然后您需要修复 tform1.button1click()以使用正确的构造函数和属性,例如:

procedure TForm1.Button1Click(Sender: TObject);
var
  btn: myButton;
begin
  btn := myButton.Create(Self);
  with btn do
  begin
    Parent := Self;

    Top := 25;
    Left := 25;
    Height := 45;
    Width := 50;
    // or: SetBounds(25, 25, 50, 45);

    Caption := 'MyButton';
    Visible := True;
  end;
end;

Why are you introducing your own left/top/width/height/caption functionality in myButton? You are not assigning any values to the existing properties of the same names that are inherited from TButton. 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 virtual SetBounds() method, and handle the CM_TEXTCHANGED message, as needed.

Also, why is myButton setting itself as its own Owner 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:

type
  myButton = class(TButton)
  protected
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  end;

procedure myButton.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;
  // do something...
end;

procedure myButton.CMTextChanged(var Message: TMessage);
begin
  inherited;
  // do something...
end;

And then you need to fix TForm1.Button1Click() to use the correct constructor and properties, eg:

procedure TForm1.Button1Click(Sender: TObject);
var
  btn: myButton;
begin
  btn := myButton.Create(Self);
  with btn do
  begin
    Parent := Self;

    Top := 25;
    Left := 25;
    Height := 45;
    Width := 50;
    // or: SetBounds(25, 25, 50, 45);

    Caption := 'MyButton';
    Visible := True;
  end;
end;
黯淡〆 2025-01-29 09:35:05

因此,在@Remy的帮助下,这是我使用的代码,并解决了我的问题。

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
      ftop, fleft, fheight, fwidth: Integer;
      procedure setBounds(ALeft, ATop, AHeight, AWidth: Integer);override;
//      procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;

    public
      constructor Create(aOwner: TComponent);override;
  end;

implementation
uses
  unit1;
constructor myButton.Create(aowner: TComponent);
begin
  inherited create(AOwner);
  parent := form1;
  top := ftop;
  left := fleft;
  height := fheight;
  width := fwidth;
  caption := 'MyButton';
end;
procedure myButton.setBounds(ALeft, ATop, AHeight, AWidth: Integer);
begin
  inherited;
   fleft := aLeft;
   ftop := ATop;
   fheight := AHeight;
   fwidth := AWidth;
end;
 end.

这是 onClick ,它创建一个新按钮

procedure TForm1.Button1Click(Sender: TObject);
var
  p: myButton;
begin
  p := mybutton.Create(self);
  p.setbounds(50, 85, 78, 92);

end;

So, with the help from @Remy, here is the code that I used and that solved my issue.

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
      ftop, fleft, fheight, fwidth: Integer;
      procedure setBounds(ALeft, ATop, AHeight, AWidth: Integer);override;
//      procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;

    public
      constructor Create(aOwner: TComponent);override;
  end;

implementation
uses
  unit1;
constructor myButton.Create(aowner: TComponent);
begin
  inherited create(AOwner);
  parent := form1;
  top := ftop;
  left := fleft;
  height := fheight;
  width := fwidth;
  caption := 'MyButton';
end;
procedure myButton.setBounds(ALeft, ATop, AHeight, AWidth: Integer);
begin
  inherited;
   fleft := aLeft;
   ftop := ATop;
   fheight := AHeight;
   fwidth := AWidth;
end;
 end.

And here is the OnClick that creates a new button

procedure TForm1.Button1Click(Sender: TObject);
var
  p: myButton;
begin
  p := mybutton.Create(self);
  p.setbounds(50, 85, 78, 92);

end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文