Erasing canvas area in old Delphi

102 Views Asked by At

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);):

enter image description here

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.

0

There are 0 best solutions below