Reputation: 9094
I am trying to create a set of custom components like TEdit, TDBEdit, TComboBox with a new kind of border (rounded corner) and I have created this code:
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.
But after I tried to put the component in the Form, this message came:
So, how to I fix that? I am new to construct components and I need a good tutorial on the web. Something tells me that I need to make that DrawRoundedRect
outside the Constructor... But where?
Edit 1 - 2012-07-27 14:50
Sertac Akyuz's Answer was great and resolved the problem, but the result was kind of ugly. I don't know what I am doing wrong. The text of the EditBox is too close to the top-left. Does anyone know how do I fix it?
Upvotes: 2
Views: 1075
Reputation: 596206
Creating a new region in SetBounds()
should be fine. Just be sure to call inherited
first, and then use the updated Width
/Height
to create the new region. CreateWnd()
should still create the initial region using the current Width
/Height
. SetBounds()
should recreate the region only if HandleAllocated()
is True.
Upvotes: 1
Reputation: 54802
You are requesting 'ClientRect' but the edit control window has not been created yet (no window, no rectangle). You can move your region modifying code to some place after it is created. Example:
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;
The error message itself reflects the effort of the VCL to create the window once its handle has been requested. It can't do so because it cannot resolve in what window the control is to be placed.
Upvotes: 5