NaN
NaN

Reputation: 9094

How to draw extra stuff on a custom component after creation at DT/RT?

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:

Control '' has no Parent

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

Result

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

Answers (2)

Remy Lebeau
Remy Lebeau

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

Sertac Akyuz
Sertac Akyuz

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

Related Questions