unit TBXThemes; // TBX Package // Copyright 2001-2004 Alex A. Denisov. All Rights Reserved // See TBX.chm for license and installation instructions // // Id: TBXThemes.pas 16 2004-05-26 02:02:55Z Alex@ZEISS interface {$I TB2Ver.inc} uses Windows, Messages, Classes, Forms, Graphics, ImgList, Controls, TB2Item; { TBX_SYSCOMMAND message } const TBX_SYSCOMMAND = WM_USER + 312; TSC_BEFOREVIEWCHANGE = 1; TSC_VIEWCHANGE = 2; TSC_AFTERVIEWCHANGE = 3; TSC_APPACTIVATE = 4; TSC_APPDEACTIVATE = 5; { Integer Metric IDs } const TMI_SPLITBTN_ARROWWIDTH = 10; TMI_DROPDOWN_ARROWWIDTH = 20; TMI_DROPDOWN_ARROWMARGIN = 21; TMI_MENU_IMGTEXTSPACE = 32; TMI_MENU_LCAPTIONMARGIN = 33; TMI_MENU_RCAPTIONMARGIN = 34; TMI_MENU_SEPARATORSIZE = 35; TMI_TLBR_SEPARATORSIZE = 50; TMI_EDIT_FRAMEWIDTH = 60; TMI_EDIT_TEXTMARGINHORZ = 61; TMI_EDIT_TEXTMARGINVERT = 62; TMI_EDIT_BTNWIDTH = 65; TMI_EDIT_MENURIGHTINDENT = 66; { Boolean Metric IDs } const TMB_OFFICEXPPOPUPALIGNMENT = 1; TMB_EDITMENUFULLSELECT = 3; // highlights the full edit item TMB_EDITHEIGHTEVEN = 4; // forces the height of the edit item to be even number (otherwise it will be odd) TMB_PAINTDOCKBACKGROUND = 5; // docks are painted by the theme instead of having a uniform color TMB_SOLIDTOOLBARNCAREA = 6; // no transparency in NC area of toolbars { Margins Metric IDs} const MID_TOOLBARITEM = 1; MID_MENUITEM = 2; MID_STATUSPANE = 3; { View types } const VT_UNKNOWN = $0; VT_TOOLBAR = $01000; VT_POPUP = $02000; VT_DOCKPANEL = $04000; VT_DOCKWINDOW = $08000; VT_STATUSBAR = $10000; // technicaly, this is not a view VT_SECTIONHEADER = $20000; // for retrieving colors only { Toolbar view types } TVT_FLOATING = $800; TVT_RESIZABLE = $400; // valid only when floating TVT_EMBEDDED = $200; // when the toolbar is not floating or docked TVT_NORMALTOOLBAR = VT_TOOLBAR or $01; TVT_MENUBAR = VT_TOOLBAR or $02; TVT_TOOLWINDOW = VT_TOOLBAR or $04; { Popup view types } PVT_POPUPMENU = VT_POPUP or $01; PVT_LISTBOX = VT_POPUP or $02; PVT_TOOLBOX = VT_POPUP or $04; PVT_CHEVRONMENU = VT_POPUP or $08; { Dockable panel view types } DPVT_FLOATING = $800; DPVT_RESIZABLE = $400; DPVT_NORMAL = VT_DOCKPANEL or $01; { Dockable window view types } DWVT_FLOATING = $800; DWVT_RESIZABLE = $400; DWVT_NORMAL = VT_DOCKWINDOW or $01; { Item types } const IT_TOOLBARBUTTON = 1; IT_MENUITEM = 2; { Item options (bit flags) } const IO_TOOLBARSTYLE = $01; IO_SUBMENUITEM = $04; IO_COMBO = $08; IO_DESIGNING = $10; IO_APPACTIVE = $20; // True when Application.Active = True IO_RADIO = $40; { Drag handle styles } const DHS_DOUBLE = 0; DHS_NONE = 1; DHS_SINGLE = 2; { Caption/drag handle button states (bit flags) } const CDBS_VISIBLE = $1; CDBS_HOT = $2; CDBS_PRESSED = $4; { Window info's RedrawPart (bit flags) } const WRP_BORDER = $1; WRP_CAPTION = $2; WRP_CLOSEBTN = $4; { Popup shadow types } const PST_NONE = 0; // no popup shadows PST_WINDOWSXP = 1; PST_OFFICEXP = 2; PST_WINDOWS2K = 3; { Edit (ComboBox) button types } const EBT_DROPDOWN = 1; EBT_SPIN = 2; { Edit (ComboBox) button states for EBT_DROPDOWN type (bit flags) } EBDS_DISABLED = $1; EBDS_HOT = $2; EBDS_PRESSED = $4; { Edit (ComboBox) button states for EBT_SPIN type (bit flags) } EBSS_DISABLED = $1; EBSS_HOT = $2; EBSS_UP = $4; EBSS_DOWN = $8; { Page scroll button types } const PSBT_UP = 1; PSBT_DOWN = 2; PSBT_LEFT = 3; PSBT_RIGHT = 4; { Item state flags } const ISF_DISABLED = $001; ISF_HOT = $002; ISF_PUSHED = $004; ISF_SELECTED = $008; ISF_LOCATIONMASK = $F00; ISF_TOOLBARCOLOR = $000; // for text and images painted in toolbars ISF_MENUCOLOR = $100; // for text and images painted in popups and DkPanels ISF_STATUSCOLOR = $200; // for text and images painted in status bars { StatusBar parts } const SBP_BODY = 0; SBP_PANE = 1; SBP_LASTPANE = 2; SBP_GRIPPER = 3; { Dock positions } const DP_TOP = 1; DP_BOTTOM = 2; DP_LEFT = 3; DP_RIGHT = 4; type TTBXItemLayout = (tbxlAuto, tbxlGlyphLeft, tbxlGlyphTop); TTBXMargins = record LeftWidth: Integer; RightWidth: Integer; TopHeight: Integer; BottomHeight: Integer; end; TTBXHoverKind = (hkNone, hkKeyboardHover, hkMouseHover); TTBXComboPart = (cpNone, cpCombo, cpSplitLeft, cpSplitRight); TTBXItemInfo = record Control: TControl; ViewType: Integer; // VT_*, TVT_*, PVT_*, or DPVT_* constant ItemOptions: Integer; // IO_* flags Enabled: Boolean; Pushed: Boolean; HoverKind: TTBXHoverKind; Selected: Boolean; ImageShown: Boolean; ImageWidth: Integer; ImageHeight: Integer; IsVertical: Boolean; ComboPart: TTBXComboPart; IsPopupParent: Boolean; // used in officexp theme PopupMargin: Integer; AppFlags: Integer; // reserved for extensions AppData: Integer; end; TTBXWindowInfo = record ParentControl: TControl; ParentHandle: HWND; // handle of a parent floating window WindowHandle: HWND; // handle of a toolbar or dockable panel ViewType: Integer; // TVT_* or DPVT_* view types (loating) ClientWidth: Integer; ClientHeight: Integer; ShowCaption: Boolean; FloatingBorderSize: TPoint; CloseButtonState: Integer; // CDBS_* state flags RedrawPart: Integer; // WRP_ constants Caption: PChar; EffectiveColor: TColor; Active: Boolean; AppFlags: Integer; // reserved for extensions AppData: Integer; end; TTBXPopupInfo = record WindowHandle: HWND; ViewType: Integer; ParentRect: TRect; BorderSize: TPoint; AppFlags: Integer; // reserved for extensions AppData: Integer; end; TTBXToolbarInfo = record WindowHandle: HWND; ViewType: Integer; // TVT_* view types (docked) IsVertical: Boolean; AllowDrag: Boolean; BorderStyle: TBorderStyle; BorderSize: TPoint; ClientWidth: Integer; ClientHeight: Integer; DragHandleStyle: Integer; CloseButtonState: Integer; // CDBS_* state flags Caption: PChar; EffectiveColor: TColor; AppFlags: Integer; // reserved for extensions AppData: Integer; end; TTBXDockPanelInfo = record WindowHandle: HWND; ViewType: Integer; // DPVT_* view types (docked) IsVertical: Boolean; AllowDrag: Boolean; BorderStyle: TBorderStyle; BorderSize: TPoint; ClientWidth: Integer; ClientHeight: Integer; ShowCaption: Boolean; CloseButtonState: Integer; Caption: PChar; EffectiveColor: TColor; AppFlags: Integer; // reserved for extensions AppData: Integer; end; TTBXEditBtnInfo = record ButtonType: Integer; // EBT_* button type ButtonState: Integer; end; TTBXEditInfo = record LeftBtnWidth: Integer; RightBtnWidth: Integer; LeftBtnInfo: TTBXEditBtnInfo; // valid only if LeftBtnWidth > 0 RightBtnInfo: TTBXEditBtnInfo; // valid only if RightBtnWidth > 0 end; TTBXTheme = class private FName: string; FTag: Integer; public constructor Create(const AName: string); virtual; { Margins, color, etc. } function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; virtual; abstract; function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract; procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); virtual; abstract; function GetPopupShadowType: Integer; virtual; abstract; // returns one of the PST_ constants procedure GetViewBorder(Control: TControl; ViewType: Integer; out Border: TPoint); virtual; abstract; function GetViewColor(ViewType: Integer): TColor; virtual; abstract; procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); virtual; abstract; function GetSysColor(nIndex: Integer): DWORD; virtual; abstract; { General painting routines } procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); virtual; abstract; procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); virtual; abstract; procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; procedure PaintEditFrame(Monitor: TMonitor; Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); virtual; abstract; procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); virtual; abstract; procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); virtual; abstract; procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); virtual; abstract; procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); virtual; abstract; procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); virtual; abstract; procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract; procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); virtual; abstract; procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); virtual; abstract; procedure PaintToolbarNCArea(Monitor: TMonitor; Canvas: TCanvas; R: TRect; const WindowInfo: TTBXToolbarInfo); virtual; abstract; procedure PaintStatusBar(Control: TWinControl; Canvas: TCanvas; R: TRect; Part: Integer); virtual; abstract; function GetIntegerMetrics(Viewer: TTBItemViewer; Index: Integer): Integer; overload; function GetIntegerMetrics(Monitor: TMonitor; Index: Integer): Integer; overload; virtual; abstract; { Boolean metrics access } function GetBooleanMetrics(Index: Integer): Boolean; virtual; abstract; property OfficeXPPopupAlignment: Boolean index TMB_OFFICEXPPOPUPALIGNMENT read GetBooleanMetrics; property EditMenuFullSelect: Boolean index TMB_EDITMENUFULLSELECT read GetBooleanMetrics; property EditHeightEven: Boolean index TMB_EDITHEIGHTEVEN read GetBooleanMetrics; property PaintDockBackground: Boolean index TMB_PAINTDOCKBACKGROUND read GetBooleanMetrics; property SolidToolbarNCArea: Boolean index TMB_SOLIDTOOLBARNCAREA read GetBooleanMetrics; property Name: string read FName; property Tag: Integer read FTag write FTag; end; TTBXThemeClass = class of TTBXTheme; const { TBXSysParam Params } TSP_FLATMENUSTYLE = 1; TSP_XPVISUALSTYLE = 2; { Flat menu styles } FMS_AUTOMATIC = 0; FMS_DISABLED = 1; FMS_ENABLED = 2; { XP visual styles} XPVS_AUTOMATIC = 0; XPVS_DISABLED = 2; procedure SetTBXSysParam(Param: Integer; Value: Integer); function GetTBXSysParam(Param: Integer): Integer; procedure AddTBXSysChangeNotification(AObject: TObject); procedure RemoveTBXSysChangeNotification(AObject: TObject); procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass); procedure UnregisterTBXTheme(const AName: string); function IsTBXThemeAvailable(const AName: string): Boolean; procedure GetAvailableTBXThemes(Strings: TStrings); function GetTBXTheme(const AName: string): TTBXTheme; procedure ReleaseTBXTheme(var ATheme: TTBXTheme); { Additional "system" variables - do not change } var { Additional colors } clHotLight: TColor; clPopup: TColor; clPopupText: TColor; clToolbar: TColor; clToolbarText: TColor; { Auxiliary flags corresponding to the system color scheme } TBXLoColor: Boolean; var USE_FLATMENUS: Boolean; USE_THEMES: Boolean; { Misc. Functions } { Warning: These functions may be changed or relocated in future versions } function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder, MinusCloseButton: Boolean): TRect; function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder: Boolean): TRect; function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect; function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer; implementation uses SysUtils, TBXUtils, UxTheme, Types, PasTools; const SPI_GETFLATMENU = $1022; type TThemeInfo = record Name: {MP}string; ThemeClass: TTBXThemeClass; ThemeInstance: TTBXTheme; RefCount: Integer; end; var Themes: array of TThemeInfo; InitedThemeLibrary: Boolean; { TTBXThemeManager } type TTBXThemeManager = class private FEnableVisualStyles: Boolean; FFlatMenuStyle: Integer; FNotifies: TList; FWindowHandle: HWND; procedure SetEnableVisualStyles(Value: Boolean); procedure SetFlatMenuStyle(Value: Integer); protected procedure VisualStylesClose; procedure VisualStylesOpen; procedure UpdateVariables; procedure WndProc(var Message: TMessage); public constructor Create; destructor Destroy; override; function Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer; procedure Notify; procedure AddNotification(AObject: TObject); procedure RemoveNotification(AObject: TObject); property EnableVisualStyles: Boolean read FEnableVisualStyles write SetEnableVisualStyles; property FlatMenuStyle: Integer read FFlatMenuStyle write SetFlatMenuStyle; end; var ThemeManager: TTBXThemeManager; procedure SetTBXSysParam(Param: Integer; Value: Integer); begin case Param of TSP_FLATMENUSTYLE: ThemeManager.FlatMenuStyle := Value; TSP_XPVISUALSTYLE: ThemeManager.EnableVisualStyles := (Value = XPVS_AUTOMATIC); end; end; function GetTBXSysParam(Param: Integer): Integer; const CXPVStyles: array [Boolean] of Integer = (XPVS_DISABLED, XPVS_AUTOMATIC); begin Assert(ThemeManager <> nil); case Param of TSP_FLATMENUSTYLE: Result := ThemeManager.FlatMenuStyle; TSP_XPVISUALSTYLE: Result := CXPVStyles[ThemeManager.EnableVisualStyles]; else Result := -1; end; end; procedure AddTBXSysChangeNotification(AObject: TObject); begin ThemeManager.AddNotification(AObject); end; procedure RemoveTBXSysChangeNotification(AObject: TObject); begin ThemeManager.RemoveNotification(AObject); end; function FindTBXTheme(const AName: string): Integer; begin for Result := 0 to Length(Themes) - 1 do if CompareText(Themes[Result].Name, AName) = 0 then Exit; Result := -1; end; procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass); var Index: Integer; begin if (Length(AName) = 0) or (AThemeClass = nil) then raise Exception.Create('Cannot register theme'); Index := FindTBXTheme(AName); if Index >= 0 then raise Exception.CreateFmt('Theme %s is already registered', [AName]); Index := Length(Themes); SetLength(Themes, Index + 1); with Themes[Index] do begin Name := AName; ThemeClass := AThemeClass; ThemeInstance := nil; RefCount := 0; end; end; procedure UnregisterTBXTheme(const AName: string); var Index, L: Integer; begin Index := FindTBXTheme(AName); if Index < 0 then raise Exception.CreateFmt('Cannot unregister unknown theme %s', [AName]); L := Length(Themes); if Index < L - 1 then Move(Themes[Index + 1], Themes[Index], SizeOf(TThemeInfo) * (L - Index - 1)); SetLength(Themes, L - 1); end; function IsTBXThemeAvailable(const AName: string): Boolean; begin Result := FindTBXTheme(AName) >= 0; end; procedure GetAvailableTBXThemes(Strings: TStrings); var I: Integer; begin Assert(Strings <> nil); for I := 0 to Length(Themes) - 1 do Strings.Add(Themes[I].Name); end; function GetTBXTheme(const AName: string): TTBXTheme; var Index: Integer; M: TMessage; begin Index := FindTBXTheme(AName); if Index < 0 then raise Exception.Create('Unknown theme ' + AName); with Themes[Index] do begin if RefCount = 0 then begin { Create a new instance and increase reference count } Assert(ThemeInstance = nil); ThemeInstance := ThemeClass.Create(Name); M.Msg := TBX_SYSCOMMAND; M.WParam := Integer(Application.Active); M.LParam := 0; M.Result := 0; ThemeInstance.Dispatch(M); end; Inc(RefCount); Result := ThemeInstance; end; end; procedure ReleaseTBXTheme(var ATheme: TTBXTheme); var Index: Integer; begin for Index := 0 to Length(Themes) - 1 do with Themes[Index] do if ThemeInstance = ATheme then begin if RefCount < 1 then raise Exception.Create('Cannot release theme ' + Themes[Index].Name); Dec(RefCount); if RefCount = 0 then begin ThemeInstance.Free; ThemeInstance := nil; ATheme := nil; end; Exit; end; raise Exception.Create('Cannot release theme'); end; { TTBXTheme } constructor TTBXTheme.Create(const AName: string); begin FName := AName; end; function TTBXTheme.GetIntegerMetrics(Viewer: TTBItemViewer; Index: Integer): Integer; begin Result := GetIntegerMetrics(Viewer.View.GetMonitor, Index); end; { Misc. Functions } function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder, MinusCloseButton: Boolean): TRect; begin Result := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetricsForControl(WindowInfo.ParentControl, SM_CYSMCAPTION) - 1); if MinusCloseButton then Dec(Result.Right, Result.Bottom); if AdjustForBorder then with WindowInfo.FloatingBorderSize do OffsetRect(Result, X, Y); end; function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder: Boolean): TRect; begin Result := GetTBXCaptionRect(WindowInfo, AdjustForBorder, False); Result.Left := Result.Right - Result.Bottom + Result.Top; end; function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect; var X, Y, Z: Integer; begin with ToolbarInfo do begin Z := GetTBXDragHandleSize(ToolbarInfo) - 1; if not IsVertical then begin X := BorderSize.X; Y := BorderSize.Y; end else begin X := (ClientWidth + BorderSize.X) - Z; Y := BorderSize.Y; end; Result := Bounds(X, Y, Z, Z); end; end; function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer; const DragHandleSizes: array [Boolean, 0..2] of Integer = ((9, 0, 6), (14, 14, 14)); begin with ToolbarInfo do begin if AllowDrag then Result := ScaleByPixelsPerInch( DragHandleSizes[(CloseButtonState and CDBS_VISIBLE) <> 0, DragHandleStyle], Screen.MonitorFromWindow(ToolbarInfo.WindowHandle, mdNearest)) else Result := 0; end; end; { TTBXThemeManager } procedure TTBXThemeManager.AddNotification(AObject: TObject); begin FNotifies.Add(AObject); end; function TTBXThemeManager.Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer; var I: Integer; M: TMessage; begin if FNotifies.Count > 0 then begin M.Msg := Msg; M.WParam := Param1; M.LParam := Param2; M.Result := 0; for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M); Result := M.Result; end else Result := 0; end; constructor TTBXThemeManager.Create; begin FEnableVisualStyles := True; FFlatMenuStyle := FMS_AUTOMATIC; FNotifies := TList.Create; FWindowHandle := Classes.AllocateHWnd(WndProc); UpdateVariables; end; destructor TTBXThemeManager.Destroy; begin VisualStylesClose; Classes.DeallocateHWnd(FWindowHandle); FNotifies.Free; VisualStylesClose; inherited; end; procedure TTBXThemeManager.Notify; begin if FNotifies.Count > 0 then begin Broadcast(TBX_SYSCOMMAND, TSC_BEFOREVIEWCHANGE, 0); Broadcast(TBX_SYSCOMMAND, TSC_VIEWCHANGE, 0); Broadcast(TBX_SYSCOMMAND, TSC_AFTERVIEWCHANGE, 0); end; end; procedure TTBXThemeManager.RemoveNotification(AObject: TObject); begin FNotifies.Remove(AObject); end; procedure TTBXThemeManager.SetEnableVisualStyles(Value: Boolean); begin if Value <> FEnableVisualStyles then begin FEnableVisualStyles := Value; UpdateVariables; Notify; end; end; procedure TTBXThemeManager.SetFlatMenuStyle(Value: Integer); begin if Value <> FFlatMenuStyle then begin FFlatMenuStyle := Value; UpdateVariables; Notify; end; end; procedure TTBXThemeManager.UpdateVariables; var DC: HDC; SysFlatMenus: Boolean; ToolbarTheme: THandle; begin TBXUtils.RecreateStock; DC := GetDC(0); try TBXLoColor := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES) < 12; finally ReleaseDC(0, DC); end; VisualStylesClose; VisualStylesOpen; clToolbar := clBtnFace; clToolbarText := clBtnText; if USE_THEMES then begin ToolbarTheme := OpenThemeData(FWindowHandle, 'TOOLBAR'); GetThemeColor(ToolbarTheme, 0, 0, TMT_FILLCOLOR, Cardinal(clToolbar)); GetThemeColor(ToolbarTheme, 0, 0, TMT_TEXTCOLOR, Cardinal(clToolbarText)); CloseThemeData(ToolbarTheme); end; SysFlatMenus := False; SystemParametersInfo(SPI_GETFLATMENU, 0, @SysFlatMenus, 0); if SysFlatMenus then // System indicates support for flat menus begin if FlatMenuStyle in [FMS_AUTOMATIC, FMS_ENABLED] then begin USE_FLATMENUS := True; clPopup := clMenu; clPopupText := clMenuText; end else begin USE_FLATMENUS := False; clPopup := clToolbar; clPopupText := clToolbarText; end; end else begin if FlatMenuStyle = FMS_ENABLED then begin USE_FLATMENUS := True; clPopup := clWindow; clPopupText := clWindowText; end else begin USE_FLATMENUS := False; clPopup := clMenu; clPopupText := clMenuText; end; end; end; procedure TTBXThemeManager.VisualStylesClose; begin if InitedThemeLibrary then begin InitedThemeLibrary := False; FreeThemeLibrary; end; end; procedure TTBXThemeManager.VisualStylesOpen; begin USE_THEMES := False; if EnableVisualStyles then begin InitedThemeLibrary := InitThemeLibrary; USE_THEMES := UseThemes; end; end; procedure TTBXThemeManager.WndProc(var Message: TMessage); const ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE); begin case Message.Msg of WM_DISPLAYCHANGE, WM_SYSCOLORCHANGE, WM_THEMECHANGED: begin UpdateVariables; Notify; end; WM_ACTIVATEAPP: Broadcast(TBX_SYSCOMMAND, ActiveFlags[Boolean(Message.WParam)], 0); end; with Message do Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam); end; initialization if GetSysColorBrush(COLOR_HOTLIGHT) = 0 then clHotLight := clHighlight else clHotLight := TColor($80000000 or 26); Themes := nil; ThemeManager := TTBXThemeManager.Create; finalization ThemeManager.Free; SetLength(Themes, 0); end.