TBXThemes.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  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. var
  451. Index: Integer;
  452. M: TMessage;
  453. begin
  454. Index := FindTBXTheme(AName);
  455. if Index < 0 then raise Exception.Create('Unknown theme ' + AName);
  456. with Themes[Index] do
  457. begin
  458. if RefCount = 0 then
  459. begin
  460. { Create a new instance and increase reference count }
  461. Assert(ThemeInstance = nil);
  462. ThemeInstance := ThemeClass.Create(Name);
  463. M.Msg := TBX_SYSCOMMAND;
  464. M.WParam := Integer(Application.Active);
  465. M.LParam := 0;
  466. M.Result := 0;
  467. ThemeInstance.Dispatch(M);
  468. end;
  469. Inc(RefCount);
  470. Result := ThemeInstance;
  471. end;
  472. end;
  473. procedure ReleaseTBXTheme(var ATheme: TTBXTheme);
  474. var
  475. Index: Integer;
  476. begin
  477. for Index := 0 to Length(Themes) - 1 do
  478. with Themes[Index] do
  479. if ThemeInstance = ATheme then
  480. begin
  481. if RefCount < 1 then raise Exception.Create('Cannot release theme ' + Themes[Index].Name);
  482. Dec(RefCount);
  483. if RefCount = 0 then
  484. begin
  485. ThemeInstance.Free;
  486. ThemeInstance := nil;
  487. ATheme := nil;
  488. end;
  489. Exit;
  490. end;
  491. raise Exception.Create('Cannot release theme');
  492. end;
  493. { TTBXTheme }
  494. constructor TTBXTheme.Create(const AName: string);
  495. begin
  496. FName := AName;
  497. end;
  498. function TTBXTheme.GetIntegerMetrics(Viewer: TTBItemViewer; Index: Integer): Integer;
  499. begin
  500. Result := GetIntegerMetrics(Viewer.View.GetMonitor, Index);
  501. end;
  502. { Misc. Functions }
  503. function GetTBXCaptionRect(const WindowInfo: TTBXWindowInfo;
  504. AdjustForBorder, MinusCloseButton: Boolean): TRect;
  505. begin
  506. Result := Rect(0, 0, WindowInfo.ClientWidth, GetSystemMetricsForControl(WindowInfo.ParentControl, SM_CYSMCAPTION) - 1);
  507. if MinusCloseButton then Dec(Result.Right, Result.Bottom);
  508. if AdjustForBorder then
  509. with WindowInfo.FloatingBorderSize do OffsetRect(Result, X, Y);
  510. end;
  511. function GetTBXCloseButtonRect(const WindowInfo: TTBXWindowInfo;
  512. AdjustForBorder: Boolean): TRect;
  513. begin
  514. Result := GetTBXCaptionRect(WindowInfo, AdjustForBorder, False);
  515. Result.Left := Result.Right - Result.Bottom + Result.Top;
  516. end;
  517. function GetTBXDockedCloseButtonRect(const ToolbarInfo: TTBXToolbarInfo): TRect;
  518. var
  519. X, Y, Z: Integer;
  520. begin
  521. with ToolbarInfo do
  522. begin
  523. Z := GetTBXDragHandleSize(ToolbarInfo) - 1;
  524. if not IsVertical then
  525. begin
  526. X := BorderSize.X;
  527. Y := BorderSize.Y;
  528. end
  529. else
  530. begin
  531. X := (ClientWidth + BorderSize.X) - Z;
  532. Y := BorderSize.Y;
  533. end;
  534. Result := Bounds(X, Y, Z, Z);
  535. end;
  536. end;
  537. function GetTBXDragHandleSize(const ToolbarInfo: TTBXToolbarInfo): Integer;
  538. const
  539. DragHandleSizes: array [Boolean, 0..2] of Integer = ((9, 0, 6), (14, 14, 14));
  540. begin
  541. with ToolbarInfo do
  542. begin
  543. if AllowDrag then
  544. Result :=
  545. ScaleByPixelsPerInch(
  546. DragHandleSizes[(CloseButtonState and CDBS_VISIBLE) <> 0, DragHandleStyle],
  547. Screen.MonitorFromWindow(ToolbarInfo.WindowHandle, mdNearest))
  548. else
  549. Result := 0;
  550. end;
  551. end;
  552. { TTBXThemeManager }
  553. procedure TTBXThemeManager.AddNotification(AObject: TObject);
  554. begin
  555. FNotifies.Add(AObject);
  556. end;
  557. function TTBXThemeManager.Broadcast(Msg: Cardinal; Param1, Param2: Integer): Integer;
  558. var
  559. I: Integer;
  560. M: TMessage;
  561. begin
  562. if FNotifies.Count > 0 then
  563. begin
  564. M.Msg := Msg;
  565. M.WParam := Param1;
  566. M.LParam := Param2;
  567. M.Result := 0;
  568. for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M);
  569. Result := M.Result;
  570. end
  571. else Result := 0;
  572. end;
  573. constructor TTBXThemeManager.Create;
  574. begin
  575. FEnableVisualStyles := True;
  576. FFlatMenuStyle := FMS_AUTOMATIC;
  577. FNotifies := TList.Create;
  578. FWindowHandle := Classes.AllocateHWnd(WndProc);
  579. UpdateVariables;
  580. end;
  581. destructor TTBXThemeManager.Destroy;
  582. begin
  583. VisualStylesClose;
  584. Classes.DeallocateHWnd(FWindowHandle);
  585. FNotifies.Free;
  586. VisualStylesClose;
  587. inherited;
  588. end;
  589. procedure TTBXThemeManager.Notify;
  590. begin
  591. if FNotifies.Count > 0 then
  592. begin
  593. Broadcast(TBX_SYSCOMMAND, TSC_BEFOREVIEWCHANGE, 0);
  594. Broadcast(TBX_SYSCOMMAND, TSC_VIEWCHANGE, 0);
  595. Broadcast(TBX_SYSCOMMAND, TSC_AFTERVIEWCHANGE, 0);
  596. end;
  597. end;
  598. procedure TTBXThemeManager.RemoveNotification(AObject: TObject);
  599. begin
  600. FNotifies.Remove(AObject);
  601. end;
  602. procedure TTBXThemeManager.SetEnableVisualStyles(Value: Boolean);
  603. begin
  604. if Value <> FEnableVisualStyles then
  605. begin
  606. FEnableVisualStyles := Value;
  607. UpdateVariables;
  608. Notify;
  609. end;
  610. end;
  611. procedure TTBXThemeManager.SetFlatMenuStyle(Value: Integer);
  612. begin
  613. if Value <> FFlatMenuStyle then
  614. begin
  615. FFlatMenuStyle := Value;
  616. UpdateVariables;
  617. Notify;
  618. end;
  619. end;
  620. procedure TTBXThemeManager.UpdateVariables;
  621. var
  622. DC: HDC;
  623. SysFlatMenus: Boolean;
  624. ToolbarTheme: THandle;
  625. begin
  626. TBXUtils.RecreateStock;
  627. DC := GetDC(0);
  628. try
  629. TBXLoColor := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES) < 12;
  630. finally
  631. ReleaseDC(0, DC);
  632. end;
  633. VisualStylesClose;
  634. VisualStylesOpen;
  635. clToolbar := clBtnFace;
  636. clToolbarText := clBtnText;
  637. if USE_THEMES then
  638. begin
  639. ToolbarTheme := OpenThemeData(FWindowHandle, 'TOOLBAR');
  640. GetThemeColor(ToolbarTheme, 0, 0, TMT_FILLCOLOR, Cardinal(clToolbar));
  641. GetThemeColor(ToolbarTheme, 0, 0, TMT_TEXTCOLOR, Cardinal(clToolbarText));
  642. CloseThemeData(ToolbarTheme);
  643. end;
  644. SysFlatMenus := False;
  645. SystemParametersInfo(SPI_GETFLATMENU, 0, @SysFlatMenus, 0);
  646. if SysFlatMenus then // System indicates support for flat menus
  647. begin
  648. if FlatMenuStyle in [FMS_AUTOMATIC, FMS_ENABLED] then
  649. begin
  650. USE_FLATMENUS := True;
  651. clPopup := clMenu;
  652. clPopupText := clMenuText;
  653. end
  654. else
  655. begin
  656. USE_FLATMENUS := False;
  657. clPopup := clToolbar;
  658. clPopupText := clToolbarText;
  659. end;
  660. end
  661. else
  662. begin
  663. if FlatMenuStyle = FMS_ENABLED then
  664. begin
  665. USE_FLATMENUS := True;
  666. clPopup := clWindow;
  667. clPopupText := clWindowText;
  668. end
  669. else
  670. begin
  671. USE_FLATMENUS := False;
  672. clPopup := clMenu;
  673. clPopupText := clMenuText;
  674. end;
  675. end;
  676. end;
  677. procedure TTBXThemeManager.VisualStylesClose;
  678. begin
  679. if InitedThemeLibrary then
  680. begin
  681. InitedThemeLibrary := False;
  682. FreeThemeLibrary;
  683. end;
  684. end;
  685. procedure TTBXThemeManager.VisualStylesOpen;
  686. begin
  687. USE_THEMES := False;
  688. if EnableVisualStyles then
  689. begin
  690. InitedThemeLibrary := InitThemeLibrary;
  691. USE_THEMES := UseThemes;
  692. end;
  693. end;
  694. procedure TTBXThemeManager.WndProc(var Message: TMessage);
  695. const
  696. ActiveFlags: array [Boolean] of Integer = (TSC_APPDEACTIVATE, TSC_APPACTIVATE);
  697. begin
  698. case Message.Msg of
  699. WM_DISPLAYCHANGE, WM_SYSCOLORCHANGE, WM_THEMECHANGED:
  700. begin
  701. UpdateVariables;
  702. Notify;
  703. end;
  704. WM_ACTIVATEAPP:
  705. Broadcast(TBX_SYSCOMMAND, ActiveFlags[Boolean(Message.WParam)], 0);
  706. end;
  707. with Message do Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
  708. end;
  709. initialization
  710. if GetSysColorBrush(COLOR_HOTLIGHT) = 0 then clHotLight := clHighlight
  711. else clHotLight := TColor($80000000 or 26);
  712. Themes := nil;
  713. ThemeManager := TTBXThemeManager.Create;
  714. finalization
  715. ThemeManager.Free;
  716. SetLength(Themes, 0);
  717. end.