TBXThemes.pas 25 KB

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