Files
HeidiSQL/source/vcl-styles-utils/Vcl.Styles.Utils.ComCtrls.pas

2827 lines
84 KiB
ObjectPascal

//**************************************************************************************************
//
// Unit Vcl.Styles.Utils.ComCtrls
// unit for the VCL Styles Utils
// https://github.com/RRUZ/vcl-styles-utils/
//
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
// you may not use this file except in compliance with the License. You may obtain a copy of the
// License at http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
// ANY KIND, either express or implied. See the License for the specific language governing rights
// and limitations under the License.
//
//
// Portions created by Mahdi Safsafi [SMP3] e-mail SMP@LIVE.FR
// Portions created by Rodrigo Ruz V. are Copyright (C) 2013-2023 Rodrigo Ruz V.
// All Rights Reserved.
//
//************************************************************************************************
unit Vcl.Styles.Utils.ComCtrls;
{$I VCL.Styles.Utils.inc}
interface
uses
System.Classes,
System.Types,
System.SysUtils,
Winapi.Windows,
Winapi.Messages,
Winapi.CommCtrl,
Winapi.RichEdit,
Vcl.Styles,
Vcl.Themes,
Vcl.Graphics,
{$IFDEF USE_Vcl.Styles.Hooks}
Vcl.Styles.Hooks,
{$ENDIF}
Vcl.Styles.Utils.SysStyleHook,
Vcl.Styles.Utils.StdCtrls,
Vcl.Forms,
Vcl.ImgList,
Vcl.ComCtrls,
Vcl.ExtCtrls,
Vcl.Styles.Utils.Forms,
Vcl.Controls;
type
TSysListViewStyleHook = class(TSysScrollingStyleHook)
private type
{$REGION 'TSysHeaderStyleHook'}
TSysHeaderStyleHook = class(TMouseTrackSysControlStyleHook)
private type
{$REGION 'TSysSection'}
TSysSection = class
private
FIndex: Integer;
FColumnIndex: Integer;
FImageIndex: Integer;
FImageListHandle: THandle;
FText: String;
FSectionRect: TRect;
FHeaderHandle: THandle;
FHasSplitButton: Boolean;
FTextFormat: TTextFormat;
FBitmapOnRight: Boolean;
FShowImage: Boolean;
FDropDownRect: TRect;
protected
procedure DoGetSectionInfo;
public
constructor Create(SysParent: TSysControl; Index: Integer); virtual;
Destructor Destroy; override;
property Text: string read FText;
property ImageListHandle: THandle read FImageListHandle;
property ImageIndex: Integer read FImageIndex;
property SectionRect: TRect read FSectionRect;
property ColumnIndex: Integer read FColumnIndex;
property ShowImage: Boolean read FShowImage;
property BitmapOnRight: Boolean read FBitmapOnRight;
property TextFormat: TTextFormat read FTextFormat;
property HasSplitButton: Boolean read FHasSplitButton;
property DropDownRect: TRect read FDropDownRect;
end;
{$ENDREGION}
private
FPressedSection: Integer;
FMouseDown: Boolean;
FSysSection: TSysSection;
FListViewStyleHook: TSysListViewStyleHook;
function GetButtonsCount: Integer;
function GetItem(Index: Integer): TSysSection;
protected
procedure MouseLeave; override;
procedure WndProc(var Message: TMessage); override;
procedure Paint(Canvas: TCanvas); override;
procedure PaintBackground(Canvas: TCanvas); override;
public
constructor Create(AHandle: THandle); override;
Destructor Destroy; override;
property ButtonsCount: Integer read GetButtonsCount;
property Items[Index: Integer]: TSysSection read GetItem;
end;
{$ENDREGION}
private
FHeaderHandle: THandle;
FHeaderStyleHook: TSysHeaderStyleHook;
protected
procedure Scroll(const Kind: TScrollBarKind; const ScrollType: TSysScrollingType; Pos, Delta: Integer); override;
procedure UpdateColors; override;
procedure WndProc(var Message: TMessage); override;
procedure PaintBackground(Canvas: TCanvas); override;
procedure Paint(Canvas: TCanvas); override;
public
procedure SetSelectedColumn(iCol: Integer);
constructor Create(AHandle: THandle); override;
Destructor Destroy; override;
property HeaderHandle: THandle read FHeaderHandle write FHeaderHandle;
end;
TSysTreeViewStyleHook = class(TSysScrollingStyleHook)
protected
procedure Scroll(const Kind: TScrollBarKind; const ScrollType: TSysScrollingType; Pos, Delta: Integer); override;
procedure UpdateColors; override;
procedure WndProc(var Message: TMessage); override;
public
constructor Create(AHandle: THandle); override;
Destructor Destroy; override;
end;
TSysTabControlStyleHook = class(TMouseTrackSysControlStyleHook)
private
FHotTabIndex: Integer;
function GetDisplayRect: TRect;
function GetTabCount: Integer;
function GetTabIndex: Integer;
function GetImages: TCustomImageList;
function GetTabRect(Index: Integer): TRect;
function GetTabPosition: TTabPosition;
function GetTabs(Index: Integer): string;
procedure AngleTextOut(Canvas: TCanvas; const Angle, X, Y: Integer; const Text: string);
protected
procedure DrawTab(Canvas: TCanvas; const Index: Integer);
procedure PaintBackground(Canvas: TCanvas); override;
procedure Paint(Canvas: TCanvas); override;
procedure PaintNC(Canvas: TCanvas); override;
procedure WndProc(var Message: TMessage); override;
public
constructor Create(AHandle: THandle); override;
Destructor Destroy; override;
property DisplayRect: TRect read GetDisplayRect;
property TabCount: Integer read GetTabCount;
property TabIndex: Integer read GetTabIndex;
property Images: TCustomImageList read GetImages;
property TabRect[Index: Integer]: TRect read GetTabRect;
property TabPosition: TTabPosition read GetTabPosition;
property Tabs[Index: Integer]: string read GetTabs;
end;
TSysRichEditStyleHook = class(TSysScrollingStyleHook)
strict private
procedure EMSetBkgndColor(var Message: TMessage); message EM_SETBKGNDCOLOR;
procedure EMSetCharFormat(var Message: TMessage); message EM_SETCHARFORMAT;
strict private
FBackColor: TColor;
protected
procedure UpdateColors; override;
procedure WndProc(var Message: TMessage); override;
function GetBorderSize: TRect; override;
public
property BackColor: TColor read FBackColor write FBackColor;
constructor Create(AHandle: THandle); override;
end;
type
TSysToolbarButtonState = set of (bsEnabled, bsPressed, bsChecked, bsHidden);
TSysToolbarButtonStyle = set of (bsBtn, bsSep, bsCheck, bsGroup, bsCheckGroup, bsDropDown);
TSysReBarStyleHook = class(TSysStyleHook)
strict private
function GetBandText(const Index: Integer): string;
function GetBandRect(const Index: Integer): TRect;
function GetBandBorder(const Index: Integer): TRect;
function GetBandCount: Integer;
strict protected
procedure PaintBackground(Canvas: TCanvas); override;
procedure Paint(Canvas: TCanvas); override;
procedure PaintNC(Canvas: TCanvas); override;
procedure WndProc(var Message: TMessage); override;
public
constructor Create(AHandle: THandle); override;
end;
TSysStatusBarStyleHook = class(TSysStyleHook)
strict protected
procedure Paint(Canvas: TCanvas); override;
procedure WndProc(var Message: TMessage); override;
public
constructor Create(AHandle: THandle); override;
end;
TSysTrackBarStyleHook = class(TSysStyleHook)
strict private
FMouseOnThumb: Boolean;
FThumbPressed: Boolean;
strict protected
procedure Paint(Canvas: TCanvas); override;
procedure PaintBackground(Canvas: TCanvas); override;
procedure WndProc(var Message: TMessage); override;
public
constructor Create(AHandle: THandle); override;
end;
TSysToolbarStyleHook = class(TMouseTrackSysControlStyleHook)
private type
{$REGION 'TSysToolbarButton'}
TSysToolbarButton = class
private
FParent: TSysControl;
FIndex: Integer;
FText: String;
FImageIndex: Integer;
FState: TSysToolbarButtonState;
FStyle: TSysToolbarButtonStyle;
function GetItemRect: TRect;
procedure DoGetItemInfo;
function GetDropDownWidth: Integer;
public
constructor Create(SysParent: TSysControl; Index: Integer); virtual;
Destructor Destroy; override;
property ItemRect: TRect read GetItemRect;
property Parent: TSysControl read FParent;
property Text: String Read FText;
Property ImageIndex: Integer read FImageIndex;
property State: TSysToolbarButtonState read FState;
property Style: TSysToolbarButtonStyle read FStyle;
property DropDownWidth: Integer read GetDropDownWidth;
end;
{$ENDREGION}
var
FImages: TImageList;
FDisabledImages: TImageList;
FSysToolbarButton: TSysToolbarButton;
FButtonsPainted: Boolean;
function GetItem(Index: Integer): TSysToolbarButton;
function GetCount: Integer;
function IsToolbarTransparent: Boolean;
function IsToolbarFlat: Boolean;
function GetShowText: Boolean;
function IsToolbarList: Boolean;
function IsToolbarWrapable: Boolean;
protected
procedure ApplyImageList;
procedure PaintBackground(Canvas: TCanvas); override;
procedure Paint(Canvas: TCanvas); override;
procedure PaintNC(Canvas: TCanvas); override;
procedure WndProc(var Message: TMessage); override;
public
constructor Create(AHandle: THandle); override;
Destructor Destroy; override;
property Items[index: Integer]: TSysToolbarButton read GetItem;
property Count: Integer read GetCount;
Property Flat: Boolean Read IsToolbarFlat;
Property Transparent: Boolean Read IsToolbarTransparent;
property ShowText: Boolean read GetShowText;
property List: Boolean read IsToolbarList;
property Wrapable: Boolean read IsToolbarWrapable;
end;
TSysProgressBarStyleHook = class(TSysStyleHook)
strict private
FStep: Integer;
// FLastPos: Integer;
FOrientation: TProgressBarOrientation;
FTimer: TTimer;
procedure TimerAction(Sender: TObject);
function GetBarRect: TRect;
function GetBorderWidth: Integer;
function GetMax: Integer;
function GetMin: Integer;
function GetOrientation: TProgressBarOrientation;
function GetPercent: Single;
function GetPosition: Integer;
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
strict protected
procedure PaintBackground(Canvas: TCanvas); override;
procedure PaintBar(Canvas: TCanvas); virtual;
procedure PaintFrame(Canvas: TCanvas); virtual;
procedure Paint(Canvas: TCanvas); override;
procedure WndProc(var Message: TMessage); override;
property BarRect: TRect read GetBarRect;
property BorderWidth: Integer read GetBorderWidth;
property Max: Integer read GetMax;
property Min: Integer read GetMin;
property Orientation: TProgressBarOrientation read GetOrientation;
property Position: Integer read GetPosition;
public
constructor Create(AHandle: THandle); override;
destructor Destroy; override;
end;
TSysUpDownStyleHook = class(TMouseTrackSysControlStyleHook)
strict private
FLeftPressed, FRightPressed: Boolean;
FMouseOnLeft, FMouseOnRight: Boolean;
function GetOrientation: TUDOrientation;
procedure WMLButtonDblClk(var Message: TWMMouse); message WM_LBUTTONDBLCLK;
procedure WMLButtonDown(var Message: TWMMouse); message WM_LBUTTONDOWN;
procedure WMLButtonUp(var Message: TWMMouse); message WM_LBUTTONUP;
procedure WMMouseMove(var Message: TWMMouse); message WM_MOUSEMOVE;
protected
procedure Paint(Canvas: TCanvas); override;
procedure MouseLeave; override;
procedure WndProc(var Message: TMessage); override;
public
constructor Create(AHandle: THandle); override;
destructor Destroy; override;
end;
TSysLinkStyleHook = class(TSysStaticStyleHook)
private
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
protected
procedure PaintNC(Canvas: TCanvas); override;
procedure Paint(Canvas: TCanvas); override;
procedure WndProc(var Message: TMessage); override;
public
constructor Create(AHandle: THandle); override;
Destructor Destroy; override;
end;
implementation
uses
// IOUtils,
Vcl.Styles.Utils.SysControls, Vcl.Styles.Utils.Graphics;
//
// procedure Addlog(const Msg: string);
// begin
// TFile.AppendAllText('C:\Test\log.txt',Format('%s %s %s',[FormatDateTime('hh:nn:ss.zzz', Now), msg, sLineBreak]));
// end;
{ TSysListViewStyleHook }
constructor TSysListViewStyleHook.Create(AHandle: THandle);
begin
inherited;
FHeaderStyleHook := nil;
FHeaderHandle := 0;
{$IF CompilerVersion > 23}
StyleElements := [seFont, seBorder];
{$ELSE}
OverridePaint := False;
OverridePaintNC := True;
OverrideFont := True;
{$IFEND}
OverrideEraseBkgnd := True;
SendMessage(Handle, WM_NOTIFY, 0, 0);
end;
procedure TSysListViewStyleHook.Scroll(const Kind: TScrollBarKind; const ScrollType: TSysScrollingType; Pos, Delta: Integer);
var
R: TRect;
begin
if ScrollType = skTracking then
begin
if Kind = sbVertical then
begin
if ListView_GetView(Handle) = LVS_REPORT then
begin
R := Rect(0, 0, 0, 0);
ListView_GetItemRect(Handle, 0, R, LVIR_BOUNDS);
Delta := Delta * R.Height;
end;
ListView_Scroll(Handle, 0, Delta);
end;
if Kind = sbHorizontal then
begin
if ListView_GetView(Handle) = LVS_LIST then
begin
R := TRect.Empty;
ListView_GetItemRect(Handle, 0, R, LVIR_BOUNDS);
Delta := Delta * R.Width;
end;
ListView_Scroll(Handle, Delta, 0);
end;
end
else
inherited;
end;
procedure TSysListViewStyleHook.SetSelectedColumn(iCol: Integer);
begin
ListView_SetSelectedColumn(Handle, iCol);
end;
destructor TSysListViewStyleHook.Destroy;
begin
if Assigned(FHeaderStyleHook) then
FreeAndNil(FHeaderStyleHook);
inherited;
end;
procedure TSysListViewStyleHook.UpdateColors;
begin
inherited;
if OverrideEraseBkgnd then
Color := StyleServices.GetStyleColor(scListView)
else
Color := clWindow;
if OverrideFont then
FontColor := StyleServices.GetSystemColor(clWindowText)
else
FontColor := clWindowText;
ListView_SetBkColor(Handle, ColorToRGB(Color));
ListView_SetTextBkColor(Handle, ColorToRGB(Color));
ListView_SetTextColor(Handle, ColorToRGB(FontColor));
end;
procedure TSysListViewStyleHook.WndProc(var Message: TMessage);
begin
case Message.Msg of
WM_CREATE, LVM_UPDATE:
begin
Message.Result := CallDefaultProc(Message);
UpdateColors;
SetSelectedColumn(-1);
Exit;
end;
WM_ERASEBKGND:
begin
UpdateColors;
SetSelectedColumn(-1);
Message.Result := CallDefaultProc(Message);
Exit;
end;
WM_NOTIFY:
begin
if not Assigned(FHeaderStyleHook) then
begin
HeaderHandle := ListView_GetHeader(Handle);
if (HeaderHandle <> 0) then
begin
FHeaderStyleHook := TSysHeaderStyleHook.Create(HeaderHandle);
FHeaderStyleHook.FListViewStyleHook := Self;
end;
end;
if (Message.WParam <> 0) or (Message.LParam <> 0) then
Message.Result := CallDefaultProc(Message);
Exit;
end;
else inherited;
end;
end;
{ TSysListViewStyleHook.TSysHeaderStyleHook }
constructor TSysListViewStyleHook.TSysHeaderStyleHook.Create(AHandle: THandle);
begin
inherited;
{$IF CompilerVersion > 23}
StyleElements := [seClient];
{$ELSE}
OverridePaint := True;
OverridePaintNC := False;
OverrideFont := False;
{$IFEND}
FPressedSection := -1;
FSysSection := nil;
end;
destructor TSysListViewStyleHook.TSysHeaderStyleHook.Destroy;
begin
if Assigned(FSysSection) then
FreeAndNil(FSysSection);
inherited;
end;
function TSysListViewStyleHook.TSysHeaderStyleHook.GetButtonsCount: Integer;
begin
Result := Header_GetItemCount(Handle);
end;
function TSysListViewStyleHook.TSysHeaderStyleHook.GetItem(Index: Integer): TSysSection;
begin
Result := nil;
if (Index > -1) and (index < ButtonsCount) then
begin
if Assigned(FSysSection) then
FreeAndNil(FSysSection);
FSysSection := TSysSection.Create(SysControl, Index);
Result := FSysSection;
end;
end;
procedure TSysListViewStyleHook.TSysHeaderStyleHook.MouseLeave;
begin
Invalidate;
end;
procedure TSysListViewStyleHook.TSysHeaderStyleHook.Paint(Canvas: TCanvas);
var
i: Integer;
Bmp: TBitmap;
LImageList: TImageList;
R, TxtRect, ImgRect: TRect;
LSectionRect: TRect;
LTextFormat: TTextFormat;
LText: String;
LSplitDetails, LDetails: TThemedElementDetails;
DC: HDC;
SectionHot: Boolean;
LDropDownRect: TRect;
P: TPoint;
begin
Bmp := TBitmap.Create;
try
Bmp.SetSize(SysControl.Width, SysControl.Height);
Bmp.Canvas.Brush.Color := Color;
R := Rect(0, 0, Bmp.Width, Bmp.Height);
Bmp.Canvas.FillRect(R);
DC := Bmp.Canvas.Handle;
LDetails := StyleServices.GetElementDetails(thHeaderItemNormal);
DrawStyleElement(DC, LDetails, R);
for i := 0 to ButtonsCount - 1 do
begin
with Items[i] do
begin
LSectionRect := SectionRect;
LTextFormat := TextFormat;
LText := Text;
LDropDownRect := DropDownRect;
end;
SectionHot := False;
if (MouseInControl) and (not FMouseDown) then
begin
GetCursorPos(P);
ScreenToClient(Handle, P);
if LSectionRect.Contains(P) then
SectionHot := True;
end;
LDetails := StyleServices.GetElementDetails(thHeaderItemNormal);
if SectionHot then
LDetails := StyleServices.GetElementDetails(thHeaderItemHot);
if FPressedSection = i then
LDetails := StyleServices.GetElementDetails(thHeaderItemPressed);
DrawStyleElement(DC, LDetails, LSectionRect);
TxtRect := LSectionRect;
inc(TxtRect.Left, 4);
if Items[i].HasSplitButton then
begin
LSplitDetails := StyleServices.GetElementDetails(ttbDropDownButtonGlyphHot);;
R := LDropDownRect;
if SectionHot then
begin
DrawStyleElement(DC, LSplitDetails, R);
with Bmp.Canvas do
begin
Pen.Color := StyleServices.GetSystemColor(clBtnShadow);
MoveTo(R.Left, 3);
LineTo(R.Left, R.Height - 3);
Pen.Color := StyleServices.GetSystemColor(clBtnHighLight);
MoveTo(R.Left - 1, 3);
LineTo(R.Left - 1, R.Height - 3);
end;
end;
dec(TxtRect.Right, R.Width);
end;
if (Items[i].ShowImage) and (Items[i].ImageListHandle > 0) then
begin
LImageList := TImageList.Create(nil);
try
LImageList.Handle := Items[i].ImageListHandle;
LImageList.Masked := True;
LImageList.BkColor := clNone; { Transparent bitmap }
R := LSectionRect;
ImgRect := Rect(0, 0, LImageList.Width, LImageList.Height);
ImgRect := RectCenter(ImgRect, R);
if not Items[i].BitmapOnRight then
begin
ImgRect.Left := R.Left + 2;
ImgRect.Right := ImgRect.Left + 2 + LImageList.Width;
inc(TxtRect.Left, ImgRect.Width + 2);
end
else
begin
ImgRect.Left := LSectionRect.Right - LImageList.Width - 2;
ImgRect.Right := LSectionRect.Right;
TxtRect.Right := TxtRect.Right - ImgRect.Width - 2;
end;
LImageList.Draw(Bmp.Canvas, ImgRect.Left, ImgRect.Top, Items[i].ImageIndex);
finally
LImageList.Free;
end;
end;
include(LTextFormat, tfSingleLine);
include(LTextFormat, tfVerticalCenter);
StyleServices.DrawText(DC, LDetails, LText, TxtRect, LTextFormat);
end;
Canvas.Draw(0, 0, Bmp);
finally
Bmp.Free;
end;
end;
procedure TSysListViewStyleHook.TSysHeaderStyleHook.PaintBackground(Canvas: TCanvas);
begin
// inherited;
{ Leave this block clean . }
end;
procedure TSysListViewStyleHook.Paint(Canvas: TCanvas);
begin
{ Leave this block clean . }
end;
procedure TSysListViewStyleHook.PaintBackground(Canvas: TCanvas);
begin
{ Leave this block clean . }
end;
procedure TSysListViewStyleHook.TSysHeaderStyleHook.WndProc(var Message: TMessage);
var
Info: THDHitTestInfo;
begin
case Message.Msg of
WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
begin
FMouseDown := True;
Info.Point.X := TWMMouse(Message).XPos;
Info.Point.Y := TWMMouse(Message).YPos;
SendMessage(Handle, HDM_HITTEST, 0, IntPtr(@Info));
if (Info.Flags and HHT_ONDIVIDER = 0) and (Info.Flags and HHT_ONDIVOPEN = 0) then
FPressedSection := Info.item
else
FPressedSection := -1;
end;
WM_LBUTTONUP, WM_RBUTTONUP:
begin
FMouseDown := False;
FPressedSection := -1;
end;
end;
inherited;
end;
{ TSysListViewStyleHook.TSysHeaderStyleHook.TSysSection }
constructor TSysListViewStyleHook.TSysHeaderStyleHook.TSysSection.Create(SysParent: TSysControl; Index: Integer);
begin
inherited Create;
FTextFormat := [];
FIndex := Index;
FText := '';
FImageListHandle := 0;
FImageIndex := -1;
FColumnIndex := -1;
FSectionRect := TRect.Empty;
FDropDownRect := TRect.Empty;
FHasSplitButton := False;
FShowImage := False;
FHeaderHandle := SysParent.Handle;
DoGetSectionInfo;
end;
destructor TSysListViewStyleHook.TSysHeaderStyleHook.TSysSection.Destroy;
begin
inherited;
end;
procedure TSysListViewStyleHook.TSysHeaderStyleHook.TSysSection.DoGetSectionInfo;
var
SectionOrder: array of Integer;
R: TRect;
item: THDItem;
Buffer: array [0 .. 255] of Char;
LRtlReading: Boolean;
begin
FillChar(Buffer, 255, Char(0));
SetLength(SectionOrder, Header_GetItemCount(FHeaderHandle));
Header_GetOrderArray(FHeaderHandle, Header_GetItemCount(FHeaderHandle), Pointer(SectionOrder));
FColumnIndex := SectionOrder[FIndex];
Header_GetItemRect(FHeaderHandle, ColumnIndex, @R);
FSectionRect := R;
FillChar(item, sizeof(item), 0);
item.mask := HDI_TEXT or HDI_FORMAT or HDI_IMAGE;
item.pszText := @Buffer;
item.cchTextMax := Length(Buffer);
if Header_GetItem(FHeaderHandle, FColumnIndex, item) then
begin
with item do
begin
FImageIndex := iImage;
FText := String(pszText);
FHasSplitButton := (fmt and HDF_SPLITBUTTON = HDF_SPLITBUTTON);
LRtlReading := (fmt and HDF_RTLREADING = HDF_RTLREADING);
FTextFormat := [];
if (fmt and HDF_LEFT = HDF_LEFT) then
include(FTextFormat, tfLeft)
else if (fmt and HDF_RIGHT = HDF_RIGHT) then
include(FTextFormat, tfRight)
else if (fmt and HDF_CENTER = HDF_CENTER) then
include(FTextFormat, tfCenter);
if LRtlReading then
include(FTextFormat, tfRtlReading);
FBitmapOnRight := (fmt and HDF_BITMAP_ON_RIGHT = HDF_BITMAP_ON_RIGHT);
FShowImage := (FImageIndex > -1) and (fmt and HDF_BITMAP = HDF_BITMAP);
end;
end;
R := TRect.Empty;
if Header_GetItemDropDownRect(FHeaderHandle, FIndex, R) then
FDropDownRect := R;
FImageListHandle := Header_GetImageList(FHeaderHandle);
end;
{ TSysTreeViewStyleHook }
constructor TSysTreeViewStyleHook.Create(AHandle: THandle);
begin
inherited;
{$IF CompilerVersion > 23}
StyleElements := [seFont{, seBorder}]; //Allow to the Vcl.Styles.Hook handle the NC and scroll paint
{$ELSE}
OverrideFont := True;
OverridePaintNC := False; //Allow to the Vcl.Styles.Hook handle the NC and scroll paint
{$IFEND}
OverrideEraseBkgnd := True;
end;
destructor TSysTreeViewStyleHook.Destroy;
begin
inherited;
end;
procedure TSysTreeViewStyleHook.Scroll(const Kind: TScrollBarKind;
const ScrollType: TSysScrollingType; Pos, Delta: Integer);
begin
if Kind = sbVertical then
begin
case ScrollType of
skTracking:
begin
LstPos := Pos;
//OutputDebugString(PChar(Format('sbVertical Pos %d Delta %d AllowScrolling %s', [Pos, Delta, BooltoStr(AllowScrolling, True)])));
AllowScrolling := True;
SendMessage(Handle, WM_VSCROLL, MakeWParam(SB_THUMBTRACK, Pos), 0);
AllowScrolling := False;
//OutputDebugString(PChar(Format('sbVertical Pos %d Delta %d', [Pos, Delta])));
end;
skLineUp: SendMessage(Handle, WM_VSCROLL, SB_LINEUP, 0);
skLineDown: SendMessage(Handle, WM_VSCROLL, SB_LINEDOWN, 0);
skPageUp: SendMessage(Handle, WM_VSCROLL, SB_PAGEUP, 0);
skPageDown: SendMessage(Handle, WM_VSCROLL, SB_PAGEDOWN, 0);
end;
end
else
if Kind = sbHorizontal then
begin
case ScrollType of
skTracking:
begin
LstPos := Pos;
//OutputDebugString(PChar(Format('sbHorizontal Pos %d Delta %d AllowScrolling %s', [Pos, Delta, BooltoStr(AllowScrolling, True)])));
AllowScrolling := True;
SendMessage(Handle, WM_HSCROLL, MakeWParam(SB_THUMBTRACK, Pos), 0);
AllowScrolling := False;
//OutputDebugString(PChar(Format('sbHorizontal Pos %d Delta %d', [Pos, Delta])));
end;
skLineLeft: SendMessage(Handle, WM_HSCROLL, SB_LINELEFT, 0);
skLineRight: SendMessage(Handle, WM_HSCROLL, SB_LINERIGHT, 0);
skPageLeft: SendMessage(Handle, WM_HSCROLL, SB_PAGELEFT, 0);
skPageRight: SendMessage(Handle, WM_HSCROLL, SB_PAGERIGHT, 0);
end;
end;
end;
procedure TSysTreeViewStyleHook.UpdateColors;
begin
inherited;
if OverrideEraseBkgnd then
Color := StyleServices.GetStyleColor(scTreeView)
else
Color := clWhite;
if OverrideFont then
FontColor := StyleServices.GetSystemColor(clWindowText)
else
FontColor := clWindowText;
end;
procedure TSysTreeViewStyleHook.WndProc(var Message: TMessage);
begin
case Message.Msg of
WM_ERASEBKGND:
begin
UpdateColors;
if (Longint(TreeView_GetBkColor(Handle))<>ColorToRGB(Color)) then
TreeView_SetBkColor(Handle, ColorToRGB(Color));
if (Longint(TreeView_GetTextColor(Handle))<>ColorToRGB(FontColor)) then
TreeView_SetTextColor(Handle, ColorToRGB(FontColor));
Message.Result := CallDefaultProc(Message);
Exit;
end;
else inherited;
end;
end;
{ TSysTabControlStyleHook }
procedure TSysTabControlStyleHook.AngleTextOut(Canvas: TCanvas; const Angle, X, Y: Integer; const Text: string);
var
SaveIndex: Integer;
begin
SaveIndex := SaveDC(Canvas.Handle);
try
SetBkMode(Canvas.Handle, Transparent);
Canvas.Font.Orientation := Angle;
Canvas.TextOut(X, Y, Text);
finally
RestoreDC(Canvas.Handle, SaveIndex);
end;
end;
constructor TSysTabControlStyleHook.Create(AHandle: THandle);
begin
inherited;
{$IF CompilerVersion > 23}
StyleElements := [seClient, seFont];
{$ELSE}
OverridePaint := True;
OverridePaintNC := False;
OverrideFont := True;
{$IFEND}
// OverrideEraseBkgnd:=True;
FHotTabIndex := -1;
end;
destructor TSysTabControlStyleHook.Destroy;
begin
inherited;
end;
function TSysTabControlStyleHook.GetDisplayRect: TRect;
begin
//Result := Rect(0, 0, 0, 0);
Result := SysControl.ClientRect;
SendMessage(Handle, TCM_ADJUSTRECT, 0, IntPtr(@Result));
inc(Result.Top, 2);
end;
function TSysTabControlStyleHook.GetImages: TCustomImageList;
begin
Result := nil;
end;
function TSysTabControlStyleHook.GetTabCount: Integer;
begin
Result := SendMessage(Handle, TCM_GETITEMCOUNT, 0, 0);
end;
function TSysTabControlStyleHook.GetTabIndex: Integer;
begin
Result := SendMessage(Handle, TCM_GETCURSEL, 0, 0);
end;
function TSysTabControlStyleHook.GetTabPosition: TTabPosition;
begin
Result := tpTop;
end;
function TSysTabControlStyleHook.GetTabRect(Index: Integer): TRect;
begin
Result := Rect(0, 0, 0, 0);
TabCtrl_GetItemRect(Handle, Index, Result);
end;
function TSysTabControlStyleHook.GetTabs(Index: Integer): string;
var
TCItem: TTCItem;
Buffer: array [0 .. 254] of Char;
begin
FillChar(TCItem, sizeof(TCItem), 0);
TCItem.mask := TCIF_TEXT;
TCItem.pszText := @Buffer;
TCItem.cchTextMax := sizeof(Buffer);
if SendMessageW(Handle, TCM_GETITEMW, Index, IntPtr(@TCItem)) <> 0 then
Result := TCItem.pszText
else
Result := '';
end;
procedure TSysTabControlStyleHook.Paint(Canvas: TCanvas);
var
R: TRect;
i, SaveIndex: Integer;
Details: TThemedElementDetails;
begin
SaveIndex := SaveDC(Canvas.Handle);
try
R := DisplayRect;
ExcludeClipRect(Canvas.Handle, R.Left, R.Top, R.Right, R.Bottom);
PaintBackground(Canvas);
finally
RestoreDC(Canvas.Handle, SaveIndex);
end;
{ Draw tabs }
for i := 0 to TabCount - 1 do
begin
// if I = TabIndex then
// Continue;
DrawTab(Canvas, i);
end;
case TabPosition of
tpTop: InflateRect(R, SysControl.Width - R.Right, SysControl.Height - R.Bottom);
tpLeft: InflateRect(R, SysControl.Width - R.Right, SysControl.Height - R.Bottom);
tpBottom: InflateRect(R, R.Left, R.Top);
tpRight: InflateRect(R, R.Left, R.Top);
end;
if StyleServices.Available then
begin
Details := StyleServices.GetElementDetails(ttPane);
DrawStyleElement(Canvas.Handle, Details, R);
end;
{ Draw active tab }
if TabIndex >= 0 then
DrawTab(Canvas, TabIndex);
end;
procedure TSysTabControlStyleHook.DrawTab(Canvas: TCanvas; const Index: Integer);
var
R, LayoutR, GlyphR: TRect;
ImageWidth, ImageHeight, ImageStep, TX, TY: Integer;
DrawState: TThemedTab;
Details: TThemedElementDetails;
ThemeTextColor: TColor;
FImageIndex: Integer;
begin
if (Images <> nil) and (Index < Images.Count) then
begin
ImageWidth := Images.Width;
ImageHeight := Images.Height;
ImageStep := 3;
end
else
begin
ImageWidth := 0;
ImageHeight := 0;
ImageStep := 0;
end;
R := TabRect[Index];
if R.Left < 0 then
Exit;
if TabPosition in [tpTop, tpBottom] then
begin
if Index = TabIndex then
InflateRect(R, 0, 2);
end
else if Index = TabIndex then
dec(R.Left, 2)
else
dec(R.Right, 2);
// Canvas.Font.Assign(TCustomTabControl(Control).Font);
LayoutR := R;
DrawState := ttTabDontCare;
case TabPosition of
tpTop:
begin
if Index = TabIndex then
DrawState := ttTabItemSelected
else if (Index = FHotTabIndex) and MouseInControl then
DrawState := ttTabItemHot
else
DrawState := ttTabItemNormal;
end;
tpLeft:
begin
if Index = TabIndex then
DrawState := ttTabItemLeftEdgeSelected
else if (Index = FHotTabIndex) and MouseInControl then
DrawState := ttTabItemLeftEdgeHot
else
DrawState := ttTabItemLeftEdgeNormal;
end;
tpBottom:
begin
if Index = TabIndex then
DrawState := ttTabItemBothEdgeSelected
else if (Index = FHotTabIndex) and MouseInControl then
DrawState := ttTabItemBothEdgeHot
else
DrawState := ttTabItemBothEdgeNormal;
end;
tpRight:
begin
if Index = TabIndex then
DrawState := ttTabItemRightEdgeSelected
else if (Index = FHotTabIndex) and MouseInControl then
DrawState := ttTabItemRightEdgeHot
else
DrawState := ttTabItemRightEdgeNormal;
end;
end;
if StyleServices.Available then
begin
Details := StyleServices.GetElementDetails(DrawState);
DrawStyleElement(Canvas.Handle, Details, R);
end;
{ Image }
FImageIndex := Index;
if (Images <> nil) and (FImageIndex >= 0) and (FImageIndex < Images.Count) then
begin
GlyphR := LayoutR;
case TabPosition of
tpTop, tpBottom:
begin
GlyphR.Left := GlyphR.Left + ImageStep;
GlyphR.Right := GlyphR.Left + ImageWidth;
LayoutR.Left := GlyphR.Right;
GlyphR.Top := GlyphR.Top + (GlyphR.Bottom - GlyphR.Top) div 2 - ImageHeight div 2;
if (TabPosition = tpTop) and (Index = TabIndex) then
OffsetRect(GlyphR, 0, -1)
else if (TabPosition = tpBottom) and (Index = TabIndex) then
OffsetRect(GlyphR, 0, 1);
end;
tpLeft:
begin
GlyphR.Bottom := GlyphR.Bottom - ImageStep;
GlyphR.Top := GlyphR.Bottom - ImageHeight;
LayoutR.Bottom := GlyphR.Top;
GlyphR.Left := GlyphR.Left + (GlyphR.Right - GlyphR.Left) div 2 - ImageWidth div 2;
end;
tpRight:
begin
GlyphR.Top := GlyphR.Top + ImageStep;
GlyphR.Bottom := GlyphR.Top + ImageHeight;
LayoutR.Top := GlyphR.Bottom;
GlyphR.Left := GlyphR.Left + (GlyphR.Right - GlyphR.Left) div 2 - ImageWidth div 2;
end;
end;
if StyleServices.Available then
StyleServices.DrawIcon(Canvas.Handle, Details, GlyphR, Images.Handle, FImageIndex);
end;
{ Text }
if StyleServices.Available then
begin
if (TabPosition = tpTop) and (Index = TabIndex) then
OffsetRect(LayoutR, 0, -1)
else if (TabPosition = tpBottom) and (Index = TabIndex) then
OffsetRect(LayoutR, 0, 1);
if TabPosition = tpLeft then
begin
TX := LayoutR.Left + (LayoutR.Right - LayoutR.Left) div 2 - Canvas.TextHeight(Tabs[Index]) div 2;
TY := LayoutR.Top + (LayoutR.Bottom - LayoutR.Top) div 2 + Canvas.TextWidth(Tabs[Index]) div 2;
if StyleServices.GetElementColor(Details, ecTextColor, ThemeTextColor) then
Canvas.Font.Color := ThemeTextColor;
AngleTextOut(Canvas, 900, TX, TY, Tabs[Index]);
end
else if TabPosition = tpRight then
begin
TX := LayoutR.Left + (LayoutR.Right - LayoutR.Left) div 2 + Canvas.TextHeight(Tabs[Index]) div 2;
TY := LayoutR.Top + (LayoutR.Bottom - LayoutR.Top) div 2 - Canvas.TextWidth(Tabs[Index]) div 2;
if StyleServices.GetElementColor(Details, ecTextColor, ThemeTextColor) then
Canvas.Font.Color := ThemeTextColor;
AngleTextOut(Canvas, -900, TX, TY, Tabs[Index]);
end
else
StyleServices.DrawText(Canvas.Handle, Details, Tabs[Index], LayoutR, [tfSingleLine, tfVerticalCenter, tfCenter, tfNoClip]);
// DrawControlText(Canvas, Details, Tabs[Index], LayoutR,
// DT_VCENTER or DT_CENTER or DT_SINGLELINE or DT_NOCLIP);
end;
end;
procedure TSysTabControlStyleHook.PaintBackground(Canvas: TCanvas);
begin
inherited;
end;
procedure TSysTabControlStyleHook.PaintNC(Canvas: TCanvas);
begin
inherited;
end;
procedure TSysTabControlStyleHook.WndProc(var Message: TMessage);
begin
// Addlog(Format('TSysTabControlStyleHook $0x%x %s', [SysControl.Handle, WM_To_String(Message.Msg)]));
// case Message.Msg of
// WM_MOUSEMOVE:
// begin
//
// end;
// else
// inherited;
// end;
inherited;
end;
{ TSysToolbarStyleHook }
{$REGION 'TSysToolbarStyleHook'}
constructor TSysToolbarStyleHook.Create(AHandle: THandle);
begin
inherited;
{$IF CompilerVersion > 23}
StyleElements := [seClient, seFont];
{$ELSE}
OverridePaint := True;
OverrideFont := True;
{$IFEND}
OverrideEraseBkgnd := False;
FImages := nil;
FDisabledImages := nil;
FSysToolbarButton := nil;
FButtonsPainted := False;
end;
destructor TSysToolbarStyleHook.Destroy;
begin
if Assigned(FImages) then
FreeAndNil(FImages);
if Assigned(FDisabledImages) then
FreeAndNil(FDisabledImages);
if Assigned(FSysToolbarButton) then
FreeAndNil(FSysToolbarButton);
inherited;
end;
function TSysToolbarStyleHook.GetItem(Index: Integer): TSysToolbarButton;
begin
Result := nil;
if (Index > -1) and (index <= Count) then
begin
if Assigned(FSysToolbarButton) then
FreeAndNil(FSysToolbarButton);
FSysToolbarButton := TSysToolbarButton.Create(SysControl, Index);
Result := FSysToolbarButton;
end;
end;
function TSysToolbarStyleHook.GetShowText: Boolean;
begin
Result := (SysControl.Style and BTNS_SHOWTEXT = BTNS_SHOWTEXT);
end;
function TSysToolbarStyleHook.IsToolbarFlat: Boolean;
begin
{ MSDN :
In a flat toolbar, both the toolbar and the buttons are transparent
and hot-tracking is enabled.
}
Result := (SysControl.Style and TBSTYLE_FLAT = TBSTYLE_FLAT)
end;
function TSysToolbarStyleHook.IsToolbarList: Boolean;
begin
Result := (SysControl.Style and TBSTYLE_LIST = TBSTYLE_LIST);
end;
function TSysToolbarStyleHook.IsToolbarTransparent: Boolean;
begin
{ MSDN:
In a transparent toolbar, the toolbar is transparent but the buttons are not.
}
Result := (SysControl.Style and TBSTYLE_TRANSPARENT = TBSTYLE_TRANSPARENT)
end;
function TSysToolbarStyleHook.IsToolbarWrapable: Boolean;
begin
Result := (SysControl.Style and TBSTYLE_WRAPABLE = TBSTYLE_WRAPABLE)
end;
function TSysToolbarStyleHook.GetCount: Integer;
begin
Result := SendMessage(Handle, TB_BUTTONCOUNT, 0, 0);
end;
procedure TSysToolbarStyleHook.ApplyImageList;
var
H: LRESULT;
begin
H := SendMessage(Handle, TB_GETIMAGELIST, 0, 0);
if (H <> 0) and (FImages = nil) then
begin
FImages := TImageList.Create(nil);
FImages.ShareImages := True;
FImages.Handle := THandle(H);
end;
H := SendMessage(Handle, TB_GETDISABLEDIMAGELIST, 0, 0);
if (H <> 0) and (FDisabledImages = nil) then
begin
FDisabledImages := TImageList.Create(nil);
FDisabledImages.ShareImages := True;
FDisabledImages.Handle := THandle(H);
end;
end;
procedure TSysToolbarStyleHook.Paint(Canvas: TCanvas);
var
i: Integer;
ItemRect, R, R2: TRect;
LDetails: TThemedElementDetails;
DC: HDC;
LButtonHot: Boolean;
P: TPoint;
LStyle: TSysToolbarButtonStyle;
LState: TSysToolbarButtonState;
Bmp: TBitmap;
ImgRect, TxtRect: TRect;
LText: String;
LImageIndex, LDropDownWidth: Integer;
TxtFlags: DWORD;
TxtFormat: TTextFormat;
begin
Bmp := TBitmap.Create;
try
ApplyImageList;
if Assigned(FImages) then
begin
FImages.Masked := True;
FImages.BkColor := clNone; { Transparent bitmap }
end;
ImgRect := Rect(0, 0, 0, 0);
TxtRect := Rect(0, 0, 0, 0);
Bmp.SetSize(SysControl.Width, SysControl.Height);
R := Rect(0, 0, Bmp.Width, Bmp.Height);
// Bmp.Canvas.Brush.Color := StyleServices.GetStyleColor(scWindow);
// Bmp.Canvas.FillRect(R);
DC := Bmp.Canvas.Handle;
DrawParentBackground(DC);
TxtFlags := 0;
if (SysControl.Style and TBSTYLE_NOPREFIX = TBSTYLE_NOPREFIX) then
TxtFlags := DT_NOPREFIX;
if Flat or Transparent then
begin
{ Dont paint the toolbar background => the toolbar is transparent . }
end
else
begin
{ Toolbar is not transparent }
LDetails.Element := teToolBar;
LDetails.Part := 0;
LDetails.State := 0;
if StyleServices.HasTransparentParts(LDetails) then
StyleServices.DrawParentBackground(Handle, DC, LDetails, False);
DrawStyleElement(DC, LDetails, R);
end;
except
Bmp.Free;
Exit;
end;
try
{ Draw toolbar buttons }
for i := 0 to Count - 1 do
begin
if i = Count - 1 then
FButtonsPainted := True;
ItemRect := Items[i].ItemRect;
with Items[i] do
begin
LState := State;
LStyle := Style;
LText := Text;
LImageIndex := ImageIndex;
LDropDownWidth := DropDownWidth;
end;
LButtonHot := False;
if not(bsHidden in LState) then
begin
if MouseInControl then
begin
GetCursorPos(P);
ScreenToClient(Handle, P);
if ItemRect.Contains(P) then
LButtonHot := True;
end;
if (bsEnabled in LState) then
LDetails := StyleServices.GetElementDetails(ttbButtonNormal)
else
LDetails := StyleServices.GetElementDetails(ttbButtonDisabled);
if (LButtonHot) and (bsEnabled in LState) then
begin
LDetails := StyleServices.GetElementDetails(ttbButtonHot);
end;
if (bsPressed in LState) and (bsEnabled in LState) then
LDetails := StyleServices.GetElementDetails(ttbButtonPressed);
if bsChecked in LState then
LDetails := StyleServices.GetElementDetails(ttbButtonChecked);
if not(bsSep in LStyle) then
begin
if Flat then
begin
// Bmp.Canvas.FillRect(ItemRect);
DrawParentBackground(DC, @ItemRect);
if (LButtonHot or (bsPressed in LState) or (bsChecked in LState)) and (bsEnabled in LState) then
begin
DrawStyleElement(DC, LDetails, ItemRect);
end;
end
else
DrawStyleElement(DC, LDetails, ItemRect);
end
else
begin
LDetails := StyleServices.GetElementDetails(ttbSeparatorNormal);
DrawStyleElement(DC, LDetails, ItemRect);
end;
if not(bsSep in LStyle) then
begin
R := ItemRect;
ImgRect := TRect.Empty;
if Assigned(FImages) then
ImgRect := Rect(0, 0, FImages.Width, FImages.Height);
ImgRect := CenteredRect(R, ImgRect);
if bsDropDown in LStyle then
begin
{ If button is DropDown then draw the button glyph. }
R := ItemRect;
R := Rect(R.Right - LDropDownWidth, R.Top, R.Right, R.Bottom);
if bsEnabled in LState then
LDetails := StyleServices.GetElementDetails(ttbDropDownButtonGlyphNormal)
else
LDetails := StyleServices.GetElementDetails(ttbDropDownButtonGlyphDisabled);
if (LButtonHot and (bsEnabled in LState)) then
LDetails := StyleServices.GetElementDetails(ttbDropDownButtonGlyphHot);
if ((bsPressed in LState) and (bsEnabled in LState)) then
LDetails := StyleServices.GetElementDetails(ttbDropDownButtonGlyphPressed);
DrawStyleElement(DC, LDetails, R);
{ Adjust bitmap position }
if Assigned(FImages) then
ImgRect := Rect(0, 0, FImages.Width, FImages.Height);
R := ItemRect;
R.Right := R.Right - LDropDownWidth;
ImgRect := CenteredRect(R, ImgRect);
inc(ImgRect.Left, 2);
end;
{ Adjust bitmap & Text positions }
if Wrapable then
begin
R := Rect(0, 0, 0, 0);
if (ShowText and not List) then
begin
Winapi.Windows.DrawText(DC, LText, -1, R, DT_CENTER or DT_CALCRECT);
end;
ImgRect.Offset(0, -R.Height);
end
else if List then
begin
R := Rect(0, 0, 0, 0);
if ShowText then
begin
Winapi.Windows.DrawText(DC, LText, -1, R, DT_CENTER or DT_CALCRECT or TxtFlags);
end;
ImgRect := Rect(0, 0, FImages.Width, FImages.Height);
R2 := ItemRect;
dec(R2.Right, R.Width + 2);
ImgRect := CenteredRect(R2, ImgRect);
end;
{ Draw Bitmap }
if (LImageIndex > -1) and (Assigned(FImages)) then
begin
if bsEnabled in LState then
FImages.DrawingStyle := Vcl.ImgList.TDrawingStyle.dsNormal
else
FImages.DrawingStyle := Vcl.ImgList.TDrawingStyle.dsSelected;
FImages.Draw(Bmp.Canvas, ImgRect.Left, ImgRect.Top, LImageIndex);
end;
{ Draw Text }
TxtRect := Rect(0, 0, 0, 0);
if ShowText then
begin
if not List then
begin
{ Text appear under the button bitmap }
if (ImgRect.Width > 0) and (LImageIndex > -1) then
TxtRect := Rect(ItemRect.Left, ImgRect.Bottom, ItemRect.Right, ItemRect.Bottom)
else
TxtRect := ItemRect;
if LText <> '' then
DrawTextCentered(DC, LDetails, TxtRect, LText, TxtFlags);
end
else
begin
{ List }
{ Text appear to the right of the button bitmap }
if (ImgRect.Width > 0) and (LImageIndex > -1) then
TxtRect := Rect(ImgRect.Right + 2, ItemRect.Top, ItemRect.Right, ItemRect.Bottom)
else
TxtRect := ItemRect;
TxtFormat := [tfCenter, tfVerticalCenter, tfSingleLine, tfLeft];
if TxtFlags <> 0 then
include(TxtFormat, tfNoPrefix);
if LText <> '' then
StyleServices.DrawText(DC, LDetails, LText, TxtRect, TxtFormat);
end;
end;
end;
end;
end;
Canvas.Draw(0, 0, Bmp);
finally
Bmp.Free;
end;
end;
procedure TSysToolbarStyleHook.PaintBackground(Canvas: TCanvas);
begin
inherited;
end;
procedure TSysToolbarStyleHook.PaintNC(Canvas: TCanvas);
begin
inherited;
end;
procedure TSysToolbarStyleHook.WndProc(var Message: TMessage);
begin
inherited;
end;
{$ENDREGION}
{$REGION 'TSysToolbarButton'}
{ TSysToolbarStyleHook.TSysToolbarButton }
constructor TSysToolbarStyleHook.TSysToolbarButton.Create(SysParent: TSysControl; Index: Integer);
begin
FIndex := Index;
FParent := SysParent;
FText := '';
FImageIndex := -1;
FState := [];
FStyle := [];
DoGetItemInfo;
end;
destructor TSysToolbarStyleHook.TSysToolbarButton.Destroy;
begin
inherited;
end;
Procedure TSysToolbarStyleHook.TSysToolbarButton.DoGetItemInfo;
const
BufferSize = 255;
var
TB: TTBButton;
Buffer: array [0 .. BufferSize - 1] of Char;
BtnInfo: TTBButtonInfo;
begin
FillChar(Buffer, BufferSize, Char(0));
FillChar(TB, sizeof(TB), 0);
SendMessage(FParent.Handle, TB_GETBUTTON, FIndex, IntPtr(@TB));
FillChar(BtnInfo, sizeof(BtnInfo), Char(0));
BtnInfo.cbSize := sizeof(TTBButtonInfo);
BtnInfo.dwMask := TBIF_STATE or TBIF_STYLE or TBIF_IMAGE or TBIF_TEXT;
BtnInfo.cchText := BufferSize;
BtnInfo.pszText := @Buffer;
SendMessage(FParent.Handle, TB_GETBUTTONINFO, TB.idCommand, LParam(@BtnInfo));
BtnInfo.fsStyle := TB.fsStyle;
SendMessage(FParent.Handle, TB_GETBUTTONTEXT, TB.idCommand, LParam(BtnInfo.pszText));
FText := String(Buffer);
FImageIndex := BtnInfo.iImage;
with BtnInfo do
begin
{ Button State }
if fsState and TBSTATE_ENABLED = TBSTATE_ENABLED then
include(FState, bsEnabled);
if fsState and TBSTATE_PRESSED = TBSTATE_PRESSED then
include(FState, bsPressed);
if fsState and TBSTATE_CHECKED = TBSTATE_CHECKED then
include(FState, bsChecked);
if fsState and TBSTATE_HIDDEN = TBSTATE_HIDDEN then
include(FState, bsHidden);
{ Button Style }
if fsStyle and TBSTYLE_BUTTON = TBSTYLE_BUTTON then
include(FStyle, bsBtn);
if fsStyle and TBSTYLE_SEP = TBSTYLE_SEP then
include(FStyle, bsSep);
if fsStyle and TBSTYLE_CHECK = TBSTYLE_CHECK then
include(FStyle, bsCheck);
if fsStyle and TBSTYLE_GROUP = TBSTYLE_GROUP then
include(FStyle, bsGroup);
if fsStyle and TBSTYLE_CHECKGROUP = TBSTYLE_CHECKGROUP then
include(FStyle, bsCheckGroup);
if (fsStyle and TBSTYLE_DROPDOWN = TBSTYLE_DROPDOWN) or (fsStyle and BTNS_WHOLEDROPDOWN = BTNS_WHOLEDROPDOWN) then
include(FStyle, bsDropDown);
end;
end;
function TSysToolbarStyleHook.TSysToolbarButton.GetItemRect: TRect;
begin
Result := TRect.Empty;
if not BOOL(SendMessage(FParent.Handle, TB_GETITEMRECT, FIndex, LParam(@Result))) then
Result := TRect.Empty;
end;
function TSysToolbarStyleHook.TSysToolbarButton.GetDropDownWidth: Integer;
var
R: TRect;
begin
if BOOL(SendMessage(FParent.Handle, TB_GETITEMDROPDOWNRECT, FIndex, LParam(@R))) then
Result := R.Right - R.Left
else
Result := 15; // default width when runtime themes are enabled
end;
{$ENDREGION}
{ TSysProgressBarStyleHook }
constructor TSysProgressBarStyleHook.Create(AHandle: THandle);
begin
inherited;
if (SysControl.Style And PBS_VERTICAL) <> 0 then
FOrientation := pbVertical
else
FOrientation := pbHorizontal;
// DoubleBuffered := True;
OverridePaint := True;
// OverrideEraseBkgnd :=True;
// FLastPos:=-1;
FStep := 0;
FTimer := TTimer.Create(nil);
FTimer.Interval := 100;
FTimer.Enabled := False;
// if ((SysControl.Style And PBS_MARQUEE) <> 0) then
begin
FTimer.OnTimer := TimerAction;
FTimer.Enabled := True;
end;
end;
destructor TSysProgressBarStyleHook.Destroy;
begin
FTimer.Free;
inherited;
end;
function TSysProgressBarStyleHook.GetBarRect: TRect;
begin
Result := TRect.Create(0, 0, SysControl.Width, SysControl.Height);
InflateRect(Result, -BorderWidth, -BorderWidth);
end;
function TSysProgressBarStyleHook.GetBorderWidth: Integer;
begin
Result := 0;
end;
function TSysProgressBarStyleHook.GetMax: Integer;
begin
Result := SendMessage(Handle, PBM_GetRange, 0, 0);
end;
function TSysProgressBarStyleHook.GetMin: Integer;
begin
Result := SendMessage(Handle, PBM_GetRange, 1, 0);
end;
function TSysProgressBarStyleHook.GetOrientation: TProgressBarOrientation;
begin
Result := pbHorizontal;
if (Handle <> 0) and (GetWindowLong(Handle, GWL_STYLE) and PBS_VERTICAL = PBS_VERTICAL) then
Result := pbVertical;
end;
function TSysProgressBarStyleHook.GetPercent: Single;
var
LMin, LMax, LPos: Integer;
begin
LMin := Min;
LMax := Max;
LPos := Position;
if (LMin >= 0) and (LPos >= LMin) and (LMax >= LPos) and (LMax - LMin <> 0) then
Result := (LPos - LMin) / (LMax - LMin)
else
Result := 0;
end;
function TSysProgressBarStyleHook.GetPosition: Integer;
begin
Result := SendMessage(Handle, PBM_GETPOS, 0, 0);
end;
procedure TSysProgressBarStyleHook.Paint(Canvas: TCanvas);
var
LDetails: TThemedElementDetails;
begin
// if ((SysControl.Style And PBS_MARQUEE) <> 0) or ((FLastPos=-1) or (Position<FLastPos)) then
// begin
if StyleServices.Available then
begin
LDetails.Element := teProgress;
if StyleServices.HasTransparentParts(LDetails) then
StyleServices.DrawParentBackground(Handle, Canvas.Handle, LDetails, False);
end;
PaintFrame(Canvas);
// end;
PaintBar(Canvas);
end;
procedure TSysProgressBarStyleHook.PaintBackground(Canvas: TCanvas);
begin
inherited;
end;
procedure TSysProgressBarStyleHook.PaintBar(Canvas: TCanvas);
var
FillR, LRect: TRect;
LWidth, LPos: Integer;
LDetails: TThemedElementDetails;
begin
LRect := BarRect;
if ((SysControl.Style And PBS_MARQUEE) <> 0) then
begin
InflateRect(LRect, -2, -2);
if Orientation = pbHorizontal then
LWidth := LRect.Width
else
LWidth := LRect.Height;
LPos := Round(LWidth * 0.05);
FillR := LRect;
if Orientation = pbHorizontal then
begin
FillR.Right := FillR.Left + LPos;
LDetails := StyleServices.GetElementDetails(tpChunk);
end
else
begin
FillR.Top := FillR.Bottom - LPos;
LDetails := StyleServices.GetElementDetails(tpChunkVert);
end;
FillR.SetLocation(FStep * FillR.Width, FillR.Top);
DrawStyleElement(Canvas.Handle, LDetails, FillR);
// Inc(FStep,1);
// if FStep mod 20=0 then
// FStep:=0;
end
else
begin
InflateRect(LRect, -2, -2);
if Orientation = pbHorizontal then
LWidth := LRect.Width
else
LWidth := LRect.Height;
LPos := Round(LWidth * GetPercent);
// FLastPos := GetPosition;
FillR := LRect;
if Orientation = pbHorizontal then
begin
FillR.Right := FillR.Left + LPos;
LDetails := StyleServices.GetElementDetails(tpChunk);
end
else
begin
FillR.Top := FillR.Bottom - LPos;
LDetails := StyleServices.GetElementDetails(tpChunkVert);
end;
DrawStyleElement(Canvas.Handle, LDetails, FillR);
end;
end;
procedure TSysProgressBarStyleHook.PaintFrame(Canvas: TCanvas);
var
R: TRect;
Details: TThemedElementDetails;
begin
if not StyleServices.Available then
Exit;
R := BarRect;
if Orientation = pbHorizontal then
Details := StyleServices.GetElementDetails(tpBar)
else
Details := StyleServices.GetElementDetails(tpBarVert);
DrawStyleElement(Canvas.Handle, Details, R);
end;
procedure TSysProgressBarStyleHook.TimerAction(Sender: TObject);
var
LCanvas: TCanvas;
LHandle: THandle;
begin
// if StyleServices.Available and ((SysControl.Style And PBS_MARQUEE) <> 0) then
// begin
LHandle := 0;
LCanvas := TCanvas.Create;
try
LHandle := GetWindowDC(Self.Handle);
if LHandle<>0 then
begin
LCanvas.Handle := LHandle;
if SysControl.Visible then
begin
PaintFrame(LCanvas);
PaintBar(LCanvas);
end;
end;
inc(FStep, 1);
if FStep mod 20 = 0 then
FStep := 0;
finally
if LHandle<>0 then
ReleaseDC(Handle, LHandle);
LCanvas.Handle := 0;
LCanvas.Free;
end;
// end
// else
// FTimer.Enabled := False;
end;
procedure TSysProgressBarStyleHook.WMNCCalcSize(var Message: TWMNCCalcSize);
begin
Message.Result := 0;
Handled := True;
end;
procedure TSysProgressBarStyleHook.WndProc(var Message: TMessage);
begin
// Addlog(Format('TSysProgressBarStyleHook $0x%x %s', [SysControl.Handle, WM_To_String(Message.Msg)]));
//
case Message.Msg of
WM_TIMER:; // avoid flicker in progress bar and memory increased;
else inherited;
end;
end;
{ TSysRichEditStyleHook }
constructor TSysRichEditStyleHook.Create(AHandle: THandle);
begin
inherited;
{$IF CompilerVersion > 23}
StyleElements := [seBorder];
{$ELSE}
OverridePaintNC := True;
OverrideFont := False;
{$IFEND}
end;
procedure TSysRichEditStyleHook.EMSetBkgndColor(var Message: TMessage);
begin
Message.LParam := Color;
Handled := False;
end;
function TSysRichEditStyleHook.GetBorderSize: TRect;
begin
if SysControl.HasBorder then
Result := Rect(2, 2, 2, 2)
else
Result := Rect(0, 0, 0, 0);
end;
procedure TSysRichEditStyleHook.UpdateColors;
var
cf: TCharFormat2;
const
TextColor: array [Boolean] of TStyleFont = (sfEditBoxTextDisabled, sfEditBoxTextNormal);
BkColor: array [Boolean] of TStyleColor = (scEditDisabled, scEdit);
begin
Color := ColorToRGB(StyleServices.GetStyleColor(scEdit));
FontColor := ColorToRGB(StyleServices.GetStyleFontColor(TextColor[SysControl.Enabled]));
BackColor := ColorToRGB(StyleServices.GetStyleColor(BkColor[SysControl.Enabled]));
ZeroMemory(@cf, sizeof(TCharFormat2));
cf.cbSize := sizeof(TCharFormat2);
cf.dwMask := CFM_ALL;
{ Need to send this message .. }
SendMessage(Handle, EM_SETBKGNDCOLOR, 0, 0);
SendMessage(Handle, EM_GETCHARFORMAT, SCF_DEFAULT, LParam(@cf));
SendMessage(Handle, EM_SETCHARFORMAT, SCF_DEFAULT, LParam(@cf));
end;
procedure TSysRichEditStyleHook.EMSetCharFormat(var Message: TMessage);
type
PCharFormat2 = ^TCharFormat2;
var
Format: PCharFormat2;
begin
Format := PCharFormat2(Message.LParam);
Format.crTextColor := FontColor;
Format.crBackColor := BackColor;
Format.dwEffects := Format.dwEffects and not CFE_AUTOCOLOR;
Handled := False;
end;
procedure TSysRichEditStyleHook.WndProc(var Message: TMessage);
begin
inherited;
end;
{ TSysReBarStyleHook }
constructor TSysReBarStyleHook.Create(AHandle: THandle);
begin
inherited;
OverrideEraseBkgnd := True;
OverridePaint := True;
OverridePaintNC := True;
end;
function TSysReBarStyleHook.GetBandBorder(const Index: Integer): TRect;
begin
SendMessage(Handle, RB_GETBANDBORDERS, Index, IntPtr(@Result));
end;
function TSysReBarStyleHook.GetBandCount: Integer;
begin
Result := SendMessage(Handle, RB_GETBANDCOUNT, 0, 0);
end;
function TSysReBarStyleHook.GetBandRect(const Index: Integer): TRect;
begin
Result := Rect(0, 0, 0, 0);
SendMessage(Handle, RB_GETRECT, Index, IntPtr(@Result));
end;
function SizeOfReBarBandInfo: Integer;
var
ReBarBandInfo: TReBarBandInfo;
begin
ZeroMemory(@ReBarBandInfo, sizeof(ReBarBandInfo));
if GetComCtlVersion >= $60001 then
Result := sizeof(TReBarBandInfo)
else
// Platforms prior to Vista do not support the fields rcChevronLocation & uChevronState
Result := sizeof(ReBarBandInfo) - sizeof(ReBarBandInfo.rcChevronLocation) - sizeof(ReBarBandInfo.uChevronState);
end;
function TSysReBarStyleHook.GetBandText(const Index: Integer): string;
const
BufSize = 255;
var
Info: TReBarBandInfo;
Buffer: array [0 .. BufSize - 1] of Char;
begin
FillChar(Info, sizeof(Info), 0);
Info.cbSize := SizeOfReBarBandInfo;
// Size differs depending on OS and ComCtl32.dll version
Info.fMask := RBBIM_TEXT;
Info.lpText := @Buffer;
Info.cch := BufSize;
if BOOL(SendMessage(Handle, RB_GETBANDINFO, Index, IntPtr(@Info))) then
Result := Info.lpText
else
Result := '';
end;
procedure TSysReBarStyleHook.Paint(Canvas: TCanvas);
var
i: Integer;
R, Margin, LTextRect: TRect;
S: string;
Details: TThemedElementDetails;
begin
for i := 0 to GetBandCount - 1 do
begin
R := GetBandRect(i);
Margin := GetBandBorder(i);
InflateRect(R, 1, 1);
if R.Top < 0 then
R.Top := 0;
if R.Left < 0 then
R.Left := 0;
if R.Right > SysControl.ClientRect.Right then
R.Right := SysControl.ClientRect.Right;
if R.Bottom > SysControl.ClientRect.Bottom then
R.Bottom := SysControl.ClientRect.Bottom;
{ band }
Details := StyleServices.GetElementDetails(trBand);
DrawStyleElement(Canvas.Handle, Details, R);
{ text }
LTextRect := Rect(R.Left + 10, R.Top, R.Left + Margin.Left, R.Bottom);
S := GetBandText(i);
if S <> '' then
DrawControlText(Canvas, Details, S, LTextRect, DT_CENTER or DT_VCENTER or DT_SINGLELINE);
{ gripper }
R := Rect(R.Left + 2, R.Top + 2, R.Left + 6, R.Bottom - 2);
Details := StyleServices.GetElementDetails(trGripper);
DrawStyleElement(Canvas.Handle, Details, R);
end;
end;
procedure TSysReBarStyleHook.PaintBackground(Canvas: TCanvas);
var
LRect: TRect;
LDetails: TThemedElementDetails;
begin
LRect := Rect(0, 0, SysControl.ClientWidth, SysControl.ClientHeight);
InflateRect(LRect, 2, 2);
LDetails.Element := teToolBar;
LDetails.Part := 0;
if StyleServices.HasTransparentParts(LDetails) then
StyleServices.DrawParentBackground(Handle, Canvas.Handle, LDetails, False);
DrawStyleElement(Canvas.Handle, LDetails, LRect);
end;
procedure TSysReBarStyleHook.PaintNC(Canvas: TCanvas);
var
LDetails: TThemedElementDetails;
begin
ExcludeClipRect(Canvas.Handle, 2, 2, SysControl.Width - 2, SysControl.Height - 2);
Canvas.Brush.Color := StyleServices.ColorToRGB(clBtnFace);
Canvas.FillRect(Rect(0, 0, SysControl.Width, SysControl.Height));
LDetails.Element := teToolBar;
LDetails.Part := 0;
DrawStyleElement(Canvas.Handle, LDetails, Rect(0, 0, SysControl.Width, SysControl.Height));
end;
procedure TSysReBarStyleHook.WndProc(var Message: TMessage);
begin
case Message.Msg of
WM_SIZE:
begin
CallDefaultProc(Message);
Invalidate;
Handled := True;
end;
else inherited;
end;
end;
{ TSysStatusBarStyleHook }
constructor TSysStatusBarStyleHook.Create(AHandle: THandle);
begin
inherited;
OverridePaint := True;
// DoubleBuffered := True;
end;
procedure TSysStatusBarStyleHook.Paint(Canvas: TCanvas);
const
AlignStyles: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
var
R, R1: TRect;
Res, Count, i: Integer;
Idx, Flags: Cardinal;
Details: TThemedElementDetails;
LText: string;
Borders: array [0 .. 2] of Integer;
begin
Details := StyleServices.GetElementDetails(tsStatusRoot);
DrawStyleElement(Canvas.Handle, Details, Rect(0, 0, SysControl.Width, SysControl.Height));
if SendMessage(Handle, SB_ISSIMPLE, 0, 0) > 0 then
begin
R := SysControl.ClientRect;
FillChar(Borders, sizeof(Borders), 0);
SendMessage(Handle, SB_GETBORDERS, 0, IntPtr(@Borders));
R.Left := Borders[0] + Borders[2];
R.Top := Borders[1];
R.Bottom := R.Bottom - Borders[1];
R.Right := R.Right - Borders[2];
Details := StyleServices.GetElementDetails(tsPane);
DrawStyleElement(Canvas.Handle, Details, R);
R1 := SysControl.ClientRect;
R1.Left := R1.Right - R.Height;
Details := StyleServices.GetElementDetails(tsGripper);
DrawStyleElement(Canvas.Handle, Details, R1);
Details := StyleServices.GetElementDetails(tsPane);
SetLength(LText, Word(SendMessage(Handle, SB_GETTEXTLENGTH, 0, 0)));
if Length(LText) > 0 then
begin
SendMessage(Handle, SB_GETTEXT, 0, IntPtr(@LText[1]));
Flags := SysControl.DrawTextBiDiModeFlags(DT_LEFT);
DrawControlText(Canvas, Details, LText, R, Flags);
end;
end
else
begin
Count := SendMessage(Handle, SB_GETPARTS, 0, 0);
for i := 0 to Count - 1 do
begin
R := Rect(0, 0, 0, 0);
SendMessage(Handle, SB_GETRECT, i, IntPtr(@R));
if IsRectEmpty(R) then
Exit;
Details := StyleServices.GetElementDetails(tsPane);
DrawStyleElement(Canvas.Handle, Details, R);
if i = Count - 1 then
begin
R1 := SysControl.ClientRect;
R1.Left := R1.Right - R.Height;
Details := StyleServices.GetElementDetails(tsGripper);
DrawStyleElement(Canvas.Handle, Details, R1);
end;
Details := StyleServices.GetElementDetails(tsPane);
InflateRect(R, -1, -1);
Flags := SysControl.DrawTextBiDiModeFlags(DT_LEFT);
Idx := i;
SetLength(LText, Word(SendMessage(Handle, SB_GETTEXTLENGTH, Idx, 0)));
if Length(LText) > 0 then
begin
Res := SendMessage(Handle, SB_GETTEXT, Idx, IntPtr(@LText[1]));
if (Res and SBT_OWNERDRAW = 0) then
DrawControlText(Canvas, Details, LText, R, Flags);
end;
end;
end;
end;
procedure TSysStatusBarStyleHook.WndProc(var Message: TMessage);
begin
inherited;
end;
{ TSysTrackBarStyleHook }
constructor TSysTrackBarStyleHook.Create(AHandle: THandle);
begin
inherited;
OverridePaint := True;
// OverrideEraseBkgnd :=True;
DoubleBuffered := True;
FThumbPressed := False;
end;
procedure TSysTrackBarStyleHook.Paint(Canvas: TCanvas);
var
LDetails: TThemedElementDetails;
TrackBarStyle: Cardinal;
LThemedTrackBar: TThemedTrackBar;
i, TickCount, TickStart, TickEnd, TickPos: Integer;
LRect: TRect;
LRect2: TRect;
LThumbRect: TRect;
begin
if not StyleServices.Available then
Exit;
LThemedTrackBar := ttbTrackBarDontCare;
{ Track }
TrackBarStyle := GetWindowLong(Handle, GWL_STYLE);
SendMessage(Handle, TBM_GETCHANNELRECT, 0, IntPtr(@LRect));
if TrackBarStyle and TBS_VERT = 0 then
begin
LDetails := StyleServices.GetElementDetails(ttbTrack);
DrawStyleElement(Canvas.Handle, LDetails, LRect);
end
else
begin
LRect2 := LRect;
LRect.Left := LRect2.Top;
LRect.Top := LRect2.Left;
LRect.Right := LRect2.Bottom;
LRect.Bottom := LRect2.Right;
LDetails := StyleServices.GetElementDetails(ttbTrackVert);
DrawStyleElement(Canvas.Handle, LDetails, LRect);
end;
SendMessage(Handle, TBM_GETCHANNELRECT, 0, IntPtr(@LRect));
SendMessage(Handle, TBM_GETTHUMBRECT, 0, IntPtr(@LThumbRect));
// Ticks
if TrackBarStyle and TBS_NOTICKS = 0 then
begin
TickCount := SendMessage(Handle, TBM_GETNUMTICS, 0, 0);
Canvas.Pen.Color := StyleServices.ColorToRGB(clBtnText);
// First
if TrackBarStyle and TBS_VERT = 0 then
begin
TickPos := LRect.Left + LThumbRect.Width div 2;
if (TrackBarStyle and TBS_TOP = TBS_TOP) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(TickPos, LRect.Top - 7);
Canvas.LineTo(TickPos, LRect.Top - 3);
end;
if (TrackBarStyle and TBS_TOP = 0) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(TickPos, LRect.Bottom + 3);
Canvas.LineTo(TickPos, LRect.Bottom + 7);
end;
TickStart := TickPos;
end
else
begin
TickPos := LRect.Left + LThumbRect.Height div 2;
if (TrackBarStyle and TBS_TOP = TBS_TOP) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(LRect.Top - 7, TickPos);
Canvas.LineTo(LRect.Top - 3, TickPos);
end;
if (TrackBarStyle and TBS_TOP = 0) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(LRect.Bottom + 3, TickPos);
Canvas.LineTo(LRect.Bottom + 7, TickPos);
end;
TickStart := TickPos;
end;
// last
if TrackBarStyle and TBS_VERT = 0 then
begin
TickPos := LRect.Right - LThumbRect.Width div 2;
if (TrackBarStyle and TBS_TOP = TBS_TOP) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(TickPos, LRect.Top - 7);
Canvas.LineTo(TickPos, LRect.Top - 3);
end;
if (TrackBarStyle and TBS_TOP = 0) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(TickPos, LRect.Bottom + 3);
Canvas.LineTo(TickPos, LRect.Bottom + 7);
end;
TickEnd := TickPos;
end
else
begin
TickPos := LRect.Right - LThumbRect.Height div 2;
if (TrackBarStyle and TBS_TOP = TBS_TOP) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(LRect.Top - 7, TickPos);
Canvas.LineTo(LRect.Top - 3, TickPos);
end;
if (TrackBarStyle and TBS_TOP = 0) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(LRect.Bottom + 3, TickPos);
Canvas.LineTo(LRect.Bottom + 7, TickPos);
end;
TickEnd := TickPos;
end;
// ticks
for i := 1 to TickCount - 1 do
begin
TickPos := TickStart + Round((TickEnd - TickStart) * (i / (TickCount - 1)));
if TrackBarStyle and TBS_VERT = 0 then
begin
if (TrackBarStyle and TBS_TOP = TBS_TOP) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(TickPos, LRect.Top - 6);
Canvas.LineTo(TickPos, LRect.Top - 3);
end;
if (TrackBarStyle and TBS_TOP = 0) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(TickPos, LRect.Bottom + 3);
Canvas.LineTo(TickPos, LRect.Bottom + 6);
end;
end
else
begin
if (TrackBarStyle and TBS_TOP = TBS_TOP) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(LRect.Top - 6, TickPos);
Canvas.LineTo(LRect.Top - 3, TickPos);
end;
if (TrackBarStyle and TBS_TOP = 0) or (TrackBarStyle and TBS_BOTH = TBS_BOTH) then
begin
Canvas.MoveTo(LRect.Bottom + 3, TickPos);
Canvas.LineTo(LRect.Bottom + 6, TickPos);
end;
end;
end;
end;
// Thumb
if TrackBarStyle and TBS_NOTHUMB = 0 then
begin
SendMessage(Handle, TBM_GETTHUMBRECT, 0, IntPtr(@LRect));
if not SysControl.Enabled then
begin
if TrackBarStyle and TBS_VERT = 0 then
begin
if TrackBarStyle and TBS_BOTH = TBS_BOTH then
LThemedTrackBar := ttbThumbDisabled
else if TrackBarStyle and TBS_TOP = TBS_TOP then
LThemedTrackBar := ttbThumbTopDisabled
else if TrackBarStyle and TBS_BOTTOM = TBS_BOTTOM then
LThemedTrackBar := ttbThumbBottomDisabled;
end
else
begin
LThemedTrackBar := ttbThumbRightDisabled;
if TrackBarStyle and TBS_TOP = TBS_TOP then
LThemedTrackBar := ttbThumbLeftDisabled
else if TrackBarStyle and TBS_BOTH = TBS_BOTH then
LThemedTrackBar := ttbThumbVertDisabled;
end;
end
else if FThumbPressed then
begin
if TrackBarStyle and TBS_VERT = 0 then
begin
if TrackBarStyle and TBS_BOTH = TBS_BOTH then
LThemedTrackBar := ttbThumbPressed
else if TrackBarStyle and TBS_TOP = TBS_TOP then
LThemedTrackBar := ttbThumbTopPressed
else if TrackBarStyle and TBS_BOTTOM = TBS_BOTTOM then
LThemedTrackBar := ttbThumbBottomPressed;
end
else
begin
LThemedTrackBar := ttbThumbRightPressed;
if TrackBarStyle and TBS_TOP = TBS_TOP then
LThemedTrackBar := ttbThumbLeftPressed
else if TrackBarStyle and TBS_BOTH = TBS_BOTH then
LThemedTrackBar := ttbThumbVertPressed;
end;
end
else if FMouseOnThumb then
begin
if TrackBarStyle and TBS_VERT = 0 then
begin
if TrackBarStyle and TBS_BOTH = TBS_BOTH then
LThemedTrackBar := ttbThumbHot
else if TrackBarStyle and TBS_TOP = TBS_TOP then
LThemedTrackBar := ttbThumbTopHot
else if TrackBarStyle and TBS_BOTTOM = TBS_BOTTOM then
LThemedTrackBar := ttbThumbBottomHot;
end
else
begin
LThemedTrackBar := ttbThumbRightHot;
if TrackBarStyle and TBS_TOP = TBS_TOP then
LThemedTrackBar := ttbThumbLeftHot
else if TrackBarStyle and TBS_BOTH = TBS_BOTH then
LThemedTrackBar := ttbThumbVertHot;
end;
end
else
begin
if TrackBarStyle and TBS_VERT = 0 then
begin
if TrackBarStyle and TBS_BOTH = TBS_BOTH then
LThemedTrackBar := ttbThumbNormal
else if TrackBarStyle and TBS_TOP = TBS_TOP then
LThemedTrackBar := ttbThumbTopNormal
else if TrackBarStyle and TBS_BOTTOM = TBS_BOTTOM then
LThemedTrackBar := ttbThumbBottomNormal;
end
else
begin
LThemedTrackBar := ttbThumbRightNormal;
if TrackBarStyle and TBS_TOP = TBS_TOP then
LThemedTrackBar := ttbThumbLeftNormal
else if TrackBarStyle and TBS_BOTH = TBS_BOTH then
LThemedTrackBar := ttbThumbVertNormal;
end;
end;
LDetails := StyleServices.GetElementDetails(LThemedTrackBar);
DrawStyleElement(Canvas.Handle, LDetails, LRect);
end;
if Focused then
Canvas.DrawFocusRect(Rect(0, 0, SysControl.Width, SysControl.Height));
end;
procedure TSysTrackBarStyleHook.PaintBackground(Canvas: TCanvas);
var
LDetails: TThemedElementDetails;
begin
LDetails.Element := teTrackBar;
StyleServices.DrawParentBackground(Handle, Canvas.Handle, LDetails, False);
end;
procedure TSysTrackBarStyleHook.WndProc(var Message: TMessage);
var
LRect: TRect;
NewValue: Boolean;
begin
// Addlog(Format('TSysTrackBarStyleHook $0x%x %s', [SysControl.Handle, WM_To_String(Message.Msg)]));
case Message.Msg of
// WM_KEYUP,
WM_VSCROLL, WM_HSCROLL, TBM_SETPOS:
begin
Invalidate;
// CallDefaultProc(Message);
end;
WM_MOUSEMOVE:
if GetWindowLong(Handle, GWL_STYLE) and TBS_NOTHUMB = 0 then
begin
SendMessage(Handle, TBM_GETTHUMBRECT, 0, IntPtr(@LRect));
NewValue := PtInRect(LRect, Point(TWMMouse(Message).XPos, TWMMouse(Message).YPos));
if NewValue <> FMouseOnThumb then
begin
FMouseOnThumb := NewValue;
Invalidate;
end;
end;
WM_LBUTTONUP:
if GetWindowLong(Handle, GWL_STYLE) and TBS_NOTHUMB = 0 then
begin
FThumbPressed := False;
Invalidate;
end;
WM_LBUTTONDOWN:
if GetWindowLong(Handle, GWL_STYLE) and TBS_NOTHUMB = 0 then
begin
SendMessage(Handle, TBM_GETTHUMBRECT, 0, IntPtr(@LRect));
if PtInRect(LRect, Point(TWMMouse(Message).XPos, TWMMouse(Message).YPos)) then
FThumbPressed := True;
Invalidate;
end;
else inherited;
end;
end;
{ TSysUpDownStyleHook }
constructor TSysUpDownStyleHook.Create(AHandle: THandle);
begin
inherited;
OverridePaint := True;
DoubleBuffered := True;
end;
destructor TSysUpDownStyleHook.Destroy;
begin
inherited;
end;
function TSysUpDownStyleHook.GetOrientation: TUDOrientation;
begin
if SysControl.Style and UDS_HORZ = UDS_HORZ then
Result := udHorizontal
else
Result := udVertical;
end;
procedure TSysUpDownStyleHook.MouseLeave;
begin
FMouseOnLeft := False;
FMouseOnRight := False;
Invalidate;
end;
procedure TSysUpDownStyleHook.Paint(Canvas: TCanvas);
var
R: TRect;
DrawState: TThemedScrollBar;
Details: TThemedElementDetails;
begin
if not StyleServices.Available then
Exit;
StyleServices.DrawParentBackground(Handle, Canvas.Handle, Details, False);
if GetOrientation = udHorizontal then
begin
R := SysControl.ClientRect;
R.Right := R.Left + R.Width div 2;
if FLeftPressed then
DrawState := tsArrowBtnLeftPressed
else if FMouseOnLeft and MouseInControl then
DrawState := tsArrowBtnLeftHot
else
DrawState := tsArrowBtnLeftNormal;
Details := StyleServices.GetElementDetails(DrawState);
DrawStyleElement(Canvas.Handle, Details, R);
R := SysControl.ClientRect;
R.Left := R.Right - R.Width div 2;
if FRightPressed then
DrawState := tsArrowBtnRightPressed
else if FMouseOnRight and MouseInControl then
DrawState := tsArrowBtnRightHot
else
DrawState := tsArrowBtnRightNormal;
Details := StyleServices.GetElementDetails(DrawState);
DrawStyleElement(Canvas.Handle, Details, R);
end
else
begin
R := SysControl.ClientRect;
R.Bottom := R.Top + R.Height div 2;
if FLeftPressed then
DrawState := tsArrowBtnUpPressed
else if FMouseOnLeft and MouseInControl then
DrawState := tsArrowBtnUpHot
else
DrawState := tsArrowBtnUpNormal;
Details := StyleServices.GetElementDetails(DrawState);
DrawStyleElement(Canvas.Handle, Details, R);
R := SysControl.ClientRect;
R.Top := R.Bottom - R.Height div 2;
if FRightPressed then
DrawState := tsArrowBtnDownPressed
else if FMouseOnRight and MouseInControl then
DrawState := tsArrowBtnDownHot
else
DrawState := tsArrowBtnDownNormal;
Details := StyleServices.GetElementDetails(DrawState);
DrawStyleElement(Canvas.Handle, Details, R);
end;
end;
procedure TSysUpDownStyleHook.WMLButtonDblClk(var Message: TWMMouse);
var
R: TRect;
begin
SetRedraw(False);
CallDefaultProc(TMessage(Message));
SetRedraw(True);
if GetOrientation = udHorizontal then
begin
R := SysControl.ClientRect;
R.Right := R.Left + R.Width div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FLeftPressed := True
else
FLeftPressed := False;
R := SysControl.ClientRect;
R.Left := R.Right - R.Width div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FRightPressed := True
else
FRightPressed := False;
end
else
begin
R := SysControl.ClientRect;
R.Bottom := R.Top + R.Height div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FLeftPressed := True
else
FLeftPressed := False;
R := SysControl.ClientRect;
R.Top := R.Bottom - R.Height div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FRightPressed := True
else
FRightPressed := False;
end;
Invalidate;
Handled := True;
end;
procedure TSysUpDownStyleHook.WMLButtonDown(var Message: TWMMouse);
var
R: TRect;
begin
SetRedraw(False);
CallDefaultProc(TMessage(Message));
SetRedraw(True);
if GetOrientation = udHorizontal then
begin
R := SysControl.ClientRect;
R.Right := R.Left + R.Width div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FLeftPressed := True
else
FLeftPressed := False;
R := SysControl.ClientRect;
R.Left := R.Right - R.Width div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FRightPressed := True
else
FRightPressed := False;
end
else
begin
R := SysControl.ClientRect;
R.Bottom := R.Top + R.Height div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FLeftPressed := True
else
FLeftPressed := False;
R := SysControl.ClientRect;
R.Top := R.Bottom - R.Height div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FRightPressed := True
else
FRightPressed := False;
end;
Invalidate;
Handled := True;
end;
procedure TSysUpDownStyleHook.WMLButtonUp(var Message: TWMMouse);
begin
SetRedraw(False);
CallDefaultProc(TMessage(Message));
SetRedraw(True);
FLeftPressed := False;
FRightPressed := False;
Invalidate;
Handled := True;
end;
procedure TSysUpDownStyleHook.WMMouseMove(var Message: TWMMouse);
var
R: TRect;
FOldMouseOnLeft, FOldMouseOnRight: Boolean;
begin
inherited;
CallDefaultProc(TMessage(Message));
FOldMouseOnLeft := FMouseOnLeft;
FOldMouseOnRight := FMouseOnRight;
if GetOrientation = udHorizontal then
begin
R := SysControl.ClientRect;
R.Right := R.Left + R.Width div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FMouseOnLeft := True
else
FMouseOnLeft := False;
R := SysControl.ClientRect;
R.Left := R.Right - R.Width div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FMouseOnRight := True
else
FMouseOnRight := False;
end
else
begin
R := SysControl.ClientRect;
R.Bottom := R.Top + R.Height div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FMouseOnLeft := True
else
FMouseOnLeft := False;
R := SysControl.ClientRect;
R.Top := R.Bottom - R.Height div 2;
if R.Contains(Point(Message.XPos, Message.YPos)) then
FMouseOnRight := True
else
FMouseOnRight := False;
end;
if (FOldMouseOnLeft <> FMouseOnLeft) and (FOldMouseOnRight <> FMouseOnRight) then
Invalidate;
Handled := True;
end;
procedure TSysUpDownStyleHook.WndProc(var Message: TMessage);
begin
inherited;
end;
{ TSysLinkStyleHook }
{
Debug Output: TSysLinkStyleHook WM_WINDOWPOSCHANGING Process ThemedSysControls.exe (1800)
Debug Output: TSysLinkStyleHook WM_NCCALCSIZE Process ThemedSysControls.exe (1800)
Debug Output: TSysLinkStyleHook WM_CHILDACTIVATE Process ThemedSysControls.exe (1800)
Debug Output: TSysLinkStyleHook WM_WINDOWPOSCHANGED Process ThemedSysControls.exe (1800)
Debug Output: TSysLinkStyleHook Unknown(067C) Process ThemedSysControls.exe (1800)
}
constructor TSysLinkStyleHook.Create(AHandle: THandle);
var
Style: DWORD;
begin
Style := GetWindowLongPtr(AHandle, GWL_STYLE);
if (Style and SS_ICON <> SS_ICON) and (Style and SS_BITMAP <> SS_BITMAP) then
inherited;
{$IF CompilerVersion > 23}
StyleElements := [seFont, seBorder, seClient];
{$ELSE}
OverridePaint := True;
OverridePaintNC := True;
OverrideFont := True;
{$IFEND}
UpdateColors;
end;
destructor TSysLinkStyleHook.Destroy;
begin
inherited;
end;
procedure TSysLinkStyleHook.Paint(Canvas: TCanvas);
const
States: array [Boolean] of TThemedTextLabel = (ttlTextLabelDisabled,
ttlTextLabelNormal);
var
LDetails: TThemedElementDetails;
LRect: TRect;
s: string;
begin
LRect := SysControl.ClientRect;
if GetBkMode(Canvas.Handle) = TRANSPARENT then
begin
LDetails := StyleServices.GetElementDetails(tbCheckBoxUncheckedNormal);
StyleServices.DrawParentBackground(Handle, Canvas.Handle, LDetails, False);
Canvas.Brush.Style := bsClear;
end
else
begin
Canvas.Brush.Color := StyleServices.GetStyleColor(scWindow);
Canvas.FillRect(LRect);
end;
LDetails := StyleServices.GetElementDetails(States[SysControl.Enabled]);
Canvas.Font := SysControl.Font;
s:=SysControl.Text;
//OutputDebugString(PChar('Text '+s));
DrawText(Canvas.Handle, LDetails, s, LRect, TextFormat);
end;
procedure TSysLinkStyleHook.PaintNC(Canvas: TCanvas);
var
LRect: TRect;
LBitMap: TBitmap;
begin
if IsFrameOrLine then
begin
LRect := Rect(0, 0, SysControl.Width, SysControl.Height);
LBitMap := TBitmap.Create;
try
LBitMap.Width := LRect.Width;
LBitMap.Height := LRect.Height;
Frame3D(LBitMap.Canvas, LRect, StyleServices.ColorToRGB(clBtnShadow),
StyleServices.ColorToRGB(clBtnHighLight), 1);
ExcludeClipRect(Canvas.Handle, 1, 1, SysControl.Width - 1,
SysControl.Height - 1);
Canvas.Draw(0, 0, LBitMap);
finally
LBitMap.Free;
end;
end;
end;
procedure TSysLinkStyleHook.WMNCCalcSize(var Message: TWMNCCalcSize);
begin
end;
procedure TSysLinkStyleHook.WndProc(var Message: TMessage);
begin
//OutputDebugString(PChar('TSysLinkStyleHook '+WM_To_String(Message.Msg)+' Handle '+IntToHex(SysControl.Handle, 8)));
case Message.Msg of
// $067C :
// begin
// CallDefaultProc(Message);
// if SysControl.Visible then
// Invalidate;
// end;
WM_SETTEXT:
begin
CallDefaultProc(Message);
if SysControl.Visible then
Invalidate;
end;
WM_ENABLE:
if SysControl.Visible then
Invalidate;
WM_PAINT:
begin
if OverridePaint and StyleServicesEnabled then
begin
if (IsText and (Length(SysControl.Text) > 0)) then
inherited
else
CallDefaultProc(Message);
end
else
CallDefaultProc(Message);
end;
else
inherited;
end;
end;
initialization
if StyleServices.Available then
begin
with TSysStyleManager do
begin
RegisterSysStyleHook(TOOLBARCLASSNAME, TSysToolbarStyleHook);
RegisterSysStyleHook(WC_LISTVIEW, TSysListViewStyleHook);
RegisterSysStyleHook(WC_TABCONTROL, TSysTabControlStyleHook);
RegisterSysStyleHook(WC_TREEVIEW, TSysTreeViewStyleHook);
{$IFNDEF USE_Vcl.Styles.Hooks}
RegisterSysStyleHook(PROGRESS_CLASS, TSysProgressBarStyleHook);
{$ENDIF}
RegisterSysStyleHook('RichEdit20A', TSysRichEditStyleHook);
RegisterSysStyleHook('RichEdit20W', TSysRichEditStyleHook);
RegisterSysStyleHook('RichEdit30A', TSysRichEditStyleHook);
RegisterSysStyleHook('RichEdit30W', TSysRichEditStyleHook);
RegisterSysStyleHook('RichEdit41A', TSysRichEditStyleHook);
RegisterSysStyleHook('RichEdit41W', TSysRichEditStyleHook);
RegisterSysStyleHook('RichEdit50A', TSysRichEditStyleHook);
RegisterSysStyleHook('RichEdit50W', TSysRichEditStyleHook);
RegisterSysStyleHook(REBARCLASSNAME, TSysReBarStyleHook);
RegisterSysStyleHook(STATUSCLASSNAME, TSysStatusBarStyleHook);
RegisterSysStyleHook(TRACKBAR_CLASS, TSysTrackBarStyleHook);
RegisterSysStyleHook(UPDOWN_CLASS, TSysUpDownStyleHook);
end;
end;
finalization
with TSysStyleManager do
begin
UnRegisterSysStyleHook(TOOLBARCLASSNAME, TSysToolbarStyleHook);
UnRegisterSysStyleHook(WC_LISTVIEW, TSysListViewStyleHook);
UnRegisterSysStyleHook(WC_TABCONTROL, TSysTabControlStyleHook);
UnRegisterSysStyleHook(WC_TREEVIEW, TSysTreeViewStyleHook);
{$IFNDEF USE_Vcl.Styles.Hooks}
UnRegisterSysStyleHook(PROGRESS_CLASS, TSysProgressBarStyleHook);
{$ENDIF}
UnRegisterSysStyleHook('RichEdit20A', TSysRichEditStyleHook);
UnRegisterSysStyleHook('RichEdit20W', TSysRichEditStyleHook);
UnRegisterSysStyleHook('RichEdit30A', TSysRichEditStyleHook);
UnRegisterSysStyleHook('RichEdit30W', TSysRichEditStyleHook);
UnRegisterSysStyleHook('RichEdit41A', TSysRichEditStyleHook);
UnRegisterSysStyleHook('RichEdit41W', TSysRichEditStyleHook);
UnRegisterSysStyleHook('RichEdit50A', TSysRichEditStyleHook);
UnRegisterSysStyleHook('RichEdit50W', TSysRichEditStyleHook);
UnRegisterSysStyleHook(REBARCLASSNAME, TSysReBarStyleHook);
UnRegisterSysStyleHook(STATUSCLASSNAME, TSysStatusBarStyleHook);
UnRegisterSysStyleHook(TRACKBAR_CLASS, TSysTrackBarStyleHook);
UnRegisterSysStyleHook(UPDOWN_CLASS, TSysUpDownStyleHook);
end;
end.