0

Quick question in regard to Delphi XE.

I'm trying to make a customized circle-shape component that has transparent background, so that when added on a form, the component can overlap other components. I've tried Brush.Style:=bsTransparent; or ellipse() and more on... but still couldn't find a way to make the edge area transparent.

Is there anyway I can make the edge area of the component transparent without using other lib or api?

Janis F
  • 2,637
  • 1
  • 25
  • 36
eesther
  • 57
  • 1
  • 7
  • Have you considered ExtCtrls.TShape as example? (if TGraphicControl is appropriate for you) – MBo Nov 24 '14 at 14:55
  • 2
    A TGraphicControl paints on the canvas of its Parent, and so will never draw over windowed controls like a button or panel. A TWinControl descendant can't be transparent, but you can fake it by painting what's underneath it, onto it, before painting your circle. You need to handle WM_ERASEBACKGROUND too. Or there is a class you can handily inherit from which I've never used but looks like it will do the trick: TCustomTransparentControl. See http://stackoverflow.com/questions/6682396/transparent-tcustomcontrol for details on how to use it. – David Nov 24 '14 at 17:53

1 Answers1

6

Well here's a quick answer, that should get you going.

type
  TEllipticPanel = class(Vcl.ExtCtrls.TPanel)
    procedure CreateWnd; override;
    procedure Paint; override;
    procedure Resize; override;
    procedure RecreateHRGN;
 end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    panl: TEllipticPanel;
  public
    { Public declarations }
  end;

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  panl := TEllipticPanel.Create(self);
  panl.Left := 10;
  panl.Top := 10;
  panl.Width := 100;
  panl.Height := 50;
  panl.ParentBackground := False;
  panl.ParentColor := False;
  panl.Color := clYellow;
  panl.Parent := self;
end;

{ TEllipticPanel }

procedure TEllipticPanel.RecreateHRGN;
var
  hr: hRgn;
begin
  inherited;
  hr := CreateEllipticRgn(0,0,Width,Height);
  SetWindowRgn(Handle, hr, True);
end;

procedure TEllipticPanel.CreateWnd;
begin
  inherited;
  RecreateHRGN;
end;

procedure TEllipticPanel.Paint;
begin
  inherited;
  Canvas.Brush.Style := bsClear;
  Canvas.Pen.Style := TPenStyle(psSolid);
  Canvas.Pen.Width := 1;
  Canvas.Pen.Color := clGray;
  Canvas.Ellipse(1,1,Width-2,Height-2);
end;

procedure TEllipticPanel.Resize;
begin
  inherited;
  RecreateHRGN;
end;

The key is the Windows CreateEllipticRgn and the GDI SetWindowRgn functions.

For more information about windows regions see Regions.

Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54
  • 1
    You would have to call `SetWindowRgn()` every time the Panel's `Handle` is recreated. – Remy Lebeau Nov 24 '14 at 21:51
  • @RemyLebeau Thanks for the heads up. But is the old hRgn leaked, or does Windows take care of it? – Tom Brunberg Nov 24 '14 at 22:43
  • 3
    Per the [documentation](http://msdn.microsoft.com/en-us/library/dd145102.aspx): "**After a successful call to SetWindowRgn, the system owns the region specified by the region handle hRgn**. The system does not make a copy of the region. Thus, you should not make any further function calls with this region handle. **In particular, do not delete this region handle. The system deletes the region handle when it no longer needed.**" – Remy Lebeau Nov 24 '14 at 23:09
  • @TomBrunberg if hr area is a square, is it possible to set a circle shape area in the center to be colored and rest area to be setWindowRgn??? Thank you so much!! – eesther Nov 25 '14 at 11:29
  • @eesther I'm not sure I follow you. You wanted a circular area, so that the corners of a component (that is rectangular) would be transparent. That is why hr is elliptical (setting panl.Width = panl.Height makes the opaque area circular). Adding a Paint procedure to TElliptical you can draw whatever in the circular area. I add it to the source in a minute. – Tom Brunberg Nov 25 '14 at 11:53
  • 1
    @RemyLebeau, not only when the Handle is recreated, but also when the control is resized. – kobik Nov 25 '14 at 12:08
  • @kobik Thanks to you too for the heads up. I add the medicine shortly. – Tom Brunberg Nov 25 '14 at 12:43
  • 1
    @eesther You are welcome! If you think the answer is correct, then mark it as such. There's one more update coming shortly (1 hour) – Tom Brunberg Nov 25 '14 at 12:45