TBXThemes.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. unit TBXThemes;
  2. // TBX Package
  3. // Copyright 2001-2004 Alex A. Denisov. All Rights Reserved
  4. // See TBX.chm for license and installation instructions
  5. //
  6. // Id: TBXThemes.pas 16 2004-05-26 02:02:55Z Alex@ZEISS
  7. interface
  8. {$I TB2Ver.inc}
  9. {$I TBX.inc}
  10. uses
  11. Windows, Messages, Classes, Forms, Graphics, ImgList;
  12. { TBX_SYSCOMMAND message }
  13. const
  14. TBX_SYSCOMMAND = WM_USER + 312;
  15. TSC_BEFOREVIEWCHANGE = 1;
  16. TSC_VIEWCHANGE = 2;
  17. TSC_AFTERVIEWCHANGE = 3;
  18. TSC_APPACTIVATE = 4;
  19. TSC_APPDEACTIVATE = 5;
  20. { Integer Metric IDs }
  21. const
  22. TMI_SPLITBTN_ARROWWIDTH = 10;
  23. TMI_DROPDOWN_ARROWWIDTH = 20;
  24. TMI_DROPDOWN_ARROWMARGIN = 21;
  25. TMI_MENU_IMGTEXTSPACE = 32;
  26. TMI_MENU_LCAPTIONMARGIN = 33;
  27. TMI_MENU_RCAPTIONMARGIN = 34;
  28. TMI_MENU_SEPARATORSIZE = 35;
  29. TMI_MENU_MDI_DW = 36;
  30. TMI_MENU_MDI_DH = 37;
  31. TMI_TLBR_SEPARATORSIZE = 50;
  32. TMI_EDIT_FRAMEWIDTH = 60;
  33. TMI_EDIT_TEXTMARGINHORZ = 61;
  34. TMI_EDIT_TEXTMARGINVERT = 62;
  35. TMI_EDIT_BTNWIDTH = 65;
  36. TMI_EDIT_MENURIGHTINDENT = 66;
  37. { Boolean Metric IDs }
  38. const
  39. TMB_OFFICEXPPOPUPALIGNMENT = 1;
  40. TMB_EDITMENUFULLSELECT = 3; // highlights the full edit item
  41. TMB_EDITHEIGHTEVEN = 4; // forces the height of the edit item to be even number (otherwise it will be odd)
  42. TMB_PAINTDOCKBACKGROUND = 5; // docks are painted by the theme instead of having a uniform color
  43. TMB_SOLIDTOOLBARNCAREA = 6; // no transparency in NC area of toolbars
  44. TMB_SOLIDTOOLBARCLIENTAREA = 7; // no transparency in client area of toolbars
  45. TMB_SOLIDTOOLBARS = TMB_SOLIDTOOLBARNCAREA; // for compatibility only
  46. { Margins Metric IDs}
  47. const
  48. MID_TOOLBARITEM = 1;
  49. MID_MENUITEM = 2;
  50. MID_STATUSPANE = 3;
  51. { View types }
  52. const
  53. VT_UNKNOWN = $0;
  54. VT_TOOLBAR = $01000;
  55. VT_POPUP = $02000;
  56. VT_DOCKPANEL = $04000;
  57. VT_DOCKWINDOW = $08000;
  58. VT_STATUSBAR = $10000; // technicaly, this is not a view
  59. VT_SECTIONHEADER = $20000; // for retrieving colors only
  60. { Toolbar view types }
  61. TVT_FLOATING = $800;
  62. TVT_RESIZABLE = $400; // valid only when floating
  63. TVT_EMBEDDED = $200; // when the toolbar is not floating or docked
  64. TVT_NORMALTOOLBAR = VT_TOOLBAR or $01;
  65. TVT_MENUBAR = VT_TOOLBAR or $02;
  66. TVT_TOOLWINDOW = VT_TOOLBAR or $04;
  67. { Popup view types }
  68. PVT_POPUPMENU = VT_POPUP or $01;
  69. PVT_LISTBOX = VT_POPUP or $02;
  70. PVT_TOOLBOX = VT_POPUP or $04;
  71. PVT_CHEVRONMENU = VT_POPUP or $08;
  72. { Dockable panel view types }
  73. DPVT_FLOATING = $800;
  74. DPVT_RESIZABLE = $400;
  75. DPVT_NORMAL = VT_DOCKPANEL or $01;
  76. { Dockable window view types }
  77. DWVT_FLOATING = $800;
  78. DWVT_RESIZABLE = $400;
  79. DWVT_NORMAL = VT_DOCKWINDOW or $01;
  80. { Item types }
  81. const
  82. IT_TOOLBARBUTTON = 1;
  83. IT_MENUITEM = 2;
  84. { Item options (bit flags) }
  85. const
  86. IO_TOOLBARSTYLE = $01;
  87. IO_SUBMENUITEM = $04;
  88. IO_COMBO = $08;
  89. IO_DESIGNING = $10;
  90. IO_APPACTIVE = $20; // True when Application.Active = True
  91. IO_RADIO = $40;
  92. { Drag handle styles }
  93. const
  94. DHS_DOUBLE = 0;
  95. DHS_NONE = 1;
  96. DHS_SINGLE = 2;
  97. { Caption/drag handle button states (bit flags) }
  98. const
  99. CDBS_VISIBLE = $1;
  100. CDBS_HOT = $2;
  101. CDBS_PRESSED = $4;
  102. { Window info's RedrawPart (bit flags) }
  103. const
  104. WRP_BORDER = $1;
  105. WRP_CAPTION = $2;
  106. WRP_CLOSEBTN = $4;
  107. { Popup shadow types }
  108. const
  109. PST_NONE = 0; // no popup shadows
  110. PST_WINDOWSXP = 1;
  111. PST_OFFICEXP = 2;
  112. PST_WINDOWS2K = 3;
  113. { Edit (ComboBox) button types }
  114. const
  115. EBT_DROPDOWN = 1;
  116. EBT_SPIN = 2;
  117. { Edit (ComboBox) button states for EBT_DROPDOWN type (bit flags) }
  118. EBDS_DISABLED = $1;
  119. EBDS_HOT = $2;
  120. EBDS_PRESSED = $4;
  121. { Edit (ComboBox) button states for EBT_SPIN type (bit flags) }
  122. EBSS_DISABLED = $1;
  123. EBSS_HOT = $2;
  124. EBSS_UP = $4;
  125. EBSS_DOWN = $8;
  126. { Page scroll button types }
  127. const
  128. PSBT_UP = 1;
  129. PSBT_DOWN = 2;
  130. PSBT_LEFT = 3;
  131. PSBT_RIGHT = 4;
  132. { PaintFrameControl kinds }
  133. const
  134. PFC_CHECKBOX = 1;
  135. PFC_RADIOBUTTON = 2;
  136. { PaintFrameControl states }
  137. PFS_CHECKED = $01;
  138. PFS_MIXED = $02;
  139. PFS_DISABLED = $04;
  140. PFS_HOT = $08;
  141. PFS_PUSHED = $10;
  142. PFS_FOCUSED = $20;
  143. { Item state flags }
  144. const
  145. ISF_DISABLED = $001;
  146. ISF_HOT = $002;
  147. ISF_PUSHED = $004;
  148. ISF_SELECTED = $008;
  149. ISF_LOCATIONMASK = $F00;
  150. ISF_TOOLBARCOLOR = $000; // for text and images painted in toolbars
  151. ISF_MENUCOLOR = $100; // for text and images painted in popups and DkPanels
  152. ISF_STATUSCOLOR = $200; // for text and images painted in status bars
  153. { StatusBar parts }
  154. const
  155. SBP_BODY = 0;
  156. SBP_PANE = 1;
  157. SBP_LASTPANE = 2;
  158. SBP_GRIPPER = 3;
  159. { Dock positions }
  160. const
  161. DP_TOP = 1;
  162. DP_BOTTOM = 2;
  163. DP_LEFT = 3;
  164. DP_RIGHT = 4;
  165. type
  166. TTBXItemLayout = (tbxlAuto, tbxlGlyphLeft, tbxlGlyphTop);
  167. TTBXMargins = record
  168. LeftWidth: Integer;
  169. RightWidth: Integer;
  170. TopHeight: Integer;
  171. BottomHeight: Integer;
  172. end;
  173. TTBXHoverKind = (hkNone, hkKeyboardHover, hkMouseHover);
  174. TTBXComboPart = (cpNone, cpCombo, cpSplitLeft, cpSplitRight);
  175. TTBXItemInfo = record
  176. ViewType: Integer; // VT_*, TVT_*, PVT_*, or DPVT_* constant
  177. ItemOptions: Integer; // IO_* flags
  178. Enabled: Boolean;
  179. Pushed: Boolean;
  180. HoverKind: TTBXHoverKind;
  181. Selected: Boolean;
  182. ImageShown: Boolean;
  183. ImageWidth: Integer;
  184. ImageHeight: Integer;
  185. IsVertical: Boolean;
  186. ComboPart: TTBXComboPart;
  187. IsPopupParent: Boolean; // used in officexp theme
  188. PopupMargin: Integer;
  189. AppFlags: Integer; // reserved for extensions
  190. AppData: Integer;
  191. end;
  192. TTBXWindowInfo = record
  193. ParentHandle: HWND; // handle of a parent floating window
  194. WindowHandle: HWND; // handle of a toolbar or dockable panel
  195. ViewType: Integer; // TVT_* or DPVT_* view types (loating)
  196. ClientWidth: Integer;
  197. ClientHeight: Integer;
  198. ShowCaption: Boolean;
  199. FloatingBorderSize: TPoint;
  200. CloseButtonState: Integer; // CDBS_* state flags
  201. RedrawPart: Integer; // WRP_ constants
  202. Caption: PChar;
  203. EffectiveColor: TColor;
  204. Active: Boolean;
  205. AppFlags: Integer; // reserved for extensions
  206. AppData: Integer;
  207. end;
  208. TTBXPopupInfo = record
  209. WindowHandle: HWND;
  210. ViewType: Integer;
  211. ParentRect: TRect;
  212. BorderSize: TPoint;
  213. AppFlags: Integer; // reserved for extensions
  214. AppData: Integer;
  215. end;
  216. TTBXToolbarInfo = record
  217. WindowHandle: HWND;
  218. ViewType: Integer; // TVT_* view types (docked)
  219. IsVertical: Boolean;
  220. AllowDrag: Boolean;
  221. BorderStyle: TBorderStyle;
  222. BorderSize: TPoint;
  223. ClientWidth: Integer;
  224. ClientHeight: Integer;
  225. DragHandleStyle: Integer;
  226. CloseButtonState: Integer; // CDBS_* state flags
  227. Caption: PChar;
  228. EffectiveColor: TColor;
  229. AppFlags: Integer; // reserved for extensions
  230. AppData: Integer;
  231. end;
  232. TTBXDockPanelInfo = record
  233. WindowHandle: HWND;
  234. ViewType: Integer; // DPVT_* view types (docked)
  235. IsVertical: Boolean;
  236. AllowDrag: Boolean;
  237. BorderStyle: TBorderStyle;
  238. BorderSize: TPoint;
  239. ClientWidth: Integer;
  240. ClientHeight: Integer;
  241. ShowCaption: Boolean;
  242. CloseButtonState: Integer;
  243. Caption: PChar;
  244. EffectiveColor: TColor;
  245. AppFlags: Integer; // reserved for extensions
  246. AppData: Integer;
  247. end;
  248. TTBXEditBtnInfo = record
  249. ButtonType: Integer; // EBT_* button type
  250. ButtonState: Integer;
  251. end;
  252. TTBXEditInfo = record
  253. LeftBtnWidth: Integer;
  254. RightBtnWidth: Integer;
  255. LeftBtnInfo: TTBXEditBtnInfo; // valid only if LeftBtnWidth > 0
  256. RightBtnInfo: TTBXEditBtnInfo; // valid only if RightBtnWidth > 0
  257. end;
  258. TTBXTheme = class
  259. private
  260. FName: string;
  261. FTag: Integer;
  262. public
  263. constructor Create(const AName: string); virtual;
  264. { Margins, color, etc. }
  265. function GetImageOffset(Canvas: TCanvas; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList): TPoint; virtual; abstract;
  266. function GetItemColor(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract;
  267. function GetItemTextColor(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract;
  268. function GetItemImageBackground(const ItemInfo: TTBXItemInfo): TColor; virtual; abstract;
  269. procedure GetMargins(MarginID: Integer; out Margins: TTBXMargins); virtual; abstract;
  270. function GetPopupShadowType: Integer; virtual; abstract; // returns one of the PST_ constants
  271. procedure GetViewBorder(ViewType: Integer; out Border: TPoint); virtual; abstract;
  272. function GetViewColor(ViewType: Integer): TColor; virtual; abstract;
  273. procedure GetViewMargins(ViewType: Integer; out Margins: TTBXMargins); virtual; abstract;
  274. { General painting routines }
  275. procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); virtual; abstract;
  276. procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  277. procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); virtual; abstract;
  278. procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  279. procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  280. procedure PaintEditFrame(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); virtual; abstract;
  281. procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); virtual; abstract;
  282. procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); virtual; abstract;
  283. procedure PaintDockPanelNCArea(Canvas: TCanvas; R: TRect; const DockPanelInfo: TTBXDockPanelInfo); virtual; abstract;
  284. procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  285. procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); virtual; abstract;
  286. procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  287. procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); virtual; abstract;
  288. procedure PaintMDIButton(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ButtonKind: Cardinal); virtual; abstract;
  289. procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); virtual; abstract;
  290. procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  291. procedure PaintPageScrollButton(Canvas: TCanvas; const ARect: TRect; ButtonType: Integer; Hot: Boolean); virtual; abstract;
  292. procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); virtual; abstract;
  293. procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); virtual; abstract;
  294. procedure PaintToolbarNCArea(Canvas: TCanvas; R: TRect; const WindowInfo: TTBXToolbarInfo); virtual; abstract;
  295. procedure PaintFrameControl(Canvas: TCanvas; R: TRect; Kind, State: Integer; Params: Pointer); virtual; abstract;
  296. procedure PaintStatusBar(Canvas: TCanvas; R: TRect; Part: Integer); virtual; abstract;
  297. { Integer metrics access }
  298. function GetIntegerMetrics(Index: Integer): Integer; virtual; abstract;
  299. property SplitBtnArrowWidth: Integer index TMI_SPLITBTN_ARROWWIDTH read GetIntegerMetrics;
  300. property DropdownArrowWidth: Integer index TMI_DROPDOWN_ARROWWIDTH read GetIntegerMetrics;
  301. property DropdownArrowMargin: Integer index TMI_DROPDOWN_ARROWMARGIN read GetIntegerMetrics;
  302. property MenuImageTextSpace: Integer index TMI_MENU_IMGTEXTSPACE read GetIntegerMetrics;
  303. property MenuLeftCaptionMargin: Integer index TMI_MENU_LCAPTIONMARGIN read GetIntegerMetrics;
  304. property MenuRightCaptionMargin: Integer index TMI_MENU_RCAPTIONMARGIN read GetIntegerMetrics;
  305. property MenuSeparatorSize: Integer index TMI_MENU_SEPARATORSIZE read GetIntegerMetrics;
  306. property MenuMDIDW: Integer index TMI_MENU_MDI_DW read GetIntegerMetrics;
  307. property MenuMDIDH: Integer index TMI_MENU_MDI_DH read GetIntegerMetrics;
  308. property TlbrSeparatorSize: Integer index TMI_TLBR_SEPARATORSIZE read GetIntegerMetrics;
  309. property EditFrameWidth: Integer index TMI_EDIT_FRAMEWIDTH read GetIntegerMetrics;
  310. property EditTextMarginHorz: Integer index TMI_EDIT_TEXTMARGINHORZ read GetIntegerMetrics;
  311. property EditTextMarginVert: Integer index TMI_EDIT_TEXTMARGINVERT read GetIntegerMetrics;
  312. property EditBtnWidth: Integer index TMI_EDIT_BTNWIDTH read GetIntegerMetrics;
  313. property EditMenuRightIndent: Integer index TMI_EDIT_MENURIGHTINDENT read GetIntegerMetrics;
  314. { Boolean metrics access }
  315. function GetBooleanMetrics(Index: Integer): Boolean; virtual; abstract;
  316. property OfficeXPPopupAlignment: Boolean index TMB_OFFICEXPPOPUPALIGNMENT read GetBooleanMetrics;
  317. property EditMenuFullSelect: Boolean index TMB_EDITMENUFULLSELECT read GetBooleanMetrics;
  318. property EditHeightEven: Boolean index TMB_EDITHEIGHTEVEN read GetBooleanMetrics;
  319. property PaintDockBackground: Boolean index TMB_PAINTDOCKBACKGROUND read GetBooleanMetrics;
  320. property SolidToolbarNCArea: Boolean index TMB_SOLIDTOOLBARNCAREA read GetBooleanMetrics;
  321. property SolidToolbarClientArea: Boolean index TMB_SOLIDTOOLBARCLIENTAREA read GetBooleanMetrics;
  322. property Name: string read FName;
  323. property Tag: Integer read FTag write FTag;
  324. end;
  325. TTBXThemeClass = class of TTBXTheme;
  326. const
  327. { TBXSysParam Params }
  328. TSP_FLATMENUSTYLE = 1;
  329. TSP_XPVISUALSTYLE = 2;
  330. { Flat menu styles }
  331. FMS_AUTOMATIC = 0;
  332. FMS_DISABLED = 1;
  333. FMS_ENABLED = 2;
  334. { XP visual styles}
  335. XPVS_AUTOMATIC = 0;
  336. XPVS_DISABLED = 2;
  337. procedure SetTBXSysParam(Param: Integer; Value: Integer);
  338. function GetTBXSysParam(Param: Integer): Integer;
  339. procedure AddTBXSysChangeNotification(AObject: TObject);
  340. procedure RemoveTBXSysChangeNotification(AObject: TObject);
  341. procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass);
  342. procedure UnregisterTBXTheme(const AName: string);
  343. function IsTBXThemeAvailable(const AName: string): Boolean;
  344. procedure GetAvailableTBXThemes(Strings: TStrings);
  345. function GetTBXTheme(const AName: string): TTBXTheme;
  346. procedure ReleaseTBXTheme(var ATheme: TTBXTheme);
  347. { Additional "system" variables - do not change }
  348. var
  349. { Additional colors }
  350. clHotLight: TColor;
  351. clPopup: TColor;
  352. clPopupText: TColor;
  353. clToolbar: TColor;
  354. clToolbarText: TColor;
  355. { Auxiliary flags corresponding to the system color scheme }
  356. TBXLoColor: Boolean;
  357. TBXHiContrast: Boolean; // this can me removed in future
  358. TBXNoBlending: Boolean; // TBXNoColor or TBXHiContrast
  359. { Handles for Windows XP visual styles }
  360. SCROLLBAR_THEME: THandle;
  361. REBAR_THEME: THandle;
  362. BUTTON_THEME: THandle;
  363. TOOLBAR_THEME: THandle;
  364. WINDOW_THEME: THandle;
  365. COMBO_THEME: THandle;
  366. EXPLORERBAR_THEME: THandle;
  367. STATUSBAR_THEME: THandle;
  368. SPIN_THEME: THandle;
  369. var
  370. USE_FLATMENUS: Boolean;
  371. USE_THEMES: Boolean;
  372. { Misc. Functions }
  373. { Warning: These functions may be changed or relocated in future versions }
  374. function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder, MinusCloseButton: Boolean): TRect;
  375. function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder: Boolean): TRect;
  376. function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect;
  377. function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer;
  378. implementation
  379. uses
  380. SysUtils, TBXUtils, UxTheme, Types;
  381. const
  382. SPI_GETFLATMENU = $1022;
  383. type
  384. TThemeInfo = record
  385. Name: {MP}string;
  386. ThemeClass: TTBXThemeClass;
  387. ThemeInstance: TTBXTheme;
  388. RefCount: Integer;
  389. end;
  390. var
  391. Themes: array of TThemeInfo;
  392. InitedThemeLibrary: Boolean;
  393. { TTBXThemeManager }
  394. type
  395. TTBXThemeManager = class
  396. private
  397. FEnableVisualStyles: Boolean;
  398. FFlatMenuStyle: Integer;
  399. FNotifies: TList;
  400. FWindowHandle: HWND;
  401. procedure SetEnableVisualStyles(Value: Boolean);
  402. procedure SetFlatMenuStyle(Value: Integer);
  403. protected
  404. procedure VisualStylesClose;
  405. procedure VisualStylesOpen;
  406. procedure UpdateVariables;
  407. procedure WndProc(var Message: TMessage);
  408. public
  409. constructor Create;
  410. destructor Destroy; override;
  411. function Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer;
  412. procedure Notify;
  413. procedure AddNotification(AObject: TObject);
  414. procedure RemoveNotification(AObject: TObject);
  415. property EnableVisualStyles: Boolean read FEnableVisualStyles write SetEnableVisualStyles;
  416. property FlatMenuStyle: Integer read FFlatMenuStyle write SetFlatMenuStyle;
  417. end;
  418. var
  419. ThemeManager: TTBXThemeManager;
  420. procedure SetTBXSysParam(Param: Integer; Value: Integer);
  421. begin
  422. case Param of
  423. TSP_FLATMENUSTYLE: ThemeManager.FlatMenuStyle := Value;
  424. TSP_XPVISUALSTYLE: ThemeManager.EnableVisualStyles := (Value = XPVS_AUTOMATIC);
  425. end;
  426. end;
  427. function GetTBXSysParam(Param: Integer): Integer;
  428. const
  429. CXPVStyles: array [Boolean] of Integer = (XPVS_DISABLED, XPVS_AUTOMATIC);
  430. begin
  431. Assert(ThemeManager <> nil);
  432. case Param of
  433. TSP_FLATMENUSTYLE: Result := ThemeManager.FlatMenuStyle;
  434. TSP_XPVISUALSTYLE: Result := CXPVStyles[ThemeManager.EnableVisualStyles];
  435. else
  436. Result := -1;
  437. end;
  438. end;
  439. procedure AddTBXSysChangeNotification(AObject: TObject);
  440. begin
  441. ThemeManager.AddNotification(AObject);
  442. end;
  443. procedure RemoveTBXSysChangeNotification(AObject: TObject);
  444. begin
  445. ThemeManager.RemoveNotification(AObject);
  446. end;
  447. function FindTBXTheme(const AName: string): Integer;
  448. begin
  449. for Result := 0 to Length(Themes) - 1 do
  450. if CompareText(Themes[Result].Name, AName) = 0 then Exit;
  451. Result := -1;
  452. end;
  453. procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass);
  454. var
  455. Index: Integer;
  456. begin
  457. if (Length(AName) = 0) or (AThemeClass = nil) then
  458. raise Exception.Create('Cannot register theme');
  459. Index := FindTBXTheme(AName);
  460. if Index >= 0 then raise Exception.CreateFmt('Theme %s is already registered', [AName]);
  461. Index := Length(Themes);
  462. SetLength(Themes, Index + 1);
  463. with Themes[Index] do
  464. begin
  465. Name := AName;
  466. ThemeClass := AThemeClass;
  467. ThemeInstance := nil;
  468. RefCount := 0;
  469. end;
  470. end;
  471. procedure UnregisterTBXTheme(const AName: string);
  472. var
  473. Index, L: Integer;
  474. begin
  475. Index := FindTBXTheme(AName);
  476. if Index < 0 then raise Exception.CreateFmt('Cannot unregister unknown theme %s', [AName]);
  477. L := Length(Themes);
  478. if Index < L - 1 then
  479. Move(Themes[Index + 1], Themes[Index], SizeOf(TThemeInfo) * (L - Index - 1));
  480. SetLength(Themes, L - 1);
  481. end;
  482. function IsTBXThemeAvailable(const AName: string): Boolean;
  483. begin
  484. Result := FindTBXTheme(AName) >= 0;
  485. end;
  486. procedure GetAvailableTBXThemes(Strings: TStrings);
  487. var
  488. I: Integer;
  489. begin
  490. Assert(Strings <> nil);
  491. for I := 0 to Length(Themes) - 1 do
  492. Strings.Add(Themes[I].Name);
  493. end;
  494. function GetTBXTheme(const AName: string): TTBXTheme;
  495. const
  496. ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE);
  497. var
  498. Index: Integer;
  499. M: TMessage;
  500. begin
  501. Index := FindTBXTheme(AName);
  502. if Index < 0 then raise Exception.Create('Unknown theme ' + AName);
  503. with Themes[Index] do
  504. begin
  505. if RefCount = 0 then
  506. begin
  507. { Create a new instance and increase reference count }
  508. Assert(ThemeInstance = nil);
  509. ThemeInstance := ThemeClass.Create(Name);
  510. M.Msg := TBX_SYSCOMMAND;
  511. M.WParam := Integer(Application.Active);
  512. M.LParam := 0;
  513. M.Result := 0;
  514. ThemeInstance.Dispatch(M);
  515. end;
  516. Inc(RefCount);
  517. Result := ThemeInstance;
  518. end;
  519. end;
  520. procedure ReleaseTBXTheme(var ATheme: TTBXTheme);
  521. var
  522. Index: Integer;
  523. begin
  524. for Index := 0 to Length(Themes) - 1 do
  525. with Themes[Index] do
  526. if ThemeInstance = ATheme then
  527. begin
  528. if RefCount < 1 then raise Exception.Create('Cannot release theme ' + Themes[Index].Name);
  529. Dec(RefCount);
  530. if RefCount = 0 then
  531. begin
  532. ThemeInstance.Free;
  533. ThemeInstance := nil;
  534. ATheme := nil;
  535. end;
  536. Exit;
  537. end;
  538. raise Exception.Create('Cannot release theme');
  539. end;
  540. { TTBXTheme }
  541. constructor TTBXTheme.Create(const AName: string);
  542. begin
  543. FName := AName;
  544. end;
  545. { Misc. Functions }
  546. function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo;
  547. AdjustForBorder, MinusCloseButton: Boolean): TRect;
  548. begin
  549. Result := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetrics(SM_CYSMCAPTION) - 1);
  550. if MinusCloseButton then Dec(Result.Right, Result.Bottom);
  551. if AdjustForBorder then
  552. with WindowInfo.FloatingBorderSize do OffsetRect(Result, X, Y);
  553. end;
  554. function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo;
  555. AdjustForBorder: Boolean): TRect;
  556. begin
  557. Result := GetTBXCaptionRect(WindowInfo, AdjustForBorder, False);
  558. Result.Left := Result.Right - Result.Bottom + Result.Top;
  559. end;
  560. function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect;
  561. var
  562. X, Y, Z: Integer;
  563. begin
  564. with ToolbarInfo do
  565. begin
  566. Z := GetTBXDragHandleSize(ToolbarInfo) - 1;
  567. if not IsVertical then
  568. begin
  569. X := BorderSize.X;
  570. Y := BorderSize.Y;
  571. end
  572. else
  573. begin
  574. X := (ClientWidth + BorderSize.X) - Z;
  575. Y := BorderSize.Y;
  576. end;
  577. Result := Bounds(X, Y, Z, Z);
  578. end;
  579. end;
  580. function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer;
  581. const
  582. DragHandleSizes: array [Boolean, 0..2] of Integer = ((9, 0, 6), (14, 14, 14));
  583. begin
  584. with ToolbarInfo do
  585. begin
  586. if AllowDrag then
  587. Result := MulDiv(DragHandleSizes[(CloseButtonState and CDBS_VISIBLE) <> 0, DragHandleStyle], Screen.PixelsPerInch, USER_DEFAULT_SCREEN_DPI)
  588. else
  589. Result := 0;
  590. end;
  591. end;
  592. { TTBXThemeManager }
  593. procedure TTBXThemeManager.AddNotification(AObject: TObject);
  594. begin
  595. FNotifies.Add(AObject);
  596. end;
  597. function TTBXThemeManager.Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer;
  598. var
  599. I: Integer;
  600. M: TMessage;
  601. begin
  602. if FNotifies.Count > 0 then
  603. begin
  604. M.Msg := Msg;
  605. M.WParam := Param1;
  606. M.LParam := Param2;
  607. M.Result := 0;
  608. for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M);
  609. Result := M.Result;
  610. end
  611. else Result := 0;
  612. end;
  613. constructor TTBXThemeManager.Create;
  614. begin
  615. FEnableVisualStyles := True;
  616. FFlatMenuStyle := FMS_AUTOMATIC;
  617. FNotifies := TList.Create;
  618. FWindowHandle := {$IFDEF JR_D6}Classes.{$ENDIF}AllocateHWnd(WndProc);
  619. UpdateVariables;
  620. end;
  621. destructor TTBXThemeManager.Destroy;
  622. begin
  623. VisualStylesClose;
  624. {$IFDEF JR_D6}Classes.{$ENDIF}DeallocateHWnd(FWindowHandle);
  625. FNotifies.Free;
  626. VisualStylesClose;
  627. inherited;
  628. end;
  629. procedure TTBXThemeManager.Notify;
  630. begin
  631. if FNotifies.Count > 0 then
  632. begin
  633. Broadcast(TBX_SYSCOMMAND, TSC_BEFOREVIEWCHANGE, 0);
  634. Broadcast(TBX_SYSCOMMAND, TSC_VIEWCHANGE, 0);
  635. Broadcast(TBX_SYSCOMMAND, TSC_AFTERVIEWCHANGE, 0);
  636. end;
  637. end;
  638. procedure TTBXThemeManager.RemoveNotification(AObject: TObject);
  639. begin
  640. FNotifies.Remove(AObject);
  641. end;
  642. procedure TTBXThemeManager.SetEnableVisualStyles(Value: Boolean);
  643. begin
  644. if Value <> FEnableVisualStyles then
  645. begin
  646. FEnableVisualStyles := Value;
  647. UpdateVariables;
  648. Notify;
  649. end;
  650. end;
  651. procedure TTBXThemeManager.SetFlatMenuStyle(Value: Integer);
  652. begin
  653. if Value <> FFlatMenuStyle then
  654. begin
  655. FFlatMenuStyle := Value;
  656. UpdateVariables;
  657. Notify;
  658. end;
  659. end;
  660. procedure TTBXThemeManager.UpdateVariables;
  661. var
  662. DC: HDC;
  663. SysFlatMenus: Boolean;
  664. begin
  665. TBXUtils.RecreateStock;
  666. DC := GetDC(0);
  667. try
  668. TBXLoColor := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES) < 12;
  669. TBXHiContrast := GetSysColor(COLOR_BTNFACE) = $00FFFFFF;
  670. TBXNoBlending := TBXLoColor or TBXHiContrast;
  671. finally
  672. ReleaseDC(0, DC);
  673. end;
  674. VisualStylesClose;
  675. VisualStylesOpen;
  676. clToolbar := clBtnFace;
  677. clToolbarText := clBtnText;
  678. if USE_THEMES then
  679. begin
  680. GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_FILLCOLOR, Cardinal(clToolbar));
  681. GetThemeColor(TOOLBAR_THEME, 0, 0, TMT_TEXTCOLOR, Cardinal(clToolbarText));
  682. end;
  683. SysFlatMenus := False;
  684. SystemParametersInfo(SPI_GETFLATMENU, 0, @SysFlatMenus, 0);
  685. if SysFlatMenus then // System indicates support for flat menus
  686. begin
  687. if FlatMenuStyle in [FMS_AUTOMATIC, FMS_ENABLED] then
  688. begin
  689. USE_FLATMENUS := True;
  690. clPopup := clMenu;
  691. clPopupText := clMenuText;
  692. end
  693. else
  694. begin
  695. USE_FLATMENUS := False;
  696. clPopup := clToolbar;
  697. clPopupText := clToolbarText;
  698. end;
  699. end
  700. else
  701. begin
  702. if FlatMenuStyle = FMS_ENABLED then
  703. begin
  704. USE_FLATMENUS := True;
  705. clPopup := clWindow;
  706. clPopupText := clWindowText;
  707. end
  708. else
  709. begin
  710. USE_FLATMENUS := False;
  711. clPopup := clMenu;
  712. clPopupText := clMenuText;
  713. end;
  714. end;
  715. end;
  716. procedure TTBXThemeManager.VisualStylesClose;
  717. procedure Close(var ATheme: THandle);
  718. begin
  719. if ATheme <> 0 then begin CloseThemeData(ATheme); ATheme := 0; end;
  720. end;
  721. begin
  722. if USE_THEMES then
  723. begin
  724. Close(BUTTON_THEME);
  725. Close(SCROLLBAR_THEME);
  726. Close(REBAR_THEME);
  727. Close(TOOLBAR_THEME);
  728. Close(WINDOW_THEME);
  729. Close(COMBO_THEME);
  730. Close(EXPLORERBAR_THEME);
  731. Close(STATUSBAR_THEME);
  732. Close(SPIN_THEME);
  733. end;
  734. if InitedThemeLibrary then
  735. begin
  736. InitedThemeLibrary := False;
  737. FreeThemeLibrary;
  738. end;
  739. end;
  740. procedure TTBXThemeManager.VisualStylesOpen;
  741. begin
  742. USE_THEMES := False;
  743. if EnableVisualStyles then
  744. begin
  745. InitedThemeLibrary := InitThemeLibrary;
  746. USE_THEMES := UseThemes;
  747. try
  748. BUTTON_THEME := OpenThemeData(FWindowHandle, 'BUTTON');
  749. SCROLLBAR_THEME := OpenThemeData(FWindowHandle, 'SCROLLBAR');
  750. REBAR_THEME := OpenThemeData(FWindowHandle, 'REBAR');
  751. TOOLBAR_THEME := OpenThemeData(FWindowHandle, 'TOOLBAR');
  752. WINDOW_THEME := OpenThemeData(FWindowHandle, 'WINDOW');
  753. COMBO_THEME := OpenThemeData(FWindowHandle, 'COMBOBOX');
  754. EXPLORERBAR_THEME := OpenThemeData(FWindowHandle, 'EXPLORERBAR');
  755. STATUSBAR_THEME := OpenThemeData(FWindowHandle, 'STATUS');
  756. SPIN_THEME := OpenThemeData(FWindowHandle, 'SPIN');
  757. except
  758. VisualStylesClose;
  759. end;
  760. end;
  761. end;
  762. procedure TTBXThemeManager.WndProc(var Message: TMessage);
  763. const
  764. ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE);
  765. begin
  766. case Message.Msg of
  767. WM_DISPLAYCHANGE, WM_SYSCOLORCHANGE, WM_THEMECHANGED:
  768. begin
  769. UpdateVariables;
  770. ResetBrushedFillCache;
  771. Notify;
  772. end;
  773. WM_ACTIVATEAPP:
  774. Broadcast(TBX_SYSCOMMAND, ActiveFlags[Boolean(Message.WParam)], 0);
  775. end;
  776. with Message do Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
  777. end;
  778. initialization
  779. if GetSysColorBrush(COLOR_HOTLIGHT) = 0 then clHotLight := clHighlight
  780. else clHotLight := TColor($80000000 or 26);
  781. Themes := nil;
  782. ThemeManager := TTBXThemeManager.Create;
  783. finalization
  784. ThemeManager.Free;
  785. SetLength(Themes, 0);
  786. end.