TBX.pas 104 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474
  1. unit TBX;
  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: TBX.pas 21 2004-05-29 22:16:01Z Alex@ZEISS
  7. interface
  8. {$I TB2Ver.inc}
  9. uses
  10. Windows, Messages, Classes, SysUtils, Controls, Graphics, ImgList, Forms,
  11. TB2Item, TB2Dock, TB2Toolbar, TB2Anim, TBXUtils, TBXThemes, PasTools;
  12. const
  13. TBXVersion = 2.1;
  14. TBXVersionString = '2.1';
  15. TBXVersionText = 'TBX version ' + TBXVersionString;
  16. { TBX Messages }
  17. const
  18. TBM_THEMECHANGE = WM_USER + 314;
  19. TBM_GETVIEWTYPE = WM_USER + 237;
  20. TBM_GETEFFECTIVECOLOR = WM_USER + 238;
  21. function GetViewType(View: TTBView): Integer;
  22. function GetWinViewType(Window: TControl): Integer;
  23. function IsFloating(ViewType: Integer): Boolean;
  24. type
  25. TTextWrapping = (twNone, twEndEllipsis, twPathEllipsis, twWrap);
  26. TTextTruncation = twNone..twPathEllipsis;
  27. TTriState = (tsDefault, tsTrue, tsFalse);
  28. TFontSize = 25..1000;
  29. TFontSettings = class(TPersistent)
  30. private
  31. FBold: TTriState;
  32. FItalic: TTriState;
  33. FUnderline: TTriState;
  34. FStrikeOut: TTriState;
  35. FSize: TFontSize;
  36. FColor: TColor;
  37. FName: TFontName;
  38. FOnChange: TNotifyEvent;
  39. procedure SetBold(Value: TTriState);
  40. procedure SetColor(Value: TColor);
  41. procedure SetItalic(Value: TTriState);
  42. procedure SetName(const Value: TFontName);
  43. procedure SetSize(Value: TFontSize);
  44. procedure SetStrikeOut(Value: TTriState);
  45. procedure SetUnderline(Value: TTriState);
  46. protected
  47. procedure Modified;
  48. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  49. public
  50. constructor Create;
  51. procedure Apply(Font: TFont); overload;
  52. procedure Apply(var LF: TLogFont; var FontColor: TColor); overload;
  53. procedure Assign(Src: TPersistent); override;
  54. function CreateTransformedFont(Src: HFont; var FontColor: TColor): HFont;
  55. published
  56. property Bold: TTriState read FBold write SetBold default tsDefault;
  57. property Italic: TTriState read FItalic write SetItalic default tsDefault;
  58. property Underline: TTriState read FUnderline write SetUnderline default tsDefault;
  59. property StrikeOut: TTriState read FStrikeOut write SetStrikeOut default tsDefault;
  60. property Size: TFontSize read FSize write SetSize default 100; // percent
  61. property Color: TColor read FColor write SetColor default clNone;
  62. property Name: TFontName read FName write SetName; // default ''
  63. end;
  64. TTBXPopupPositionInfo = record
  65. Item: TTBCustomItem; // this is a tentative type, it will be changed
  66. ParentView: TTBView; // or removed in future versions
  67. ParentViewer: TTBItemViewer;
  68. PositionAsSubmenu: Boolean;
  69. APopupPoint: TPoint;
  70. Alignment: TTBPopupAlignment;
  71. PopupWindow: TTBPopupWindow;
  72. X, Y: Integer;
  73. ParentItemRect: TRect;
  74. AppFlags: Integer; // reserved for extensions
  75. AppData: Integer;
  76. end;
  77. TTBXThemeClass = class of TTBXTheme;
  78. function GetStateFlags(const ItemInfo: TTBXItemInfo): Integer;
  79. function GetTBXTextColor(StateFlags: Integer): TColor;
  80. procedure DrawTBXCaption(Canvas: TCanvas; Rect: TRect; const Text: string;
  81. Format: Cardinal; StateFlags: Integer);
  82. procedure DrawTBXImage(Canvas: TCanvas; Rect: TRect; ImageList: TCustomImageList;
  83. ImageIndex: Integer; StateFlags: Integer);
  84. type
  85. { TTBXItem }
  86. TAdjustFontEvent = procedure(Item: TTBCustomItem; Viewer: TTBItemViewer;
  87. Font: TFont; StateFlags: Integer) of object; // state flags are the combination of ISF_* constants
  88. TDrawImageEvent = procedure(Item: TTBCustomItem; Viewer: TTBItemViewer;
  89. Canvas: TCanvas; ImageRect: TRect; ImageOffset: TPoint; StateFlags: Integer) of object;
  90. TTBXCustomItem = class(TTBCustomItem)
  91. private
  92. FAlwaysSelectFirst: Boolean;
  93. FFontSettings: TFontSettings;
  94. FLayout: TTBXItemLayout;
  95. FMinHeight: Integer;
  96. FMinWidth: Integer;
  97. FToolBoxPopup: Boolean;
  98. FOnAdjustFont: TAdjustFontEvent;
  99. FOnDrawImage: TDrawImageEvent;
  100. procedure FontSettingsChanged(Sender: TObject);
  101. function GetStretch: Boolean;
  102. procedure SetFontSettings(Value: TFontSettings);
  103. procedure SetLayout(Value: TTBXItemLayout);
  104. procedure SetMinHeight(Value: Integer);
  105. procedure SetMinWidth(Value: Integer);
  106. procedure SetStretch(Value: Boolean);
  107. protected
  108. function CreatePopup(const ParentView: TTBView; const ParentViewer: TTBItemViewer;
  109. const PositionAsSubmenu, SelectFirstItem, Customizing: Boolean;
  110. const APopupPoint: TPoint; const Alignment: TTBPopupAlignment): TTBPopupWindow; override;
  111. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  112. procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow;
  113. var PopupPositionRec: TTBPopupPositionRec); override;
  114. function GetPopupWindowClass: TTBPopupWindowClass; override;
  115. property ToolBoxPopup: Boolean read FToolBoxPopup write FToolBoxPopup default False;
  116. property OnAdjustFont: TAdjustFontEvent read FOnAdjustFont write FOnAdjustFont;
  117. property OnDrawImage: TDrawImageEvent read FOnDrawImage write FOnDrawImage;
  118. public
  119. constructor Create(AOwner: TComponent); override;
  120. destructor Destroy; override;
  121. procedure Invalidate;
  122. property AlwaysSelectFirst: Boolean read FAlwaysSelectFirst write FAlwaysSelectFirst default False;
  123. property FontSettings: TFontSettings read FFontSettings write SetFontSettings;
  124. property Layout: TTBXItemLayout read FLayout write SetLayout default tbxlAuto;
  125. property MinHeight: Integer read FMinHeight write SetMinHeight default 0;
  126. property MinWidth: Integer read FMinWidth write SetMinWidth default 0;
  127. property Stretch: Boolean read GetStretch write SetStretch default False;
  128. end;
  129. TTBXItem = class (TTBXCustomItem)
  130. property Action;
  131. property AutoCheck;
  132. property Caption;
  133. property Checked;
  134. property DisplayMode;
  135. property Enabled;
  136. property FontSettings;
  137. property GroupIndex;
  138. property HelpContext;
  139. { MP }
  140. property HelpKeyword;
  141. property Hint;
  142. property ImageIndex;
  143. property Images;
  144. property InheritOptions;
  145. property Layout;
  146. property MaskOptions;
  147. property MinHeight;
  148. property MinWidth;
  149. property Options;
  150. property RadioItem;
  151. property ShortCut;
  152. property Stretch;
  153. property Visible;
  154. property OnAdjustFont;
  155. property OnDrawImage;
  156. property OnClick;
  157. property OnSelect;
  158. end;
  159. TTBXItemViewer = class(TTBItemViewer)
  160. private
  161. FWide: Boolean;
  162. protected
  163. procedure DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect;
  164. var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean); virtual;
  165. function GetAccRole: Integer; override;
  166. function GetImageSize: TSize; dynamic;
  167. function GetItemType: Integer; virtual;
  168. function GetTextFlags: Cardinal; dynamic;
  169. function GetTextSize(Canvas: TCanvas; const Text: string; TextFlags: Cardinal; Rotated: Boolean; StateFlags: Integer): TSize; dynamic;
  170. function IsToolbarSize: Boolean; override;
  171. procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override;
  172. procedure DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); virtual;
  173. procedure DoAdjustFont(AFont: TFont; StateFlags: Integer); virtual;
  174. function GetImageShown: Boolean; virtual;
  175. function IsPtInButtonPart(X, Y: Integer): Boolean; override;
  176. procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override;
  177. procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override;
  178. property Wide: Boolean read FWide write FWide default True;
  179. public
  180. constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override;
  181. function IsToolbarStyle: Boolean; override;
  182. end;
  183. { TTBXSubmenuItem }
  184. TTBXSubmenuItem = class(TTBXCustomItem)
  185. private
  186. function GetDropdownCombo: Boolean;
  187. procedure SetDropdownCombo(Value: Boolean);
  188. public
  189. constructor Create(AOwner: TComponent); override;
  190. published
  191. property Action;
  192. property AlwaysSelectFirst;
  193. property AutoCheck;
  194. property Caption;
  195. property Checked;
  196. property DisplayMode;
  197. property DropdownCombo: Boolean read GetDropdownCombo write SetDropdownCombo default False;
  198. property Enabled;
  199. property FontSettings;
  200. property GroupIndex;
  201. property HelpContext;
  202. { MP }
  203. property HelpKeyword;
  204. property Hint;
  205. property ImageIndex;
  206. property Images;
  207. property InheritOptions;
  208. property Layout;
  209. property LinkSubitems;
  210. property MaskOptions;
  211. property MinHeight;
  212. property MinWidth;
  213. property Options;
  214. property RadioItem;
  215. property ShortCut;
  216. property Stretch;
  217. property SubMenuImages;
  218. property ToolBoxPopup;
  219. property Visible;
  220. property OnAdjustFont;
  221. property OnDrawImage;
  222. property OnClick;
  223. property OnPopup;
  224. property OnSelect;
  225. end;
  226. { TTBXSeparatorItem }
  227. TTBXSeparatorItem = class(TTBSeparatorItem)
  228. private
  229. FSize: Integer;
  230. procedure SetSize(Value: Integer);
  231. public
  232. constructor Create(AOwner: TComponent); override;
  233. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  234. published
  235. property Size: Integer read FSize write SetSize default -1;
  236. property MaskOptions;
  237. property Options;
  238. end;
  239. TTBXSeparatorItemViewer = class(TTBSeparatorItemViewer)
  240. protected
  241. procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override;
  242. procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect;
  243. IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override;
  244. function IsToolbarSize: Boolean; override;
  245. public
  246. function IsToolbarStyle: Boolean; override;
  247. end;
  248. { TTBXPopupWindow }
  249. TTBXPopupWindow = class(TTBPopupWindow)
  250. private
  251. FControlRect: TRect;
  252. FShadows: TShadows;
  253. procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
  254. procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
  255. procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE;
  256. procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
  257. procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT;
  258. procedure WMPrint(var Message: TMessage); message WM_PRINT;
  259. procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  260. procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED;
  261. procedure WMTB2kPopupShowing(var Message: TMessage); message WM_TB2K_POPUPSHOWING;
  262. protected
  263. procedure CreateParams(var Params: TCreateParams); override;
  264. procedure CreateShadow; virtual;
  265. procedure DestroyShadow; virtual;
  266. function GetNCSize: TPoint; override;
  267. function GetShowShadow: Boolean; virtual;
  268. function GetViewClass: TTBViewClass; override;
  269. procedure PaintScrollArrows; override;
  270. public
  271. destructor Destroy; override;
  272. function GetFillColor: TColor;
  273. end;
  274. TTBXPopupView = class(TTBPopupView);
  275. { TTBXToolbarView }
  276. TTBXToolbarView = class(TTBToolbarView)
  277. protected
  278. procedure GetMargins(AOrientation: TTBViewOrientation; var Margins: TRect); override;
  279. end;
  280. { TTBXToolbar }
  281. TTBXItemTransparency = (itAuto, itEnable, itDisable);
  282. TTBXToolbar = class(TTBCustomToolbar)
  283. private
  284. FEffectiveColor: TColor;
  285. FItemTransparency: TTBXItemTransparency;
  286. FSnapDistance: Integer;
  287. procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  288. procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE;
  289. procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED;
  290. procedure SetItemTransparency(const Value: TTBXItemTransparency);
  291. procedure SetSnapDistance(Value: Integer);
  292. procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE;
  293. procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR;
  294. procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE;
  295. procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  296. procedure WMDpiChangedBeforeParent(var Message: TMessage); message WM_DPICHANGED_BEFOREPARENT;
  297. procedure WMDpiChangedAfterParent(var Message: TMessage); message WM_DPICHANGED_AFTERPARENT;
  298. protected
  299. procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN); override;
  300. function GetChevronItemClass: TTBChevronItemClass; override;
  301. function GetFloatingWindowParentClass: TTBFloatingWindowParentClass; override;
  302. procedure GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo); virtual;
  303. function GetViewClass: TTBToolbarViewClass; override;
  304. procedure Loaded; override;
  305. procedure SetParent(AParent: TWinControl); override;
  306. procedure UpdateEffectiveColor;
  307. procedure Rebuild;
  308. public
  309. constructor Create(AOwner: TComponent); override;
  310. destructor Destroy; override;
  311. function Embedded: Boolean;
  312. function GetFloatingBorderSize: TPoint; override;
  313. procedure UpdateChildColors;
  314. property EffectiveColor: TColor read FEffectiveColor;
  315. published
  316. property ActivateParent;
  317. property Align;
  318. property AutoResize;
  319. property BorderStyle;
  320. property Caption;
  321. property ChevronHint;
  322. property ChevronMoveItems;
  323. property ChevronPriorityForNewItems;
  324. property CloseButton;
  325. property CloseButtonWhenDocked;
  326. property CurrentDock;
  327. property DblClickUndock default False;
  328. property DefaultDock;
  329. property DockableTo;
  330. property DockMode;
  331. property DockPos;
  332. property DockRow;
  333. property DragHandleStyle;
  334. property FloatingMode;
  335. property Font;
  336. property FullSize;
  337. property HideWhenInactive;
  338. property Images;
  339. property Items;
  340. property ItemTransparency: TTBXItemTransparency read FItemTransparency write SetItemTransparency default itAuto;
  341. property LastDock;
  342. property LinkSubitems;
  343. property MenuBar;
  344. property Options;
  345. property ParentFont;
  346. property ParentShowHint;
  347. property PopupMenu;
  348. property ProcessShortCuts;
  349. property Resizable;
  350. property ShowCaption;
  351. property ShowHint;
  352. property ShrinkMode;
  353. property SmoothDrag;
  354. property SnapDistance: Integer read FSnapDistance write SetSnapDistance default 0;
  355. property Stretch;
  356. property SystemFont;
  357. property TabOrder;
  358. property TabStop;
  359. property UpdateActions;
  360. property UseLastDock;
  361. property Visible;
  362. property Color default clNone;
  363. property OnClose;
  364. property OnCloseQuery;
  365. property OnContextPopup;
  366. property OnDragDrop;
  367. property OnDragOver;
  368. property OnMouseDown;
  369. property OnMouseMove;
  370. property OnMouseUp;
  371. property OnMove;
  372. property OnRecreated;
  373. property OnRecreating;
  374. property OnDockChanged;
  375. property OnDockChanging;
  376. property OnDockChangingHidden;
  377. property OnResize;
  378. property OnShortCut;
  379. property OnVisibleChanged;
  380. { MP }
  381. property OnGetBaseSize;
  382. end;
  383. { TTBXChevronItem }
  384. TTBXChevronItem = class(TTBChevronItem)
  385. public
  386. procedure GetPopupPosition(ParentView: TTBView;
  387. PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); override;
  388. function GetPopupWindowClass: TTBPopupWindowClass; override;
  389. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  390. end;
  391. TTBXChevronItemViewer = class(TTBItemViewer)
  392. protected
  393. procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect;
  394. IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override;
  395. function CaptionShown: Boolean; override;
  396. end;
  397. TTBXChevronPopupWindow = class(TTBXPopupWindow);
  398. { TTBXPopupMenu }
  399. TTBXRootItem = class(TTBRootItem)
  400. private
  401. FPopupControlRect: TRect;
  402. protected
  403. function CreatePopupEx(SelectFirstItem: Boolean; const AControlRect: TRect;
  404. Alignment: TTBPopupAlignment): TTBPopupWindow; virtual;
  405. function GetPopupWindowClass: TTBPopupWindowClass; override;
  406. procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow;
  407. var PopupPositionRec: TTBPopupPositionRec); override;
  408. function OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean;
  409. const ControlRect: TRect; const Alignment: TTBPopupAlignment;
  410. const ReturnClickedItemOnly: Boolean): TTBCustomItem;
  411. function PopupEx(const ControlRect: TRect; TrackRightButton: Boolean;
  412. Alignment: TTBPopupAlignment = tbpaLeft;
  413. ReturnClickedItemOnly: Boolean = False): TTBCustomItem;
  414. end;
  415. TTBXPopupMenu = class(TTBPopupMenu)
  416. private
  417. FToolBoxPopup: Boolean;
  418. procedure TBMGetViewType(var Message: TMessage); message TBM_GETVIEWTYPE;
  419. protected
  420. function GetRootItemClass: TTBRootItemClass; override;
  421. public
  422. function PopupEx(const ControlRect: TRect;
  423. ReturnClickedItemOnly: Boolean = False): TTBCustomItem;
  424. property ToolBoxPopup: Boolean read FToolBoxPopup write FToolBoxPopup default False;
  425. end;
  426. TTBXFloatingWindowParent = class(TTBFloatingWindowParent)
  427. private
  428. FCloseButtonHover: Boolean;
  429. FSnapDistance: Integer;
  430. procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  431. procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND;
  432. procedure WMNCMouseLeave(var Message: TMessage); message $2A2 {WM_NCMOUSELEAVE};
  433. procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE;
  434. procedure WMWindowPosChanging(var Message: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING;
  435. protected
  436. procedure CancelNCHover;
  437. procedure DrawNCArea(const DrawToDC: Boolean; const ADC: HDC;
  438. const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat); override;
  439. property CloseButtonHover: Boolean read FCloseButtonHover;
  440. public
  441. property SnapDistance: Integer read FSnapDistance write FSnapDistance default 0;
  442. end;
  443. TTBXDock = class(TTBDock)
  444. private
  445. FMoving: Boolean;
  446. FResizing: Boolean;
  447. FUseParentBackground: Boolean;
  448. procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  449. procedure TBMGetEffectiveColor(var Message: TMessage); message TBM_GETEFFECTIVECOLOR;
  450. procedure TBMThemeChange(var Message: TMessage); message TBM_THEMECHANGE;
  451. procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  452. procedure WMMove(var Message: TWMMove); message WM_MOVE;
  453. procedure WMSize(var Message: TWMSize); message WM_SIZE;
  454. protected
  455. function ThemedBackground: Boolean; virtual;
  456. procedure DrawBackground(DC: HDC; const DrawRect: TRect); override;
  457. procedure Resize; override;
  458. procedure SetUseParentBackground(Value: Boolean);
  459. function UsingBackground: Boolean; override;
  460. public
  461. constructor Create(AOwner: TComponent); override;
  462. destructor Destroy; override;
  463. published
  464. property Color default clNone;
  465. property UseParentBackground: Boolean read FUseParentBackground write SetUseParentBackground default False;
  466. end;
  467. { TTBXMenuAnimation }
  468. TMenuAnimation = (maNone, maUnfold, maSlide, maFade);
  469. TAnimationMode = (amNone, amSysDefault, amRandom, amUnfold, amSlide, amFade);
  470. TAnimationModes = set of TAnimationMode;
  471. TTBXMenuAnimation = class
  472. private
  473. FAnimationMode: TAnimationMode;
  474. function SysParamEnabled(Param: Cardinal): Boolean;
  475. function GetAvailableModes: TAnimationModes;
  476. function GetMenuAnimation: TMenuAnimation;
  477. procedure SetAnimationMode(Value: TAnimationMode);
  478. property MenuAnimation: TMenuAnimation read GetMenuAnimation;
  479. public
  480. constructor Create(AAnimationMode: TAnimationMode = amSysDefault);
  481. property AnimationMode: TAnimationMode read FAnimationMode write SetAnimationMode;
  482. property AvailableModes: TAnimationModes read GetAvailableModes;
  483. end;
  484. var
  485. CurrentTheme: TTBXTheme;
  486. TBXMenuAnimation: TTBXMenuAnimation;
  487. procedure TBXSetTheme(const AThemeName: string);
  488. function TBXCurrentTheme: string;
  489. procedure AddThemeNotification(AObject: TObject);
  490. procedure RemoveThemeNotification(AObject: TObject);
  491. { Additional system colors }
  492. procedure AddTBXColor(var AColor: TColor; const AName: string);
  493. function TBXIdentToColor(const Ident: string; var Color: Longint): Boolean;
  494. function TBXColorToString(Color: TColor): string;
  495. function TBXStringToColor(S: string): TColor;
  496. procedure TBXGetColorValues(Proc: TGetStrProc);
  497. { Internal routines - do not use }
  498. function GetPopupMargin(ItemViewer: TTBItemViewer): Integer;
  499. function GetEffectiveColor(C: TControl): TColor;
  500. procedure DrawParentBackground(Control: TControl; DC: HDC; R: TRect);
  501. procedure AddToList(var List: TList; Item: Pointer);
  502. procedure RemoveFromList(var List: TList; Item: Pointer);
  503. function CreateTBXPopupMenu(Owner: TComponent): TTBXPopupMenu;
  504. implementation
  505. {$R tbx_glyphs.res}
  506. uses
  507. TBXExtItems, TBXLists, TB2Common, UxTheme, MultiMon, TBXOfficeXPTheme,
  508. ComCtrls, Menus, MMSystem, Types, UITypes;
  509. type
  510. TTBItemAccess = class(TTBCustomItem);
  511. TTBViewAccess = class(TTBView);
  512. TTBItemViewerAccess = class(TTBItemViewer);
  513. TTBFloatingWindowParentAccess = class(TTBFloatingWindowParent);
  514. TTBCustomDockableWindowAccess = class(TTBCustomDockableWindow);
  515. TTBXToolbarAccess = class(TTBXToolbar);
  516. TControlAccess = class(TControl);
  517. TTBXThemeAccess = class(TTBXTheme);
  518. TDockAccess = class(TTBDock);
  519. TTBPopupWindowAccess = class(TTBPopupWindow);
  520. { TTBNexus }
  521. TTBXNexus = class
  522. private
  523. FNotifies: TList;
  524. procedure TBXSysCommand(var Message: TMessage); message TBX_SYSCOMMAND;
  525. protected
  526. procedure Broadcast(Msg: Cardinal; WParam, LParam: Integer);
  527. public
  528. constructor Create(const DefaultTheme: string);
  529. destructor Destroy; override;
  530. procedure SetTheme(const AThemeName: string);
  531. function GetTheme: string;
  532. procedure AddNotifie(AObject: TObject);
  533. procedure RemoveNotifie(AObject: TObject);
  534. end;
  535. var
  536. TBXNexus: TTBXNexus;
  537. procedure AddThemeNotification(AObject: TObject);
  538. begin
  539. TBXNexus.AddNotifie(AObject);
  540. end;
  541. procedure RemoveThemeNotification(AObject: TObject);
  542. begin
  543. TBXNexus.RemoveNotifie(AObject);
  544. end;
  545. function GetEffectiveColor(C: TControl): TColor;
  546. var
  547. Message: TMessage;
  548. begin
  549. if C = nil then Result := clBtnFace
  550. else
  551. begin
  552. Message.Msg := TBM_GETEFFECTIVECOLOR;
  553. Message.WParam := 0;
  554. Message.LParam := 0;
  555. Message.Result := 0;
  556. C.Dispatch(Message);
  557. if Message.Result <> 0 then Result := Message.WParam
  558. else if (C is TForm) and (TForm(C).FormStyle = fsMDIForm) then
  559. Result := clBtnFace
  560. else
  561. Result := TControlAccess(C).Color;
  562. end;
  563. end;
  564. procedure DrawParentBackground(Control: TControl; DC: HDC; R: TRect);
  565. var
  566. Parent: TWinControl;
  567. Theme: HTHEME;
  568. R2: TRect;
  569. Shift: TPoint;
  570. UsingThemes: Boolean;
  571. Msg: TMessage;
  572. begin
  573. Parent := Control.Parent;
  574. if Parent = nil then FillRectEx(DC, R, clBtnFace)
  575. else
  576. begin
  577. Shift.X := 0; Shift.Y := 0;
  578. Shift := Parent.ScreenToClient(Control.ClientToScreen(Shift));
  579. SaveDC(DC);
  580. try
  581. SetWindowOrgEx(DC, Shift.X, Shift.Y, nil);
  582. Msg.Msg := WM_ERASEBKGND;
  583. Msg.WParam := Integer(DC);
  584. Msg.LParam := Integer(DC);
  585. Msg.Result := 0;
  586. Parent.Dispatch(Msg);
  587. finally
  588. RestoreDC(DC, -1);
  589. end;
  590. if Msg.Result <> 0 then Exit;
  591. UsingThemes := USE_THEMES and not (csDesigning in Control.ComponentState);
  592. if Parent is TTBDock then
  593. begin
  594. SaveDC(DC);
  595. SetWindowOrgEx(DC, Control.Left, Control.Top, nil);
  596. TDockAccess(Parent).DrawBackground(DC, R);
  597. RestoreDC(DC, -1);
  598. end
  599. else if not UsingThemes then
  600. FillRectEx(DC, R, GetEffectiveColor(Parent))
  601. else
  602. begin
  603. { Unfortunately, DrawThemeParentBackground does seem to have some problems
  604. with the back buffer. Therefore some sort of workaround is used which
  605. will work for tab sheets }
  606. // if Control is TWinControl then
  607. // DrawThemeParentBackground(TWinControl(Control).Handle, DC, @R);
  608. if Parent is TTabSheet then
  609. begin
  610. Theme := OpenThemeData(Parent.Handle, 'TAB');
  611. R2 := Parent.ClientRect;
  612. R2.TopLeft := Control.ScreenToClient(Parent.ClientToScreen(R2.TopLeft));
  613. R2.BottomRight := Control.ScreenToClient(Parent.ClientToScreen(R2.BottomRight));
  614. DrawThemeBackground(Theme, DC, TABP_BODY, 0, R2, @R);
  615. CloseThemeData(Theme);
  616. end
  617. else FillRectEx(DC, R, GetEffectiveColor(Parent));
  618. end;
  619. end;
  620. end;
  621. function GetViewType(View: TTBView): Integer;
  622. var
  623. Message: TMessage;
  624. begin
  625. Result := VT_UNKNOWN;
  626. if (View <> nil) and (View.Owner <> nil) then
  627. begin
  628. Message.Msg := TBM_GETVIEWTYPE;
  629. Message.WParam := 0;
  630. Message.LParam := 0;
  631. Message.Result := VT_UNKNOWN;
  632. View.Window.Dispatch(Message);
  633. Result := Message.Result;
  634. end;
  635. end;
  636. function GetWinViewType(Window: TControl): Integer;
  637. var
  638. Message: TMessage;
  639. begin
  640. Result := VT_UNKNOWN;
  641. if Window <> nil then
  642. begin
  643. Message.Msg := TBM_GETVIEWTYPE;
  644. Message.WParam := 0;
  645. Message.LParam := 0;
  646. Message.Result := VT_UNKNOWN;
  647. Window.Dispatch(Message);
  648. Result := Message.Result;
  649. end;
  650. end;
  651. function IsFloating(ViewType: Integer): Boolean;
  652. begin
  653. Result := ViewType and TVT_FLOATING <> 0;
  654. end;
  655. procedure UpdateNCArea(Control: TWinControl; ViewType: Integer);
  656. begin
  657. with Control do
  658. begin
  659. ClientWidth := ClientWidth;
  660. ClientHeight := ClientHeight;
  661. end;
  662. SetWindowPos(Control.Handle, 0, 0, 0, 0, 0,
  663. SWP_FRAMECHANGED or SWP_NOACTIVATE or SWP_NOZORDER or SWP_NOMOVE or SWP_NOSIZE);
  664. Control.Invalidate;
  665. end;
  666. function GetPopupMargin(ItemViewer: TTBItemViewer): Integer;
  667. var
  668. ImgList: TCustomImageList;
  669. Sz: TSize;
  670. TextMetric: TTextMetric;
  671. H, M2: Integer;
  672. Margins: TTBXMargins;
  673. begin
  674. Sz.Cx := 0;
  675. Sz.Cy := 0;
  676. if ItemViewer is TTBXItemViewer then
  677. Sz := TTBXItemViewer(ItemViewer).GetImageSize;
  678. if (Sz.Cx = 0) or (Sz.Cy = 0) then
  679. begin
  680. ImgList := TTBItemViewerAccess(ItemViewer).GetImageList;
  681. if ImgList <> nil then
  682. begin
  683. Sz.Cx := ImgList.Width;
  684. Sz.Cy := ImgList.Height;
  685. end;
  686. if (Sz.Cx = 0) or (Sz.Cy = 0) then
  687. begin
  688. Sz.Cx := 16;
  689. Sz.Cy := 16;
  690. end;
  691. end;
  692. StockBitmap1.Canvas.Font := TTBViewAccess(ItemViewer.View).GetFont;
  693. GetTextMetrics(StockBitmap1.Canvas.Handle, TextMetric);
  694. CurrentTheme.GetMargins(MID_MENUITEM, Margins);
  695. M2 := Margins.TopHeight + Margins.BottomHeight;
  696. Result := TextMetric.tmHeight + TextMetric.tmExternalLeading + M2;
  697. H := Sz.CY + M2;
  698. if H > Result then Result := H;
  699. Result := (Sz.Cx + M2) * Result div H;
  700. end;
  701. procedure GetOfficeXPPopupPosition1(var PopupPositionRec: TTBPopupPositionRec);
  702. begin
  703. with PopupPositionRec do
  704. begin
  705. if not PositionAsSubmenu then
  706. begin
  707. NCSizeX := 0;
  708. NCSizeY := 0;
  709. Dec(ParentItemRect.Right);
  710. if X = ParentItemRect.Right + 1 then Dec(X);
  711. if X + W <= ParentItemRect.Left then Inc(X);
  712. Dec(ParentItemRect.Bottom);
  713. if Y = ParentItemRect.Bottom + 1 then Dec(Y);
  714. if Y + H <= ParentItemRect.Top then Inc(Y);
  715. Dec(W);
  716. Dec(H);
  717. end
  718. else
  719. begin
  720. Inc(X, NCSizeX);
  721. Inc(Y, NCSizeY);
  722. NCSizeX := 0;
  723. NCSizeY := 0;
  724. end;
  725. end;
  726. end;
  727. procedure GetOfficeXPPopupPosition2(var PopupPositionRec: TTBPopupPositionRec);
  728. begin
  729. with PopupPositionRec do if not PositionAsSubmenu then
  730. begin
  731. Inc(W);
  732. Inc(H);
  733. end;
  734. end;
  735. procedure AddToList(var List: TList; Item: Pointer);
  736. begin
  737. if List = nil then List := TList.Create;
  738. List.Add(Item)
  739. end;
  740. procedure RemoveFromList(var List: TList; Item: Pointer);
  741. begin
  742. if List <> nil then
  743. begin
  744. List.Remove(Item);
  745. if List.Count = 0 then
  746. begin
  747. List.Free;
  748. List := nil;
  749. end;
  750. end;
  751. end;
  752. //============================================================================//
  753. { Misc. Routines }
  754. procedure InvalidateAll(const Ctl: TWinControl);
  755. begin
  756. if Ctl.HandleAllocated then
  757. RedrawWindow(Ctl.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or
  758. RDW_ERASE);
  759. end;
  760. function GetStateFlags(const ItemInfo: TTBXItemInfo): Integer;
  761. const
  762. CEnabledStates: array [Boolean] of Integer = (ISF_DISABLED, 0);
  763. CHotStates: array [Boolean] of Integer = (0, ISF_HOT);
  764. CPushedStates: array [Boolean] of Integer = (0, ISF_PUSHED);
  765. CSelectedStates: array [Boolean] of Integer = (0, ISF_SELECTED);
  766. begin
  767. with ItemInfo do
  768. Result := CEnabledStates[ItemInfo.Enabled] or CPushedStates[ItemInfo.Pushed] or
  769. CHotStates[ItemInfo.HoverKind = hkMouseHover] or CSelectedStates[ItemInfo.Selected];
  770. end;
  771. function GetTBXTextColor(StateFlags: Integer): TColor;
  772. const
  773. HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover);
  774. var
  775. ItemInfo: TTBXItemInfo;
  776. begin
  777. FillChar(ItemInfo, SizeOf(ItemInfo), 0);
  778. case StateFlags and ISF_LOCATIONMASK of
  779. ISF_TOOLBARCOLOR:
  780. begin
  781. ItemInfo.ViewType := VT_TOOLBAR;
  782. ItemInfo.ItemOptions := IO_TOOLBARSTYLE;
  783. end;
  784. ISF_MENUCOLOR:
  785. begin
  786. ItemInfo.ViewType := VT_DOCKPANEL;
  787. end;
  788. ISF_STATUSCOLOR:
  789. begin
  790. ItemInfo.ViewType := VT_STATUSBAR;
  791. end;
  792. else
  793. ItemInfo.ViewType := VT_UNKNOWN;
  794. end;
  795. ItemInfo.Enabled := StateFlags and ISF_DISABLED = 0;
  796. ItemInfo.Pushed := StateFlags and ISF_PUSHED <> 0;
  797. ItemInfo.HoverKind := HoverKinds[StateFlags and ISF_HOT <> 0];
  798. ItemInfo.Selected := StateFlags and ISF_SELECTED <> 0;
  799. Result := CurrentTheme.GetItemTextColor(ItemInfo);
  800. end;
  801. procedure DrawTBXCaption(Canvas: TCanvas; Rect: TRect; const Text: string; Format: Cardinal; StateFlags: Integer);
  802. const
  803. HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover);
  804. var
  805. ItemInfo: TTBXItemInfo;
  806. begin
  807. FillChar(ItemInfo, SizeOf(ItemInfo), 0);
  808. case StateFlags and ISF_LOCATIONMASK of
  809. ISF_TOOLBARCOLOR:
  810. begin
  811. ItemInfo.ViewType := VT_TOOLBAR;
  812. ItemInfo.ItemOptions := IO_TOOLBARSTYLE;
  813. end;
  814. ISF_MENUCOLOR:
  815. begin
  816. ItemInfo.ViewType := VT_DOCKPANEL;
  817. end;
  818. ISF_STATUSCOLOR:
  819. begin
  820. ItemInfo.ViewType := VT_STATUSBAR;
  821. end;
  822. end;
  823. ItemInfo.Enabled := StateFlags and ISF_DISABLED = 0;
  824. ItemInfo.Pushed := StateFlags and ISF_PUSHED <> 0;
  825. ItemInfo.HoverKind := HoverKinds[StateFlags and ISF_HOT <> 0];
  826. ItemInfo.Selected := StateFlags and ISF_SELECTED <> 0;
  827. CurrentTheme.PaintCaption(Canvas, Rect, ItemInfo, Text, Format, False);
  828. end;
  829. procedure DrawTBXImage(Canvas: TCanvas; Rect: TRect; ImageList: TCustomImageList;
  830. ImageIndex: Integer; StateFlags: Integer);
  831. const
  832. HoverKinds: array [Boolean] of TTBXHoverKind = (hkNone, hkMouseHover);
  833. var
  834. ItemInfo: TTBXItemInfo;
  835. begin
  836. FillChar(ItemInfo, SizeOf(ItemInfo), 0);
  837. case StateFlags and ISF_LOCATIONMASK of
  838. ISF_TOOLBARCOLOR:
  839. begin
  840. ItemInfo.ViewType := VT_TOOLBAR;
  841. ItemInfo.ItemOptions := IO_TOOLBARSTYLE;
  842. end;
  843. ISF_MENUCOLOR:
  844. begin
  845. ItemInfo.ViewType := VT_DOCKPANEL;
  846. end;
  847. ISF_STATUSCOLOR:
  848. begin
  849. ItemInfo.ViewType := VT_STATUSBAR;
  850. end;
  851. end;
  852. ItemInfo.Enabled := not Boolean(StateFlags and ISF_DISABLED);
  853. ItemInfo.Pushed := Boolean(StateFlags and ISF_PUSHED);
  854. ItemInfo.HoverKind := HoverKinds[Boolean(StateFlags and ISF_HOT)];
  855. ItemInfo.Selected := Boolean(StateFlags and ISF_SELECTED);
  856. CurrentTheme.PaintImage(Canvas, Rect, ItemInfo, ImageList, ImageIndex);
  857. end;
  858. //============================================================================//
  859. { TFontSettings }
  860. procedure TFontSettings.Apply(Font: TFont);
  861. var
  862. FS: TFontStyles;
  863. begin
  864. if Size <> 100 then Font.Size := (Font.Size * FSize + 50) div 100;
  865. if Color <> clNone then Font.Color := Color;
  866. if Name <> '' then Font.Name := Name;
  867. FS := Font.Style;
  868. if Bold = tsTrue then Include(FS, fsBold)
  869. else if Bold = tsFalse then Exclude(FS, fsBold);
  870. if Italic = tsTrue then Include(FS, fsItalic)
  871. else if Italic = tsFalse then Exclude(FS, fsItalic);
  872. if Underline = tsTrue then Include(FS, fsUnderline)
  873. else if Underline = tsFalse then Exclude(FS, fsUnderline);
  874. if StrikeOut = tsTrue then Include(FS, fsStrikeOut)
  875. else if StrikeOut = tsFalse then Exclude(FS, fsStrikeOut);
  876. Font.Style := FS;
  877. end;
  878. procedure TFontSettings.Apply(var LF: TLogFont; var FontColor: TColor);
  879. begin
  880. if Size <> 100 then LF.lfHeight := (LF.lfHeight * Size + 50) div 100;
  881. if Color <> clNone then FontColor := Color;
  882. if Name <> '' then StrPLCopy(LF.lfFaceName, Name, 31);
  883. if Bold = tsTrue then LF.lfWeight := FW_BOLD
  884. else if Bold = tsFalse then LF.lfWeight := FW_NORMAL;
  885. if Italic = tsTrue then LF.lfItalic := 1
  886. else if Italic = tsFalse then LF.lfItalic := 0;
  887. if Underline = tsTrue then LF.lfUnderline := 1
  888. else if Underline = tsFalse then LF.lfUnderline := 0;
  889. if StrikeOut = tsTrue then LF.lfStrikeOut := 1
  890. else if StrikeOut = tsFalse then LF.lfStrikeOut := 0;
  891. end;
  892. procedure TFontSettings.Assign(Src: TPersistent);
  893. var
  894. F: TFontSettings;
  895. begin
  896. if Src is TPersistent then
  897. begin
  898. F := TFontSettings(Src);
  899. if (FBold <> F.Bold) or (FItalic <> F.Italic) or (FUnderline <> F.Underline) or
  900. (FStrikeOut <> F.StrikeOut) or (FSize <> F.Size) or (FColor <> F.Color) or
  901. (FName <> F.Name) then
  902. begin
  903. FBold := F.Bold;
  904. FItalic := F.Italic;
  905. FUnderline := F.Underline;
  906. FStrikeOut := F.StrikeOut;
  907. FSize := F.Size;
  908. FColor := F.Color;
  909. FName := F.Name;
  910. Modified;
  911. end;
  912. end
  913. else inherited;
  914. end;
  915. constructor TFontSettings.Create;
  916. begin
  917. FSize := 100;
  918. FColor := clNone;
  919. end;
  920. function TFontSettings.CreateTransformedFont(Src: HFont; var FontColor: TColor): HFont;
  921. var
  922. LF: TLogFont;
  923. begin
  924. GetObject(Src, SizeOf(LF), @LF);
  925. Apply(LF, FontColor);
  926. Result := CreateFontIndirect(LF);
  927. end;
  928. procedure TFontSettings.Modified;
  929. begin
  930. if Assigned(FOnChange) then FOnChange(Self);
  931. end;
  932. procedure TFontSettings.SetBold(Value: TTriState);
  933. begin
  934. if FBold <> Value then
  935. begin
  936. FBold := Value;
  937. Modified;
  938. end;
  939. end;
  940. procedure TFontSettings.SetColor(Value: TColor);
  941. begin
  942. if FColor <> Value then
  943. begin
  944. FColor := Value;
  945. Modified;
  946. end;
  947. end;
  948. procedure TFontSettings.SetItalic(Value: TTriState);
  949. begin
  950. if FItalic <> Value then
  951. begin
  952. FItalic := Value;
  953. Modified;
  954. end;
  955. end;
  956. procedure TFontSettings.SetName(const Value: TFontName);
  957. begin
  958. if FName <> Value then
  959. begin
  960. FName := Value;
  961. Modified;
  962. end;
  963. end;
  964. procedure TFontSettings.SetSize(Value: TFontSize);
  965. begin
  966. if FSize <> Value then
  967. begin
  968. FSize := Value;
  969. Modified;
  970. end;
  971. end;
  972. procedure TFontSettings.SetStrikeOut(Value: TTriState);
  973. begin
  974. if FStrikeOut <> Value then
  975. begin
  976. FStrikeOut := Value;
  977. Modified;
  978. end;
  979. end;
  980. procedure TFontSettings.SetUnderline(Value: TTriState);
  981. begin
  982. if FUnderline <> Value then
  983. begin
  984. FUnderline := Value;
  985. Modified;
  986. end;
  987. end;
  988. //============================================================================//
  989. { TTBXCustomItem }
  990. constructor TTBXCustomItem.Create(AOwner: TComponent);
  991. begin
  992. inherited;
  993. FFontSettings := TFontSettings.Create;
  994. FFontSettings.OnChange := FontSettingsChanged;
  995. end;
  996. function TTBXCustomItem.CreatePopup(const ParentView: TTBView;
  997. const ParentViewer: TTBItemViewer; const PositionAsSubmenu,
  998. SelectFirstItem, Customizing: Boolean; const APopupPoint: TPoint;
  999. const Alignment: TTBPopupAlignment): TTBPopupWindow;
  1000. var
  1001. DoSelectFirstItem: Boolean;
  1002. begin
  1003. if AlwaysSelectFirst then DoSelectFirstItem := True
  1004. else DoSelectFirstItem := SelectFirstItem;
  1005. Result := inherited CreatePopup(ParentView, ParentViewer, PositionAsSubmenu,
  1006. DoSelectFirstItem, Customizing, APopupPoint, Alignment);
  1007. end;
  1008. destructor TTBXCustomItem.Destroy;
  1009. begin
  1010. FFontSettings.Free;
  1011. inherited;
  1012. end;
  1013. procedure TTBXCustomItem.FontSettingsChanged(Sender: TObject);
  1014. begin
  1015. Change(True);
  1016. end;
  1017. function TTBXCustomItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  1018. begin
  1019. Result := TTBXItemViewer;
  1020. end;
  1021. procedure TTBXCustomItem.GetPopupPosition(ParentView: TTBView;
  1022. PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec);
  1023. var
  1024. VT: Integer;
  1025. begin
  1026. if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do
  1027. begin
  1028. GetOfficeXPPopupPosition1(PopupPositionRec);
  1029. inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec);
  1030. GetOfficeXPPopupPosition2(PopupPositionRec);
  1031. VT := GetWinViewType(PopupWindow);
  1032. PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX);
  1033. end
  1034. else inherited;
  1035. end;
  1036. function TTBXCustomItem.GetPopupWindowClass: TTBPopupWindowClass;
  1037. begin
  1038. Result := TTBXPopupWindow;
  1039. end;
  1040. function TTBXCustomItem.GetStretch: Boolean;
  1041. begin
  1042. Result := tbisStretch in ItemStyle;
  1043. end;
  1044. procedure TTBXCustomItem.Invalidate;
  1045. begin
  1046. Change(False);
  1047. end;
  1048. procedure TTBXCustomItem.SetFontSettings(Value: TFontSettings);
  1049. begin
  1050. FFontSettings.Assign(Value);
  1051. end;
  1052. procedure TTBXCustomItem.SetLayout(Value: TTBXItemLayout);
  1053. begin
  1054. if Value <> FLayout then
  1055. begin
  1056. FLayout := Value;
  1057. Change(True);
  1058. end;
  1059. end;
  1060. procedure TTBXCustomItem.SetMinHeight(Value: Integer);
  1061. begin
  1062. if Value <> FMinHeight then
  1063. begin
  1064. FMinHeight := Value;
  1065. Change(True);
  1066. end;
  1067. end;
  1068. procedure TTBXCustomItem.SetMinWidth(Value: Integer);
  1069. begin
  1070. if Value <> FMinWidth then
  1071. begin
  1072. FMinWidth := Value;
  1073. Change(True);
  1074. end;
  1075. end;
  1076. procedure TTBXCustomItem.SetStretch(Value: Boolean);
  1077. begin
  1078. if Value xor (tbisStretch in ItemStyle) then
  1079. begin
  1080. if Value then ItemStyle := ItemStyle + [tbisStretch]
  1081. else ItemStyle := ItemStyle - [tbisStretch];
  1082. Change(True);
  1083. end;
  1084. end;
  1085. //============================================================================//
  1086. { TTBXItemViewer }
  1087. procedure TTBXItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer);
  1088. const
  1089. CMarginIDs: array [Boolean] of Integer = (MID_MENUITEM, MID_TOOLBARITEM);
  1090. CStartSize: array [Boolean] of Integer = (0, 6);
  1091. var
  1092. W, H: Integer;
  1093. ImgSize: TSize;
  1094. Item: TTBCustomItem;
  1095. ItemLayout, SaveLayout: TTBXItemLayout;
  1096. IsCaptionShown: Boolean;
  1097. IsTextRotated: Boolean;
  1098. ToolbarStyle: Boolean;
  1099. S: string;
  1100. TextFlags: Cardinal;
  1101. TextMetric: TTextMetric;
  1102. TextSize: TSize;
  1103. Margins: TTBXMargins;
  1104. Two, Three: Integer;
  1105. begin
  1106. Item := TTBCustomItem(Self.Item);
  1107. ToolbarStyle := IsToolbarStyle;
  1108. ImgSize := GetImageSize;
  1109. if (ImgSize.CX <= 0) or (ImgSize.CY <= 0) then
  1110. begin
  1111. ImgSize.CX := 0;
  1112. ImgSize.CY := 0;
  1113. end;
  1114. if Item is TTBXCustomItem then ItemLayout := TTBXCustomItem(Item).Layout
  1115. else ItemLayout := tbxlAuto;
  1116. SaveLayout := ItemLayout;
  1117. if ItemLayout = tbxlAuto then
  1118. begin
  1119. if tboImageAboveCaption in Item.EffectiveOptions then ItemLayout := tbxlGlyphTop
  1120. else
  1121. begin
  1122. if View.Orientation <> tbvoVertical then ItemLayout := tbxlGlyphLeft
  1123. else ItemLayout := tbxlGlyphTop;
  1124. end;
  1125. end;
  1126. { Setup font }
  1127. TextFlags := 0;
  1128. IsCaptionShown := CaptionShown;
  1129. IsTextRotated := (View.Orientation = tbvoVertical) and ToolbarStyle;
  1130. if IsCaptionShown then
  1131. begin
  1132. S := GetCaptionText;
  1133. if not (SaveLayout = tbxlAuto) or (tboImageAboveCaption in Item.EffectiveOptions) then IsTextRotated := False;
  1134. if IsTextRotated or not ToolbarStyle then TextFlags := DT_SINGLELINE;
  1135. TextSize := GetTextSize(Canvas, S, TextFlags, IsTextRotated, 0);
  1136. end
  1137. else
  1138. begin
  1139. SetLength(S, 0);
  1140. TextSize.CX := 0;
  1141. TextSize.CY := 0;
  1142. IsTextRotated := False;
  1143. end;
  1144. { Measure size }
  1145. if ToolbarStyle then
  1146. begin
  1147. if not IsTextRotated then
  1148. begin
  1149. AWidth := 3;
  1150. AHeight := 6;
  1151. end
  1152. else
  1153. begin
  1154. AWidth := 6;
  1155. AHeight := 3;
  1156. end;
  1157. if CaptionShown then
  1158. begin
  1159. Three := ScaleByPixelsPerInch(3, View.GetMonitor);
  1160. Inc(AWidth, TextSize.CX);
  1161. Inc(AHeight, TextSize.CY);
  1162. if not IsTextRotated then Inc(AWidth, 2 * Three)
  1163. else Inc(AHeight, 2 * Three);
  1164. end;
  1165. if GetImageShown and (ImgSize.CX > 0) and (ImgSize.CY > 0) then
  1166. begin
  1167. if ItemLayout = tbxlGlyphLeft then
  1168. begin
  1169. Inc(AWidth, ImgSize.CX + 3);
  1170. if Wide then Inc(AWidth);
  1171. if AHeight < ImgSize.CY + 6 then AHeight := ImgSize.CY + 6;
  1172. end
  1173. else
  1174. begin
  1175. Inc(AHeight, ImgSize.CY + 3);
  1176. if AWidth < ImgSize.CX + 7 then AWidth := ImgSize.CX + 7;
  1177. end;
  1178. end;
  1179. if tbisSubmenu in TTBItemAccess(Item).ItemStyle then with CurrentTheme do
  1180. begin
  1181. if tbisCombo in TTBItemAccess(Item).ItemStyle then Inc(AWidth, GetIntegerMetrics(Self, TMI_SPLITBTN_ARROWWIDTH))
  1182. else if tboDropdownArrow in Item.EffectiveOptions then
  1183. begin
  1184. if (ItemLayout <> tbxlGlyphTop) or (ImgSize.CX = 0) or IsTextRotated then
  1185. begin
  1186. Two := ScaleByPixelsPerInch(2, View.GetMonitor);
  1187. if View.Orientation <> tbvoVertical then
  1188. begin
  1189. Inc(AWidth, Two + GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH))
  1190. end
  1191. else
  1192. begin
  1193. Inc(AHeight,
  1194. GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH) + Two +
  1195. GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWMARGIN));
  1196. end;
  1197. end
  1198. else
  1199. begin
  1200. if (ItemLayout = tbxlGlyphTop) and (IsTextRotated xor (View.Orientation <> tbvoVertical)) then
  1201. begin
  1202. W := ImgSize.CX + GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH) + 2;
  1203. if W > AWidth - 7 then AWidth := W + 7;
  1204. end
  1205. else
  1206. begin
  1207. H := ImgSize.CY + GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH) + 2;
  1208. if H > AHeight - 7 then AHeight := H + 7;
  1209. end;
  1210. end
  1211. end;
  1212. end;
  1213. end
  1214. else // Not a ToolbarStyle
  1215. with CurrentTheme do
  1216. begin
  1217. GetTextMetrics(Canvas.Handle, TextMetric);
  1218. Inc(TextSize.CY, TextMetric.tmExternalLeading);
  1219. AWidth := TextSize.CX;
  1220. AHeight := TextSize.CY;
  1221. if ImgSize.CY = 0 then ImgSize.CY := 16;
  1222. if AHeight < ImgSize.CY then AHeight := ImgSize.CY;
  1223. GetMargins(MID_MENUITEM, Margins);
  1224. Inc(AWidth, Margins.LeftWidth + Margins.RightWidth);
  1225. Inc(AHeight, Margins.TopHeight + Margins.BottomHeight);
  1226. Inc(AWidth,
  1227. GetPopupMargin(Self) + GetIntegerMetrics(Self, TMI_MENU_IMGTEXTSPACE) +
  1228. GetIntegerMetrics(Self, TMI_MENU_LCAPTIONMARGIN) + GetIntegerMetrics(Self, TMI_MENU_RCAPTIONMARGIN));
  1229. S := Item.GetShortCutText;
  1230. if Length(S) > 0 then Inc(AWidth, (AHeight - 6) + GetTextWidth(Canvas.Handle, S, True));
  1231. Inc(AWidth, AHeight); { Note: maybe this should be controlled by the theme }
  1232. end;
  1233. if Item is TTBXCustomItem then with TTBXCustomItem(Item) do
  1234. begin
  1235. if AWidth < MinWidth then AWidth := MinWidth;
  1236. if AHeight < MinHeight then AHeight := MinHeight;
  1237. end;
  1238. end;
  1239. constructor TTBXItemViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer);
  1240. begin
  1241. inherited;
  1242. FWide := True;
  1243. end;
  1244. procedure TTBXItemViewer.DoAdjustFont(AFont: TFont; StateFlags: Integer);
  1245. begin
  1246. if tboDefault in Item.EffectiveOptions then with AFont do Style := Style + [fsBold];
  1247. if Item is TTBXCustomItem then
  1248. with TTBXCustomItem(Item) do
  1249. begin
  1250. FontSettings.Apply(AFont);
  1251. if Assigned(FOnAdjustFont) then FOnAdjustFont(Item, Self, AFont, StateFlags);
  1252. end
  1253. else if Item is TTBXEditItem then
  1254. with TTBXEditItem(Item) do
  1255. begin
  1256. FontSettings.Apply(AFont);
  1257. end;
  1258. end;
  1259. procedure TTBXItemViewer.DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect;
  1260. var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean);
  1261. begin
  1262. // do nothing
  1263. end;
  1264. procedure TTBXItemViewer.DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo);
  1265. var
  1266. ImgList: TCustomImageList;
  1267. I: TTBXCustomItem;
  1268. begin
  1269. ImgList := GetImageList;
  1270. if (ImgList <> nil) and (Item.ImageIndex >= 0) and (Item.ImageIndex < ImgList.Count) then
  1271. begin
  1272. CurrentTheme.PaintImage(Canvas, ARect, ItemInfo, ImgList, Item.ImageIndex);
  1273. if Item is TTBXCustomItem then
  1274. begin
  1275. I := TTBXCustomItem(Item);
  1276. if Assigned(I.FOnDrawImage) then
  1277. I.FOnDrawImage(I, Self, Canvas, ARect,
  1278. CurrentTheme.GetImageOffset(Canvas, ItemInfo, ImgList),
  1279. GetStateFlags(ItemInfo));
  1280. end;
  1281. end;
  1282. end;
  1283. function TTBXItemViewer.GetAccRole: Integer;
  1284. { Returns the MSAA "role" of the viewer. }
  1285. const
  1286. { Constants from OleAcc.h }
  1287. ROLE_SYSTEM_BUTTONDROPDOWNGRID = $3A;
  1288. begin
  1289. Result := inherited GetAccRole;
  1290. if (Item is TTBXCustomItem) and TTBXCustomItem(Item).ToolBoxPopup and
  1291. (tbisSubmenu in TTBXCustomItem(Item).ItemStyle) then
  1292. Result := ROLE_SYSTEM_BUTTONDROPDOWNGRID;
  1293. end;
  1294. function TTBXItemViewer.GetImageShown: Boolean;
  1295. begin
  1296. Result := (Item.ImageIndex >= 0) and
  1297. ((Item.DisplayMode in [nbdmDefault, nbdmImageAndText]) or
  1298. (IsToolbarStyle and (Item.DisplayMode = nbdmTextOnlyInMenus)));
  1299. end;
  1300. function TTBXItemViewer.GetImageSize: TSize;
  1301. var
  1302. ImgList: TCustomImageList;
  1303. begin
  1304. ImgList := GetImageList;
  1305. with Result do if ImgList <> nil then
  1306. begin
  1307. CX := ImgList.Width;
  1308. CY := ImgList.Height;
  1309. end
  1310. else
  1311. begin
  1312. CX := 0;
  1313. CY := 0;
  1314. end;
  1315. end;
  1316. function TTBXItemViewer.GetItemType: Integer;
  1317. begin
  1318. if IsToolbarStyle then Result := IT_TOOLBARBUTTON
  1319. else Result := IT_MENUITEM;
  1320. end;
  1321. function TTBXItemViewer.GetTextFlags: Cardinal;
  1322. begin
  1323. Result := 0;
  1324. if not AreKeyboardCuesEnabled and (vsUseHiddenAccels in View.Style) and
  1325. not (vsShowAccels in View.State) then Result := DT_HIDEPREFIX;
  1326. end;
  1327. function TTBXItemViewer.GetTextSize(Canvas: TCanvas; const Text: string;
  1328. TextFlags: Cardinal; Rotated: Boolean; StateFlags: Integer): TSize;
  1329. var
  1330. DC: HDC;
  1331. R: TRect;
  1332. RotatedFont, SaveFont: HFONT;
  1333. TextMetric: TTextMetric;
  1334. begin
  1335. { note: rotated font size is consistent only for single-line captions! }
  1336. if Length(Text) = 0 then with Result do
  1337. begin
  1338. CX := 0;
  1339. CY := 0;
  1340. Exit;
  1341. end;
  1342. { Select proper font }
  1343. Canvas.Font := TTBViewAccess(View).GetFont;
  1344. DoAdjustFont(Canvas.Font, StateFlags);
  1345. if not Rotated then with R, Result do
  1346. begin
  1347. Left := 0; Right := 1;
  1348. Top := 0; Bottom := 0;
  1349. DrawText(Canvas.Handle, PChar(Text), Length(Text), R, TextFlags or DT_CALCRECT);
  1350. CX := Right;
  1351. CY := Bottom;
  1352. end
  1353. else
  1354. begin
  1355. DC := Canvas.Handle;
  1356. RotatedFont := CreateRotatedFont(DC);
  1357. SaveFont := SelectObject(DC, RotatedFont);
  1358. GetTextMetrics(DC, TextMetric);
  1359. Result.CX := TextMetric.tmHeight;
  1360. Result.CY := GetTextWidth(DC, Text, True);
  1361. SelectObject(DC, SaveFont);
  1362. DeleteObject(RotatedFont);
  1363. end;
  1364. end;
  1365. function TTBXItemViewer.IsPtInButtonPart(X, Y: Integer): Boolean;
  1366. var
  1367. W: Integer;
  1368. begin
  1369. Result := not (tbisSubmenu in TTBItemAccess(Item).ItemStyle);
  1370. if (tbisCombo in TTBItemAccess(Item).ItemStyle) then
  1371. begin
  1372. if IsToolbarStyle then W := CurrentTheme.GetIntegerMetrics(Self, TMI_SPLITBTN_ARROWWIDTH)
  1373. else W := GetSystemMetricsForControl(View.Window, SM_CXMENUCHECK);
  1374. Result := X < (BoundsRect.Right - BoundsRect.Left) - W;
  1375. end;
  1376. end;
  1377. function TTBXItemViewer.IsToolbarSize: Boolean;
  1378. begin
  1379. Result := inherited IsToolbarSize;
  1380. Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX);
  1381. end;
  1382. function TTBXItemViewer.IsToolbarStyle: Boolean;
  1383. begin
  1384. Result := inherited IsToolbarStyle;
  1385. Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX);
  1386. end;
  1387. procedure TTBXItemViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean);
  1388. begin
  1389. inherited;
  1390. { Force the item to behave as a 'normal' menu item
  1391. That is make it respond to mouse as an item with IsToolbarStyle = False }
  1392. if Item.Enabled and not ((tbisSubmenu in TTBItemAccess(Item).ItemStyle) and
  1393. not IsPtInButtonPart(X, Y)) then
  1394. begin
  1395. if View.MouseOverSelected then
  1396. begin
  1397. Execute(True);
  1398. end;
  1399. end;
  1400. end;
  1401. procedure TTBXItemViewer.Paint(const Canvas: TCanvas;
  1402. const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean);
  1403. const
  1404. CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE);
  1405. CCombo: array [Boolean] of Integer = (0, IO_COMBO);
  1406. CSubmenuItem: array [Boolean] of Integer = (0, IO_SUBMENUITEM);
  1407. CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING);
  1408. CAppActive: array [Boolean] of Integer = (0, IO_APPACTIVE);
  1409. var
  1410. Item: TTBXCustomItem;
  1411. View: TTBViewAccess;
  1412. ItemInfo: TTBXItemInfo;
  1413. R: TRect;
  1414. ComboRect: TRect;
  1415. CaptionRect: TRect;
  1416. ImageRect: TRect;
  1417. C: TColor;
  1418. ToolbarStyle: Boolean;
  1419. HasArrow: Boolean;
  1420. IsSplit: Boolean;
  1421. ImageIsShown: Boolean;
  1422. ImageOrCheckShown: Boolean;
  1423. ImgAndArrowWidth: Integer;
  1424. ImgSize: TSize;
  1425. IsComboPushed: Boolean;
  1426. IsCaptionShown: Boolean;
  1427. IsTextRotated: Boolean;
  1428. ItemLayout: TTBXItemLayout;
  1429. PaintDefault: Boolean;
  1430. S: string;
  1431. StateFlags: Integer;
  1432. IsSpecialDropDown: Boolean;
  1433. TextFlags: Cardinal;
  1434. TextMetrics: TTextMetric;
  1435. TextSize: TSize;
  1436. Margins: TTBXMargins;
  1437. Three: Integer;
  1438. begin
  1439. Item := TTBXCustomItem(Self.Item);
  1440. View := TTBViewAccess(Self.View);
  1441. ToolbarStyle := IsToolbarStyle;
  1442. IsSplit := tbisCombo in Item.ItemStyle;
  1443. IsComboPushed := IsSplit and IsPushed and not View.Capture;
  1444. if IsComboPushed then IsPushed := False;
  1445. if GetImageShown then
  1446. begin
  1447. ImgSize := GetImageSize;
  1448. with ImgSize do if (CX <= 0) or (CY <= 0) then
  1449. begin
  1450. CX := 0;
  1451. CY := 0;
  1452. ImageIsShown := False;
  1453. end
  1454. else ImageIsShown := True;
  1455. end
  1456. else
  1457. begin
  1458. ImgSize.CX := 0;
  1459. ImgSize.CY := 0;
  1460. ImageIsShown := False;
  1461. end;
  1462. IsSplit := tbisCombo in Item.ItemStyle;
  1463. FillChar(ItemInfo, SizeOf(ItemInfo), 0);
  1464. ItemInfo.Control := View.Window;
  1465. ItemInfo.ViewType := GetViewType(View);
  1466. ItemInfo.ItemOptions := CToolbarStyle[ToolbarStyle] or CCombo[IsSplit] or
  1467. CDesigning[csDesigning in Item.ComponentState] or CSubmenuItem[tbisSubmenu in Item.ItemStyle] or
  1468. CAppActive[Application.Active];
  1469. ItemInfo.Enabled := Item.Enabled or View.Customizing;
  1470. ItemInfo.Pushed := IsPushed;
  1471. ItemInfo.Selected := Item.Checked;
  1472. ItemInfo.ImageShown := ImageIsShown;
  1473. ItemInfo.ImageWidth := ImgSize.CX;
  1474. ItemInfo.ImageHeight := ImgSize.CY;
  1475. if IsHoverItem then
  1476. begin
  1477. if not ItemInfo.Enabled and not View.MouseOverSelected then ItemInfo.HoverKind := hkKeyboardHover
  1478. else if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover;
  1479. end
  1480. else ItemInfo.HoverKind := hkNone;
  1481. ItemInfo.IsPopupParent := ToolbarStyle and
  1482. (((vsModal in View.State) and Assigned(View.OpenViewer)) or (tbisSubmenu in Item.ItemStyle)) and
  1483. ((IsSplit and IsComboPushed) or (not IsSplit and IsPushed));
  1484. ItemInfo.IsVertical := (View.Orientation = tbvoVertical) and not IsSplit;
  1485. ItemInfo.PopupMargin := GetPopupMargin(Self);
  1486. ItemLayout := Item.Layout;
  1487. if ItemLayout = tbxlAuto then
  1488. begin
  1489. if tboImageAboveCaption in Item.EffectiveOptions then ItemLayout := tbxlGlyphTop
  1490. else if View.Orientation <> tbvoVertical then ItemLayout := tbxlGlyphLeft
  1491. else ItemLayout := tbxlGlyphTop;
  1492. end;
  1493. HasArrow := (tbisSubmenu in Item.ItemStyle) and
  1494. ((tbisCombo in Item.ItemStyle) or (tboDropdownArrow in Item.EffectiveOptions));
  1495. if GetImageShown then
  1496. begin
  1497. ImgSize := GetImageSize;
  1498. with ImgSize do if (CX <= 0) or (CY <= 0) then
  1499. begin
  1500. CX := 0;
  1501. CY := 0;
  1502. ImageIsShown := False;
  1503. end
  1504. else ImageIsShown := True;
  1505. end
  1506. else
  1507. begin
  1508. ImgSize.CX := 0;
  1509. ImgSize.CY := 0;
  1510. ImageIsShown := False;
  1511. end;
  1512. ImageOrCheckShown := ImageIsShown or (not ToolbarStyle and Item.Checked);
  1513. StateFlags := GetStateFlags(ItemInfo);
  1514. Canvas.Font := TTBViewAccess(View).GetFont;
  1515. Canvas.Font.Color := CurrentTheme.GetItemTextColor(ItemInfo);
  1516. DoAdjustFont(Canvas.Font, StateFlags);
  1517. C := Canvas.Font.Color;
  1518. { Setup font }
  1519. TextFlags := GetTextFlags;
  1520. IsCaptionShown := CaptionShown;
  1521. IsTextRotated := (View.Orientation = tbvoVertical) and ToolbarStyle;
  1522. if IsCaptionShown then
  1523. begin
  1524. S := GetCaptionText;
  1525. if (Item.Layout <> tbxlAuto) or (tboImageAboveCaption in Item.EffectiveOptions) then
  1526. IsTextRotated := False;
  1527. if IsTextRotated or not ToolbarStyle then TextFlags := TextFlags or DT_SINGLELINE;
  1528. TextSize := GetTextSize(Canvas, S, TextFlags, IsTextRotated, StateFlags);
  1529. end
  1530. else
  1531. begin
  1532. StateFlags := 0;
  1533. SetLength(S, 0);
  1534. IsTextRotated := False;
  1535. TextSize.CX := 0;
  1536. TextSize.CY := 0;
  1537. end;
  1538. IsSpecialDropDown := HasArrow and not IsSplit and ToolbarStyle and
  1539. ((Item.Layout = tbxlGlyphTop) or (Item.Layout = tbxlAuto) and (tboImageAboveCaption in Item.EffectiveOptions)) and
  1540. (ImgSize.CX > 0) and not (IsTextRotated) and (TextSize.CX > 0);
  1541. { Border & Arrows }
  1542. R := ClientAreaRect;
  1543. with CurrentTheme do if ToolbarStyle then
  1544. begin
  1545. GetMargins(MID_TOOLBARITEM, Margins);
  1546. if HasArrow then with R do
  1547. begin
  1548. ItemInfo.ComboPart := cpCombo;
  1549. if IsSplit then
  1550. begin
  1551. ItemInfo.ComboPart := cpSplitLeft;
  1552. ComboRect := R;
  1553. Dec(Right, GetIntegerMetrics(Self, TMI_SPLITBTN_ARROWWIDTH));
  1554. ComboRect.Left := Right;
  1555. end
  1556. else if not IsSpecialDropDown then
  1557. begin
  1558. if View.Orientation <> tbvoVertical then
  1559. begin
  1560. ComboRect :=
  1561. Rect(
  1562. Right - GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH) -
  1563. GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWMARGIN), 0,
  1564. Right - GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWMARGIN), Bottom);
  1565. end
  1566. else
  1567. begin
  1568. ComboRect :=
  1569. Rect(0,
  1570. Bottom - GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH) -
  1571. GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWMARGIN),
  1572. Right, Bottom - GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWMARGIN));
  1573. end;
  1574. end
  1575. else
  1576. begin
  1577. ImgAndArrowWidth := ImgSize.CX + GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH) + 2;
  1578. ComboRect.Right := (R.Left + R.Right + ImgAndArrowWidth + 2) div 2;
  1579. ComboRect.Left := ComboRect.Right - GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH);
  1580. ComboRect.Top := (R.Top + R.Bottom - ImgSize.cy - 2 - TextSize.CY) div 2;
  1581. ComboRect.Bottom := ComboRect.Top + ImgSize.CY;
  1582. end;
  1583. end
  1584. else SetRectEmpty(ComboRect);
  1585. if not IsSplit then
  1586. begin
  1587. PaintButton(Canvas, R, ItemInfo);
  1588. if HasArrow then
  1589. begin
  1590. PaintDropDownArrow(Canvas, ComboRect, ItemInfo);
  1591. if not IsSpecialDropDown then
  1592. begin
  1593. if View.Orientation <> tbvoVertical then Dec(R.Right, GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH))
  1594. else Dec(R.Bottom, GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH));
  1595. end;
  1596. end;
  1597. end
  1598. else // IsSplit
  1599. begin
  1600. CurrentTheme.PaintButton(Canvas, R, ItemInfo);
  1601. ItemInfo.Pushed := IsComboPushed;
  1602. ItemInfo.Selected := False;
  1603. ItemInfo.ComboPart := cpSplitRight;
  1604. CurrentTheme.PaintButton(Canvas, ComboRect, ItemInfo);
  1605. ItemInfo.ComboPart := cpSplitLeft;
  1606. ItemInfo.Pushed := IsPushed;
  1607. ItemInfo.Selected := Item.Checked;
  1608. end;
  1609. InflateRect(R, -2, -2);
  1610. end
  1611. else // not toolbar style
  1612. begin
  1613. GetMargins(MID_MENUITEM, Margins);
  1614. PaintMenuItem(Canvas, R, ItemInfo);
  1615. Inc(R.Left, Margins.LeftWidth);
  1616. Dec(R.Right, Margins.RightWidth);
  1617. Inc(R.Top, Margins.TopHeight);
  1618. Dec(R.Bottom, Margins.BottomHeight);
  1619. end;
  1620. { Caption }
  1621. if IsCaptionShown then
  1622. begin
  1623. if ToolbarStyle then
  1624. begin
  1625. CaptionRect := R;
  1626. TextFlags := TextFlags or DT_CENTER or DT_VCENTER;
  1627. Three := ScaleByPixelsPerInch(3, View.GetMonitor);
  1628. if ImageIsShown then with CaptionRect do
  1629. case ItemLayout of
  1630. tbxlGlyphLeft:
  1631. begin
  1632. Inc(Left, ImgSize.CX + Three + 1);
  1633. Top := (Top + Bottom - TextSize.CY) div 2;
  1634. Bottom := Top + TextSize.CY;
  1635. Left := (Left + Right - TextSize.CX) div 2;
  1636. Right := Left + TextSize.CX;
  1637. TextFlags := TextFlags and not DT_CENTER;
  1638. end;
  1639. tbxlGlyphTop:
  1640. begin
  1641. Inc(Top, ImgSize.CY + 1);
  1642. if IsTextRotated then Inc(CaptionRect.Top, 3);
  1643. Top := (Top + Bottom - TextSize.CY) div 2;
  1644. Bottom := Top + TextSize.CY;
  1645. Left := (Left + Right - TextSize.CX) div 2;
  1646. Right := Left + TextSize.CX;
  1647. TextFlags := TextFlags and not DT_VCENTER;
  1648. end;
  1649. end
  1650. else
  1651. begin
  1652. with CaptionRect, TextSize do
  1653. begin
  1654. Left := (Left + R.Right - CX) div 2;
  1655. Top := (Top + R.Bottom - CY) div 2;
  1656. Right := Left + CX;
  1657. Bottom := Top + CY;
  1658. end;
  1659. end;
  1660. Canvas.Font.Color := C;
  1661. PaintDefault := True;
  1662. DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault);
  1663. if PaintDefault then
  1664. CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, IsTextRotated);
  1665. end
  1666. else with CurrentTheme do
  1667. begin
  1668. TextFlags := DT_LEFT or DT_VCENTER or TextFlags;
  1669. TextSize := GetTextSize(Canvas, S, TextFlags, False, StateFlags); { TODO : Check if this line is required }
  1670. GetTextMetrics(Canvas.Handle, TextMetrics);
  1671. CaptionRect := R;
  1672. Inc(CaptionRect.Left,
  1673. ItemInfo.PopupMargin + GetIntegerMetrics(Self, TMI_MENU_IMGTEXTSPACE) +
  1674. GetIntegerMetrics(Self, TMI_MENU_LCAPTIONMARGIN));
  1675. with TextMetrics, CaptionRect do
  1676. if (Bottom - Top) - (tmHeight + tmExternalLeading) = Margins.BottomHeight then Dec(Bottom);
  1677. Inc(CaptionRect.Top, TextMetrics.tmExternalLeading);
  1678. CaptionRect.Right := CaptionRect.Left + TextSize.CX;
  1679. Canvas.Font.Color := C;
  1680. PaintDefault := True;
  1681. DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault);
  1682. if PaintDefault then
  1683. CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, IsTextRotated);
  1684. end;
  1685. end;
  1686. { Shortcut and/or submenu arrow (menus only) }
  1687. if not ToolbarStyle then
  1688. begin
  1689. S := Item.GetShortCutText;
  1690. if Length(S) > 0 then
  1691. begin
  1692. CaptionRect := R;
  1693. with CaptionRect, TextMetrics do
  1694. begin
  1695. Left := Right - (Bottom - Top) - GetTextWidth(Canvas.Handle, S, True);
  1696. if (Bottom - Top) - (tmHeight + tmExternalLeading) = Margins.BottomHeight then Dec(Bottom);
  1697. Inc(Top, TextMetrics.tmExternalLeading);
  1698. end;
  1699. Canvas.Font.Color := C;
  1700. PaintDefault := True;
  1701. DoPaintCaption(Canvas, ClientAreaRect, CaptionRect, IsTextRotated, PaintDefault);
  1702. if PaintDefault then
  1703. CurrentTheme.PaintCaption(Canvas, CaptionRect, ItemInfo, S, TextFlags, False);
  1704. end;
  1705. end;
  1706. { Image, or check box }
  1707. if ImageOrCheckShown then
  1708. begin
  1709. ImageRect := R;
  1710. if ToolBarStyle then
  1711. begin
  1712. if IsSpecialDropDown then
  1713. OffsetRect(ImageRect, (-CurrentTheme.GetIntegerMetrics(Self, TMI_DROPDOWN_ARROWWIDTH) + 1) div 2, 0);
  1714. if ItemLayout = tbxlGlyphLeft then ImageRect.Right := ImageRect.Left + ImgSize.CX + 2
  1715. else
  1716. begin
  1717. ImageRect.Top := (ImageRect.Top + ImageRect.Bottom - ImgSize.cy - 2 - TextSize.cy) div 2;
  1718. ImageRect.Bottom := ImageRect.Top + ImgSize.CY;
  1719. end;
  1720. end
  1721. else ImageRect.Right := ImageRect.Left + ClientAreaRect.Bottom - ClientAreaRect.Top;
  1722. if ImageIsShown then with ImageRect, ImgSize do
  1723. begin
  1724. Left := Left + ((Right - Left) - CX) div 2;
  1725. ImageRect.Top := Top + ((Bottom - Top) - CY) div 2;
  1726. Right := Left + CX;
  1727. Bottom := Top + CY;
  1728. DrawItemImage(Canvas, ImageRect, ItemInfo);
  1729. end
  1730. else
  1731. if not ToolbarStyle and Item.Checked then
  1732. begin
  1733. if Item.RadioItem then
  1734. with ItemInfo do ItemOptions := ItemOptions or IO_RADIO;
  1735. CurrentTheme.PaintCheckMark(Canvas, ImageRect, ItemInfo);
  1736. end;
  1737. end;
  1738. end;
  1739. //============================================================================//
  1740. { TTBXSubmenuItem }
  1741. constructor TTBXSubmenuItem.Create(AOwner: TComponent);
  1742. begin
  1743. inherited;
  1744. ItemStyle := ItemStyle + [tbisSubMenu, tbisSubitemsEditable];
  1745. end;
  1746. function TTBXSubmenuItem.GetDropdownCombo: Boolean;
  1747. begin
  1748. Result := tbisCombo in ItemStyle;
  1749. end;
  1750. procedure TTBXSubmenuItem.SetDropdownCombo(Value: Boolean);
  1751. begin
  1752. if (tbisCombo in ItemStyle) <> Value then begin
  1753. if Value then ItemStyle := ItemStyle + [tbisCombo]
  1754. else ItemStyle := ItemStyle - [tbisCombo];
  1755. Change (True);
  1756. end;
  1757. end;
  1758. //============================================================================//
  1759. { TTBXSeparatorItem }
  1760. constructor TTBXSeparatorItem.Create(AOwner: TComponent);
  1761. begin
  1762. inherited;
  1763. FSize := -1; // use default from as in TTBSeparatorItem
  1764. end;
  1765. function TTBXSeparatorItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  1766. begin
  1767. Result := TTBXSeparatorItemViewer;
  1768. end;
  1769. procedure TTBXSeparatorItem.SetSize(Value: Integer);
  1770. begin
  1771. if Value < -1 then Value := -1;
  1772. if Value <> FSize then
  1773. begin
  1774. FSize := Value;
  1775. Change(True);
  1776. end;
  1777. end;
  1778. //============================================================================//
  1779. { TTBXSeparatorItemViewer }
  1780. procedure TTBXSeparatorItemViewer.CalcSize(const Canvas: TCanvas;
  1781. var AWidth, AHeight: Integer);
  1782. var
  1783. SZ: Integer;
  1784. begin
  1785. SZ := TTBXSeparatorItem(Item).Size;
  1786. if SZ < 0 then
  1787. begin
  1788. if not IsToolbarStyle then SZ := CurrentTheme.GetIntegerMetrics(Self, TMI_MENU_SEPARATORSIZE)
  1789. else SZ := CurrentTheme.GetIntegerMetrics(Self, TMI_TLBR_SEPARATORSIZE);
  1790. if SZ < 0 then inherited CalcSize(Canvas, AWidth, AHeight)
  1791. else
  1792. begin
  1793. AWidth := SZ;
  1794. AHeight := SZ;
  1795. end;
  1796. end
  1797. else if not IsToolbarStyle then
  1798. begin
  1799. AHeight := SZ;
  1800. AWidth := 0;
  1801. end
  1802. else
  1803. begin
  1804. AWidth := SZ;
  1805. AHeight := SZ;
  1806. end;
  1807. end;
  1808. function TTBXSeparatorItemViewer.IsToolbarSize: Boolean;
  1809. begin
  1810. Result := inherited IsToolbarSize;
  1811. Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX);
  1812. end;
  1813. function TTBXSeparatorItemViewer.IsToolbarStyle: Boolean;
  1814. begin
  1815. Result := inherited IsToolbarStyle;
  1816. Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX);
  1817. end;
  1818. procedure TTBXSeparatorItemViewer.Paint(const Canvas: TCanvas;
  1819. const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean);
  1820. const
  1821. CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE);
  1822. CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING);
  1823. var
  1824. Item: TTBXSeparatorItem;
  1825. ItemInfo: TTBXItemInfo;
  1826. R: TRect;
  1827. LineSep, HorzLine: Boolean;
  1828. begin
  1829. Item := TTBXSeparatorItem(Self.Item);
  1830. if Item.Size = 0 then Exit;
  1831. FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0);
  1832. ItemInfo.ViewType := GetViewType(View);
  1833. ItemInfo.ItemOptions := CToolbarStyle[IsToolbarStyle] or
  1834. CDesigning[csDesigning in Item.ComponentState];
  1835. ItemInfo.Enabled := not Item.Blank;
  1836. ItemInfo.Pushed := IsPushed;
  1837. ItemInfo.Selected := False;
  1838. ItemInfo.ImageShown := False;
  1839. ItemInfo.ImageWidth := 0;
  1840. ItemInfo.ImageHeight := 0;
  1841. ItemInfo.IsVertical := View.Orientation = tbvoVertical;
  1842. if not IsToolbarStyle then ItemInfo.PopupMargin := GetPopupMargin(Self);
  1843. R := ClientAreaRect;
  1844. LineSep := tbisLineSep in State;
  1845. with ItemInfo do
  1846. begin
  1847. HorzLine := (IsVertical xor LineSep) or View.IsPopup;
  1848. if (((ViewType and VT_POPUP) = VT_POPUP) and
  1849. ((ViewType and PVT_CHEVRONMENU) = PVT_CHEVRONMENU)) then
  1850. HorzLine := (HorzLine and LineSep);
  1851. end;
  1852. CurrentTheme.PaintSeparator(Canvas, R, ItemInfo, HorzLine, LineSep);
  1853. end;
  1854. //============================================================================//
  1855. //============================================================================//
  1856. { TTBXPopupWindow }
  1857. procedure TTBXPopupWindow.CMHintShow(var Message: TCMHintShow);
  1858. begin
  1859. with Message.HintInfo^ do
  1860. begin
  1861. HintStr := '';
  1862. if Assigned(View.Selected) then
  1863. begin
  1864. CursorRect := View.Selected.BoundsRect;
  1865. HintStr := View.Selected.GetHintText;
  1866. View.Selected.Dispatch(Message);
  1867. end;
  1868. end;
  1869. end;
  1870. procedure TTBXPopupWindow.CMShowingChanged(var Message: TMessage);
  1871. const
  1872. ShowFlags: array[Boolean] of UINT = (
  1873. SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_HIDEWINDOW,
  1874. SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_SHOWWINDOW);
  1875. var
  1876. MenuAni: TMenuAnimation;
  1877. AniDir: TTBAnimationDirection;
  1878. begin
  1879. { Must override TCustomForm/TForm's CM_SHOWINGCHANGED handler so that the
  1880. form doesn't get activated when Visible is set to True. }
  1881. { Handle animation. NOTE: I do not recommend trying to enable animation on
  1882. Windows 95 and NT 4.0 because there's a difference in the way the
  1883. SetWindowPos works on those versions. See the comment in the
  1884. TBStartAnimation function of TB2Anim.pas. }
  1885. if ((View.ParentView = nil) or not(vsNoAnimation in View.ParentView.State)) and
  1886. Showing and (View.Selected = nil) and not IsWindowVisible(WindowHandle) and
  1887. (TBXMenuAnimation.AnimationMode <> amNone) then
  1888. begin
  1889. { Start animation only if WM_TB2K_POPUPSHOWING returns zero (or not handled) }
  1890. if SendMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_ANIMSTART, 0) = 0 then
  1891. begin
  1892. MenuAni := TBXMenuAnimation.MenuAnimation;
  1893. { MP (do not animate if disallowed by system-wide config) }
  1894. if MenuAni <> maNone then
  1895. begin
  1896. AniDir := TTBPopupWindowAccess(Self).AnimationDirection;
  1897. if MenuAni = maUnfold then
  1898. if [tbadDown, tbadUp] * AniDir <> []
  1899. then Include(AniDir, tbadRight)
  1900. else Include(AniDir, tbadDown);
  1901. TBStartAnimation(WindowHandle, MenuAni = maFade, AniDir);
  1902. Exit;
  1903. end;
  1904. end;
  1905. end;
  1906. { No animation... }
  1907. if not Showing then begin
  1908. { Call TBEndAnimation to ensure WS_EX_LAYERED style is removed before
  1909. hiding, otherwise windows under the popup window aren't repainted
  1910. properly. }
  1911. TBEndAnimation(WindowHandle);
  1912. end;
  1913. SetWindowPos(WindowHandle, 0, 0, 0, 0, 0, ShowFlags[Showing]);
  1914. if Showing then SendNotifyMessage(WindowHandle, WM_TB2K_POPUPSHOWING, TPS_NOANIM, 0);
  1915. end;
  1916. procedure TTBXPopupWindow.CreateParams(var Params: TCreateParams);
  1917. const
  1918. CS_DROPSHADOW = $00020000;
  1919. begin
  1920. inherited CreateParams(Params);
  1921. with Params do
  1922. begin
  1923. WindowClass.Style := WindowClass.Style and not (CS_DROPSHADOW or CS_DBLCLKS);
  1924. if GetShowShadow and (CurrentTheme.GetPopupShadowType = PST_WINDOWSXP) then
  1925. begin
  1926. WindowClass.Style := WindowClass.Style or CS_DROPSHADOW;
  1927. StrPCopy(WinClassName, ClassName + 'S');
  1928. end;
  1929. end;
  1930. end;
  1931. procedure TTBXPopupWindow.CreateShadow;
  1932. var
  1933. PR: TRect;
  1934. ParentViewer: TTBItemViewer;
  1935. VT: Integer;
  1936. ChevronParent: Boolean;
  1937. begin
  1938. PR := Rect(0, 0, 0, 0);
  1939. if CurrentTheme.GetPopupShadowType = PST_OFFICEXP then
  1940. begin
  1941. if (View <> nil) and (View.ParentView <> nil) then
  1942. begin
  1943. ParentViewer := TTBViewAccess(View.ParentView).OpenViewer;
  1944. ChevronParent := Self is TTBXChevronPopupWindow;
  1945. if ((ParentViewer is TTBXItemViewer) or ChevronParent) then
  1946. begin
  1947. VT := GetViewType(ParentViewer.View);
  1948. if ((VT and PVT_POPUPMENU) <> PVT_POPUPMENU) or ChevronParent then
  1949. begin
  1950. PR := ParentViewer.BoundsRect;
  1951. PR.TopLeft := View.ParentView.Window.ClientToScreen(PR.TopLeft);
  1952. PR.BottomRight := View.ParentView.Window.ClientToScreen(PR.BottomRight);
  1953. end;
  1954. end;
  1955. end
  1956. else if not IsRectEmpty(FControlRect) then
  1957. begin
  1958. PR := FControlRect;
  1959. end;
  1960. end;
  1961. FShadows := TShadows.Create(PR, BoundsRect, 4, 61, TBXLoColor);
  1962. FShadows.Show(Handle);
  1963. end;
  1964. destructor TTBXPopupWindow.Destroy;
  1965. begin
  1966. DestroyShadow;
  1967. inherited;
  1968. end;
  1969. procedure TTBXPopupWindow.DestroyShadow;
  1970. var
  1971. SaveShadows: TObject;
  1972. begin
  1973. SaveShadows := FShadows;
  1974. FShadows := nil;
  1975. SaveShadows.Free;
  1976. end;
  1977. function TTBXPopupWindow.GetFillColor: TColor;
  1978. begin
  1979. Result := CurrentTheme.GetViewColor(GetViewType(View));
  1980. View.BackgroundColor := Result;
  1981. end;
  1982. function TTBXPopupWindow.GetNCSize: TPoint;
  1983. begin
  1984. Result := inherited GetNCSize;
  1985. CurrentTheme.GetViewBorder(Self, GetViewType(View), Result);
  1986. end;
  1987. function TTBXPopupWindow.GetShowShadow: Boolean;
  1988. begin
  1989. Result := ((GetViewType(View) and PVT_LISTBOX) <> PVT_LISTBOX );
  1990. end;
  1991. function TTBXPopupWindow.GetViewClass: TTBViewClass;
  1992. begin
  1993. Result := TTBXPopupView;
  1994. end;
  1995. procedure TTBXPopupWindow.PaintScrollArrows;
  1996. function _GetPopupMargin: Integer;
  1997. begin
  1998. if View.ParentView <> nil then
  1999. Result := GetPopupMargin(TTBViewAccess(View.ParentView).OpenViewer)
  2000. else if View.ViewerCount > 0 then
  2001. Result := GetPopupMargin(View.Viewers[0])
  2002. else Result := -1;
  2003. end;
  2004. procedure DrawArrows;
  2005. var
  2006. ItemInfo: TTBXItemInfo;
  2007. Index: Integer;
  2008. begin
  2009. FillChar(ItemInfo, SizeOf(ItemInfo), 0);
  2010. ItemInfo.ViewType := PVT_POPUPMENU;
  2011. ItemInfo.Enabled := True;
  2012. ItemInfo.PopupMargin := _GetPopupMargin;
  2013. if ItemInfo.PopupMargin > 0 then
  2014. begin
  2015. if TTBViewAccess(View).ShowUpArrow then
  2016. for Index := 0 to View.ViewerCount- 1 do
  2017. if View.Viewers[Index].Show then
  2018. begin
  2019. CurrentTheme.PaintMenuItemFrame(Canvas, Rect(0, 0, ClientWidth,
  2020. View.Viewers[Index].BoundsRect.Top), ItemInfo);
  2021. Break;
  2022. end;
  2023. if TTBViewAccess(View).ShowDownArrow then
  2024. for Index := View.ViewerCount- 1 downto 0 do
  2025. if View.Viewers[Index].Show then
  2026. begin
  2027. CurrentTheme.PaintMenuItemFrame(Canvas, Rect(0,
  2028. View.Viewers[Index].BoundsRect.Bottom, ClientWidth,
  2029. ClientHeight), ItemInfo);
  2030. Break;
  2031. end;
  2032. end;
  2033. end;
  2034. begin
  2035. with TTBViewAccess(View) do
  2036. if ShowUpArrow or ShowDownArrow then
  2037. DrawArrows;
  2038. inherited;
  2039. end;
  2040. procedure TTBXPopupWindow.TBMGetViewType(var Message: TMessage);
  2041. var
  2042. PI: TTBCustomItem;
  2043. begin
  2044. Message.Result := PVT_POPUPMENU;
  2045. if View <> nil then
  2046. if Self is TTBXChevronPopupWindow then
  2047. Message.Result := PVT_CHEVRONMENU
  2048. else
  2049. begin
  2050. PI := View.ParentItem;
  2051. if PI <> nil then
  2052. begin
  2053. if (PI.Count = 1) and (PI.Items[0] is TTBXCustomList) then
  2054. Message.Result := PVT_LISTBOX
  2055. else if PI is TTBXEditItem then
  2056. begin
  2057. Message.Result := PVT_TOOLBOX;
  2058. end
  2059. else if (PI is TTBXCustomItem) and (TTBXCustomItem(PI).ToolBoxPopup) then
  2060. Message.Result := PVT_TOOLBOX
  2061. end;
  2062. end;
  2063. end;
  2064. procedure TTBXPopupWindow.WMEraseBkgnd(var Message: TWmEraseBkgnd);
  2065. var
  2066. Canvas: TCanvas;
  2067. R: TRect;
  2068. begin
  2069. TBEndAnimation(WindowHandle);
  2070. Canvas := TCanvas.Create;
  2071. Canvas.Handle := Message.DC;
  2072. R := ClientRect;
  2073. CurrentTheme.PaintBackgnd(Canvas, R, R, R, GetFillColor, False, GetViewType(View));
  2074. Canvas.Handle := 0;
  2075. Canvas.Free;
  2076. Message.Result := 1;
  2077. end;
  2078. procedure TTBXPopupWindow.WMNCCalcSize(var Message: TWMNCCalcSize);
  2079. var
  2080. Sz: TPoint;
  2081. begin
  2082. CurrentTheme.GetViewBorder(Self, GetViewType(View), Sz);
  2083. with Message.CalcSize_Params^.rgrc[0], Sz do
  2084. begin
  2085. Inc(Left, X);
  2086. Inc(Top, Y);
  2087. Dec(Right, X);
  2088. Dec(Bottom, Y);
  2089. end;
  2090. Message.Result := 1;
  2091. end;
  2092. procedure TBXPopupNCPaintProc(Control: TControl; Wnd: HWND; DC: HDC; AppData: Longint);
  2093. var
  2094. R, R2: TRect;
  2095. Canvas: TCanvas;
  2096. View: TTBPopupView;
  2097. PopupInfo: TTBXPopupInfo;
  2098. ParentViewer: TTBItemViewer;
  2099. begin
  2100. Assert(DC <> 0, 'TBXPopupNCPaintProc');
  2101. Canvas := TCanvas.Create;
  2102. try
  2103. Canvas.Handle := DC;
  2104. FillChar(PopupInfo, SizeOf(PopupInfo), 0);
  2105. View := TTBPopupView(AppData);
  2106. PopupInfo.WindowHandle := View.Window.Handle;
  2107. PopupInfo.ViewType := GetViewType(View);
  2108. if View.ParentView <> nil then
  2109. begin
  2110. ParentViewer := TTBViewAccess(View.ParentView).OpenViewer;
  2111. if ((ParentViewer is TTBXItemViewer) or (View.Window is TTBXChevronPopupWindow))
  2112. and TTBItemViewerAccess(ParentViewer).IsToolbarStyle then
  2113. begin
  2114. R := ParentViewer.BoundsRect;
  2115. R.TopLeft := View.ParentView.Window.ClientToScreen(R.TopLeft);
  2116. R.BottomRight := View.ParentView.Window.ClientToScreen(R.BottomRight);
  2117. GetWindowRect(Wnd, R2);
  2118. OffsetRect(R, -R2.Left, -R2.Top);
  2119. PopupInfo.ParentRect := R;
  2120. end;
  2121. end
  2122. else if View.ParentItem is TTBXRootItem then
  2123. begin
  2124. R := TTBXRootItem(View.ParentItem).FPopupControlRect;
  2125. if not IsRectEmpty(R) then
  2126. begin
  2127. GetWindowRect(Wnd, R2);
  2128. OffsetRect(R, -R2.Left, -R2.Top);
  2129. PopupInfo.ParentRect := R;
  2130. end;
  2131. end;
  2132. GetWindowRect(Wnd, R);
  2133. OffsetRect(R, -R.Left, -R.Top);
  2134. CurrentTheme.GetViewBorder(Control, PopupInfo.ViewType, PopupInfo.BorderSize);
  2135. R2 := R;
  2136. with PopupInfo.BorderSize do InflateRect(R2, -X, -Y);
  2137. with R2 do ExcludeClipRect(Canvas.Handle, Left, Top, Right, Bottom);
  2138. CurrentTheme.PaintPopupNCArea(Canvas, R, PopupInfo);
  2139. finally
  2140. Canvas.Handle := 0;
  2141. Canvas.Free;
  2142. end;
  2143. end;
  2144. procedure TTBXPopupWindow.WMNCPaint(var Message: TMessage);
  2145. var
  2146. DC: HDC;
  2147. begin
  2148. DC := GetWindowDC(Handle);
  2149. try
  2150. Assert(DC <> 0, 'TTBXPopupWindow.WMNCPaint');
  2151. SelectNCUpdateRgn(Handle, DC, HRGN(Message.WParam));
  2152. TBXPopupNCPaintProc(Self, Handle, DC, LongInt(Self.View));
  2153. finally
  2154. ReleaseDC(Handle, DC);
  2155. end;
  2156. end;
  2157. procedure TTBXPopupWindow.WMPrint(var Message: TMessage);
  2158. begin
  2159. HandleWMPrint(Self, Handle, Message, TBXPopupNCPaintProc, LongInt(Self.View));
  2160. end;
  2161. procedure TTBXPopupWindow.WMTB2kPopupShowing(var Message: TMessage);
  2162. begin
  2163. if Message.WParam in [TPS_ANIMFINISHED, TPS_NOANIM] then
  2164. begin
  2165. if not (csDestroying in ComponentState) and GetShowShadow and
  2166. (CurrentTheme.GetPopupShadowType in [PST_OFFICEXP, PST_WINDOWS2K]) then CreateShadow;
  2167. end;
  2168. end;
  2169. procedure TTBXPopupWindow.WMWindowPosChanged(var Message: TWMWindowPosChanged);
  2170. begin
  2171. inherited;
  2172. with Message.WindowPos^ do
  2173. if ((flags and SWP_SHOWWINDOW) = 0) and ((flags and SWP_HIDEWINDOW) = 0) then
  2174. begin
  2175. if FShadows <> nil then
  2176. begin
  2177. DestroyShadow;
  2178. CreateShadow;
  2179. end;
  2180. end;
  2181. end;
  2182. //============================================================================//
  2183. { TTBXToolbarView }
  2184. procedure TTBXToolbarView.GetMargins(AOrientation: TTBViewOrientation; var Margins: TRect);
  2185. var
  2186. VT: Integer;
  2187. M: TTBXMargins;
  2188. begin
  2189. VT := GetWinViewType(TTBXToolbar(Owner));
  2190. if (VT and VT_TOOLBAR) = VT_TOOLBAR then
  2191. begin
  2192. if AOrientation = tbvoFloating then VT := VT or TVT_FLOATING
  2193. else VT := VT and not TVT_FLOATING
  2194. end
  2195. else if (VT and VT_DOCKPANEL) = VT_DOCKPANEL then
  2196. begin
  2197. if AOrientation = tbvoFloating then VT := VT or DPVT_FLOATING
  2198. else VT := VT and not DPVT_FLOATING
  2199. end;
  2200. CurrentTheme.GetViewMargins(VT, M);
  2201. Margins.Left := M.LeftWidth;
  2202. Margins.Top := M.TopHeight;
  2203. Margins.Right := M.RightWidth;
  2204. Margins.Bottom := M.BottomHeight;
  2205. end;
  2206. //============================================================================//
  2207. { TTBXToolbar }
  2208. procedure TTBXToolbar.CMColorChanged(var Message: TMessage);
  2209. begin
  2210. UpdateEffectiveColor;
  2211. if Docked and HandleAllocated then
  2212. begin
  2213. RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or
  2214. RDW_ERASE or RDW_UPDATENOW or RDW_ALLCHILDREN);
  2215. end;
  2216. UpdateChildColors;
  2217. Invalidate;
  2218. end;
  2219. procedure TTBXToolbar.CMControlChange(var Message: TCMControlChange);
  2220. begin
  2221. inherited;
  2222. if Message.Inserting and (Color = clNone) then
  2223. Message.Control.Perform(CM_PARENTCOLORCHANGED, 1, EffectiveColor);
  2224. end;
  2225. procedure TTBXToolbar.CMParentColorChanged(var Message: TMessage);
  2226. begin
  2227. if Embedded and (Color = clNone) then
  2228. begin
  2229. UpdateEffectiveColor;
  2230. if (Message.WParam = 0) then
  2231. begin
  2232. Message.WParam := 1;
  2233. Message.LParam := EffectiveColor;
  2234. end;
  2235. end;
  2236. inherited;
  2237. Invalidate;
  2238. end;
  2239. constructor TTBXToolbar.Create(AOwner: TComponent);
  2240. begin
  2241. inherited;
  2242. AddThemeNotification(Self);
  2243. FEffectiveColor := Color;
  2244. Color := clNone;
  2245. ControlStyle := ControlStyle - [csOpaque];
  2246. DblClickUndock := False;
  2247. end;
  2248. destructor TTBXToolbar.Destroy;
  2249. begin
  2250. RemoveThemeNotification(Self);
  2251. inherited;
  2252. end;
  2253. procedure TTBXToolbar.DrawNCArea(const DrawToDC: Boolean; const ADC: HDC; const Clip: HRGN);
  2254. var
  2255. DC: HDC;
  2256. R, CR, R2: TRect;
  2257. ACanvas: TCanvas;
  2258. ToolbarInfo: TTBXToolbarInfo;
  2259. UsingBackground: Boolean;
  2260. begin
  2261. if not Docked or not HandleAllocated then Exit;
  2262. if not DrawToDC then DC := GetWindowDC(Handle)
  2263. else DC := ADC;
  2264. UsingBackground := TDockAccess(CurrentDock).UsingBackground;
  2265. try
  2266. GetToolbarInfo(ToolbarInfo);
  2267. GetWindowRect(Handle, R);
  2268. OffsetRect(R, -R.Left, -R.Top);
  2269. if not DrawToDC then
  2270. begin
  2271. SelectNCUpdateRgn(Handle, DC, Clip);
  2272. CR := R;
  2273. with ToolbarInfo.BorderSize, CR do
  2274. begin
  2275. InflateRect(CR, -X, -Y);
  2276. if ToolbarInfo.IsVertical then Inc(Top, GetTBXDragHandleSize(ToolbarInfo))
  2277. else Inc(Left, GetTBXDragHandleSize(ToolbarInfo));
  2278. ExcludeClipRect(DC, Left, Top, Right, Bottom);
  2279. end;
  2280. end;
  2281. ACanvas := TCanvas.Create;
  2282. try
  2283. ACanvas.Handle := DC;
  2284. if CurrentTheme.SolidToolbarNCArea then
  2285. begin
  2286. ACanvas.Brush.Color := EffectiveColor;
  2287. ACanvas.Brush.Style := bsSolid;
  2288. end
  2289. else if UsingBackground then
  2290. begin
  2291. ACanvas.Brush.Color := EffectiveColor;
  2292. R2 := CurrentDock.ClientRect;
  2293. OffsetRect(R2, -Left, -Top);
  2294. TDockAccess(CurrentDock).DrawBackground(DC, R2);
  2295. end
  2296. else
  2297. begin
  2298. ACanvas.Brush.Color := GetEffectiveColor(CurrentDock);
  2299. ACanvas.FillRect(R);
  2300. ACanvas.Brush.Color := EffectiveColor;
  2301. ACanvas.Brush.Style := bsSolid;
  2302. end;
  2303. CurrentTheme.PaintToolbarNCArea(GetMonitorFromControl(Self), ACanvas, R, ToolbarInfo);
  2304. finally
  2305. ACanvas.Handle := 0;
  2306. ACanvas.Free;
  2307. end;
  2308. finally
  2309. if not DrawToDC then ReleaseDC(Handle, DC);
  2310. end;
  2311. end;
  2312. function TTBXToolbar.Embedded: Boolean;
  2313. begin
  2314. Result := not (Floating or Docked);
  2315. end;
  2316. function TTBXToolbar.GetChevronItemClass: TTBChevronItemClass;
  2317. begin
  2318. Result := TTBXChevronItem;
  2319. end;
  2320. function TTBXToolbar.GetFloatingBorderSize: TPoint;
  2321. begin
  2322. CurrentTheme.GetViewBorder(Self, GetViewType(View) or TVT_FLOATING, Result);
  2323. end;
  2324. function TTBXToolbar.GetFloatingWindowParentClass: TTBFloatingWindowParentClass;
  2325. begin
  2326. Result := TTBXFloatingWindowParent;
  2327. end;
  2328. procedure TTBXToolbar.GetToolbarInfo(out ToolbarInfo: TTBXToolbarInfo);
  2329. begin
  2330. FillChar(ToolbarInfo, SizeOf(ToolbarInfo), 0);
  2331. ToolbarInfo.WindowHandle := Handle;
  2332. ToolbarInfo.ViewType := GetWinViewType(Self);
  2333. if CurrentDock <> nil then
  2334. ToolbarInfo.IsVertical := CurrentDock.Position in [dpLeft,dpRight];
  2335. ToolbarInfo.AllowDrag := CurrentDock.AllowDrag;
  2336. ToolbarInfo.DragHandleStyle := Ord(DragHandleStyle);
  2337. ToolbarInfo.ClientWidth := ClientWidth;
  2338. ToolbarInfo.ClientHeight := ClientHeight;
  2339. if ToolbarInfo.AllowDrag and CloseButtonWhenDocked then
  2340. begin
  2341. ToolbarInfo.CloseButtonState := CDBS_VISIBLE;
  2342. if CloseButtonDown then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_PRESSED
  2343. else if CloseButtonHover then ToolbarInfo.CloseButtonState := ToolbarInfo.CloseButtonState or CDBS_HOT;
  2344. end;
  2345. ToolbarInfo.BorderStyle := BorderStyle;
  2346. CurrentTheme.GetViewBorder(Self, ToolbarInfo.ViewType, ToolbarInfo.BorderSize);
  2347. ToolbarInfo.EffectiveColor := EffectiveColor;
  2348. end;
  2349. function TTBXToolbar.GetViewClass: TTBToolbarViewClass;
  2350. begin
  2351. Result := TTBXToolbarView;
  2352. end;
  2353. procedure TTBXToolbar.SetItemTransparency(const Value: TTBXItemTransparency);
  2354. begin
  2355. FItemTransparency := Value;
  2356. Invalidate;
  2357. end;
  2358. procedure TTBXToolbar.Loaded;
  2359. begin
  2360. inherited;
  2361. UpdateEffectiveColor;
  2362. end;
  2363. procedure TTBXToolbar.SetParent(AParent: TWinControl);
  2364. begin
  2365. inherited;
  2366. if AParent is TTBXFloatingWindowParent then
  2367. TTBXFloatingWindowParent(AParent).SnapDistance := SnapDistance;
  2368. end;
  2369. procedure TTBXToolbar.SetSnapDistance(Value: Integer);
  2370. begin
  2371. if Value < 0 then Value := 0;
  2372. FSnapDistance := Value;
  2373. if (Parent <> nil) and (Parent is TTBXFloatingWindowParent) then
  2374. TTBXFloatingWindowParent(Parent).SnapDistance := Value;
  2375. end;
  2376. procedure TTBXToolbar.TBMGetEffectiveColor(var Message: TMessage);
  2377. begin
  2378. Message.WParam := EffectiveColor;
  2379. Message.Result := 1;
  2380. end;
  2381. procedure TTBXToolbar.TBMGetViewType(var Message: TMessage);
  2382. begin
  2383. if MenuBar then Message.Result := TVT_MENUBAR
  2384. else Message.Result := TVT_NORMALTOOLBAR;
  2385. if Floating then Message.Result := Message.Result or TVT_FLOATING;
  2386. if Resizable then Message.Result := Message.Result or TVT_RESIZABLE;
  2387. case ItemTransparency of
  2388. itAuto:
  2389. if not (Floating or Docked) then Message.Result := Message.Result or TVT_EMBEDDED;
  2390. itDisable:
  2391. Message.Result := Message.Result or TVT_EMBEDDED;
  2392. end;
  2393. end;
  2394. procedure TTBXToolbar.Rebuild;
  2395. begin
  2396. if Floating then UpdateNCArea(TTBXFloatingWindowParent(Parent), GetWinViewType(Self))
  2397. else UpdateNCArea(Self, GetWinViewType(Self));
  2398. Invalidate;
  2399. Arrange;
  2400. end;
  2401. procedure TTBXToolbar.TBMThemeChange(var Message: TMessage);
  2402. begin
  2403. case Message.WParam of
  2404. TSC_BEFOREVIEWCHANGE: BeginUpdate;
  2405. TSC_AFTERVIEWCHANGE:
  2406. begin
  2407. EndUpdate;
  2408. UpdateEffectiveColor;
  2409. Rebuild;
  2410. UpdateChildColors;
  2411. end;
  2412. TSC_APPACTIVATE, TSC_APPDEACTIVATE:
  2413. if MenuBar then Invalidate;
  2414. end;
  2415. end;
  2416. procedure TTBXToolbar.WMDpiChangedBeforeParent(var Message: TMessage);
  2417. begin
  2418. BeginUpdate;
  2419. end;
  2420. procedure TTBXToolbar.WMDpiChangedAfterParent(var Message: TMessage);
  2421. begin
  2422. EndUpdate;
  2423. Rebuild;
  2424. end;
  2425. procedure TTBXToolbar.UpdateChildColors;
  2426. var
  2427. M: TMessage;
  2428. begin
  2429. M.Msg := CM_PARENTCOLORCHANGED;
  2430. M.WParam := 1;
  2431. M.LParam := EffectiveColor;
  2432. M.Result := 0;
  2433. Broadcast(M);
  2434. end;
  2435. procedure TTBXToolbar.UpdateEffectiveColor;
  2436. begin
  2437. if Color = clNone then
  2438. begin
  2439. if Embedded and (Parent <> nil) then
  2440. FEffectiveColor := GetEffectiveColor(Parent)
  2441. else
  2442. FEffectiveColor := CurrentTheme.GetViewColor(GetViewType(View));
  2443. end
  2444. else FEffectiveColor := Color;
  2445. end;
  2446. procedure TTBXToolbar.WMEraseBkgnd(var Message: TWmEraseBkgnd);
  2447. var
  2448. Canvas: TCanvas;
  2449. R, CR: TRect;
  2450. Transparent: Boolean;
  2451. begin
  2452. Transparent := False;
  2453. CR := ClientRect;
  2454. if Color = clNone then
  2455. if Embedded then
  2456. begin
  2457. Transparent := True;
  2458. DrawParentBackground(Self, Message.DC, CR);
  2459. end;
  2460. Canvas := TCanvas.Create;
  2461. Canvas.Handle := Message.DC;
  2462. try
  2463. if Docked then
  2464. begin
  2465. R := CurrentDock.ClientRect;
  2466. R.TopLeft := ScreenToClient(CurrentDock.ClientToScreen(R.TopLeft));
  2467. R.BottomRight := ScreenToClient(CurrentDock.ClientToScreen(R.BottomRight));
  2468. end
  2469. else R := Rect(0, 0, 0, 0);
  2470. CurrentTheme.PaintBackgnd(Canvas, R, CR, CR, EffectiveColor, Transparent, GetWinViewType(Self));
  2471. Message.Result := 1;
  2472. finally
  2473. Canvas.Handle := 0;
  2474. Canvas.Free;
  2475. end;
  2476. end;
  2477. //============================================================================//
  2478. { TTBXChevronItem }
  2479. function TTBXChevronItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  2480. begin
  2481. Result := TTBXChevronItemViewer;
  2482. end;
  2483. procedure TTBXChevronItem.GetPopupPosition(ParentView: TTBView;
  2484. PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec);
  2485. begin
  2486. if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do
  2487. begin
  2488. GetOfficeXPPopupPosition1(PopupPositionRec);
  2489. inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec);
  2490. GetOfficeXPPopupPosition2(PopupPositionRec);
  2491. end
  2492. else inherited;
  2493. end;
  2494. function TTBXChevronItem.GetPopupWindowClass: TTBPopupWindowClass;
  2495. begin
  2496. Result := TTBXChevronPopupWindow;
  2497. end;
  2498. //============================================================================//
  2499. { TTBXChevronItemViewer }
  2500. procedure TTBXChevronItemViewer.Paint(const Canvas: TCanvas;
  2501. const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean);
  2502. const
  2503. CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING);
  2504. var
  2505. ItemInfo: TTBXItemInfo;
  2506. begin
  2507. FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0);
  2508. ItemInfo.ViewType := GetViewType(View);
  2509. ItemInfo.ItemOptions := IO_TOOLBARSTYLE or CDesigning[csDesigning in Item.ComponentState];
  2510. ItemInfo.Enabled := Item.Enabled or View.Customizing;
  2511. ItemInfo.Pushed := IsPushed;
  2512. ItemInfo.Selected := False;
  2513. ItemInfo.ImageShown := False;
  2514. ItemInfo.ImageWidth := 0;
  2515. ItemInfo.ImageHeight := 0;
  2516. ItemInfo.IsPopupParent := IsPushed;
  2517. if IsHoverItem then
  2518. begin
  2519. if not ItemInfo.Enabled and not TTBViewAccess(View).MouseOverSelected then ItemInfo.HoverKind := hkKeyboardHover
  2520. else if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover;
  2521. end
  2522. else ItemInfo.HoverKind := hkNone;
  2523. ItemInfo.IsVertical := View.Orientation = tbvoVertical;
  2524. CurrentTheme.PaintChevron(Canvas, ClientAreaRect, ItemInfo);
  2525. end;
  2526. function TTBXChevronItemViewer.CaptionShown: Boolean;
  2527. begin
  2528. Result := False;
  2529. end;
  2530. //============================================================================//
  2531. { TTBXRootItem }
  2532. function TTBXRootItem.CreatePopupEx(SelectFirstItem: Boolean;
  2533. const AControlRect: TRect; Alignment: TTBPopupAlignment): TTBPopupWindow;
  2534. var
  2535. SavePopupRect: TRect;
  2536. Pt: TPoint;
  2537. begin
  2538. SavePopupRect := FPopupControlRect;
  2539. try
  2540. FPopupControlRect := AControlRect;
  2541. Pt.X := AControlRect.Left;
  2542. Pt.Y := AControlRect.Bottom;
  2543. Result := inherited CreatePopup(nil, nil, False, SelectFirstItem, False, Pt, Alignment);
  2544. if Result is TTBXPopupWindow then TTBXPopupWindow(Result).FControlRect := FPopupControlRect;
  2545. finally
  2546. FPopupControlRect := SavePopupRect;
  2547. end;
  2548. end;
  2549. procedure TTBXRootItem.GetPopupPosition(ParentView: TTBView;
  2550. PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec);
  2551. var
  2552. Y2: Integer;
  2553. VT: Integer;
  2554. begin
  2555. if IsRectEmpty(FPopupControlRect) then inherited
  2556. else with PopupPositionRec do
  2557. begin
  2558. ParentItemRect := FPopupControlRect;
  2559. if Y + H > MonitorRect.Bottom then
  2560. begin
  2561. Y2 := FPopupControlRect.Top - H;
  2562. if Y2 >= MonitorRect.Top then Y := Y2;
  2563. end;
  2564. if Y < MonitorRect.Top then Y := MonitorRect.Top
  2565. else if Y + H > MonitorRect.Bottom then Y := MonitorRect.Bottom - H;
  2566. if Alignment = tbpaRight then X := FPopupControlRect.Right - W;
  2567. if X + W > MonitorRect.Right then X := MonitorRect.Right - W;
  2568. if X < MonitorRect.Left then X := MonitorRect.Left;
  2569. end;
  2570. if CurrentTheme.OfficeXPPopupAlignment then with PopupPositionRec do
  2571. begin
  2572. GetOfficeXPPopupPosition1(PopupPositionRec);
  2573. inherited GetPopupPosition(ParentView, PopupWindow, PopupPositionRec);
  2574. GetOfficeXPPopupPosition2(PopupPositionRec);
  2575. VT := GetWinViewType(PopupWindow);
  2576. PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX);
  2577. end
  2578. else inherited;
  2579. end;
  2580. function TTBXRootItem.GetPopupWindowClass: TTBPopupWindowClass;
  2581. begin
  2582. Result := TTBXPopupWindow;
  2583. end;
  2584. function TTBXRootItem.OpenPopupEx(const SelectFirstItem, TrackRightButton: Boolean;
  2585. const ControlRect: TRect; const Alignment: TTBPopupAlignment;
  2586. const ReturnClickedItemOnly: Boolean): TTBCustomItem;
  2587. var
  2588. ModalHandler: TTBModalHandler;
  2589. Popup: TTBPopupWindow;
  2590. DoneActionData: TTBDoneActionData;
  2591. State: TTBViewState;
  2592. {MP}
  2593. I: Integer;
  2594. MinWidth: Integer;
  2595. Border: TPoint;
  2596. Control: TControl;
  2597. begin
  2598. ModalHandler := TTBModalHandler.Create(0);
  2599. try
  2600. {MP BEGIN}
  2601. // Make sure menu is not narrower than its popup control (button)
  2602. if not IsRectEmpty(ControlRect) then
  2603. begin
  2604. // see TTBPopupView.AutoSize and TTBXPopupWindow.GetNCSize
  2605. Control := FindVCLWindow(Point(ControlRect.Left, ControlRect.Top));
  2606. CurrentTheme.GetViewBorder(Control, PVT_POPUPMENU, Border);
  2607. MinWidth := ControlRect.Width - (2*Border.X);
  2608. for I := 0 to Count - 1 do
  2609. begin
  2610. if Items[I] is TTBXCustomItem then
  2611. if TTBXCustomItem(Items[I]).MinWidth < MinWidth then
  2612. TTBXCustomItem(Items[I]).MinWidth := MinWidth;
  2613. end
  2614. end;
  2615. {MP END}
  2616. Popup := CreatePopupEx(SelectFirstItem, ControlRect, Alignment);
  2617. try
  2618. State := Popup.View.State;
  2619. Include(State, vsIgnoreFirstMouseUp);
  2620. TTBViewAccess(Popup.View).SetState(State);
  2621. ModalHandler.Loop(Popup.View, False, False, False, TrackRightButton);
  2622. DoneActionData := TTBViewAccess(Popup.View).DoneActionData;
  2623. finally
  2624. { Remove vsModal state from the root view before any TTBView.Destroy
  2625. methods get called, so that NotifyFocusEvent becomes a no-op }
  2626. State := Popup.View.State;
  2627. Exclude(State, vsModal);
  2628. TTBViewAccess(Popup.View).SetState(State);
  2629. Popup.Free;
  2630. end;
  2631. finally
  2632. ModalHandler.Free;
  2633. end;
  2634. Result := ProcessDoneAction(DoneActionData, ReturnClickedItemOnly);
  2635. end;
  2636. function TTBXRootItem.PopupEx(const ControlRect: TRect;
  2637. TrackRightButton: Boolean; Alignment: TTBPopupAlignment = tbpaLeft;
  2638. ReturnClickedItemOnly: Boolean = False): TTBCustomItem;
  2639. begin
  2640. Result := OpenPopupEx(False, TrackRightButton, ControlRect,
  2641. Alignment, ReturnClickedItemOnly);
  2642. end;
  2643. //============================================================================//
  2644. { TTBXPopupMenu }
  2645. function TTBXPopupMenu.GetRootItemClass: TTBRootItemClass;
  2646. begin
  2647. Result := TTBXRootItem;
  2648. end;
  2649. function TTBXPopupMenu.PopupEx(const ControlRect: TRect;
  2650. ReturnClickedItemOnly: Boolean = False): TTBCustomItem;
  2651. begin
  2652. SetPopupPoint(Point(ControlRect.Left, ControlRect.Bottom));
  2653. Result := TTBXRootItem(Items).PopupEx(ControlRect, TrackButton = tbRightButton,
  2654. TTBPopupAlignment(Alignment), ReturnClickedItemOnly);
  2655. end;
  2656. procedure TTBXPopupMenu.TBMGetViewType(var Message: TMessage);
  2657. begin
  2658. Message.Result := PVT_POPUPMENU;
  2659. end;
  2660. //============================================================================//
  2661. { TTBXFloatingWindowParent }
  2662. procedure TTBXFloatingWindowParent.CancelNCHover;
  2663. begin
  2664. if FCloseButtonHover then
  2665. begin
  2666. FCloseButtonHover := False;
  2667. if HandleAllocated and IsWindowVisible(Handle) then
  2668. DrawNCArea(False, 0, 0, [twrdCloseButton]);
  2669. end;
  2670. end;
  2671. procedure TTBXFloatingWindowParent.CMMouseLeave(var Message: TMessage);
  2672. begin
  2673. inherited;
  2674. CancelNCHover;
  2675. end;
  2676. procedure TTBXFloatingWindowParent.DrawNCArea(const DrawToDC: Boolean;
  2677. const ADC: HDC; const Clip: HRGN; RedrawWhat: TTBToolWindowNCRedrawWhat);
  2678. const
  2679. CDown: array [Boolean] of Integer = (0, CDBS_PRESSED);
  2680. CHover: array [Boolean] of Integer = (0, CDBS_HOT);
  2681. CBord: array [Boolean] of Integer = (0, WRP_BORDER);
  2682. CCapt: array [Boolean] of Integer = (0, WRP_CAPTION);
  2683. CBtn: array [Boolean] of Integer = (0, WRP_CLOSEBTN);
  2684. var
  2685. DC: HDC;
  2686. R: TRect;
  2687. Canvas: TCanvas;
  2688. WindowInfo: TTBXWindowInfo;
  2689. DockWindow: TTBCustomDockableWindowAccess;
  2690. begin
  2691. if not HandleAllocated then Exit;
  2692. if not DrawToDC then DC := GetWindowDC(Handle)
  2693. else DC := ADC;
  2694. try
  2695. if not DrawToDC then SelectNCUpdateRgn(Handle, DC, Clip);
  2696. GetWindowRect(Handle, R);
  2697. OffsetRect(R, -R.Left, -R.Top);
  2698. with R do IntersectClipRect(DC, Left, Top, Right, Bottom);
  2699. Canvas := TCanvas.Create;
  2700. try
  2701. Canvas.Handle := DC;
  2702. GetWindowRect(Handle, R);
  2703. OffsetRect(R, -R.Left, -R.Top);
  2704. DockWindow := TTBCustomDockableWindowAccess(DockableWindow);
  2705. FillChar(WindowInfo, SizeOf(WindowInfo), 0);
  2706. WindowInfo.ParentControl := Self;
  2707. WindowInfo.ParentHandle := Handle;
  2708. WindowInfo.WindowHandle := DockWindow.Handle;
  2709. WindowInfo.ViewType := GetWinViewType(DockWindow);
  2710. WindowInfo.ClientWidth := ClientWidth;
  2711. WindowInfo.ClientHeight := ClientHeight;
  2712. WindowInfo.ShowCaption := DockWindow.ShowCaption;
  2713. WindowInfo.FloatingBorderSize := DockWindow.GetFloatingBorderSize;
  2714. if DockWindow.CloseButton and DockWindow.ShowCaption then
  2715. begin
  2716. WindowInfo.CloseButtonState := CDBS_VISIBLE;
  2717. if CloseButtonDown then WindowInfo.CloseButtonState := WindowInfo.CloseButtonState or CDBS_PRESSED
  2718. else if CloseButtonHover then WindowInfo.CloseButtonState := WindowInfo.CloseButtonState or CDBS_HOT;
  2719. end;
  2720. WindowInfo.RedrawPart :=
  2721. CBord[twrdBorder in RedrawWhat] or
  2722. CCapt[twrdCaption in RedrawWhat] or
  2723. CBtn[twrdCloseButton in RedrawWhat];
  2724. WindowInfo.Caption := PChar(Caption);
  2725. WindowInfo.EffectiveColor := GetEffectiveColor(DockWindow);
  2726. WindowInfo.Active := not DockWindow.InactiveCaption;
  2727. Canvas.Brush.Color := WindowInfo.EffectiveColor;
  2728. CurrentTheme.PaintFloatingBorder(Canvas, R, WindowInfo);
  2729. finally
  2730. Canvas.Handle := 0;
  2731. Canvas.Free;
  2732. end;
  2733. finally
  2734. if not DrawToDC then ReleaseDC(Handle, DC);
  2735. end;
  2736. end;
  2737. procedure TTBXFloatingWindowParent.WMEraseBkgnd(var Message: TMessage);
  2738. begin
  2739. Message.Result := 1;
  2740. end;
  2741. procedure TTBXFloatingWindowParent.WMNCMouseLeave(var Message: TMessage);
  2742. begin
  2743. if not MouseCapture then CancelNCHover;
  2744. inherited;
  2745. end;
  2746. procedure TTBXFloatingWindowParent.WMNCMouseMove(var Message: TWMNCMouseMove);
  2747. var
  2748. InArea: Boolean;
  2749. begin
  2750. inherited;
  2751. { Note: TME_NONCLIENT was introduced in Windows 98 and 2000 }
  2752. CallTrackMouseEvent (Handle, TME_LEAVE or $10 {TME_NONCLIENT});
  2753. InArea := Message.HitTest = 2001; {HT_TB2k_Close}
  2754. if FCloseButtonHover <> InArea then
  2755. begin
  2756. FCloseButtonHover := InArea;
  2757. if HandleAllocated and IsWindowVisible(Handle) then
  2758. DrawNCArea(False, 0, 0, [twrdCloseButton]);
  2759. end;
  2760. end;
  2761. procedure TTBXFloatingWindowParent.WMWindowPosChanging(var Message: TWMWindowPosChanging);
  2762. var
  2763. R: TRect;
  2764. MonInfo: TMonitorInfo;
  2765. begin
  2766. if SnapDistance > 0 then with Message.WindowPos^ do
  2767. begin
  2768. if (cx = Width) and (cy = Height) then
  2769. begin
  2770. MonInfo.cbSize := SizeOf(MonInfo);
  2771. GetMonitorInfo(Monitor.Handle, @MonInfo);
  2772. R := MonInfo.rcWork;
  2773. if Abs(x + Width - R.Right) < SnapDistance then x := R.Right - Width;
  2774. if Abs(y + Height - R.Bottom) < SnapDistance then y := R.Bottom - Height;
  2775. if Abs(x - R.Left) < SnapDistance then x := R.Left;
  2776. if Abs(y - R.Top) < SnapDistance then y := R.Top;
  2777. end;
  2778. end;
  2779. inherited;
  2780. end;
  2781. //============================================================================//
  2782. { Additional system colors }
  2783. type
  2784. TColorEntry = packed record
  2785. ColorPtr: ^TColor;
  2786. Name: string;
  2787. end;
  2788. var
  2789. ColorRegistry: array of TColorEntry;
  2790. procedure AddTBXColor(var AColor: TColor; const AName: string);
  2791. var
  2792. L: Integer;
  2793. begin
  2794. L := Length(ColorRegistry);
  2795. SetLength(ColorRegistry, L + 1);
  2796. with ColorRegistry[L] do
  2797. begin
  2798. ColorPtr := @AColor;
  2799. Name := AName;
  2800. end;
  2801. end;
  2802. function TBXColorToString(Color: TColor): string;
  2803. var
  2804. I: Integer;
  2805. begin
  2806. if not ColorToIdent(Color, Result) then
  2807. begin
  2808. for I := 0 to Length(ColorRegistry) - 1 do
  2809. if ColorRegistry[I].ColorPtr^ = Color then
  2810. begin
  2811. Result := ColorRegistry[I].Name;
  2812. Exit;
  2813. end;
  2814. FmtStr(Result, '%s%.8x', [HexDisplayPrefix, Color]);
  2815. end;
  2816. end;
  2817. function TBXIdentToColor(const Ident: string; var Color: Longint): Boolean;
  2818. var
  2819. I: Integer;
  2820. begin
  2821. for I := 0 to Length(ColorRegistry) - 1 do
  2822. if CompareText(ColorRegistry[I].Name, Ident) = 0 then
  2823. begin
  2824. Color := ColorRegistry[I].ColorPtr^;
  2825. Result := True;
  2826. Exit;
  2827. end;
  2828. Result := IdentToColor(Ident, Color);
  2829. end;
  2830. function TBXStringToColor(S: string): TColor;
  2831. begin
  2832. if not TBXIdentToColor(S, Longint(Result)) then Result := StringToColor(S);
  2833. end;
  2834. procedure TBXGetColorValues(Proc: TGetStrProc);
  2835. var
  2836. I: Integer;
  2837. begin
  2838. GetColorValues(Proc);
  2839. for I := 0 to Length(ColorRegistry) - 1 do Proc(ColorRegistry[I].Name);
  2840. end;
  2841. procedure TBXSetTheme(const AThemeName: string);
  2842. begin
  2843. TBXNexus.SetTheme(AThemeName);
  2844. end;
  2845. function TBXCurrentTheme: string;
  2846. begin
  2847. Result := TBXNexus.GetTheme;
  2848. end;
  2849. //============================================================================//
  2850. { TTBXNexus }
  2851. procedure TTBXNexus.AddNotifie(AObject: TObject);
  2852. begin
  2853. if FNotifies.IndexOf(AObject) < 0 then FNotifies.Add(AObject);
  2854. Exit; asm db 0,'TBX (C) 2001-2003 Alex Denisov',0 end;
  2855. end;
  2856. procedure TTBXNexus.Broadcast(Msg: Cardinal; WParam, LParam: Integer);
  2857. var
  2858. M: TMessage;
  2859. I: Integer;
  2860. begin
  2861. if FNotifies.Count > 0 then
  2862. begin
  2863. M.Msg := Msg;
  2864. M.WParam := WParam;
  2865. M.LParam := LParam;
  2866. M.Result := 0;
  2867. for I := 0 to FNotifies.Count - 1 do TObject(FNotifies[I]).Dispatch(M);
  2868. end;
  2869. end;
  2870. constructor TTBXNexus.Create(const DefaultTheme: string);
  2871. begin
  2872. FNotifies := TList.Create;
  2873. CurrentTheme := GetTBXTheme(DefaultTheme);
  2874. AddTBXSysChangeNotification(Self);
  2875. end;
  2876. destructor TTBXNexus.Destroy;
  2877. begin
  2878. RemoveTBXSysChangeNotification(Self);
  2879. ReleaseTBXTheme(CurrentTheme);
  2880. FNotifies.Free;
  2881. inherited;
  2882. end;
  2883. function TTBXNexus.GetTheme: string;
  2884. begin
  2885. Result := CurrentTheme.Name;
  2886. end;
  2887. procedure TTBXNexus.RemoveNotifie(AObject: TObject);
  2888. begin
  2889. FNotifies.Remove(AObject);
  2890. end;
  2891. procedure TTBXNexus.SetTheme(const AThemeName: string);
  2892. begin
  2893. if IsTBXThemeAvailable(AThemeName) then
  2894. begin
  2895. ReleaseTBXTheme(CurrentTheme);
  2896. CurrentTheme := GetTBXTheme(AThemeName);
  2897. Broadcast(TBM_THEMECHANGE, TSC_BEFOREVIEWCHANGE, 1);
  2898. Broadcast(TBM_THEMECHANGE, TSC_VIEWCHANGE, 1);
  2899. Broadcast(TBM_THEMECHANGE, TSC_AFTERVIEWCHANGE, 1);
  2900. end;
  2901. end;
  2902. procedure TTBXNexus.TBXSysCommand(var Message: TMessage);
  2903. begin
  2904. { Retranslate TBX_SYSCOMMAND to TBM_THEMECHANGE }
  2905. if Message.Msg = TBX_SYSCOMMAND then
  2906. Broadcast(TBM_THEMECHANGE, Message.WParam, 0);
  2907. end;
  2908. { TTBXDock }
  2909. procedure TTBXDock.CMColorChanged(var Message: TMessage);
  2910. var
  2911. I: Integer;
  2912. begin
  2913. inherited;
  2914. for I := 0 to Self.ControlCount - 1 do
  2915. if Controls[I] is TWinControl then
  2916. InvalidateAll(TWinControl(Controls[I]));
  2917. end;
  2918. constructor TTBXDock.Create(AOwner: TComponent);
  2919. begin
  2920. inherited;
  2921. Color := clNone;
  2922. AddThemeNotification(Self);
  2923. end;
  2924. destructor TTBXDock.Destroy;
  2925. begin
  2926. RemoveThemeNotification(Self);
  2927. inherited;
  2928. end;
  2929. procedure TTBXDock.DrawBackground(DC: HDC; const DrawRect: TRect);
  2930. const
  2931. DOCK_POSITIONS: array [TTBDockPosition] of Integer = (DP_TOP, DP_BOTTOM, DP_LEFT, DP_RIGHT);
  2932. var
  2933. Canvas: TCanvas;
  2934. begin
  2935. if UseParentBackground then DrawParentBackground(Self, DC, ClientRect)
  2936. else if ThemedBackground then
  2937. begin
  2938. Canvas := TCanvas.Create;
  2939. Canvas.Handle := DC;
  2940. CurrentTheme.PaintDock(Canvas, ClientRect, DrawRect, DOCK_POSITIONS[Position]);
  2941. Canvas.Handle := 0;
  2942. Canvas.Free;
  2943. end
  2944. else inherited;
  2945. end;
  2946. procedure TTBXDock.Resize;
  2947. var
  2948. I, J: Integer;
  2949. V: TTBItemViewer;
  2950. R: TRect;
  2951. begin
  2952. inherited Resize;
  2953. if UsingBackground then
  2954. begin
  2955. for J := 0 to ToolbarCount - 1 do
  2956. begin
  2957. Invalidate;
  2958. if Toolbars[J] is TTBXToolbar then with TTBXToolbar(Toolbars[J]) do
  2959. begin
  2960. for I := 0 to View.ViewerCount - 1 do
  2961. begin
  2962. V := View.Viewers[I];
  2963. if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem)
  2964. then View.Invalidate(V);
  2965. end;
  2966. Update;
  2967. if HandleAllocated then
  2968. RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASE);
  2969. for I := 0 to View.ViewerCount - 1 do
  2970. begin
  2971. V := View.Viewers[I];
  2972. if V.Show and not IsRectEmpty(V.BoundsRect) and not (V.Item is TTBControlItem)
  2973. then
  2974. begin
  2975. R := V.BoundsRect;
  2976. ValidateRect(Handle, @R);
  2977. end;
  2978. end;
  2979. end
  2980. end;
  2981. end;
  2982. end;
  2983. procedure TTBXDock.SetUseParentBackground(Value: Boolean);
  2984. begin
  2985. if Value <> FUseParentBackground then
  2986. begin
  2987. FUseParentBackground := Value;
  2988. if HandleAllocated then
  2989. RedrawWindow(Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or
  2990. RDW_ERASE or RDW_ALLCHILDREN);
  2991. end;
  2992. end;
  2993. procedure TTBXDock.TBMGetEffectiveColor(var Message: TMessage);
  2994. begin
  2995. if Color <> clNone then Message.WParam := Color
  2996. else if Parent <> nil then Message.WParam := GetEffectiveColor(Parent)
  2997. else Message.WParam := WPARAM(clBtnFace);
  2998. Message.Result := 1;
  2999. end;
  3000. procedure TTBXDock.TBMThemeChange(var Message: TMessage);
  3001. begin
  3002. case Message.WParam of
  3003. TSC_AFTERVIEWCHANGE:
  3004. begin
  3005. Invalidate;
  3006. end;
  3007. end;
  3008. end;
  3009. function TTBXDock.ThemedBackground: Boolean;
  3010. begin
  3011. Result := (Color = clNone) and CurrentTheme.PaintDockBackground;
  3012. end;
  3013. function TTBXDock.UsingBackground: Boolean;
  3014. begin
  3015. Result := UseParentBackground or (ThemedBackground and not FMoving) or
  3016. inherited UsingBackground;
  3017. end;
  3018. procedure TTBXDock.WMEraseBkgnd(var Message: TWMEraseBkgnd);
  3019. var
  3020. R: TRect;
  3021. C: TColor;
  3022. begin
  3023. R := Self.ClientRect;
  3024. if UsingBackground then
  3025. begin
  3026. DrawBackground(Message.DC, R);
  3027. Message.Result := 1;
  3028. end
  3029. else
  3030. begin
  3031. C := Color;
  3032. if C = clNone then C := GetEffectiveColor(Parent);
  3033. FillRectEx(Message.DC, R, C);
  3034. Message.Result := 1;
  3035. end;
  3036. end;
  3037. procedure TTBXDock.WMMove(var Message: TWMMove);
  3038. begin
  3039. FMoving := True;
  3040. inherited;
  3041. FMoving := False;
  3042. end;
  3043. procedure TTBXDock.WMSize(var Message: TWMSize);
  3044. begin
  3045. FResizing := True;
  3046. inherited;
  3047. FResizing := False;
  3048. end;
  3049. { TTBXMenuAnimation }
  3050. constructor TTBXMenuAnimation.Create(AAnimationMode: TAnimationMode = amSysDefault);
  3051. begin
  3052. AnimationMode := AAnimationMode;
  3053. end;
  3054. function TTBXMenuAnimation.GetAvailableModes: TAnimationModes;
  3055. begin
  3056. Result := [amNone, amSysDefault, amRandom, amUnfold, amSlide, amFade];
  3057. end;
  3058. function TTBXMenuAnimation.GetMenuAnimation: TMenuAnimation;
  3059. function GetSysDefault: TMenuAnimation;
  3060. const
  3061. SPI_GETMENUFADE = $1012;
  3062. SysDefAni: array[Boolean] of TMenuAnimation = (maSlide, maFade);
  3063. begin
  3064. if SysParamEnabled(SPI_GETMENUANIMATION)
  3065. then Result := SysDefAni[SysParamEnabled(SPI_GETMENUFADE)]
  3066. else Result := maNone;
  3067. end;
  3068. function GetRandom: TMenuAnimation;
  3069. var Max: Integer;
  3070. begin
  3071. Max := Ord(High(TMenuAnimation));
  3072. if not (amFade in AvailableModes) then
  3073. Dec(Max);
  3074. Result := Succ(TMenuAnimation(Random(Max)));
  3075. end;
  3076. begin
  3077. case AnimationMode of
  3078. amSysDefault: Result := GetSysDefault;
  3079. amRandom: Result := GetRandom;
  3080. amUnfold: Result := maUnfold;
  3081. amSlide: Result := maSlide;
  3082. amFade: Result := maFade;
  3083. else
  3084. Result := maNone;
  3085. end;
  3086. end;
  3087. procedure TTBXMenuAnimation.SetAnimationMode(Value: TAnimationMode);
  3088. var AvailModes: TAnimationModes;
  3089. begin
  3090. AvailModes := AvailableModes;
  3091. while not (Value in AvailModes) do
  3092. Value := Pred(Value);
  3093. FAnimationMode := Value;
  3094. end;
  3095. function TTBXMenuAnimation.SysParamEnabled(Param: Cardinal): Boolean;
  3096. var B: BOOL;
  3097. begin
  3098. Result := SystemParametersInfo(Param, 0, @B, 0) and B;
  3099. end;
  3100. { Work around delayed menu showing in Windows 2000+ }
  3101. var
  3102. FixPlaySoundThreadHandle: Cardinal;
  3103. function FixPlaySoundThreadFunc(Param: Pointer): Integer; stdcall;
  3104. begin
  3105. Sleep(250);
  3106. PlaySound(nil, 0, 0);
  3107. CloseHandle(FixPlaySoundThreadHandle); { Harakiri :~| }
  3108. Result := $4E494150; { :) }
  3109. end;
  3110. procedure FixPlaySoundDelay;
  3111. var ThreadId: TThreadID;
  3112. begin
  3113. if (FixPlaySoundThreadHandle = 0) then
  3114. FixPlaySoundThreadHandle := CreateThread(nil, $1000,
  3115. @FixPlaySoundThreadFunc, nil, 0, ThreadId);
  3116. end;
  3117. function CreateTBXPopupMenu(Owner: TComponent): TTBXPopupMenu;
  3118. begin
  3119. Result := TTBXPopupMenu.Create(Owner);
  3120. end;
  3121. initialization
  3122. FixPlaySoundDelay;
  3123. RegisterTBXTheme('OfficeXP', TTBXOfficeXPTheme);
  3124. TBXNexus := TTBXNexus.Create('OfficeXP');
  3125. TBXMenuAnimation := TTBXMenuAnimation.Create;
  3126. finalization
  3127. TBXNexus.Free;
  3128. FreeAndNil(TBXMenuAnimation);
  3129. ColorRegistry := nil;
  3130. end.