I have to deal with some legacy Delphi 5 code. I have to draw some complex graphics on a transparent canvas. Transparency works, but the drawing can be constructed the easiest if I draw something and then I erase portions of it. Now, I am unable to erase.
For the sake of simplicity, let's say, that I want to erase the portion of the border that is underneath the text (now filled, drawn with FillRect(R);):
But indifferent to the brush settings I use, the area is at best not drawn/filled at all, but the line portion is never erased.
[update: "reproducible example"]
unit TransparentControls;
interface
uses
Forms, Classes, Controls, StdCtrls, Messages, Windows, Graphics;
type
TTransparentGroupbox = class(TGroupBox)
protected
procedure CreateParams(var params: TCreateParams); override;
procedure WMEraseBkGnd(var msg: TWMEraseBkGnd); message WM_ERASEBKGND;
procedure Paint; override;
end;
procedure Register;
implementation
procedure TTransparentGroupbox.CreateParams(var params: TCreateParams);
begin
inherited CreateParams(params);
params.ExStyle := params.ExStyle or WS_EX_TRANSPARENT;
end;
procedure TTransparentGroupbox.WMEraseBkGnd(var msg: TWMEraseBkGnd);
begin
SetBkMode(msg.DC, TRANSPARENT);
msg.result := 1;
end;
procedure TTransparentGroupbox.Paint;
var
H: Integer;
R: TRect;
Flags: Longint;
begin
with Canvas do
begin
Font := Self.Font;
H := TextHeight('0');
R := Rect(0, H div 2 - 1, Width, Height);
if Ctl3D then
begin
Inc(R.Left);
Inc(R.Top);
Brush.Color := clBtnHighlight;
FrameRect(R);
OffsetRect(R, -1, -1);
Brush.Color := clBtnShadow;
end else
Brush.Color := clWindowFrame;
FrameRect(R);
if Text <> '' then
begin
if not UseRightToLeftAlignment then
R := Rect(8, 0, 0, H)
else
R := Rect(R.Right - Canvas.TextWidth(Text) - 8, 0, 0, H);
Flags := DrawTextBiDiModeFlags(DT_SINGLELINE);
DrawText(Handle, PChar(Text), Length(Text), R, Flags or DT_CALCRECT);
Brush.Style := bsClear;
FillRect(R);
DrawText(Handle, PChar(Text), Length(Text), R, Flags);
end;
end;
end;
procedure Register;
begin
RegisterComponents('Transparent Controls', [TTransparentGroupbox]);
end;
end.
[Update 2] Looks to be a workaround: using the color chosen by the system as "transparent" as brush color works:
Brush.Style := bsSolid;
Brush.Color := Pixels[0,0];
FillRect(R);
However, I could not figure out a reliable source for this color. The arbitrary coordinates (0,0) might not work in all cases.
