TB2Toolbar.pas 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733
  1. unit TB2Toolbar;
  2. {
  3. Toolbar2000
  4. Copyright (C) 1998-2005 by Jordan Russell
  5. All rights reserved.
  6. The contents of this file are subject to the "Toolbar2000 License"; you may
  7. not use or distribute this file except in compliance with the
  8. "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in
  9. TB2k-LICENSE.txt or at:
  10. https://jrsoftware.org/files/tb2k/TB2k-LICENSE.txt
  11. Alternatively, the contents of this file may be used under the terms of the
  12. GNU General Public License (the "GPL"), in which case the provisions of the
  13. GPL are applicable instead of those in the "Toolbar2000 License". A copy of
  14. the GPL may be found in GPL-LICENSE.txt or at:
  15. https://jrsoftware.org/files/tb2k/GPL-LICENSE.txt
  16. If you wish to allow use of your version of this file only under the terms of
  17. the GPL and not to allow others to use your version of this file under the
  18. "Toolbar2000 License", indicate your decision by deleting the provisions
  19. above and replace them with the notice and other provisions required by the
  20. GPL. If you do not delete the provisions above, a recipient may use your
  21. version of this file under either the "Toolbar2000 License" or the GPL.
  22. $jrsoftware: tb2k/Source/TB2Toolbar.pas,v 1.108 2005/07/30 18:17:20 jr Exp $
  23. }
  24. interface
  25. {$I TB2Ver.inc}
  26. uses
  27. Types,
  28. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ImgList,
  29. Menus, ActnList,
  30. TB2Item, TB2Dock;
  31. type
  32. TTBCustomToolbar = class;
  33. TTBChevronItem = class;
  34. TTBChevronItemClass = class of TTBChevronItem;
  35. TTBToolbarViewClass = class of TTBToolbarView;
  36. TTBToolbarView = class(TTBView)
  37. private
  38. FToolbar: TTBCustomToolbar;
  39. protected
  40. procedure AutoSize(AWidth, AHeight: Integer); override;
  41. procedure DoUpdatePositions(var ASize: TPoint); override;
  42. function GetChevronItem: TTBCustomItem; override;
  43. function GetMDIButtonsItem: TTBCustomItem; override;
  44. function GetMDISystemMenuItem: TTBCustomItem; override;
  45. public
  46. constructor Create(AOwner: TComponent); override;
  47. function GetFont: TFont; override;
  48. procedure InvalidatePositions; override;
  49. procedure EnterToolbarLoop(Options: TTBEnterToolbarLoopOptions); override;
  50. end;
  51. TTBChevronPriorityForNewItems = (tbcpHighest, tbcpLowest);
  52. { MP }
  53. TToolbarGetBaseSizeEvent = procedure(Toolbar: TTBCustomToolbar; var ASize: TPoint) of object;
  54. TTBCustomToolbar = class(TTBCustomDockableWindow, ITBItems)
  55. private
  56. FBaseSize: TPoint;
  57. FChevronItem: TTBChevronItem;
  58. FChevronMoveItems: Boolean;
  59. FChevronMenu: Boolean;
  60. FChevronPriorityForNewItems: TTBChevronPriorityForNewItems;
  61. FDisableAlignArrange: Integer;
  62. FFloatingWidth: Integer;
  63. FIgnoreMouseLeave: Boolean;
  64. FItem: TTBRootItem;
  65. FLastWrappedLines: Integer;
  66. FMenuBar: Boolean;
  67. FOnShortCut: TShortCutEvent;
  68. FProcessShortCuts: Boolean;
  69. FMainWindowHookInstalled: Boolean;
  70. FShrinkMode: TTBShrinkMode;
  71. FSizeData: Pointer;
  72. FSystemFont: Boolean;
  73. FUpdateActions: Boolean;
  74. { MP }
  75. FOnGetBaseSize: TToolbarGetBaseSizeEvent;
  76. FOnEndModal: TNotifyEvent;
  77. procedure CancelHover;
  78. function CalcChevronOffset(const ADock: TTBDock;
  79. const AOrientation: TTBViewOrientation): Integer;
  80. function CalcWrapOffset(const ADock: TTBDock): Integer;
  81. function CreateWrapper(Index: Integer; Ctl: TControl): TTBControlItem;
  82. function FindWrapper(Ctl: TControl): TTBControlItem;
  83. function GetChevronHint: String;
  84. function GetImages: TCustomImageList;
  85. function GetItems: TTBCustomItem;
  86. function GetLinkSubitems: TTBCustomItem;
  87. function GetOptions: TTBItemOptions;
  88. procedure InstallMainWindowHook;
  89. function IsChevronHintStored: Boolean;
  90. class function MainWindowHook(var Message: TMessage): Boolean;
  91. procedure SetChevronHint(const Value: String);
  92. procedure SetChevronMoveItems(Value: Boolean);
  93. procedure SetChevronPriorityForNewItems(Value: TTBChevronPriorityForNewItems);
  94. procedure SetFloatingWidth(Value: Integer);
  95. procedure SetImages(Value: TCustomImageList);
  96. procedure SetLinkSubitems(Value: TTBCustomItem);
  97. procedure SetMainWindowHook;
  98. procedure SetMenuBar(Value: Boolean);
  99. procedure SetOptions(Value: TTBItemOptions);
  100. procedure SetProcessShortCuts(Value: Boolean);
  101. procedure SetShrinkMode(Value: TTBShrinkMode);
  102. procedure SetSystemFont(Value: Boolean);
  103. procedure UninstallMainWindowHook;
  104. procedure UpdateViewProperties;
  105. procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  106. procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE;
  107. procedure CMControlListChange(var Message: TCMControlListChange); message CM_CONTROLLISTCHANGE;
  108. procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  109. procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
  110. procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
  111. procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
  112. procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  113. procedure CMShowHintChanged(var Message: TMessage); message CM_SHOWHINTCHANGED;
  114. procedure CMWinIniChange(var Message: TWMSettingChange); message CM_WININICHANGE;
  115. procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE;
  116. procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT;
  117. procedure WMMouseLeave(var Message: TMessage); message WM_MOUSELEAVE;
  118. procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE;
  119. procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR;
  120. procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
  121. protected
  122. FMDIButtonsItem: TTBCustomItem;
  123. FMDISystemMenuItem: TTBCustomItem;
  124. FView: TTBToolbarView;
  125. procedure AlignControls(AControl: TControl; var Rect: TRect); override;
  126. procedure BuildPotentialSizesList(SizesList: TList); dynamic;
  127. procedure ControlExistsAtPos(const P: TPoint; var ControlExists: Boolean);
  128. override;
  129. function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType;
  130. NewFloating: Boolean; NewDock: TTBDock): TPoint; override;
  131. procedure DoContextPopup(MousePos: TPoint; var Handled: Boolean); override;
  132. procedure GetBaseSize(var ASize: TPoint); override;
  133. procedure GetMinBarSize(var MinimumSize: TPoint);
  134. procedure GetMinShrinkSize(var AMinimumSize: Integer); override;
  135. function GetShrinkMode: TTBShrinkMode; override;
  136. function GetChevronItemClass: TTBChevronItemClass; dynamic;
  137. function GetItemClass: TTBRootItemClass; dynamic;
  138. function GetViewClass: TTBToolbarViewClass; dynamic;
  139. procedure Loaded; override;
  140. procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  141. X, Y: Integer); override;
  142. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  143. procedure Paint; override;
  144. procedure ResizeBegin(ASizeHandle: TTBSizeHandle); override;
  145. procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); override;
  146. procedure ResizeTrackAccept; override;
  147. procedure ResizeEnd; override;
  148. procedure SetChildOrder(Child: TComponent; Order: Integer); override;
  149. procedure ChangeScale(M, D: Integer; isDpiChange: Boolean); override;
  150. property SystemFont: Boolean read FSystemFont write SetSystemFont default True;
  151. property OnShortCut: TShortCutEvent read FOnShortCut write FOnShortCut;
  152. public
  153. constructor Create(AOwner: TComponent); override;
  154. destructor Destroy; override;
  155. procedure BeginUpdate;
  156. procedure EndUpdate;
  157. procedure CreateWrappersForAllControls;
  158. procedure GetTabOrderList(List: TList); override;
  159. procedure InitiateAction; override;
  160. function IsShortCut(var Message: TWMKey): Boolean;
  161. function KeyboardOpen(Key: Char; RequirePrimaryAccel: Boolean): Boolean;
  162. procedure ReadPositionData(var S: string); override;
  163. function WritePositionData: string; override;
  164. procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  165. procedure Idle;
  166. property ChevronHint: String read GetChevronHint write SetChevronHint stored IsChevronHintStored;
  167. property ChevronMoveItems: Boolean read FChevronMoveItems write SetChevronMoveItems default True;
  168. property ChevronMenu: Boolean read FChevronMenu write FChevronMenu default False;
  169. property ChevronPriorityForNewItems: TTBChevronPriorityForNewItems read FChevronPriorityForNewItems
  170. write SetChevronPriorityForNewItems default tbcpHighest;
  171. property FloatingWidth: Integer read FFloatingWidth write SetFloatingWidth default 0;
  172. property Images: TCustomImageList read GetImages write SetImages;
  173. property Items: TTBRootItem read FItem;
  174. property LinkSubitems: TTBCustomItem read GetLinkSubitems write SetLinkSubitems;
  175. property Options: TTBItemOptions read GetOptions write SetOptions default [];
  176. property MenuBar: Boolean read FMenuBar write SetMenuBar default False;
  177. property ProcessShortCuts: Boolean read FProcessShortCuts write SetProcessShortCuts default False;
  178. property ShrinkMode: TTBShrinkMode read FShrinkMode write SetShrinkMode default tbsmChevron;
  179. property UpdateActions: Boolean read FUpdateActions write FUpdateActions default True;
  180. property View: TTBToolbarView read FView;
  181. { MP }
  182. property OnGetBaseSize: TToolbarGetBaseSizeEvent read FOnGetBaseSize write FOnGetBaseSize;
  183. property OnEndModal: TNotifyEvent read FOnEndModal write FOnEndModal;
  184. published
  185. property Hint stored False; { Hint is set dynamically; don't save it }
  186. end;
  187. TTBToolbar = class(TTBCustomToolbar)
  188. published
  189. property ActivateParent;
  190. property Align;
  191. property Anchors;
  192. property AutoResize;
  193. property BorderStyle;
  194. property Caption;
  195. property ChevronHint;
  196. property ChevronMoveItems;
  197. property ChevronMenu;
  198. property ChevronPriorityForNewItems;
  199. property CloseButton;
  200. property CloseButtonWhenDocked;
  201. property Color;
  202. property CurrentDock;
  203. property DefaultDock;
  204. property DockableTo;
  205. property DockMode;
  206. property DockPos;
  207. property DockRow;
  208. property DragHandleStyle;
  209. property FloatingMode;
  210. property FloatingWidth;
  211. property Font;
  212. property FullSize;
  213. property HideWhenInactive;
  214. property Images;
  215. property Items;
  216. property LastDock;
  217. property LinkSubitems;
  218. property MenuBar;
  219. property Options;
  220. property ParentFont;
  221. property ParentShowHint;
  222. property PopupMenu;
  223. property ProcessShortCuts;
  224. property Resizable;
  225. property ShowCaption;
  226. property ShowHint;
  227. property ShrinkMode;
  228. property SmoothDrag;
  229. property Stretch;
  230. property SystemFont;
  231. property TabOrder;
  232. property UpdateActions;
  233. property UseLastDock;
  234. property Visible;
  235. property OnClose;
  236. property OnCloseQuery;
  237. {$IFDEF JR_D5}
  238. property OnContextPopup;
  239. {$ENDIF}
  240. property OnDragDrop;
  241. property OnDragOver;
  242. property OnMouseDown;
  243. property OnMouseMove;
  244. property OnMouseUp;
  245. property OnMove;
  246. property OnRecreated;
  247. property OnRecreating;
  248. property OnDockChanged;
  249. property OnDockChanging;
  250. property OnDockChangingHidden;
  251. property OnResize;
  252. property OnShortCut;
  253. property OnVisibleChanged;
  254. { MP }
  255. property OnGetBaseSize;
  256. property OnEndModal;
  257. end;
  258. { TTBChevronItem & TTBChevronItemViewer }
  259. TTBChevronItem = class(TTBCustomItem)
  260. private
  261. FToolbar: TTBCustomToolbar;
  262. function GetDefaultHint: String;
  263. public
  264. constructor Create(AOwner: TComponent); override;
  265. function GetChevronParentView: TTBView; override;
  266. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  267. end;
  268. TTBChevronItemViewer = class(TTBItemViewer)
  269. protected
  270. procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect;
  271. IsSelected, IsPushed, UseDisabledShadow: Boolean); override;
  272. function CaptionShown: Boolean; override;
  273. end;
  274. const
  275. tbChevronSize = 12;
  276. implementation
  277. uses
  278. TB2Consts, TB2Common, TB2Hook, PasTools;
  279. const
  280. { Constants for TTBCustomToolbar-specific registry values. Do not localize! }
  281. rvFloatRightX = 'FloatRightX';
  282. DockTypeToOrientation: array[TTBDockType] of TTBViewOrientation =
  283. (tbvoHorizontal, tbvoFloating, tbvoHorizontal, tbvoVertical);
  284. type
  285. { Used internally by the TCustomToolbar97.Resize* procedures }
  286. PToolbar97SizeData = ^TToolbar97SizeData;
  287. TToolbar97SizeData = record
  288. SizeHandle: TTBSizeHandle;
  289. NewSizes: TList; { List of valid new sizes. Items are casted into TSmallPoints }
  290. OrigLeft, OrigTop, OrigWidth, OrigHeight, NCXDiff: Integer;
  291. CurRightX: Integer;
  292. DisableSensCheck, OpSide: Boolean;
  293. SizeSens: Integer;
  294. end;
  295. procedure HookProc(Code: THookProcCode; Wnd: HWND; WParam: WPARAM;
  296. LParam: LPARAM);
  297. var
  298. Msg: PMsg;
  299. MainForm: TForm;
  300. begin
  301. { Work around an annoying Windows or VCL bug. If you close all MDI child
  302. windows, the MDI client window gets the focus, and when it has the focus,
  303. pressing Alt+[char] doesn't send a WM_SYSCOMMAND message to the form for
  304. some reason. It seems silly to have to use a hook for this, but I don't
  305. see a better workaround.
  306. Also, route Alt+- to the main form so that when an MDI child form is
  307. maximized, Alt+- brings up the TB2k MDI system menu instead of the
  308. system's. }
  309. if (Code = hpGetMessage) and (WParam = PM_REMOVE) then begin
  310. Msg := PMsg(LParam);
  311. if (Msg.message = WM_SYSCHAR) and (Msg.hwnd <> 0) then begin
  312. { Note: On Windows NT/2000/XP, even though we install the hook using
  313. SetWindowsHookExW, Msg.wParam may either be an ANSI character or a
  314. Unicode character, due to an apparent bug on these platforms. It is
  315. an ANSI character when the message passes through a separate
  316. SetWindowsHookExA-installed WH_GETMESSAGE hook first, and that hook
  317. calls us via CallNextHookEx. Windows apparently "forgets" to convert
  318. the character from ANSI back to Unicode in this case.
  319. We can't convert the character code because there seems to be no way
  320. to detect whether it is ANSI or Unicode. So we can't really do much
  321. with Msg.wParam, apart from comparing it against character codes that
  322. are the same between ANSI and Unicode, such as '-'. }
  323. MainForm := Application.MainForm;
  324. if Assigned(MainForm) and MainForm.HandleAllocated and (GetCapture = 0) and
  325. ((Msg.hwnd = MainForm.ClientHandle) or
  326. ((Msg.wParam = Ord('-')) and (MainForm.ClientHandle <> 0) and
  327. IsChild(MainForm.ClientHandle, Msg.hwnd))) then begin
  328. { Redirect the message to the main form.
  329. Note: Unfortunately, due to a bug in Windows NT 4.0 (and not
  330. 2000/XP/9x/Me), modifications to the message don't take effect if
  331. another WH_GETMESSAGE hook has been installed above this one.
  332. (The bug is that CallNextHookEx copies lParam^ to a local buffer, but
  333. does not propogate the changes made by the hook back to lParam^ when
  334. it returns.) I don't know of any clean workaround, other than to
  335. ensure other WH_GETMESSAGE hooks are installed *before*
  336. Toolbar2000's. }
  337. Msg.hwnd := MainForm.Handle;
  338. end;
  339. end;
  340. end;
  341. end;
  342. constructor TTBChevronItem.Create(AOwner: TComponent);
  343. begin
  344. inherited;
  345. FToolbar := AOwner as TTBCustomToolbar;
  346. ItemStyle := ItemStyle + [tbisSubMenu, tbisNoAutoOpen];
  347. Hint := GetDefaultHint;
  348. Caption := EscapeAmpersands(GetShortHint(Hint));
  349. end;
  350. function TTBChevronItem.GetChevronParentView: TTBView;
  351. begin
  352. Result := FToolbar.FView;
  353. end;
  354. function TTBChevronItem.GetDefaultHint: String;
  355. begin
  356. Result := STBChevronItemMoreButtonsHint;
  357. end;
  358. function TTBChevronItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  359. begin
  360. Result := TTBChevronItemViewer;
  361. end;
  362. procedure TTBChevronItemViewer.Paint(const Canvas: TCanvas;
  363. const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean);
  364. const
  365. Pattern: array[Boolean, 0..15] of Byte = (
  366. ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0),
  367. ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0));
  368. var
  369. DC: HDC;
  370. R2: TRect;
  371. TempBmp: TBitmap;
  372. procedure DrawPattern(const Color, Offset: Integer);
  373. begin
  374. SelectObject(DC, GetSysColorBrush(Color));
  375. BitBlt(DC, R2.Left, R2.Top + Offset, R2.Right - R2.Left,
  376. R2.Bottom - R2.Top, TempBmp.Canvas.Handle, 0, 0, $00E20746 {ROP_DSPDxax});
  377. end;
  378. begin
  379. DC := Canvas.Handle;
  380. R2 := ClientAreaRect;
  381. if Item.Enabled then begin
  382. if IsPushed then
  383. DrawEdge(DC, R2, BDR_SUNKENOUTER, BF_RECT)
  384. else if IsSelected and not(csDesigning in Item.ComponentState) then
  385. DrawEdge(DC, R2, BDR_RAISEDINNER, BF_RECT);
  386. end;
  387. if View.Orientation <> tbvoVertical then begin
  388. R2.Top := 4;
  389. R2.Bottom := R2.Top + 5;
  390. Inc(R2.Left, 2);
  391. R2.Right := R2.Left + 8;
  392. end
  393. else begin
  394. R2.Left := R2.Right - 9;
  395. R2.Right := R2.Left + 5;
  396. Inc(R2.Top, 2);
  397. R2.Bottom := R2.Top + 8;
  398. end;
  399. if IsPushed then
  400. OffsetRect(R2, 1, 1);
  401. TempBmp := TBitmap.Create;
  402. try
  403. TempBmp.Handle := CreateBitmap(8, 8, 1, 1,
  404. @Pattern[View.Orientation = tbvoVertical]);
  405. SetTextColor(DC, clBlack);
  406. SetBkColor(DC, clWhite);
  407. if Item.Enabled then
  408. DrawPattern(COLOR_BTNTEXT, 0)
  409. else begin
  410. DrawPattern(COLOR_BTNHIGHLIGHT, 1);
  411. DrawPattern(COLOR_BTNSHADOW, 0);
  412. end;
  413. finally
  414. TempBmp.Free;
  415. end;
  416. end;
  417. function TTBChevronItemViewer.CaptionShown: Boolean;
  418. begin
  419. Result := False;
  420. end;
  421. { TTBToolbarView }
  422. constructor TTBToolbarView.Create(AOwner: TComponent);
  423. begin
  424. FToolbar := AOwner as TTBCustomToolbar;
  425. inherited;
  426. end;
  427. procedure TTBToolbarView.AutoSize(AWidth, AHeight: Integer);
  428. begin
  429. FToolbar.FBaseSize := BaseSize;
  430. if FToolbar.IsAutoResized then
  431. FToolbar.ChangeSize(AWidth, AHeight);
  432. end;
  433. procedure TTBToolbarView.DoUpdatePositions(var ASize: TPoint);
  434. begin
  435. { Reset CurrentSize because it probably won't be valid after positions
  436. are recalculated [2001-06-24] }
  437. FToolbar.CurrentSize := 0;
  438. FToolbar.GetMinBarSize(ASize);
  439. { On FullSize toolbars, increase ASize.X/Y to WrapOffset so that
  440. right-aligned items always appear at the right edge even when the toolbar
  441. isn't wrapping }
  442. if FToolbar.FullSize then begin
  443. if (Orientation = tbvoHorizontal) and (ASize.X < WrapOffset) then
  444. ASize.X := WrapOffset
  445. else if (Orientation = tbvoVertical) and (ASize.Y < WrapOffset) then
  446. ASize.Y := WrapOffset;
  447. end;
  448. { Increment FDisableAlignArrange so that we don't recursively arrange when
  449. CalculatePositions moves controls }
  450. Inc(FToolbar.FDisableAlignArrange);
  451. try
  452. inherited;
  453. finally
  454. Dec(FToolbar.FDisableAlignArrange);
  455. end;
  456. end;
  457. procedure TTBToolbarView.InvalidatePositions;
  458. begin
  459. { Reset CurrentSize because it probably won't be valid after positions
  460. are recalculated [2001-06-04] }
  461. FToolbar.CurrentSize := 0;
  462. inherited;
  463. end;
  464. function TTBToolbarView.GetFont: TFont;
  465. begin
  466. if not FToolbar.SystemFont then
  467. Result := FToolbar.Font
  468. else
  469. Result := inherited GetFont;
  470. end;
  471. function TTBToolbarView.GetChevronItem: TTBCustomItem;
  472. begin
  473. Result := FToolbar.FChevronItem;
  474. end;
  475. function TTBToolbarView.GetMDIButtonsItem: TTBCustomItem;
  476. begin
  477. Result := FToolbar.FMDIButtonsItem;
  478. end;
  479. function TTBToolbarView.GetMDISystemMenuItem: TTBCustomItem;
  480. begin
  481. Result := FToolbar.FMDISystemMenuItem;
  482. end;
  483. procedure TTBToolbarView.EnterToolbarLoop(Options: TTBEnterToolbarLoopOptions);
  484. begin
  485. inherited;
  486. if Assigned(FToolbar.OnEndModal) then
  487. FToolbar.OnEndModal(FToolbar);
  488. end;
  489. { TTBCustomToolbar }
  490. type
  491. {}TTBCustomItemAccess = class(TTBCustomItem);
  492. TTBItemViewerAccess = class(TTBItemViewer);
  493. constructor TTBCustomToolbar.Create(AOwner: TComponent);
  494. begin
  495. inherited;
  496. ControlStyle := ControlStyle + [csAcceptsControls, csActionClient] -
  497. [csCaptureMouse];
  498. DockableWindowStyles := DockableWindowStyles - [tbdsResizeEightCorner,
  499. tbdsResizeClipCursor];
  500. FItem := GetItemClass.Create(Self);
  501. FItem.ParentComponent := Self;
  502. FChevronItem := GetChevronItemClass.Create(Self);
  503. FChevronItem.LinkSubitems := FItem;
  504. FChevronMoveItems := True;
  505. FChevronMenu := False;
  506. FView := GetViewClass.CreateView(Self, nil, FItem, Self, True, False,
  507. not(csDesigning in ComponentState));
  508. // This might as well go to TTBToolbarView.Create
  509. FView.Style := FView.Style + [vsUseHiddenAccels];
  510. FView.BackgroundColor := clBtnFace;
  511. FUpdateActions := True;
  512. FShrinkMode := tbsmChevron;
  513. FSystemFont := True;
  514. Color := clBtnFace;
  515. SetBounds(Left, Top, 23, 22);{}
  516. { MP }
  517. FOnGetBaseSize := nil;
  518. FOnEndModal := nil;
  519. end;
  520. destructor TTBCustomToolbar.Destroy;
  521. begin
  522. { Call Destroying to ensure csDestroying is in ComponentState now. Only
  523. needed for Delphi 4 and earlier since Delphi 5 calls Destroying in
  524. TComponent.BeforeDestruction }
  525. Destroying;
  526. UninstallHookProc(Self, HookProc);
  527. UninstallMainWindowHook;
  528. FreeAndNil(FView);
  529. FreeAndNil(FChevronItem);
  530. FreeAndNil(FItem);
  531. inherited;
  532. end;
  533. function TTBCustomToolbar.GetItems: TTBCustomItem;
  534. begin
  535. Result := FItem;
  536. end;
  537. function TTBCustomToolbar.GetItemClass: TTBRootItemClass;
  538. begin
  539. Result := TTBRootItem;
  540. end;
  541. function TTBCustomToolbar.GetViewClass: TTBToolbarViewClass;
  542. begin
  543. Result := TTBToolbarView;
  544. end;
  545. function TTBCustomToolbar.GetChevronItemClass: TTBChevronItemClass;
  546. begin
  547. Result := TTBChevronItem;
  548. end;
  549. procedure TTBCustomToolbar.CreateWrappersForAllControls;
  550. { Create wrappers for any controls that don't already have them }
  551. var
  552. L: TList;
  553. I, J, C: Integer;
  554. begin
  555. if ControlCount = 0 then
  556. Exit;
  557. L := TList.Create;
  558. try
  559. L.Capacity := ControlCount;
  560. for I := 0 to ControlCount-1 do
  561. L.Add(Controls[I]);
  562. C := FItem.Count-1;
  563. for I := 0 to C do
  564. if FItem[I] is TTBControlItem then begin
  565. J := L.IndexOf(TTBControlItem(FItem[I]).Control);
  566. if J <> -1 then
  567. L[J] := nil;
  568. end;
  569. for I := 0 to L.Count-1 do
  570. if Assigned(L[I]) then
  571. CreateWrapper(FItem.Count, L[I]);
  572. finally
  573. L.Free;
  574. end;
  575. end;
  576. procedure TTBCustomToolbar.Loaded;
  577. begin
  578. CreateWrappersForAllControls;
  579. inherited;
  580. end;
  581. procedure TTBCustomToolbar.GetChildren(Proc: TGetChildProc; Root: TComponent);
  582. begin
  583. TTBCustomItemAccess(FItem).GetChildren(Proc, Root);
  584. inherited;
  585. end;
  586. procedure TTBCustomToolbar.SetChildOrder(Child: TComponent; Order: Integer);
  587. begin
  588. if Child is TTBCustomItem then
  589. TTBCustomItemAccess(FItem).SetChildOrder(Child, Order);
  590. end;
  591. procedure TTBCustomToolbar.AlignControls(AControl: TControl; var Rect: TRect);
  592. { VCL calls this whenever any child controls in the toolbar are moved, sized,
  593. inserted, etc., and also when the toolbar is resized. }
  594. begin
  595. if FDisableAlignArrange = 0 then
  596. Arrange;
  597. end;
  598. procedure TTBCustomToolbar.InitiateAction;
  599. begin
  600. inherited;
  601. {}{ also add this to popupmenu(?) }
  602. { Update visible top-level items }
  603. if FUpdateActions then
  604. FView.InitiateActions;
  605. end;
  606. procedure TTBCustomToolbar.CMColorChanged(var Message: TMessage);
  607. begin
  608. { Synchronize FView.BackgroundColor with the new color }
  609. if Assigned(FView) then
  610. FView.BackgroundColor := Color;
  611. inherited;
  612. end;
  613. function TTBCustomToolbar.CreateWrapper(Index: Integer;
  614. Ctl: TControl): TTBControlItem;
  615. var
  616. I: Integer;
  617. S: String;
  618. begin
  619. Result := TTBControlItem.CreateControlItem(Owner, Ctl);
  620. if (csDesigning in ComponentState) and Assigned(Owner) then begin
  621. { Needs a name for compatibility with form inheritance }
  622. I := 1;
  623. while True do begin
  624. S := Format('TBControlItem%d', [I]);
  625. if Owner.FindComponent(S) = nil then
  626. Break;
  627. Inc(I);
  628. end;
  629. Result.Name := S;
  630. end;
  631. FItem.Insert(Index, Result);
  632. end;
  633. function TTBCustomToolbar.FindWrapper(Ctl: TControl): TTBControlItem;
  634. var
  635. I: Integer;
  636. Item: TTBCustomItem;
  637. begin
  638. Result := nil;
  639. for I := 0 to FItem.Count-1 do begin
  640. Item := FItem[I];
  641. if (Item is TTBControlItem) and
  642. (TTBControlItem(Item).Control = Ctl) then begin
  643. Result := TTBControlItem(Item);
  644. Break;
  645. end;
  646. end;
  647. end;
  648. procedure TTBCustomToolbar.CMControlChange(var Message: TCMControlChange);
  649. { A CM_CONTROLCHANGE handler must be used instead of a CM_CONTROLLISTCHANGE
  650. handler because when a CM_CONTROLLISTCHANGE message is sent it is relayed to
  651. *all* parents. CM_CONTROLCHANGE messages are only sent to the immediate
  652. parent. }
  653. begin
  654. inherited;
  655. { Don't automatically create TTBControlItem wrappers if the component
  656. is loading or being updated to reflect changes in an ancestor form,
  657. because wrappers will be streamed in }
  658. if Message.Inserting and not(csLoading in ComponentState) and
  659. not(csUpdating in ComponentState) and
  660. (FindWrapper(Message.Control) = nil) then
  661. CreateWrapper(FItem.Count, Message.Control);
  662. end;
  663. procedure TTBCustomToolbar.CMControlListChange(var Message: TCMControlListChange);
  664. { Don't handle deletions inside CM_CONTROLCHANGE because CM_CONTROLCHANGE is
  665. sent *before* a control begins removing itself from its parent. (It used
  666. to handle both insertions and deletions inside CM_CONTROLCHANGE but this
  667. caused AV's.) }
  668. var
  669. Item: TTBControlItem;
  670. begin
  671. inherited;
  672. if not Message.Inserting and Assigned(FItem) then begin
  673. while True do begin
  674. Item := FindWrapper(Message.Control);
  675. if Item = nil then Break;
  676. { The control is being removed the control, not necessarily destroyed,
  677. so set DontFreeControl to True }
  678. Item.DontFreeControl := True;
  679. Item.Free;
  680. end;
  681. end;
  682. end;
  683. procedure TTBCustomToolbar.CMHintShow(var Message: TCMHintShow);
  684. { Since the items on a toolbar aren't "real" controls, it needs a CM_HINTSHOW
  685. handler for their hints to be displayed. }
  686. var
  687. V: TTBItemViewer;
  688. begin
  689. with Message.HintInfo^ do begin
  690. HintStr := '';
  691. V := FView.ViewerFromPoint(CursorPos);
  692. if Assigned(V) then begin
  693. if not IsRectEmpty(V.BoundsRect) then begin
  694. CursorRect := V.BoundsRect;
  695. HintStr := V.GetHintText;
  696. end;
  697. end;
  698. end;
  699. end;
  700. procedure TTBCustomToolbar.CMShowHintChanged(var Message: TMessage);
  701. begin
  702. inherited;
  703. if ShowHint then
  704. FView.Style := FView.Style + [vsAlwaysShowHints]
  705. else
  706. FView.Style := FView.Style - [vsAlwaysShowHints];
  707. end;
  708. procedure TTBCustomToolbar.WMGetObject(var Message: TMessage);
  709. begin
  710. if not FView.HandleWMGetObject(Message) then
  711. inherited;
  712. end;
  713. procedure TTBCustomToolbar.WMSetCursor(var Message: TWMSetCursor);
  714. var
  715. P: TPoint;
  716. Cursor: HCURSOR;
  717. R: TRect;
  718. begin
  719. if not(csDesigning in ComponentState) and
  720. (Message.CursorWnd = WindowHandle) and
  721. (Smallint(Message.HitTest) = HTCLIENT) then begin
  722. GetCursorPos(P);
  723. FView.UpdateSelection(@P, True);
  724. if Assigned(FView.Selected) then begin
  725. Cursor := 0;
  726. R := FView.Selected.BoundsRect;
  727. P := ScreenToClient(P);
  728. Dec(P.X, R.Left);
  729. Dec(P.Y, R.Top);
  730. TTBItemViewerAccess(FView.Selected).GetCursor(P, Cursor);
  731. if Cursor <> 0 then begin
  732. SetCursor(Cursor);
  733. Message.Result := 1;
  734. Exit;
  735. end;
  736. end;
  737. end;
  738. inherited;
  739. end;
  740. procedure TTBCustomToolbar.WMSysCommand(var Message: TWMSysCommand);
  741. begin
  742. if FMenuBar and Enabled and Showing then
  743. with Message do
  744. if (CmdType and $FFF0 = SC_KEYMENU) and (Key <> VK_SPACE) and
  745. (GetCapture = 0) then begin
  746. if not KeyboardOpen(Char(Key), False) then begin
  747. if Key = Ord('-') then Exit;
  748. MessageBeep(0);
  749. end;
  750. Result := 1;
  751. end;
  752. end;
  753. procedure TTBCustomToolbar.Paint;
  754. var
  755. R: TRect;
  756. begin
  757. { Draw dotted border in design mode on undocked toolbars }
  758. if not Docked and (csDesigning in ComponentState) then
  759. with Canvas do begin
  760. R := ClientRect;
  761. Pen.Style := psDot;
  762. Pen.Color := clBtnShadow;
  763. Brush.Style := bsClear;
  764. Rectangle(R.Left, R.Top, R.Right, R.Bottom);
  765. Pen.Style := psSolid;
  766. end;
  767. FView.DrawSubitems(Canvas);
  768. end;
  769. procedure TTBCustomToolbar.CMDialogKey(var Message: TCMDialogKey);
  770. begin
  771. if (Message.CharCode = VK_MENU) and FMenuBar then
  772. FView.SetAccelsVisibility(True);
  773. inherited;
  774. end;
  775. procedure TTBCustomToolbar.Idle;
  776. begin
  777. if FMenuBar and
  778. (not (vsModal in FView.State)) and
  779. ((GetAsyncKeyState(VK_MENU) and $8000) = 0) then
  780. begin
  781. FView.SetAccelsVisibility(False);
  782. end;
  783. end;
  784. procedure TTBCustomToolbar.CMDialogChar(var Message: TCMDialogChar);
  785. begin
  786. { On toolbars that aren't menu bars, handle CM_DIALOGCHAR instead of
  787. WM_SYSCOMMAND }
  788. if not FMenuBar and Enabled and Showing and (Message.CharCode <> 0) then
  789. if KeyboardOpen(Chr(Message.CharCode), True) then begin
  790. Message.Result := 1;
  791. Exit;
  792. end;
  793. inherited;
  794. end;
  795. procedure TTBCustomToolbar.CancelHover;
  796. begin
  797. if not MouseCapture then
  798. FView.UpdateSelection(nil, True);
  799. end;
  800. procedure TTBCustomToolbar.CMMouseLeave(var Message: TMessage);
  801. begin
  802. CancelHover;
  803. inherited;
  804. end;
  805. procedure TTBCustomToolbar.DoContextPopup(MousePos: TPoint;
  806. var Handled: Boolean);
  807. begin
  808. CancelHover;
  809. inherited;
  810. end;
  811. procedure TTBCustomToolbar.MouseMove(Shift: TShiftState; X, Y: Integer);
  812. var
  813. P: TPoint;
  814. Item: TTBCustomItem;
  815. begin
  816. if not(csDesigning in ComponentState) then begin
  817. P := ClientToScreen(Point(X, Y));
  818. FView.UpdateSelection(@P, True);
  819. if Assigned(FView.Selected) then begin
  820. Item := FView.Selected.Item;
  821. if not(tboLongHintInMenuOnly in Item.EffectiveOptions) then
  822. Hint := Item.Hint
  823. else
  824. Hint := '';
  825. with TTBItemViewerAccess(FView.Find(Item)) do
  826. begin
  827. MouseMove(X - BoundsRect.Left, Y - BoundsRect.Top);
  828. end;
  829. end
  830. else
  831. Hint := '';
  832. end;
  833. { Call TrackMouseEvent to be sure that we are notified when the mouse leaves
  834. the window. We won't get a CM_MOUSELEAVE message if the mouse moves
  835. directly from the toolbar to another application's window }
  836. CallTrackMouseEvent(Handle, TME_LEAVE);
  837. inherited;
  838. end;
  839. procedure TTBCustomToolbar.WMCancelMode(var Message: TWMCancelMode);
  840. begin
  841. inherited;
  842. { We can receive a WM_CANCELMODE message during a modal loop if a dialog
  843. pops up. Respond by hiding menus to make it look like the modal loop
  844. has returned, even though it really hasn't yet.
  845. Note: Similar code in TTBModalHandler.WndProc. }
  846. if vsModal in FView.State then
  847. FView.CancelMode;
  848. end;
  849. procedure TTBCustomToolbar.WMMouseLeave(var Message: TMessage);
  850. begin
  851. { A WM_MOUSELEAVE handler is necessary because the control won't get a
  852. CM_MOUSELEAVE message if the user presses Alt+Space. Also, CM_MOUSELEAVE
  853. messages are also not sent if the application is in a
  854. Application.ProcessMessages loop. }
  855. if not FIgnoreMouseLeave then
  856. CancelHover;
  857. inherited;
  858. end;
  859. procedure TTBCustomToolbar.WMNCMouseMove(var Message: TWMNCMouseMove);
  860. begin
  861. Hint := '';
  862. CancelHover;
  863. inherited;
  864. end;
  865. function TTBCustomToolbar.KeyboardOpen(Key: Char;
  866. RequirePrimaryAccel: Boolean): Boolean;
  867. var
  868. I: TTBItemViewer;
  869. IsOnlyItemWithAccel: Boolean;
  870. begin
  871. I := nil;
  872. FView.SetAccelsVisibility(True);
  873. try
  874. Result := False;
  875. if Key = #0 then begin
  876. I := FView.FirstSelectable;
  877. if I = nil then Exit;
  878. FView.Selected := I;
  879. FView.EnterToolbarLoop([]);
  880. end
  881. else begin
  882. I := FView.NextSelectableWithAccel(nil, Key, RequirePrimaryAccel,
  883. IsOnlyItemWithAccel);
  884. if (I = nil) or not I.Item.Enabled then
  885. Exit;
  886. if IsOnlyItemWithAccel then begin
  887. FView.Selected := I;
  888. FView.EnterToolbarLoop([tbetExecuteSelected]);
  889. end
  890. else if FMenuBar then begin
  891. FView.Selected := I;
  892. FView.EnterToolbarLoop([]);
  893. end
  894. else
  895. Exit;
  896. end;
  897. Result := True;
  898. finally
  899. if Assigned(I) then
  900. FView.SetAccelsVisibility(False);
  901. end;
  902. end;
  903. procedure TTBCustomToolbar.MouseDown(Button: TMouseButton; Shift: TShiftState;
  904. X, Y: Integer);
  905. var
  906. OldParent: TWinControl;
  907. P: TPoint;
  908. Item: TTBCustomItem;
  909. begin
  910. OldParent := Parent;
  911. inherited;
  912. if Parent <> OldParent then
  913. { if the inherited handler (TTBDockableWindow.MouseDown) changed the Parent
  914. (due to the toolbar moving between docks), nothing else should be done }
  915. Exit;
  916. if not(csDesigning in ComponentState) and (Button = mbLeft) then begin
  917. P := ClientToScreen(Point(X, Y));
  918. FView.UpdateSelection(@P, True);
  919. if Assigned(FView.Selected) then begin
  920. Item := FView.Selected.Item;
  921. if not(tbisClicksTransparent in TTBCustomItemAccess(Item).ItemStyle) then begin
  922. FIgnoreMouseLeave := True;
  923. try
  924. FView.EnterToolbarLoop([tbetMouseDown]);
  925. finally
  926. FIgnoreMouseLeave := False;
  927. end;
  928. end;
  929. end;
  930. end;
  931. end;
  932. procedure TTBCustomToolbar.CMFontChanged(var Message: TMessage);
  933. begin
  934. inherited;
  935. if not FSystemFont then
  936. Arrange;
  937. end;
  938. function TTBCustomToolbar.GetChevronHint: String;
  939. begin
  940. Result := FChevronItem.Hint;
  941. end;
  942. procedure TTBCustomToolbar.SetChevronHint(const Value: String);
  943. begin
  944. FChevronItem.Hint := Value;
  945. FChevronItem.Caption := EscapeAmpersands(GetShortHint(Value));
  946. end;
  947. procedure TTBCustomToolbar.SetChevronMoveItems(Value: Boolean);
  948. begin
  949. if FChevronMoveItems <> Value then begin
  950. FChevronMoveItems := Value;
  951. FView.UsePriorityList := Value and not(csDesigning in ComponentState);
  952. end;
  953. end;
  954. procedure TTBCustomToolbar.SetChevronPriorityForNewItems(Value: TTBChevronPriorityForNewItems);
  955. begin
  956. FChevronPriorityForNewItems := Value;
  957. FView.NewViewersGetHighestPriority := (Value = tbcpHighest);
  958. end;
  959. function TTBCustomToolbar.IsChevronHintStored: Boolean;
  960. begin
  961. Result := (FChevronItem.Hint <> FChevronItem.GetDefaultHint);
  962. end;
  963. function TTBCustomToolbar.GetImages: TCustomImageList;
  964. begin
  965. Result := FItem.SubMenuImages;
  966. end;
  967. procedure TTBCustomToolbar.SetImages(Value: TCustomImageList);
  968. begin
  969. FItem.SubMenuImages := Value;
  970. end;
  971. function TTBCustomToolbar.GetLinkSubitems: TTBCustomItem;
  972. begin
  973. Result := FItem.LinkSubitems;
  974. end;
  975. procedure TTBCustomToolbar.SetLinkSubitems(Value: TTBCustomItem);
  976. begin
  977. FItem.LinkSubitems := Value;
  978. end;
  979. procedure TTBCustomToolbar.SetMenuBar(Value: Boolean);
  980. begin
  981. if FMenuBar <> Value then begin
  982. FMenuBar := Value;
  983. if Value then begin
  984. ControlStyle := ControlStyle + [csMenuEvents];
  985. FView.Style := FView.Style + [vsMenuBar];
  986. end
  987. else begin
  988. ControlStyle := ControlStyle - [csMenuEvents];
  989. FView.Style := FView.Style - [vsMenuBar];
  990. end;
  991. if not(csLoading in ComponentState) then begin
  992. FullSize := Value;
  993. if Value then
  994. ShrinkMode := tbsmWrap
  995. else
  996. ShrinkMode := tbsmChevron;
  997. CloseButton := not Value;
  998. ProcessShortCuts := Value;
  999. end;
  1000. if Value and not(csDesigning in ComponentState) then
  1001. InstallHookProc(Self, HookProc, [hpGetMessage])
  1002. else
  1003. UninstallHookProc(Self, HookProc);
  1004. SetMainWindowHook;
  1005. end;
  1006. end;
  1007. function TTBCustomToolbar.GetOptions: TTBItemOptions;
  1008. begin
  1009. Result := FItem.Options;
  1010. end;
  1011. procedure TTBCustomToolbar.SetOptions(Value: TTBItemOptions);
  1012. begin
  1013. FItem.Options := Value;
  1014. end;
  1015. procedure TTBCustomToolbar.SetProcessShortCuts(Value: Boolean);
  1016. begin
  1017. if FProcessShortCuts <> Value then begin
  1018. FProcessShortCuts := Value;
  1019. SetMainWindowHook;
  1020. end;
  1021. end;
  1022. procedure TTBCustomToolbar.SetSystemFont(Value: Boolean);
  1023. begin
  1024. if FSystemFont <> Value then begin
  1025. FSystemFont := Value;
  1026. Arrange;
  1027. end;
  1028. end;
  1029. procedure TTBCustomToolbar.SetShrinkMode(Value: TTBShrinkMode);
  1030. begin
  1031. if FShrinkMode <> Value then begin
  1032. FShrinkMode := Value;
  1033. if Docked then
  1034. CurrentDock.ArrangeToolbars
  1035. else if not Floating then
  1036. Arrange;
  1037. end;
  1038. end;
  1039. procedure TTBCustomToolbar.SetFloatingWidth(Value: Integer);
  1040. begin
  1041. if FFloatingWidth <> Value then begin
  1042. FFloatingWidth := Value;
  1043. if Floating then begin
  1044. UpdateViewProperties;
  1045. Arrange;
  1046. end;
  1047. end;
  1048. end;
  1049. function TTBCustomToolbar.CalcWrapOffset(const ADock: TTBDock): Integer;
  1050. begin
  1051. if ADock = nil then
  1052. Result := FFloatingWidth
  1053. else begin
  1054. if FShrinkMode = tbsmWrap then begin
  1055. if not(ADock.Position in [dpLeft, dpRight]) then
  1056. Result := ADock.Width - ADock.NonClientWidth - NonClientWidth
  1057. else
  1058. Result := ADock.Height - ADock.NonClientHeight - NonClientHeight;
  1059. end
  1060. else
  1061. Result := 0;
  1062. end;
  1063. end;
  1064. function TTBCustomToolbar.CalcChevronOffset(const ADock: TTBDock;
  1065. const AOrientation: TTBViewOrientation): Integer;
  1066. begin
  1067. if (FShrinkMode = tbsmChevron) and Docked and (ADock = CurrentDock) then begin
  1068. Result := CurrentSize;
  1069. { Subtract non-client size }
  1070. if AOrientation <> tbvoVertical then
  1071. Dec(Result, NonClientWidth)
  1072. else
  1073. Dec(Result, NonClientHeight);
  1074. if Result < 0 then
  1075. Result := 0; { in case CurrentSize wasn't properly initialized yet }
  1076. end
  1077. else
  1078. Result := 0;
  1079. end;
  1080. procedure TTBCustomToolbar.UpdateViewProperties;
  1081. var
  1082. DT: TTBDockType;
  1083. begin
  1084. DT := TBGetDockTypeOf(CurrentDock, Floating);
  1085. FView.Orientation := DockTypeToOrientation[DT];
  1086. FView.ChevronSize := tbChevronSize;
  1087. if Assigned(CurrentDock) or Floating then begin
  1088. FView.ChevronOffset := CalcChevronOffset(CurrentDock, FView.Orientation);
  1089. FView.WrapOffset := CalcWrapOffset(CurrentDock);
  1090. end
  1091. else begin
  1092. FView.ChevronOffset := 0;
  1093. FView.WrapOffset := 0;
  1094. { Only enable chevron/wrapping when the width of the toolbar is fixed }
  1095. if not AutoResize or ((akLeft in Anchors) and (akRight in Anchors)) then begin
  1096. if FShrinkMode = tbsmChevron then
  1097. FView.ChevronOffset := Width - NonClientWidth
  1098. else if FShrinkMode = tbsmWrap then
  1099. FView.WrapOffset := Width - NonClientWidth;
  1100. end;
  1101. end;
  1102. end;
  1103. {}{DOCKING STUFF}
  1104. procedure TTBCustomToolbar.ReadPositionData(var S: string);
  1105. begin
  1106. inherited;
  1107. if Floating then
  1108. FloatingWidth := StrToIntDef(CutToChar(S, ':', true), 0);
  1109. end;
  1110. function TTBCustomToolbar.WritePositionData: string;
  1111. begin
  1112. Result := inherited;
  1113. if Floating then
  1114. Result := Result + ':' + IntToStr(FFloatingWidth);
  1115. end;
  1116. procedure TTBCustomToolbar.GetMinBarSize(var MinimumSize: TPoint);
  1117. var
  1118. WH: Integer;
  1119. begin
  1120. MinimumSize.X := 0;
  1121. MinimumSize.Y := 0;
  1122. if Docked then begin
  1123. WH := CurrentDock.GetMinRowSize(EffectiveDockRow, Self);
  1124. if not(CurrentDock.Position in [dpLeft, dpRight]) then
  1125. MinimumSize.Y := WH
  1126. else
  1127. MinimumSize.X := WH;
  1128. end;
  1129. end;
  1130. procedure TTBCustomToolbar.GetBaseSize(var ASize: TPoint);
  1131. begin
  1132. FView.ValidatePositions;
  1133. ASize := FBaseSize;
  1134. { MP }
  1135. if Assigned(FOnGetBaseSize) then FOnGetBaseSize(Self, ASize);
  1136. end;
  1137. function TTBCustomToolbar.DoArrange(CanMoveControls: Boolean;
  1138. PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint;
  1139. var
  1140. DT: TTBDockType;
  1141. O: TTBViewOrientation;
  1142. TempBaseSize: TPoint;
  1143. begin
  1144. //outputdebugstring (pchar(format('%s.DoArrange(%d)', [Name, Ord(CanMoveControls)])));
  1145. if CanMoveControls then begin
  1146. UpdateViewProperties;
  1147. Result := FView.UpdatePositions;
  1148. end
  1149. else begin
  1150. DT := TBGetDockTypeOf(NewDock, NewFloating);
  1151. O := DockTypeToOrientation[DT];
  1152. Result.X := 0;
  1153. Result.Y := 0;
  1154. FView.CalculatePositions(False, O, CalcWrapOffset(NewDock),
  1155. CalcChevronOffset(NewDock, O), tbChevronSize, TempBaseSize, Result,
  1156. FLastWrappedLines);
  1157. end;
  1158. end;
  1159. procedure TTBCustomToolbar.ControlExistsAtPos(const P: TPoint;
  1160. var ControlExists: Boolean);
  1161. var
  1162. P2: TPoint;
  1163. begin
  1164. inherited;
  1165. if not ControlExists and not(csDesigning in ComponentState) then begin
  1166. P2 := ClientToScreen(P);
  1167. FView.UpdateSelection(@P2, True);
  1168. if Assigned(FView.Selected) and
  1169. not(tbisClicksTransparent in TTBCustomItemAccess(FView.Selected.Item).ItemStyle) then
  1170. ControlExists := True;
  1171. end;
  1172. end;
  1173. procedure TTBCustomToolbar.BuildPotentialSizesList(SizesList: TList);
  1174. var
  1175. Margins: TRect;
  1176. MinX, SaveWrapX: Integer;
  1177. X, PrevWrappedLines: Integer;
  1178. S: TPoint;
  1179. S2: TSmallPoint;
  1180. begin
  1181. View.GetMargins(tbvoFloating, Margins);
  1182. MinX := Margins.Left + Margins.Right;
  1183. SaveWrapX := FFloatingWidth;
  1184. try
  1185. { Add the widest size to the list }
  1186. FFloatingWidth := 0;
  1187. S := DoArrange(False, dtNotDocked, True, nil);
  1188. SizesList.Add(Pointer(PointToSmallPoint(S)));
  1189. { Calculate and add rest of sizes to the list }
  1190. PrevWrappedLines := 1;
  1191. X := S.X-1;
  1192. while X >= MinX do begin
  1193. FFloatingWidth := X;
  1194. S := DoArrange(False, dtNotDocked, True, nil);
  1195. if S.X > X then { if it refuses to go any smaller }
  1196. Break
  1197. else
  1198. if X = S.X then begin
  1199. S2 := PointToSmallPoint(S);
  1200. if FLastWrappedLines <> PrevWrappedLines then
  1201. SizesList.Add(Pointer(S2))
  1202. else
  1203. SizesList[SizesList.Count-1] := Pointer(S2);
  1204. PrevWrappedLines := FLastWrappedLines;
  1205. Dec(X);
  1206. end
  1207. else
  1208. X := S.X;
  1209. end;
  1210. finally
  1211. FFloatingWidth := SaveWrapX;
  1212. end;
  1213. end;
  1214. function CompareNewSizes(const Item1, Item2, ExtraData: Pointer): Integer; far;
  1215. begin
  1216. { Sorts in descending order }
  1217. if ExtraData = nil then
  1218. Result := TSmallPoint(Item2).X - TSmallPoint(Item1).X
  1219. else
  1220. Result := TSmallPoint(Item2).Y - TSmallPoint(Item1).Y;
  1221. end;
  1222. procedure TTBCustomToolbar.ResizeBegin(ASizeHandle: TTBSizeHandle);
  1223. const
  1224. MaxSizeSens = 12;
  1225. var
  1226. I, NewSize: Integer;
  1227. S, N: TSmallPoint;
  1228. P: TPoint;
  1229. begin
  1230. inherited;
  1231. FSizeData := AllocMem(SizeOf(TToolbar97SizeData));
  1232. with PToolbar97SizeData(FSizeData)^ do begin
  1233. SizeHandle := ASizeHandle;
  1234. OrigLeft := Parent.Left;
  1235. OrigTop := Parent.Top;
  1236. OrigWidth := Parent.Width;
  1237. OrigHeight := Parent.Height;
  1238. NCXDiff := ClientToScreen(Point(0, 0)).X - OrigLeft;
  1239. CurRightX := FFloatingWidth;
  1240. DisableSensCheck := False;
  1241. OpSide := False;
  1242. NewSizes := TList.Create;
  1243. BuildPotentialSizesList(NewSizes);
  1244. for I := 0 to NewSizes.Count-1 do begin
  1245. P := SmallPointToPoint(TSmallPoint(NewSizes.List[I]));
  1246. AddFloatingNCAreaToSize(P);
  1247. NewSizes.List[I] := Pointer(PointToSmallPoint(P));
  1248. end;
  1249. ListSortEx(NewSizes, CompareNewSizes,
  1250. Pointer(Ord(ASizeHandle in [twshTop, twshBottom])));
  1251. SizeSens := MaxSizeSens;
  1252. { Adjust sensitivity if it's too high }
  1253. for I := 0 to NewSizes.Count-1 do begin
  1254. Pointer(S) := NewSizes[I];
  1255. if (S.X = Width) and (S.Y = Height) then begin
  1256. if I > 0 then begin
  1257. Pointer(N) := NewSizes[I-1];
  1258. if ASizeHandle in [twshLeft, twshRight] then
  1259. NewSize := N.X - S.X - 1
  1260. else
  1261. NewSize := N.Y - S.Y - 1;
  1262. if NewSize < SizeSens then SizeSens := NewSize;
  1263. end;
  1264. if I < NewSizes.Count-1 then begin
  1265. Pointer(N) := NewSizes[I+1];
  1266. if ASizeHandle in [twshLeft, twshRight] then
  1267. NewSize := S.X - N.X - 1
  1268. else
  1269. NewSize := S.Y - N.Y - 1;
  1270. if NewSize < SizeSens then SizeSens := NewSize;
  1271. end;
  1272. Break;
  1273. end;
  1274. end;
  1275. if SizeSens < 0 then SizeSens := 0;
  1276. end;
  1277. end;
  1278. procedure TTBCustomToolbar.ResizeTrack(var Rect: TRect; const OrigRect: TRect);
  1279. var
  1280. Pos: TPoint;
  1281. NewOpSide: Boolean;
  1282. Reverse: Boolean;
  1283. I: Integer;
  1284. P: TSmallPoint;
  1285. begin
  1286. inherited;
  1287. with PToolbar97SizeData(FSizeData)^ do begin
  1288. GetCursorPos(Pos);
  1289. Dec(Pos.X, OrigLeft); Dec(Pos.Y, OrigTop);
  1290. if SizeHandle = twshLeft then
  1291. Pos.X := OrigWidth-Pos.X
  1292. else
  1293. if SizeHandle = twshTop then
  1294. Pos.Y := OrigHeight-Pos.Y;
  1295. { Adjust Pos to make up for the "sizing sensitivity", as seen in Office 97 }
  1296. if SizeHandle in [twshLeft, twshRight] then
  1297. NewOpSide := Pos.X < OrigWidth
  1298. else
  1299. NewOpSide := Pos.Y < OrigHeight;
  1300. if (not DisableSensCheck) or (OpSide <> NewOpSide) then begin
  1301. DisableSensCheck := False;
  1302. OpSide := NewOpSide;
  1303. if SizeHandle in [twshLeft, twshRight] then begin
  1304. if (Pos.X >= OrigWidth-SizeSens) and (Pos.X < OrigWidth+SizeSens) then
  1305. Pos.X := OrigWidth;
  1306. end
  1307. else begin
  1308. if (Pos.Y >= OrigHeight-SizeSens) and (Pos.Y < OrigHeight+SizeSens) then
  1309. Pos.Y := OrigHeight;
  1310. end;
  1311. end;
  1312. Rect := OrigRect;
  1313. if SizeHandle in [twshLeft, twshRight] then
  1314. Reverse := Pos.X > OrigWidth
  1315. else
  1316. Reverse := Pos.Y > OrigHeight;
  1317. if not Reverse then
  1318. I := NewSizes.Count-1
  1319. else
  1320. I := 0;
  1321. while True do begin
  1322. if (not Reverse and (I < 0)) or
  1323. (Reverse and (I >= NewSizes.Count)) then
  1324. Break;
  1325. Pointer(P) := NewSizes[I];
  1326. if SizeHandle in [twshLeft, twshRight] then begin
  1327. if (not Reverse and ((I = NewSizes.Count-1) or (Pos.X >= P.X))) or
  1328. (Reverse and ((I = 0) or (Pos.X < P.X))) then begin
  1329. if I = 0 then
  1330. CurRightX := 0
  1331. else
  1332. CurRightX := P.X - NCXDiff*2;
  1333. if SizeHandle = twshRight then
  1334. Rect.Right := Rect.Left + P.X
  1335. else
  1336. Rect.Left := Rect.Right - P.X;
  1337. Rect.Bottom := Rect.Top + P.Y;
  1338. DisableSensCheck := not EqualRect(Rect, OrigRect);
  1339. end;
  1340. end
  1341. else begin
  1342. if (not Reverse and ((I = NewSizes.Count-1) or (Pos.Y >= P.Y))) or
  1343. (Reverse and ((I = 0) or (Pos.Y < P.Y))) then begin
  1344. if I = NewSizes.Count-1 then
  1345. CurRightX := 0
  1346. else
  1347. CurRightX := P.X - NCXDiff*2;
  1348. if SizeHandle = twshBottom then
  1349. Rect.Bottom := Rect.Top + P.Y
  1350. else
  1351. Rect.Top := Rect.Bottom - P.Y;
  1352. Rect.Right := Rect.Left + P.X;
  1353. DisableSensCheck := not EqualRect(Rect, OrigRect);
  1354. end;
  1355. end;
  1356. if not Reverse then
  1357. Dec(I)
  1358. else
  1359. Inc(I);
  1360. end;
  1361. end;
  1362. end;
  1363. procedure TTBCustomToolbar.ResizeTrackAccept;
  1364. begin
  1365. inherited;
  1366. FloatingWidth := PToolbar97SizeData(FSizeData)^.CurRightX;
  1367. end;
  1368. procedure TTBCustomToolbar.ResizeEnd;
  1369. begin
  1370. inherited;
  1371. if Assigned(FSizeData) then begin
  1372. PToolbar97SizeData(FSizeData)^.NewSizes.Free;
  1373. FreeMem(FSizeData);
  1374. FSizeData := nil;
  1375. end;
  1376. end;
  1377. function TTBCustomToolbar.GetShrinkMode: TTBShrinkMode;
  1378. begin
  1379. Result := FShrinkMode;
  1380. end;
  1381. procedure TTBCustomToolbar.GetMinShrinkSize(var AMinimumSize: Integer);
  1382. var
  1383. I: TTBItemViewer;
  1384. begin
  1385. I := FView.HighestPriorityViewer;
  1386. if Assigned(I) then begin
  1387. if not(CurrentDock.Position in [dpLeft, dpRight]) then
  1388. AMinimumSize := I.BoundsRect.Right - I.BoundsRect.Left
  1389. else
  1390. AMinimumSize := I.BoundsRect.Bottom - I.BoundsRect.Top;
  1391. end;
  1392. if not(CurrentDock.Position in [dpLeft, dpRight]) then
  1393. Inc(AMinimumSize, NonClientWidth)
  1394. else
  1395. Inc(AMinimumSize, NonClientHeight);
  1396. Inc(AMinimumSize, tbChevronSize);
  1397. end;
  1398. procedure TTBCustomToolbar.BeginUpdate;
  1399. begin
  1400. FView.BeginUpdate;
  1401. end;
  1402. procedure TTBCustomToolbar.EndUpdate;
  1403. begin
  1404. FView.EndUpdate;
  1405. end;
  1406. procedure TTBCustomToolbar.GetTabOrderList(List: TList);
  1407. var
  1408. CtlList: TList;
  1409. I, J: Integer;
  1410. CtlI, CtlJ: TWinControl;
  1411. begin
  1412. inherited;
  1413. { Remove off-edge items and their children from List }
  1414. CtlList := TList.Create;
  1415. try
  1416. FView.GetOffEdgeControlList(CtlList);
  1417. for I := 0 to CtlList.Count-1 do begin
  1418. CtlI := CtlList[I];
  1419. J := 0;
  1420. while J < List.Count do begin
  1421. CtlJ := List[J];
  1422. if (CtlJ = CtlI) or CtlI.ContainsControl(CtlJ) then
  1423. List.Delete(J)
  1424. else
  1425. Inc(J);
  1426. end;
  1427. end;
  1428. finally
  1429. CtlList.Free;
  1430. end;
  1431. end;
  1432. procedure TTBCustomToolbar.CMWinIniChange(var Message: TWMSettingChange);
  1433. begin
  1434. inherited;
  1435. if Message.Flag = SPI_SETNONCLIENTMETRICS then begin
  1436. TBInitToolbarSystemFont;
  1437. Arrange;
  1438. end;
  1439. end;
  1440. function TTBCustomToolbar.IsShortCut(var Message: TWMKey): Boolean;
  1441. begin
  1442. Result := False;
  1443. if Assigned(FOnShortCut) then
  1444. FOnShortCut(Message, Result);
  1445. Result := Result or FItem.IsShortCut(Message);
  1446. end;
  1447. var
  1448. HookCount: Integer;
  1449. HookList: TList;
  1450. class function TTBCustomToolbar.MainWindowHook(var Message: TMessage): Boolean;
  1451. function GetActiveForm: TCustomForm;
  1452. var
  1453. Wnd: HWND;
  1454. Ctl: TWinControl;
  1455. begin
  1456. { Note: We don't use Screen.ActiveCustomForm because when an EXE calls a
  1457. DLL that shows a modal form, Screen.ActiveCustomForm doesn't change in
  1458. the EXE; it remains set to the last form that was active in the EXE.
  1459. Use FindControl(GetActiveWindow) instead to avoid this problem; it will
  1460. return nil when a form in another module is active. }
  1461. Result := nil;
  1462. Wnd := GetActiveWindow;
  1463. if Wnd <> 0 then begin
  1464. Ctl := FindControl(Wnd);
  1465. if Assigned(Ctl) and (Ctl is TCustomForm) then
  1466. Result := TCustomForm(Ctl);
  1467. end;
  1468. end;
  1469. function HandleShortCutOnForm(const Form: TCustomForm): Boolean;
  1470. var
  1471. I: Integer;
  1472. Toolbar: TTBCustomToolbar;
  1473. begin
  1474. Result := False;
  1475. if Form = nil then
  1476. Exit;
  1477. for I := 0 to HookList.Count-1 do begin
  1478. Toolbar := HookList[I];
  1479. if Toolbar.ProcessShortCuts and
  1480. (TBGetToolWindowParentForm(Toolbar) = Form) and
  1481. IsWindowEnabled(Form.Handle) and
  1482. Toolbar.IsShortCut(TWMKey(Message)) then begin
  1483. Message.Result := 1;
  1484. Result := True;
  1485. Exit;
  1486. end;
  1487. end;
  1488. end;
  1489. function TraverseControls(Container: TWinControl): Boolean;
  1490. var
  1491. I: Integer;
  1492. Control: TControl;
  1493. begin
  1494. Result := False;
  1495. if Container.Showing then
  1496. for I := 0 to Container.ControlCount - 1 do begin
  1497. Control := Container.Controls[I];
  1498. if Control.Visible and Control.Enabled then begin
  1499. if (csMenuEvents in Control.ControlStyle) and
  1500. ((Control is TTBDock) or (Control is TTBCustomToolbar)) and
  1501. (Control.Perform(WM_SYSCOMMAND, TMessage(Message).WParam,
  1502. TMessage(Message).LParam) <> 0) or (Control is TWinControl) and
  1503. TraverseControls(TWinControl(Control)) then begin
  1504. Result := True;
  1505. Exit;
  1506. end;
  1507. end;
  1508. end;
  1509. end;
  1510. var
  1511. ActiveForm: TCustomForm;
  1512. ActiveMDIChild: TForm;
  1513. begin
  1514. Result := False;
  1515. if (Message.Msg = CM_APPKEYDOWN) and Assigned(HookList) then begin
  1516. { Process shortcuts on toolbars. Search forms in this order:
  1517. 1. If the active form is an MDI parent form, the active MDI child form
  1518. if it has the focus.
  1519. 2. The active form.
  1520. 3. The main form. }
  1521. ActiveForm := GetActiveForm;
  1522. if Assigned(ActiveForm) and (ActiveForm is TForm) and
  1523. (TForm(ActiveForm).FormStyle = fsMDIForm) then begin
  1524. ActiveMDIChild := TForm(ActiveForm).ActiveMDIChild;
  1525. { Don't search the child form if a control on the MDI parent form is
  1526. currently focused (i.e. Screen.ActiveCustomForm <> ActiveMDIChild) }
  1527. if Assigned(ActiveMDIChild) and
  1528. (Screen.ActiveCustomForm = ActiveMDIChild) and
  1529. HandleShortCutOnForm(ActiveMDIChild) then begin
  1530. Result := True;
  1531. Exit;
  1532. end;
  1533. end;
  1534. if HandleShortCutOnForm(ActiveForm) then
  1535. Result := True
  1536. else begin
  1537. if (Application.MainForm <> ActiveForm) and
  1538. HandleShortCutOnForm(Application.MainForm) then
  1539. Result := True;
  1540. end;
  1541. end
  1542. else if Message.Msg = CM_APPSYSCOMMAND then begin
  1543. { Handle "Alt or Alt+[key] pressed on secondary form" case. If there's a
  1544. menu bar on the active form we want the keypress to go to it instead of
  1545. to the main form (the VCL's default handling). }
  1546. ActiveForm := GetActiveForm;
  1547. if Assigned(ActiveForm) and IsWindowEnabled(ActiveForm.Handle) and
  1548. IsWindowVisible(ActiveForm.Handle) and TraverseControls(ActiveForm) then begin
  1549. Message.Result := 1;
  1550. Result := True;
  1551. end;
  1552. end;
  1553. end;
  1554. procedure TTBCustomToolbar.SetMainWindowHook;
  1555. begin
  1556. if (ProcessShortCuts or MenuBar) and not(csDesigning in ComponentState) then
  1557. InstallMainWindowHook
  1558. else
  1559. UninstallMainWindowHook;
  1560. end;
  1561. procedure TTBCustomToolbar.InstallMainWindowHook;
  1562. begin
  1563. if FMainWindowHookInstalled then
  1564. Exit;
  1565. if HookCount = 0 then
  1566. Application.HookMainWindow(MainWindowHook);
  1567. Inc(HookCount);
  1568. AddToList(HookList, Self);
  1569. FMainWindowHookInstalled := True;
  1570. end;
  1571. procedure TTBCustomToolbar.UninstallMainWindowHook;
  1572. begin
  1573. if not FMainWindowHookInstalled then
  1574. Exit;
  1575. FMainWindowHookInstalled := False;
  1576. RemoveFromList(HookList, Self);
  1577. Dec(HookCount);
  1578. if HookCount = 0 then
  1579. Application.UnhookMainWindow(MainWindowHook);
  1580. end;
  1581. procedure TTBCustomToolbar.ChangeScale(M, D: Integer; isDpiChange: Boolean);
  1582. begin
  1583. inherited;
  1584. Items.ChangeScale(M, D);
  1585. View.RecreateAllViewers;
  1586. end;
  1587. end.