TBXThemes.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  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. function GetSysColor(nIndex: Integer): DWORD; virtual; abstract;
  261. { General painting routines }
  262. procedure PaintBackgnd(Canvas: TCanvas; const ADockRect, ARect, AClipRect: TRect; AColor: TColor; Transparent: Boolean; AViewType: Integer); virtual; abstract;
  263. procedure PaintButton(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  264. procedure PaintCaption(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo; const ACaption: string; AFormat: Cardinal; Rotated: Boolean); virtual; abstract;
  265. procedure PaintCheckMark(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  266. procedure PaintChevron(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  267. procedure PaintEditFrame(Monitor: TMonitor; Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; const EditInfo: TTBXEditInfo); virtual; abstract;
  268. procedure PaintEditButton(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo; ButtonInfo: TTBXEditBtnInfo); virtual; abstract;
  269. procedure PaintDock(Canvas: TCanvas; const ClientRect, DockRect: TRect; DockPosition: Integer); virtual; abstract;
  270. procedure PaintDropDownArrow(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  271. procedure PaintFloatingBorder(Canvas: TCanvas; const ARect: TRect; const WindowInfo: TTBXWindowInfo); virtual; abstract;
  272. procedure PaintFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  273. procedure PaintImage(Canvas: TCanvas; ARect: TRect; const ItemInfo: TTBXItemInfo; ImageList: TCustomImageList; ImageIndex: Integer); virtual; abstract;
  274. procedure PaintMenuItem(Canvas: TCanvas; const ARect: TRect; var ItemInfo: TTBXItemInfo); virtual; abstract;
  275. procedure PaintMenuItemFrame(Canvas: TCanvas; const ARect: TRect; const ItemInfo: TTBXItemInfo); virtual; abstract;
  276. procedure PaintPopupNCArea(Canvas: TCanvas; R: TRect; const PopupInfo: TTBXPopupInfo); virtual; abstract;
  277. procedure PaintSeparator(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo; Horizontal, LineSeparator: Boolean); virtual; abstract;
  278. procedure PaintToolbarNCArea(Monitor: TMonitor; Canvas: TCanvas; R: TRect; const WindowInfo: TTBXToolbarInfo); virtual; abstract;
  279. procedure PaintStatusBar(Control: TWinControl; Canvas: TCanvas; R: TRect; Part: Integer); virtual; abstract;
  280. function GetIntegerMetrics(Viewer: TTBItemViewer; Index: Integer): Integer; overload;
  281. function GetIntegerMetrics(Monitor: TMonitor; Index: Integer): Integer; overload; virtual; abstract;
  282. { Boolean metrics access }
  283. function GetBooleanMetrics(Index: Integer): Boolean; virtual; abstract;
  284. property OfficeXPPopupAlignment: Boolean index TMB_OFFICEXPPOPUPALIGNMENT read GetBooleanMetrics;
  285. property EditMenuFullSelect: Boolean index TMB_EDITMENUFULLSELECT read GetBooleanMetrics;
  286. property EditHeightEven: Boolean index TMB_EDITHEIGHTEVEN read GetBooleanMetrics;
  287. property PaintDockBackground: Boolean index TMB_PAINTDOCKBACKGROUND read GetBooleanMetrics;
  288. property SolidToolbarNCArea: Boolean index TMB_SOLIDTOOLBARNCAREA read GetBooleanMetrics;
  289. property Name: string read FName;
  290. property Tag: Integer read FTag write FTag;
  291. end;
  292. TTBXThemeClass = class of TTBXTheme;
  293. const
  294. { TBXSysParam Params }
  295. TSP_FLATMENUSTYLE = 1;
  296. TSP_XPVISUALSTYLE = 2;
  297. { Flat menu styles }
  298. FMS_AUTOMATIC = 0;
  299. FMS_DISABLED = 1;
  300. FMS_ENABLED = 2;
  301. { XP visual styles}
  302. XPVS_AUTOMATIC = 0;
  303. XPVS_DISABLED = 2;
  304. procedure SetTBXSysParam(Param: Integer; Value: Integer);
  305. function GetTBXSysParam(Param: Integer): Integer;
  306. procedure AddTBXSysChangeNotification(AObject: TObject);
  307. procedure RemoveTBXSysChangeNotification(AObject: TObject);
  308. procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass);
  309. procedure UnregisterTBXTheme(const AName: string);
  310. function IsTBXThemeAvailable(const AName: string): Boolean;
  311. procedure GetAvailableTBXThemes(Strings: TStrings);
  312. function GetTBXTheme(const AName: string): TTBXTheme;
  313. procedure ReleaseTBXTheme(var ATheme: TTBXTheme);
  314. { Additional "system" variables - do not change }
  315. var
  316. { Additional colors }
  317. clHotLight: TColor;
  318. clPopup: TColor;
  319. clPopupText: TColor;
  320. clToolbar: TColor;
  321. clToolbarText: TColor;
  322. { Auxiliary flags corresponding to the system color scheme }
  323. TBXLoColor: Boolean;
  324. var
  325. USE_FLATMENUS: Boolean;
  326. USE_THEMES: Boolean;
  327. { Misc. Functions }
  328. { Warning: These functions may be changed or relocated in future versions }
  329. function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder, MinusCloseButton: Boolean): TRect;
  330. function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo; AdjustForBorder: Boolean): TRect;
  331. function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect;
  332. function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer;
  333. implementation
  334. uses
  335. SysUtils, TBXUtils, UxTheme, Types, PasTools;
  336. const
  337. SPI_GETFLATMENU = $1022;
  338. type
  339. TThemeInfo = record
  340. Name: {MP}string;
  341. ThemeClass: TTBXThemeClass;
  342. ThemeInstance: TTBXTheme;
  343. RefCount: Integer;
  344. end;
  345. var
  346. Themes: array of TThemeInfo;
  347. InitedThemeLibrary: Boolean;
  348. { TTBXThemeManager }
  349. type
  350. TTBXThemeManager = class
  351. private
  352. FEnableVisualStyles: Boolean;
  353. FFlatMenuStyle: Integer;
  354. FNotifies: TList;
  355. FWindowHandle: HWND;
  356. procedure SetEnableVisualStyles(Value: Boolean);
  357. procedure SetFlatMenuStyle(Value: Integer);
  358. protected
  359. procedure VisualStylesClose;
  360. procedure VisualStylesOpen;
  361. procedure UpdateVariables;
  362. procedure WndProc(var Message: TMessage);
  363. public
  364. constructor Create;
  365. destructor Destroy; override;
  366. function Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer;
  367. procedure Notify;
  368. procedure AddNotification(AObject: TObject);
  369. procedure RemoveNotification(AObject: TObject);
  370. property EnableVisualStyles: Boolean read FEnableVisualStyles write SetEnableVisualStyles;
  371. property FlatMenuStyle: Integer read FFlatMenuStyle write SetFlatMenuStyle;
  372. end;
  373. var
  374. ThemeManager: TTBXThemeManager;
  375. procedure SetTBXSysParam(Param: Integer; Value: Integer);
  376. begin
  377. case Param of
  378. TSP_FLATMENUSTYLE: ThemeManager.FlatMenuStyle := Value;
  379. TSP_XPVISUALSTYLE: ThemeManager.EnableVisualStyles := (Value = XPVS_AUTOMATIC);
  380. end;
  381. end;
  382. function GetTBXSysParam(Param: Integer): Integer;
  383. const
  384. CXPVStyles: array [Boolean] of Integer = (XPVS_DISABLED, XPVS_AUTOMATIC);
  385. begin
  386. Assert(ThemeManager <> nil);
  387. case Param of
  388. TSP_FLATMENUSTYLE: Result := ThemeManager.FlatMenuStyle;
  389. TSP_XPVISUALSTYLE: Result := CXPVStyles[ThemeManager.EnableVisualStyles];
  390. else
  391. Result := -1;
  392. end;
  393. end;
  394. procedure AddTBXSysChangeNotification(AObject: TObject);
  395. begin
  396. ThemeManager.AddNotification(AObject);
  397. end;
  398. procedure RemoveTBXSysChangeNotification(AObject: TObject);
  399. begin
  400. ThemeManager.RemoveNotification(AObject);
  401. end;
  402. function FindTBXTheme(const AName: string): Integer;
  403. begin
  404. for Result := 0 to Length(Themes) - 1 do
  405. if CompareText(Themes[Result].Name, AName) = 0 then Exit;
  406. Result := -1;
  407. end;
  408. procedure RegisterTBXTheme(const AName: string; AThemeClass: TTBXThemeClass);
  409. var
  410. Index: Integer;
  411. begin
  412. if (Length(AName) = 0) or (AThemeClass = nil) then
  413. raise Exception.Create('Cannot register theme');
  414. Index := FindTBXTheme(AName);
  415. if Index >= 0 then raise Exception.CreateFmt('Theme %s is already registered', [AName]);
  416. Index := Length(Themes);
  417. SetLength(Themes, Index + 1);
  418. with Themes[Index] do
  419. begin
  420. Name := AName;
  421. ThemeClass := AThemeClass;
  422. ThemeInstance := nil;
  423. RefCount := 0;
  424. end;
  425. end;
  426. procedure UnregisterTBXTheme(const AName: string);
  427. var
  428. Index, L: Integer;
  429. begin
  430. Index := FindTBXTheme(AName);
  431. if Index < 0 then raise Exception.CreateFmt('Cannot unregister unknown theme %s', [AName]);
  432. L := Length(Themes);
  433. if Index < L - 1 then
  434. Move(Themes[Index + 1], Themes[Index], SizeOf(TThemeInfo) * (L - Index - 1));
  435. SetLength(Themes, L - 1);
  436. end;
  437. function IsTBXThemeAvailable(const AName: string): Boolean;
  438. begin
  439. Result := FindTBXTheme(AName) >= 0;
  440. end;
  441. procedure GetAvailableTBXThemes(Strings: TStrings);
  442. var
  443. I: Integer;
  444. begin
  445. Assert(Strings <> nil);
  446. for I := 0 to Length(Themes) - 1 do
  447. Strings.Add(Themes[I].Name);
  448. end;
  449. function GetTBXTheme(const AName: string): TTBXTheme;
  450. const
  451. ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE);
  452. var
  453. Index: Integer;
  454. M: TMessage;
  455. begin
  456. Index := FindTBXTheme(AName);
  457. if Index < 0 then raise Exception.Create('Unknown theme ' + AName);
  458. with Themes[Index] do
  459. begin
  460. if RefCount = 0 then
  461. begin
  462. { Create a new instance and increase reference count }
  463. Assert(ThemeInstance = nil);
  464. ThemeInstance := ThemeClass.Create(Name);
  465. M.Msg := TBX_SYSCOMMAND;
  466. M.WParam := Integer(Application.Active);
  467. M.LParam := 0;
  468. M.Result := 0;
  469. ThemeInstance.Dispatch(M);
  470. end;
  471. Inc(RefCount);
  472. Result := ThemeInstance;
  473. end;
  474. end;
  475. procedure ReleaseTBXTheme(var ATheme: TTBXTheme);
  476. var
  477. Index: Integer;
  478. begin
  479. for Index := 0 to Length(Themes) - 1 do
  480. with Themes[Index] do
  481. if ThemeInstance = ATheme then
  482. begin
  483. if RefCount < 1 then raise Exception.Create('Cannot release theme ' + Themes[Index].Name);
  484. Dec(RefCount);
  485. if RefCount = 0 then
  486. begin
  487. ThemeInstance.Free;
  488. ThemeInstance := nil;
  489. ATheme := nil;
  490. end;
  491. Exit;
  492. end;
  493. raise Exception.Create('Cannot release theme');
  494. end;
  495. { TTBXTheme }
  496. constructor TTBXTheme.Create(const AName: string);
  497. begin
  498. FName := AName;
  499. end;
  500. function TTBXTheme.GetIntegerMetrics(Viewer: TTBItemViewer; Index: Integer): Integer;
  501. begin
  502. Result := GetIntegerMetrics(Viewer.View.GetMonitor, Index);
  503. end;
  504. { Misc. Functions }
  505. function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo;
  506. AdjustForBorder, MinusCloseButton: Boolean): TRect;
  507. begin
  508. Result := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetricsForControl(WindowInfo.ParentControl, SM_CYSMCAPTION) - 1);
  509. if MinusCloseButton then Dec(Result.Right, Result.Bottom);
  510. if AdjustForBorder then
  511. with WindowInfo.FloatingBorderSize do OffsetRect(Result, X, Y);
  512. end;
  513. function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo;
  514. AdjustForBorder: Boolean): TRect;
  515. begin
  516. Result := GetTBXCaptionRect(WindowInfo, AdjustForBorder, False);
  517. Result.Left := Result.Right - Result.Bottom + Result.Top;
  518. end;
  519. function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect;
  520. var
  521. X, Y, Z: Integer;
  522. begin
  523. with ToolbarInfo do
  524. begin
  525. Z := GetTBXDragHandleSize(ToolbarInfo) - 1;
  526. if not IsVertical then
  527. begin
  528. X := BorderSize.X;
  529. Y := BorderSize.Y;
  530. end
  531. else
  532. begin
  533. X := (ClientWidth + BorderSize.X) - Z;
  534. Y := BorderSize.Y;
  535. end;
  536. Result := Bounds(X, Y, Z, Z);
  537. end;
  538. end;
  539. function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer;
  540. const
  541. DragHandleSizes: array [Boolean, 0..2] of Integer = ((9, 0, 6), (14, 14, 14));
  542. begin
  543. with ToolbarInfo do
  544. begin
  545. if AllowDrag then
  546. Result :=
  547. ScaleByPixelsPerInch(
  548. DragHandleSizes[(CloseButtonState and CDBS_VISIBLE) <> 0, DragHandleStyle],
  549. Screen.MonitorFromWindow(ToolbarInfo.WindowHandle, mdNearest))
  550. else
  551. Result := 0;
  552. end;
  553. end;
  554. { TTBXThemeManager }
  555. procedure TTBXThemeManager.AddNotification(AObject: TObject);
  556. begin
  557. FNotifies.Add(AObject);
  558. end;
  559. function TTBXThemeManager.Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer;
  560. var
  561. I: Integer;
  562. M: TMessage;
  563. begin
  564. if FNotifies.Count > 0 then
  565. begin
  566. M.Msg := Msg;
  567. M.WParam := Param1;
  568. M.LParam := Param2;
  569. M.Result := 0;
  570. for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M);
  571. Result := M.Result;
  572. end
  573. else Result := 0;
  574. end;
  575. constructor TTBXThemeManager.Create;
  576. begin
  577. FEnableVisualStyles := True;
  578. FFlatMenuStyle := FMS_AUTOMATIC;
  579. FNotifies := TList.Create;
  580. FWindowHandle := Classes.AllocateHWnd(WndProc);
  581. UpdateVariables;
  582. end;
  583. destructor TTBXThemeManager.Destroy;
  584. begin
  585. VisualStylesClose;
  586. Classes.DeallocateHWnd(FWindowHandle);
  587. FNotifies.Free;
  588. VisualStylesClose;
  589. inherited;
  590. end;
  591. procedure TTBXThemeManager.Notify;
  592. begin
  593. if FNotifies.Count > 0 then
  594. begin
  595. Broadcast(TBX_SYSCOMMAND, TSC_BEFOREVIEWCHANGE, 0);
  596. Broadcast(TBX_SYSCOMMAND, TSC_VIEWCHANGE, 0);
  597. Broadcast(TBX_SYSCOMMAND, TSC_AFTERVIEWCHANGE, 0);
  598. end;
  599. end;
  600. procedure TTBXThemeManager.RemoveNotification(AObject: TObject);
  601. begin
  602. FNotifies.Remove(AObject);
  603. end;
  604. procedure TTBXThemeManager.SetEnableVisualStyles(Value: Boolean);
  605. begin
  606. if Value <> FEnableVisualStyles then
  607. begin
  608. FEnableVisualStyles := Value;
  609. UpdateVariables;
  610. Notify;
  611. end;
  612. end;
  613. procedure TTBXThemeManager.SetFlatMenuStyle(Value: Integer);
  614. begin
  615. if Value <> FFlatMenuStyle then
  616. begin
  617. FFlatMenuStyle := Value;
  618. UpdateVariables;
  619. Notify;
  620. end;
  621. end;
  622. procedure TTBXThemeManager.UpdateVariables;
  623. var
  624. DC: HDC;
  625. SysFlatMenus: Boolean;
  626. ToolbarTheme: THandle;
  627. begin
  628. TBXUtils.RecreateStock;
  629. DC := GetDC(0);
  630. try
  631. TBXLoColor := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES) < 12;
  632. finally
  633. ReleaseDC(0, DC);
  634. end;
  635. VisualStylesClose;
  636. VisualStylesOpen;
  637. clToolbar := clBtnFace;
  638. clToolbarText := clBtnText;
  639. if USE_THEMES then
  640. begin
  641. ToolbarTheme := OpenThemeData(FWindowHandle, 'TOOLBAR');
  642. GetThemeColor(ToolbarTheme, 0, 0, TMT_FILLCOLOR, Cardinal(clToolbar));
  643. GetThemeColor(ToolbarTheme, 0, 0, TMT_TEXTCOLOR, Cardinal(clToolbarText));
  644. CloseThemeData(ToolbarTheme);
  645. end;
  646. SysFlatMenus := False;
  647. SystemParametersInfo(SPI_GETFLATMENU, 0, @SysFlatMenus, 0);
  648. if SysFlatMenus then // System indicates support for flat menus
  649. begin
  650. if FlatMenuStyle in [FMS_AUTOMATIC, FMS_ENABLED] then
  651. begin
  652. USE_FLATMENUS := True;
  653. clPopup := clMenu;
  654. clPopupText := clMenuText;
  655. end
  656. else
  657. begin
  658. USE_FLATMENUS := False;
  659. clPopup := clToolbar;
  660. clPopupText := clToolbarText;
  661. end;
  662. end
  663. else
  664. begin
  665. if FlatMenuStyle = FMS_ENABLED then
  666. begin
  667. USE_FLATMENUS := True;
  668. clPopup := clWindow;
  669. clPopupText := clWindowText;
  670. end
  671. else
  672. begin
  673. USE_FLATMENUS := False;
  674. clPopup := clMenu;
  675. clPopupText := clMenuText;
  676. end;
  677. end;
  678. end;
  679. procedure TTBXThemeManager.VisualStylesClose;
  680. begin
  681. if InitedThemeLibrary then
  682. begin
  683. InitedThemeLibrary := False;
  684. FreeThemeLibrary;
  685. end;
  686. end;
  687. procedure TTBXThemeManager.VisualStylesOpen;
  688. begin
  689. USE_THEMES := False;
  690. if EnableVisualStyles then
  691. begin
  692. InitedThemeLibrary := InitThemeLibrary;
  693. USE_THEMES := UseThemes;
  694. end;
  695. end;
  696. procedure TTBXThemeManager.WndProc(var Message: TMessage);
  697. const
  698. ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE);
  699. begin
  700. case Message.Msg of
  701. WM_DISPLAYCHANGE, WM_SYSCOLORCHANGE, WM_THEMECHANGED:
  702. begin
  703. UpdateVariables;
  704. Notify;
  705. end;
  706. WM_ACTIVATEAPP:
  707. Broadcast(TBX_SYSCOMMAND, ActiveFlags[Boolean(Message.WParam)], 0);
  708. end;
  709. with Message do Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
  710. end;
  711. initialization
  712. if GetSysColorBrush(COLOR_HOTLIGHT) = 0 then clHotLight := clHighlight
  713. else clHotLight := TColor($80000000 or 26);
  714. Themes := nil;
  715. ThemeManager := TTBXThemeManager.Create;
  716. finalization
  717. ThemeManager.Free;
  718. SetLength(Themes, 0);
  719. end.