TBXThemes.pas 25 KB

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