2

我正在尝试使用一种新的边框(圆角)创建一组自定义组件,例如 TEdit、TDBEdit、TComboBox,并且我创建了以下代码:

unit RoundRectControls;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Windows, Messages, Forms;

type
  TRoundRectEdit = class(TEdit)
  private
    { Private declarations }
  protected
    { Protected declarations }
  public
    constructor Create(AOwner: TComponent); override;
    { Public declarations }
  published
    property BorderStyle default bsNone;
    property Ctl3D default False;
    { Published declarations }
  end;

procedure Register;
procedure DrawRoundedRect(Control: TWinControl);

implementation

constructor TRoundRectEdit.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  DrawRoundedRect(Self);
end;

procedure Register;
begin
  RegisterComponents('Eduardo', [TRoundRectEdit]);
end;

procedure DrawRoundedRect(Control: TWinControl);
var
   r: TRect;
   Rgn: HRGN;
begin
   with Control do
   begin
     r := ClientRect;
     rgn := CreateRoundRectRgn(r.Left, r.Top, r.Right, r.Bottom, 30, 30) ;
     Perform(EM_GETRECT, 0, lParam(@r)) ;
     InflateRect(r, - 4, - 4) ;
     Perform(EM_SETRECTNP, 0, lParam(@r)) ;
     SetWindowRgn(Handle, rgn, True) ;
     Invalidate;
   end;
end;

end.

但是在我尝试将组件放入表单后,出现了以下消息:

控件''没有父级

那么,我该如何解决呢?我是构建组件的新手,我需要一个很好的网络教程。有些东西告诉我,我需要DrawRoundedRect在构造函数之外进行...但是在哪里?

编辑 1 - 2012-07-27 14:50

结果

Sertac Akyuz 的回答很棒并解决了问题,但结果有点难看。我不知道我做错了什么。EditBox 的文本太靠近左上角。有谁知道我该如何解决?

4

2 回答 2

5

您正在请求“ClientRect”,但尚未创建编辑控制窗口(没有窗口,没有矩形)。您可以在创建区域修改代码后将其移动到某个位置。例子:

type
  TRoundRectEdit = class(TEdit)
  private
    { Private declarations }
  protected
    procedure CreateWnd; override;
    { Protected declarations }
  public
    constructor Create(AOwner: TComponent); override;
    ...

constructor TRoundRectEdit.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
//  DrawRoundedRect(Self);
end;

procedure TRoundRectEdit.CreateWnd;
begin
  inherited;
  DrawRoundedRect(Self);
end;


错误消息本身反映了 VCL 在请求其句柄后创建窗口的努力。它不能这样做,因为它无法解析将控件放置在哪个窗口中。

于 2012-07-27T17:02:12.570 回答
1

在其中创建一个新区域SetBounds()应该没问题。请务必先调用inherited,然后使用更新后的Width/Height创建新区域。 CreateWnd()仍应使用当前Width/创建初始区域Height。 仅当为 TrueSetBounds()时才应重新创建该区域。HandleAllocated()

于 2012-07-27T18:28:22.580 回答