1

When I have this:

if not _nightMode then
  TStyleManager.TrySetStyle('Windows', False);

I can owner-draw on Page Control:

procedure TMyMainForm.pcDetailedDrawTab(Control: TCustomTabControl; TabIndex: Integer;
    const Rect: TRect; Active: Boolean);
var
  can: TCanvas;
  cx, by: Integer;
  aclr: TColor;
begin
  if pcDetailed.Pages[TabIndex] = tsActualData then begin
    can := pcDetailed.Canvas;
    cx := Rect.Left + Rect.Width div 2;
    by := Rect.Bottom - 2;
    if _nightMode then aclr := clWhite else aclr := clBlack;
    can.Pen.Color := aclr;
    can.Brush.Color := aclr;
    can.Polygon([Point(cx - 10, by - 10), Point(cx + 10, by - 10), Point(cx, by)]);
  end;
end;

When I have this:

if _nightMode then
  TStyleManager.TrySetStyle('Cobalt XEMedia', False);

my drawn triangle goes lost.

How to draw a triangle with any VCL style?

Delphi 10 Seattle.

asd-tm
  • 3,381
  • 2
  • 24
  • 41
Paul
  • 25,812
  • 38
  • 124
  • 247

1 Answers1

3

When Styles other than the native 'Windows'-style are chosen a StyleHook-class will begin to hook paint relevant windows messages to controls. There are different StyleHook classes for different control classes.

In case of the TPageControl it is the TTabControlStyleHook. The hook-class-combination is registered with TCustomStyleEngine.RegisterStyleHook(TCustomTabControl, TTabControlStyleHook); in the class constructor of TCustomTabControl. This hook class is overriding the controls paint, because it will paint the TCustomTabControl itself when a Style is enabled.

What can be done is unregister the default TStyleHookClass and register one that will let the developer paint:

  TCustomStyleEngine.UnRegisterStyleHook(TCustomTabControl, TTabControlStyleHook);
  TCustomStyleEngine.RegisterStyleHook(TCustomTabControl, TMyTabControlStyleHook);

Where TMyTabControlStyleHook is following:

type
  TMyTabControlStyleHook = class(TTabControlStyleHook)
  public
    constructor Create(AControl: TWinControl); override;
  end;

constructor TMyTabControlStyleHook.Create(AControl: TWinControl);
begin
  inherited Create(AControl);
  OverridePaint := False;
end;

This is however not the exact equivalent to only painting the tabs in the TPageControl, as the TTabControlStyleHook is responsible for painting the complete TPageControl control.

But TTabControlStyleHook has the procedure DrawTab(Canvas: TCanvas; Index: Integer); virtual; which can be overridden for that.

type
  TMyTabControlStyleHook = class(TTabControlStyleHook)
  strict protected
    procedure DrawTab(Canvas: TCanvas; Index: Integer); override;
  end;

procedure TMyTabControlStyleHook.DrawTab(Canvas: TCanvas; Index: Integer);
begin
  DrawTabOverride(Canvas, Index, TabRect[Index], TCustomTabControl(Control).MouseInClient);
end;

Where DrawTabOverride is something like this

procedure DrawTabOverride(Canvas: TCanvas;
  TabIndex: Integer; const Rect: TRect; Active: Boolean);

so it can be called in the OnDrawTab event when drawing native and in the StyleHook class DrawTab when styled.

nil
  • 1,320
  • 1
  • 10
  • 21