我正在尝试使用一种新的边框(圆角)创建一组自定义组件,如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的文本太靠近左上角。有谁知道如何解决它?
答案 0 :(得分:4)
您正在请求'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在请求其句柄后创建窗口的努力。它不能这样做,因为它无法在控件放置的窗口中解析。
答案 1 :(得分:1)
在SetBounds()
中创建一个新区域应该没问题。请务必先致电inherited
,然后使用更新的Width
/ Height
创建新区域。 CreateWnd()
仍应使用当前Width
/ Height
创建初始区域。仅当SetBounds()
为True时,HandleAllocated()
才会重新创建该区域。