TBXExtItems.pas 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557
  1. {MP}
  2. unit TBXExtItems;
  3. // TBX Package
  4. // Copyright 2001-2004 Alex A. Denisov. All Rights Reserved
  5. // See TBX.chm for license and installation instructions
  6. //
  7. // Id: TBXExtItems.pas 16 2004-05-26 02:02:55Z Alex@ZEISS
  8. interface
  9. {$I TB2Ver.inc}
  10. {$I TBX.inc}
  11. {$IFNDEF MPEXCLUDE}
  12. {$DEFINE COMPATIBLE}
  13. {$ENDIF}
  14. uses
  15. Windows, Messages, Classes, SysUtils, Graphics, Controls, StdCtrls, ExtCtrls,
  16. TBX, TBXThemes, TB2Item, TB2Toolbar, TB2ExtItems, TBXLists{$IFNDEF MPEXCLUDE}, TB2MRU{$ENDIF};
  17. const
  18. tcrNumericProperty = 3;
  19. tcrSpinButton = 4;
  20. tcrList = 5;
  21. type
  22. TTBXEditItemViewer = class;
  23. TTBXEditChange = procedure(Sender: TObject; const Text: string) of object;
  24. { TTBXEditItem }
  25. { Extends standard TTBEditItem, providing additional features and some
  26. combo box functionality, which is used in descendants }
  27. TTBXEditItem = class(TTBEditItem)
  28. private
  29. FAlignment: TAlignment;
  30. FAutoCompleteCounter: Integer;
  31. FEditorFontSettings: TFontSettings;
  32. FFontSettings: TFontSettings;
  33. FIsChanging: Boolean;
  34. FLastEditChange: string;
  35. FPasswordChar: Char;
  36. FReadOnly: Boolean;
  37. FShowImage: Boolean;
  38. FOnChange: TTBXEditChange;
  39. procedure FontSettingsChanged(Sender: TObject);
  40. procedure SetAlignment(Value: TAlignment);
  41. procedure SetPasswordChar(Value: Char);
  42. procedure SetShowImage(const Value: Boolean);
  43. procedure SetFontSettings(Value: TFontSettings);
  44. protected
  45. function DoAcceptText(var NewText: string): Boolean; override;
  46. function DoAutoComplete(var AText: string): Boolean; virtual;
  47. procedure DoBeginEdit(Viewer: TTBEditItemViewer); override;
  48. procedure DoChange(const AText: string); virtual;
  49. procedure DoTextChanged(Reason: Integer); override;
  50. function GetImageIndex: Integer; virtual;
  51. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  52. procedure GetPopupPosition(ParentView: TTBView; PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec); override;
  53. function GetPopupWindowClass: TTBPopupWindowClass; override;
  54. procedure HandleEditChange(Edit: TEdit); virtual;
  55. public
  56. function StartEditing(AView: TTBView): Boolean;
  57. constructor Create(AOwner: TComponent); override;
  58. destructor Destroy; override;
  59. published
  60. property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
  61. property EditorFontSettings: TFontSettings read FEditorFontSettings write FEditorFontSettings;
  62. property ExtendedAccept;
  63. property FontSettings: TFontSettings read FFontSettings write SetFontSettings;
  64. property ImageIndex;
  65. property Images;
  66. property PasswordChar: Char read FPasswordChar write SetPasswordChar default #0;
  67. property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
  68. property ShowImage: Boolean read FShowImage write SetShowImage default False;
  69. property OnChange: TTBXEditChange read FOnChange write FOnChange;
  70. property OnSelect;
  71. end;
  72. TTBXEditItemViewer = class(TTBEditItemViewer)
  73. private
  74. procedure EditChangeHandler(Sender: TObject);
  75. function MeasureEditCaption: TSize;
  76. function MeasureTextHeight: Integer;
  77. procedure HandleEditChange(Edit: TEdit);
  78. protected
  79. OldWndProc: TWndMethod;
  80. procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override;
  81. function DoExecute: Boolean; override;
  82. function HandleEditMessage(var Message: TMessage): Boolean; virtual;
  83. function GetAccRole: Integer; override;
  84. procedure GetItemInfo(out ItemInfo: TTBXItemInfo; IsHoverItem, IsPushed, UseMenuColor: Boolean); virtual;
  85. function GetEditControlClass: TEditClass; override;
  86. procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); virtual;
  87. function GetIndentBefore: Integer; virtual;
  88. function GetIndentAfter: Integer; virtual;
  89. procedure GetEditRect(var R: TRect); override;
  90. function IsToolbarSize: Boolean; override;
  91. procedure NewEditWndProc(var Message: TMessage);
  92. procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override;
  93. function ShowImage: Boolean; virtual;
  94. {MP}
  95. function StripTextHotkey: Boolean; virtual;
  96. public
  97. function IsToolbarStyle: Boolean; override;
  98. end;
  99. {$IFNDEF MPEXCLUDE}
  100. { TTBXSpinEditItem }
  101. TTBXCustomSpinEditItem = class;
  102. TSEValueType = (evtInteger, evtFloat, evtHex);
  103. TDecimal = 0..10;
  104. TSEChangeEvent = procedure(Sender: TTBXCustomSpinEditItem; const AValue: Extended) of object;
  105. TSEConvertEvent = procedure(Sender: TTBXCustomSpinEditItem; const APrefix, APostfix: string; var AValue: Extended; var CanConvert: Boolean) of object;
  106. TSEStepEvent = procedure(Sender: TTBXCustomSpinEditItem; Step: Integer; const OldValue: Extended; var NewValue: Extended) of object;
  107. TSETextToValueEvent = procedure(Sender: TTBXCustomSpinEditItem; const AText: string; out AValue: Extended; var CanConvert: Boolean) of object;
  108. TSEValueToTextEvent = procedure(Sender: TTBXCustomSpinEditItem; const AValue: Extended; var Text: string) of object;
  109. TTBXCustomSpinEditItem = class(TTBXEditItem)
  110. private
  111. FDecimal: TDecimal;
  112. FLastGoodValue: Extended;
  113. FMaxValue: Extended;
  114. FMinValue: Extended;
  115. FIncrement: Extended;
  116. FSpaceBeforePostfix: Boolean;
  117. FSpaceAfterPrefix: Boolean;
  118. FPostfix: string;
  119. FPrefix: string;
  120. FSnap: Boolean;
  121. FValueType: TSEValueType;
  122. FOnConvert: TSEConvertEvent;
  123. FOnTextToValue: TSETextToValueEvent;
  124. FOnValueChange: TSEChangeEvent;
  125. FOnValueToText: TSEValueToTextEvent;
  126. FOnStep: TSEStepEvent;
  127. function IsIncrementStored: Boolean;
  128. function IsMinValueStored: Boolean;
  129. function IsMaxValueStored: Boolean;
  130. function IsValueStored: Boolean;
  131. function GetValue: Extended;
  132. procedure SetValue(NewValue: Extended);
  133. procedure SetValueType(NewType: TSEValueType);
  134. procedure SetDecimal(NewDecimal: TDecimal);
  135. procedure SetIncrement(const NewIncrement: Extended);
  136. procedure SetPostfix(const NewPostfix: string);
  137. procedure SetPrefix(const NewPrefix: string);
  138. procedure SetSpaceAfterPrefix(UseSpace: Boolean);
  139. procedure SetSpaceBeforePostfix(UseSpace: Boolean);
  140. function ValidateUnits(const S: string): Boolean;
  141. function GetAsInteger: Integer;
  142. procedure SetAsInteger(AValue: Integer);
  143. protected
  144. function CheckValue(const V: Extended): Extended;
  145. procedure ClickUp;
  146. procedure ClickDown;
  147. function DoAcceptText(var NewText: string): Boolean; override;
  148. function DoConvert(const APrefix, APostfix: string; var AValue: Extended): Boolean; virtual;
  149. procedure DoStep(Step: Integer; const OldValue: Extended; var NewValue: Extended); virtual;
  150. procedure DoTextChanged(Reason: Integer); override;
  151. function DoTextToValue(const AText: string; out AValue: Extended): Boolean; virtual;
  152. procedure DoValueChange(const V: Extended); virtual;
  153. procedure DoValueToText(const NewValue: Extended; var NewText: string); virtual;
  154. function GetAsText(AValue: Extended): string;
  155. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  156. function ParseValue(const S: string; out V: Extended): Boolean;
  157. procedure SetValueEx(NewValue: Extended; Reason: Integer);
  158. property Alignment default taRightJustify;
  159. property OnConvert: TSEConvertEvent read FOnConvert write FOnConvert;
  160. property OnStep: TSEStepEvent read FOnStep write FOnStep;
  161. property OnTextToValue: TSETextToValueEvent read FOnTextToValue write FOnTextToValue;
  162. property OnValueChange: TSEChangeEvent read FOnValueChange write FOnValueChange;
  163. property OnValueToText: TSEValueToTextEvent read FOnValueToText write FOnValueToText;
  164. public
  165. constructor Create(AOwner: TComponent); override;
  166. property ValueType: TSEValueType read FValueType write SetValueType default evtInteger;
  167. property AsInteger: Integer read GetAsInteger write SetAsInteger stored False;
  168. property Decimal: TDecimal read FDecimal write SetDecimal default 2;
  169. property Increment: Extended read FIncrement write SetIncrement stored IsIncrementStored;
  170. property MaxValue: Extended read FMaxValue write FMaxValue stored IsMaxValueStored;
  171. property MinValue: Extended read FMinValue write FMinValue stored IsMinValueStored;
  172. property Postfix: string read FPostfix write SetPostfix;
  173. property Prefix: string read FPrefix write SetPrefix;
  174. property Snap: Boolean read FSnap write FSnap default True;
  175. property SpaceAfterPrefix: Boolean read FSpaceAfterPrefix write SetSpaceAfterPrefix;
  176. property SpaceBeforePostfix: Boolean read FSpaceBeforePostfix write SetSpaceBeforePostfix;
  177. property Value: Extended read GetValue write SetValue stored IsValueStored;
  178. published
  179. property Text stored False;
  180. end;
  181. TTBXSpinEditItem = class(TTBXCustomSpinEditItem)
  182. published
  183. property ValueType;
  184. property Alignment;
  185. property Decimal;
  186. property Increment;
  187. property MaxValue;
  188. property MinValue;
  189. property Postfix;
  190. property Prefix;
  191. property Snap;
  192. property SpaceAfterPrefix;
  193. property SpaceBeforePostfix;
  194. property Value;
  195. property OnConvert;
  196. property OnStep;
  197. property OnTextToValue;
  198. property OnValueChange;
  199. property OnValueToText;
  200. end;
  201. TSEBtnState = (ebsNone, ebsUp, ebsDown);
  202. TTBXSpinEditViewer = class(TTBXEditItemViewer)
  203. private
  204. FBtnState: TSEBtnState;
  205. FBtnTimer: TTimer;
  206. procedure TimerHandler(Sender: TObject);
  207. protected
  208. function GetIndentAfter: Integer; override;
  209. procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); override;
  210. function HandleEditMessage(var Message: TMessage): Boolean; override;
  211. procedure InvalidateButtons;
  212. function IsPtInButtonPart(X, Y: Integer): Boolean; override;
  213. procedure LosingCapture; override;
  214. procedure MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean); override;
  215. procedure MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean); override;
  216. public
  217. destructor Destroy; override;
  218. end;
  219. {$ENDIF}
  220. { TTBXCustomDropDownItem }
  221. { An extended edit item tb2k with a button. The dropdown list support is
  222. implemented in descendants, such as TTBXComboBoxItem }
  223. TTBXCustomDropDownItem = class(TTBXEditItem)
  224. private
  225. FAlwaysSelectFirst: Boolean;
  226. FDropDownList: Boolean;
  227. {MP}
  228. FOnCancel: TNotifyEvent;
  229. protected
  230. function CreatePopup(const ParentView: TTBView; const ParentViewer: TTBItemViewer;
  231. const PositionAsSubmenu, SelectFirstItem, Customizing: Boolean;
  232. const APopupPoint: TPoint; const Alignment: TTBPopupAlignment): TTBPopupWindow; override;
  233. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  234. function GetPopupWindowClass: TTBPopupWindowClass; override;
  235. procedure DoCancel;
  236. public
  237. constructor Create(AOwner: TComponent); override;
  238. property AlwaysSelectFirst: Boolean read FAlwaysSelectFirst write FAlwaysSelectFirst default True;
  239. property DropDownList: Boolean read FDropDownList write FDropDownList default False;
  240. {MP}
  241. property OnCancel: TNotifyEvent read FOnCancel write FOnCancel;
  242. end;
  243. TTBXDropDownItem = class(TTBXCustomDropDownItem)
  244. published
  245. property AlwaysSelectFirst;
  246. property DropDownList;
  247. property LinkSubitems;
  248. property SubMenuImages;
  249. end;
  250. TTBXDropDownItemViewer = class(TTBXEditItemViewer)
  251. protected
  252. procedure GetCursor(const Pt: TPoint; var ACursor: HCURSOR); override;
  253. procedure GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo); override;
  254. function GetIndentAfter: Integer; override;
  255. function HandleEditMessage(var Message: TMessage): Boolean; override;
  256. function IsPtInButtonPart(X, Y: Integer): Boolean; override;
  257. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  258. end;
  259. {$IFDEF COMPATIBLE}
  260. { For compatibility with previous versions }
  261. TTBXComboItem = class(TTBXDropDownItem);
  262. {$ENDIF}
  263. { TTBXComboBoxItem }
  264. { A combination of dropdown combo with a stringlist subitem }
  265. TTBXComboBoxItem = class;
  266. TTBXCAdjustImageIndex = procedure(Sender: TTBXComboBoxItem; const AText: string;
  267. AIndex: Integer; var ImageIndex: Integer) of object;
  268. TTBXComboBoxItem = class(TTBXCustomDropDownItem)
  269. private
  270. FAutoComplete: Boolean;
  271. FList: TTBXStringList;
  272. FOnItemClick: TNotifyEvent;
  273. FOnAdjustImageIndex: TTBXCAdjustImageIndex;
  274. procedure AdjustImageIndexHandler(Sender: TTBXCustomList; AItemIndex: Integer; var ImageIndex: Integer);
  275. function GetItemIndex: Integer;
  276. function GetMaxVisibleItems: Integer;
  277. function GetMaxWidth: Integer;
  278. function GetMinWidth: Integer;
  279. function GetStrings: TStrings;
  280. function GetShowListImages: Boolean;
  281. function GetOnClearItem: TTBXLPaintEvent;
  282. function GetOnDrawItem: TTBXLPaintEvent;
  283. function GetOnMeasureHeight: TTBXLMeasureHeight;
  284. function GetOnMeasureWidth: TTBXLMeasureWidth;
  285. procedure ListChangeHandler(Sender: TObject);
  286. procedure ListClickHandler(Sender: TObject);
  287. procedure SetItemIndex(Value: Integer);
  288. procedure SetMaxVisibleItems(Value: Integer);
  289. procedure SetMaxWidth(Value: Integer);
  290. procedure SetMinWidth(Value: Integer);
  291. procedure SetOnClearItem(Value: TTBXLPaintEvent);
  292. procedure SetOnDrawItem(Value: TTBXLPaintEvent);
  293. procedure SetOnMeasureHeight(Value: TTBXLMeasureHeight);
  294. procedure SetOnMeasureWidth(Value: TTBXLMeasureWidth);
  295. procedure SetStrings(Value: TStrings);
  296. procedure SetShowListImages(Value: Boolean);
  297. protected
  298. CachedImageIndex: Integer;
  299. CacheValid: Boolean;
  300. IsChanging: Boolean;
  301. procedure AdjustImageIndex(const AText: string; AIndex: Integer; var ImageIndex: Integer); virtual;
  302. function DoAutoComplete(var AText: string): Boolean; override;
  303. procedure DoListChange; virtual;
  304. procedure DoListClick; virtual;
  305. procedure DoPopup(Sender: TTBCustomItem; FromLink: Boolean); override;
  306. function GetImageIndex: Integer; override;
  307. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  308. function GetStringListClass: TTBXStringListClass; virtual;
  309. procedure HandleEditChange(Edit: TEdit); override;
  310. public
  311. constructor Create(AOwner: TComponent); override;
  312. procedure Loaded; override;
  313. property ItemIndex: Integer read GetItemIndex write SetItemIndex default -1;
  314. published
  315. property AutoComplete: Boolean read FAutoComplete write FAutoComplete default True;
  316. property DropDownList;
  317. property MaxListWidth: Integer read GetMaxWidth write SetMaxWidth default 0;
  318. property MaxVisibleItems: Integer read GetMaxVisibleItems write SetMaxVisibleItems default 8;
  319. property MinListWidth: Integer read GetMinWidth write SetMinWidth default 64;
  320. property ShowListImages: Boolean read GetShowListImages write SetShowListImages default False;
  321. property Strings: TStrings read GetStrings write SetStrings;
  322. property SubMenuImages;
  323. property OnChange;
  324. property OnAdjustImageIndex: TTBXCAdjustImageIndex read FOnAdjustImageIndex write FOnAdjustImageIndex;
  325. property OnClearItem: TTBXLPaintEvent read GetOnClearItem write SetOnClearItem;
  326. property OnDrawItem: TTBXLPaintEvent read GetOnDrawItem write SetOnDrawItem;
  327. property OnItemClick: TNotifyEvent read FOnItemClick write FOnItemClick;
  328. property OnMeasureHeight: TTBXLMeasureHeight read GetOnMeasureHeight write SetOnMeasureHeight;
  329. property OnMeasureWidth: TTBXLMeasureWidth read GetOnMeasureWidth write SetOnMeasureWidth;
  330. property OnPopup;
  331. {MP}
  332. property OnCancel;
  333. end;
  334. {$IFDEF COMPATIBLE}
  335. { For compatibility with previous versions }
  336. TTBXComboList = class(TTBXComboBoxItem);
  337. {$ENDIF}
  338. TTBXComboBoxItemViewer = class(TTBXDropDownItemViewer)
  339. protected
  340. function HandleEditMessage(var Message: TMessage): Boolean; override;
  341. {MP}
  342. function StripTextHotkey: Boolean; override;
  343. end;
  344. { TTBXLabelItem }
  345. TTBXLabelOrientation = (tbxoAuto, tbxoHorizontal, tbxoVertical);
  346. TNonNegativeInt = 0..MaxInt;
  347. TTBXLabelItem = class(TTBCustomItem)
  348. private
  349. FCaption: TCaption;
  350. FFontSettings: TFontSettings;
  351. FMargin: Integer;
  352. FShowAccelChar: Boolean;
  353. FOrientation: TTBXLabelOrientation;
  354. {MP}
  355. FFixedSize: Integer;
  356. FSectionHeader: Boolean;
  357. FOnAdjustFont: TAdjustFontEvent;
  358. procedure FontSettingsChanged(Sender: TObject);
  359. procedure SetMargin(Value: Integer);
  360. procedure SetOrientation(Value: TTBXLabelOrientation);
  361. procedure SetCaption(const Value: TCaption);
  362. procedure SetFontSettings(Value: TFontSettings);
  363. procedure SetShowAccelChar(Value: Boolean);
  364. {MP}
  365. procedure SetFixedSize(Value: Integer);
  366. procedure SetSectionHeader(Value: Boolean);
  367. protected
  368. function GetItemViewerClass (AView: TTBView): TTBItemViewerClass; override;
  369. public
  370. constructor Create(AOwner: TComponent); override;
  371. destructor Destroy; override;
  372. procedure UpdateCaption(const Value: TCaption);
  373. published
  374. property Caption: TCaption read FCaption write SetCaption;
  375. property Enabled;
  376. property FontSettings: TFontSettings read FFontSettings write SetFontSettings;
  377. property Margin: Integer read FMargin write SetMargin default 0;
  378. property Orientation: TTBXLabelOrientation read FOrientation write SetOrientation default tbxoAuto;
  379. property ShowAccelChar: Boolean read FShowAccelChar write SetShowAccelChar default True;
  380. {MP}
  381. property FixedSize: Integer read FFixedSize write SetFixedSize default 0;
  382. property SectionHeader: Boolean read FSectionHeader write SetSectionHeader default False;
  383. property Visible;
  384. property OnAdjustFont: TAdjustFontEvent read FOnAdjustFont write FOnAdjustFont;
  385. end;
  386. TTBXLabelItemViewer = class(TTBItemViewer)
  387. protected
  388. function GetCaptionText: string; override;
  389. function GetIsHoriz: Boolean; virtual;
  390. procedure DoAdjustFont(AFont: TFont; StateFlags: Integer); virtual;
  391. procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer); override;
  392. procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect;
  393. IsHoverItem, IsPushed, UseDisabledShadow: Boolean); override;
  394. function IsToolbarSize: Boolean; override;
  395. public
  396. function IsToolbarStyle: Boolean; override;
  397. end;
  398. { TTBXColorItem }
  399. TTBXColorItem = class(TTBXCustomItem)
  400. private
  401. FColor: TColor;
  402. procedure SetColor(Value: TColor);
  403. protected
  404. function GetItemViewerClass (AView: TTBView): TTBItemViewerClass; override;
  405. public
  406. constructor Create(AOwner: TComponent); override;
  407. published
  408. property Action;
  409. property AutoCheck;
  410. property Caption;
  411. property Checked;
  412. property Color: TColor read FColor write SetColor default clWhite;
  413. property DisplayMode;
  414. property Enabled;
  415. property FontSettings;
  416. property GroupIndex;
  417. property HelpContext;
  418. { MP }
  419. property HelpKeyword;
  420. property Hint;
  421. property InheritOptions;
  422. property MaskOptions;
  423. property MinHeight;
  424. property MinWidth;
  425. property Options;
  426. { MP }
  427. property RadioItem;
  428. property ShortCut;
  429. property Visible;
  430. property OnAdjustFont;
  431. property OnClick;
  432. end;
  433. TTBXColorItemViewer = class(TTBXItemViewer)
  434. protected
  435. procedure DoPaintCaption(Canvas: TCanvas; const ClientAreaRect: TRect;
  436. var CaptionRect: TRect; IsTextRotated: Boolean; var PaintDefault: Boolean); override;
  437. function GetImageShown: Boolean; override;
  438. function GetImageSize: TSize; override;
  439. procedure DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo); override;
  440. public
  441. constructor Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer); override;
  442. end;
  443. {$IFNDEF MPEXCLUDE}
  444. { TTBXMRUList }
  445. TTBXMRUList = class(TTBMRUList)
  446. private
  447. FKeyShift: Integer;
  448. procedure SetKeyShift(Value: Integer);
  449. protected
  450. function GetFirstKey: Integer; override;
  451. function GetItemClass: TTBCustomItemClass; override;
  452. procedure SetItemCaptions; override;
  453. published
  454. property KeyShift: Integer read FKeyShift write SetKeyShift default 0;
  455. end;
  456. { TTBXMRUListItem }
  457. TTBXMRUListItem = class(TTBXCustomItem)
  458. private
  459. FMRUList: TTBMRUList;
  460. procedure SetMRUList(Value: TTBMRUList);
  461. protected
  462. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  463. public
  464. constructor Create(AOwner: TComponent); override;
  465. published
  466. property MRUList: TTBMRUList read FMRUList write SetMRUList;
  467. end;
  468. {$ENDIF}
  469. implementation
  470. uses TB2Common, TB2Consts, TypInfo, Math, ImgList, {MP}Menus, Forms {$IFNDEF JR_D5}, DsgnIntf{$ENDIF};
  471. const
  472. { Repeat intervals for spin edit items }
  473. SE_FIRSTINTERVAL = 400;
  474. SE_INTERVAL = 100;
  475. type
  476. TTBViewAccess = class(TTBView);
  477. TTBItemAccess = class(TTBCustomItem);
  478. {$IFNDEF MPEXCLUDE}
  479. TTBMRUListAccess = class(TTBMRUList);
  480. {$ENDIF}
  481. TCustomEditAccess = class(TCustomEdit);
  482. TFontSettingsAccess = class(TFontSettings);
  483. { Misc. functions }
  484. function StartsText(const ASubText, AText: string): Boolean;
  485. var
  486. P: PChar;
  487. L, L2: Integer;
  488. begin
  489. P := PChar(AText);
  490. L := Length(ASubText);
  491. L2 := Length(AText);
  492. if L > L2 then Result := False
  493. else Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  494. P, L, PChar(ASubText), L) = 2;
  495. end;
  496. //============================================================================//
  497. { TTBXEdit }
  498. type
  499. TTBXEdit = class(TEdit)
  500. private
  501. FAlignment: TAlignment;
  502. procedure SetAlignment(Value: TAlignment);
  503. protected
  504. procedure CreateParams(var Params: TCreateParams); override;
  505. public
  506. property Alignment: TAlignment read FAlignment write SetAlignment;
  507. end;
  508. procedure TTBXEdit.CreateParams(var Params: TCreateParams);
  509. const
  510. Alignments: array[TAlignment] of Cardinal = (ES_LEFT, ES_RIGHT, ES_CENTER);
  511. begin
  512. inherited CreateParams(Params);
  513. Params.Style := Params.Style or Alignments[FAlignment];
  514. end;
  515. procedure TTBXEdit.SetAlignment(Value: TAlignment);
  516. begin
  517. if Value <> FAlignment then
  518. begin
  519. FAlignment := Value;
  520. RecreateWnd;
  521. end;
  522. end;
  523. //============================================================================//
  524. { TTBXEditItem }
  525. constructor TTBXEditItem.Create(AOwner: TComponent);
  526. begin
  527. inherited;
  528. FEditorFontSettings := TFontSettings.Create;
  529. FFontSettings := TFontSettings.Create;
  530. TFontSettingsAccess(FEditorFontSettings).OnChange := FontSettingsChanged;
  531. TFontSettingsAccess(FFontSettings).OnChange := FontSettingsChanged;
  532. end;
  533. destructor TTBXEditItem.Destroy;
  534. begin
  535. FFontSettings.Free;
  536. FEditorFontSettings.Free;
  537. inherited;
  538. end;
  539. function TTBXEditItem.DoAcceptText(var NewText: string): Boolean;
  540. begin
  541. Result := inherited DoAcceptText(NewText);
  542. // if not Result then DoChange(Text);
  543. end;
  544. function TTBXEditItem.DoAutoComplete(var AText: string): Boolean;
  545. begin
  546. Result := False;
  547. end;
  548. procedure TTBXEditItem.DoBeginEdit(Viewer: TTBEditItemViewer);
  549. begin
  550. with Viewer do
  551. begin
  552. TTBXEdit(EditControl).Alignment := Alignment;
  553. EditControl.PasswordChar := PasswordChar;
  554. EditControl.SelectAll;
  555. EditControl.ReadOnly := ReadOnly;
  556. EditorFontSettings.Apply(EditControl.Font);
  557. FAutoCompleteCounter := 0;
  558. inherited;
  559. if Viewer is TTBXEditItemViewer then
  560. begin
  561. EditControl.OnChange := TTBXEditItemViewer(Viewer).EditChangeHandler;
  562. TTBXEditItemViewer(Viewer).OldWndProc := EditControl.WindowProc;
  563. EditControl.WindowProc := TTBXEditItemViewer(Viewer).NewEditWndProc;
  564. end;
  565. end;
  566. end;
  567. procedure TTBXEditItem.DoChange(const AText: string);
  568. begin
  569. if Assigned(FOnChange) then FOnChange(Self, AText);
  570. end;
  571. procedure TTBXEditItem.DoTextChanged(Reason: Integer);
  572. begin
  573. if not ((Reason = tcrEditControl) and (Text = FLastEditChange)) then
  574. DoChange(Text);
  575. end;
  576. procedure TTBXEditItem.FontSettingsChanged(Sender: TObject);
  577. begin
  578. Change(True);
  579. end;
  580. function TTBXEditItem.GetImageIndex: Integer;
  581. begin
  582. Result := ImageIndex;
  583. end;
  584. function TTBXEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  585. begin
  586. if not (tboUseEditWhenVertical in EditOptions) and
  587. (AView.Orientation = tbvoVertical) then
  588. Result := TTBXItemViewer
  589. else
  590. Result := TTBXEditItemViewer;
  591. end;
  592. procedure TTBXEditItem.GetPopupPosition(ParentView: TTBView;
  593. PopupWindow: TTBPopupWindow; var PopupPositionRec: TTBPopupPositionRec);
  594. var
  595. VT: Integer;
  596. begin
  597. inherited;
  598. VT := GetWinViewType(PopupWindow);
  599. PopupPositionRec.PlaySound := not (VT and PVT_LISTBOX = PVT_LISTBOX);
  600. end;
  601. function TTBXEditItem.GetPopupWindowClass: TTBPopupWindowClass;
  602. begin
  603. Result := TTBXPopupWindow;
  604. end;
  605. procedure TTBXEditItem.HandleEditChange(Edit: TEdit);
  606. var
  607. S, S2: string;
  608. begin
  609. if not FIsChanging then
  610. begin
  611. FIsChanging := True;
  612. try
  613. S := Edit.Text;
  614. S2 := S;
  615. if (Length(S) > 0) and (FAutoCompleteCounter > 0) and DoAutoComplete(S2) then
  616. begin
  617. Edit.Text := S2;
  618. Edit.SelStart := Length(S);
  619. Edit.SelLength := Length(S2) - Length(S);
  620. S := S2;
  621. end;
  622. {if S <> FLastEditChange then} {vb-}
  623. if AnsiCompareText(S, FLastEditChange) <> 0 then {vb+}
  624. begin
  625. DoChange(S); // note, Edit.Text may be different from Self.Text
  626. FLastEditChange := S;
  627. end;
  628. finally
  629. FIsChanging := False;
  630. end;
  631. end;
  632. end;
  633. procedure TTBXEditItem.SetAlignment(Value: TAlignment);
  634. begin
  635. if Value <> FAlignment then
  636. begin
  637. FAlignment := Value;
  638. Change(True);
  639. end;
  640. end;
  641. procedure TTBXEditItem.SetFontSettings(Value: TFontSettings);
  642. begin
  643. FFontSettings.Assign(Value);
  644. end;
  645. procedure TTBXEditItem.SetPasswordChar(Value: Char);
  646. begin
  647. if Value <> FPasswordChar then
  648. begin
  649. FPasswordChar := Value;
  650. Change(True);
  651. end;
  652. end;
  653. procedure TTBXEditItem.SetShowImage(const Value: Boolean);
  654. begin
  655. FShowImage := Value;
  656. Change(True);
  657. end;
  658. function TTBXEditItem.StartEditing(AView: TTBView): Boolean;
  659. var
  660. V: TTBItemViewer;
  661. SaveText: string;
  662. begin
  663. Result := False;
  664. V := AView.Find(Self);
  665. if V is TTBXEditItemViewer then
  666. begin
  667. SaveText := Text;
  668. TTBXEditItemViewer(V).DoExecute;
  669. Result := Text <> SaveText;
  670. end;
  671. end;
  672. //============================================================================//
  673. { TTBXEditItemViewer }
  674. procedure TTBXEditItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer);
  675. var
  676. W, B: Integer;
  677. EditBoxHeight: Integer;
  678. EditCaptionSize: TSize;
  679. begin
  680. if Self.Item is TTBXEditItem then with CurrentTheme do
  681. begin
  682. B := EditFrameWidth;
  683. AWidth := TTBXEditItem(Item).EditWidth;
  684. if not IsToolbarStyle then
  685. begin
  686. EditCaptionSize := MeasureEditCaption;
  687. W := EditCaptionSize.CX;
  688. if W > 0 then Inc(W, MenuLeftCaptionMargin + MenuRightCaptionMargin + MenuImageTextSpace);
  689. Inc(AWidth, GetPopupMargin(Self) + MenuImageTextSpace + W + EditMenuRightIndent);
  690. end
  691. else
  692. begin
  693. EditCaptionSize.CX := 0;
  694. EditCaptionSize.CY := 0;
  695. end;
  696. EditBoxHeight := MeasureTextHeight + 1;
  697. Inc(EditBoxHeight, EditTextMarginVert * 2 + B * 2);
  698. AHeight := Max(EditBoxHeight, EditCaptionSize.CY);
  699. if not IsToolbarStyle then AHeight := AHeight;
  700. if EditHeightEven then AHeight := (AHeight + 1) and not $01
  701. else AHeight := AHeight or $01;
  702. end
  703. else inherited;
  704. end;
  705. procedure TTBXEditItemViewer.EditChangeHandler(Sender: TObject);
  706. begin
  707. HandleEditChange((Sender as TEdit));
  708. end;
  709. procedure TTBXEditItemViewer.HandleEditChange(Edit: TEdit);
  710. begin
  711. TTBXEditItem(Item).HandleEditChange(Edit);
  712. end;
  713. procedure TTBXEditItemViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo);
  714. begin
  715. FillChar(EditInfo, SizeOf(EditInfo), 0);
  716. EditInfo.LeftBtnWidth := GetIndentBefore;
  717. EditInfo.RightBtnWidth := GetIndentAfter;
  718. end;
  719. function TTBXEditItemViewer.GetAccRole: Integer;
  720. const
  721. ROLE_SYSTEM_SPINBUTTON = $34;
  722. ROLE_SYSTEM_COMBOBOX = $2E;
  723. begin
  724. Result := inherited GetAccRole;
  725. {$IFNDEF MPEXCLUDE}
  726. if Self is TTBXSpinEditViewer then Result := ROLE_SYSTEM_SPINBUTTON
  727. else {$ENDIF} if Self is TTBXDropDownItemViewer then Result := ROLE_SYSTEM_COMBOBOX;
  728. end;
  729. procedure TTBXEditItemViewer.GetItemInfo(out ItemInfo: TTBXItemInfo; IsHoverItem, IsPushed, UseMenuColor: Boolean);
  730. const
  731. CToolbarStyle: array [Boolean] of Integer = (0, IO_TOOLBARSTYLE);
  732. CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING);
  733. var
  734. Item: TTBXEditItem;
  735. begin
  736. Item := TTBXEditItem(Self.Item);
  737. FillChar(ItemInfo, SizeOf(TTBXItemInfo), 0);
  738. ItemInfo.ViewType := GetViewType(View);
  739. ItemInfo.ItemOptions := CToolbarStyle[IsToolbarStyle]
  740. or CDesigning[csDesigning in Item.ComponentState];
  741. ItemInfo.Enabled := Item.Enabled or View.Customizing;
  742. ItemInfo.Pushed := IsPushed;
  743. ItemInfo.Selected := Item.Checked;
  744. if IsHoverItem then
  745. begin
  746. if not ItemInfo.Enabled and not View.MouseOverSelected then
  747. ItemInfo.HoverKind := hkKeyboardHover
  748. else
  749. if ItemInfo.Enabled then ItemInfo.HoverKind := hkMouseHover;
  750. end
  751. else ItemInfo.HoverKind := hkNone;
  752. if not IsToolbarStyle then ItemInfo.PopupMargin := GetPopupMargin(Self);
  753. end;
  754. procedure TTBXEditItemViewer.GetEditRect(var R: TRect);
  755. const
  756. TB2K_EDIT_BORDER = 3;
  757. var
  758. W, B: Integer;
  759. begin
  760. if Item is TTBXEditItem then with CurrentTheme do
  761. begin
  762. R := BoundsRect;
  763. if not IsToolbarStyle then
  764. begin
  765. W := MeasureEditCaption.CX;
  766. if W > 0 then Inc(W, MenuLeftCaptionMargin + MenuRightCaptionMargin + MenuImageTextSpace);
  767. Inc(R.Left, GetPopupMargin(Self) + MenuImageTextSpace + W);
  768. Dec(R.Right, EditMenuRightIndent);
  769. end;
  770. B := EditFrameWidth - TB2K_EDIT_BORDER;
  771. InflateRect(R, -B - EditTextMarginHorz , -B - EditTextMarginVert);
  772. Inc(R.Left, GetIndentBefore);
  773. Dec(R.Right, GetIndentAfter);
  774. end
  775. else inherited;
  776. end;
  777. function TTBXEditItemViewer.GetIndentAfter: Integer;
  778. begin
  779. Result := 0;
  780. end;
  781. function TTBXEditItemViewer.GetIndentBefore: Integer;
  782. var
  783. ImgList: TCustomImageList;
  784. begin
  785. if ShowImage then
  786. begin
  787. ImgList := GetImageList;
  788. if ImgList <> nil then Result := ImgList.Width + 2
  789. else Result := 0;
  790. end
  791. else Result := 0;
  792. end;
  793. function TTBXEditItemViewer.HandleEditMessage(var Message: TMessage): Boolean;
  794. const
  795. CharKeys = [VK_SPACE, $30..$5A, VK_NUMPAD0..VK_DIVIDE, $BA..$F5];
  796. begin
  797. if Message.Msg = WM_KEYDOWN then
  798. begin
  799. if Message.WParam in CharKeys then Inc(TTBXEditItem(Item).FAutoCompleteCounter)
  800. end
  801. else if Message.Msg = WM_KEYUP then
  802. begin
  803. if Message.WParam in CharKeys then Dec(TTBXEditItem(Item).FAutoCompleteCounter);
  804. end;
  805. Result := False;
  806. end;
  807. procedure TTBXEditItemViewer.NewEditWndProc(var Message: TMessage);
  808. begin
  809. if Assigned(OldWndProc) and not HandleEditMessage(Message) then OldWndProc(Message);
  810. end;
  811. {MP}
  812. function TTBXEditItemViewer.StripTextHotkey: Boolean;
  813. begin
  814. Result := False;
  815. end;
  816. procedure TTBXEditItemViewer.Paint(const Canvas: TCanvas;
  817. const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean);
  818. const
  819. FillColors: array [Boolean] of Integer = (COLOR_BTNFACE, COLOR_WINDOW);
  820. TextColors: array [Boolean] of Integer = (COLOR_GRAYTEXT, COLOR_WINDOWTEXT);
  821. Alignments: array [TAlignment] of Integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
  822. var
  823. DC: HDC;
  824. Item: TTBXEditItem;
  825. S: string;
  826. R, R2: TRect;
  827. M, W: Integer;
  828. ItemInfo: TTBXItemInfo;
  829. EditInfo: TTBXEditInfo;
  830. ImgList: TCustomImageList;
  831. ImgIndex: Integer;
  832. Fnt, OldFnt: HFont;
  833. C, OldColor: TColor;
  834. begin
  835. DC := Canvas.Handle;
  836. Item := TTBXEditItem(Self.Item);
  837. GetItemInfo(ItemInfo, IsHoverItem, IsPushed, UseDisabledShadow);
  838. GetEditInfo(EditInfo, ItemInfo);
  839. R := ClientAreaRect;
  840. if not IsToolbarStyle then with CurrentTheme do
  841. begin
  842. S := Item.EditCaption;
  843. if Length(S) > 0 then
  844. begin
  845. { measure EditCaption }
  846. Fnt := TTBXEditItem(Item).FontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, C);
  847. OldFnt := SelectObject(DC, Fnt);
  848. W := GetTextWidth(DC, S, True) + MenuImageTextSpace + MenuLeftCaptionMargin + MenuRightCaptionMargin;
  849. SelectObject(DC, OldFnt);
  850. end
  851. else
  852. begin
  853. Fnt := 0; // to suppress compiler warning
  854. W := 0;
  855. end;
  856. M := GetPopupMargin(Self);
  857. if not EditMenuFullSelect then R.Right := M + W
  858. else Dec(R.Right, EditMenuRightIndent);
  859. PaintMenuItemFrame(Canvas, R, ItemInfo);
  860. Inc(R.Left, M + MenuImageTextSpace);
  861. R.Right := ClientAreaRect.Right - EditMenuRightIndent;
  862. if Length(S) > 0 then
  863. begin
  864. Inc(R.Left, MenuLeftCaptionMargin);
  865. C := ColorToRGB(GetItemTextColor(ItemInfo));
  866. OldFnt := SelectObject(DC, Fnt);
  867. OldColor := SetTextColor(DC, C);
  868. PaintCaption(Canvas, R, ItemInfo, S, DT_SINGLELINE or DT_LEFT or DT_VCENTER, False);
  869. SetTextColor(DC, OldColor);
  870. W := GetTextWidth(DC, S, True);
  871. SelectObject(DC, OldFnt);
  872. DeleteObject(Fnt);
  873. Inc(R.Left, W + MenuRightCaptionMargin + MenuImageTextSpace);
  874. end;
  875. end;
  876. CurrentTheme.PaintEditFrame(Canvas, R, ItemInfo, EditInfo);
  877. W := CurrentTheme.EditFrameWidth;
  878. InflateRect(R, -W - CurrentTheme.EditTextMarginHorz, -W - CurrentTheme.EditTextMarginVert);
  879. if ShowImage then
  880. begin
  881. ImgList := GetImageList;
  882. if ImgList <> nil then
  883. begin
  884. R2.Left := R.Left;
  885. R2.Right := R.Left + ImgList.Width;
  886. R2.Top := (R.Top + R.Bottom + 1 - ImgList.Height) div 2;
  887. R2.Bottom := R2.Top + ImgList.Height;
  888. ImgIndex := TTBXEditItem(Item).GetImageIndex;
  889. if Item.Enabled then ImgList.Draw(Canvas, R.Left, R2.Top, ImgIndex)
  890. else DrawTBXImage(Canvas, R2, ImgList, ImgIndex, ISF_DISABLED);
  891. end;
  892. end;
  893. Inc(R.Left, EditInfo.LeftBtnWidth);
  894. Dec(R.Right, EditInfo.RightBtnWidth + 1);
  895. if Item.Text <> '' then
  896. begin
  897. S := Item.Text;
  898. if StripTextHotkey then S := StripHotkey(S);
  899. if TTBXEditItem(Item).PasswordChar <> #0 then S := StringOfChar(TTBXEditItem(Item).PasswordChar, Length(S));
  900. Fnt := Item.EditorFontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, C);
  901. OldFnt := SelectObject(DC, Fnt);
  902. SetBkMode(DC, TRANSPARENT);
  903. SetBkColor(DC, GetSysColor(FillColors[Item.Enabled]));
  904. SetTextColor(DC, GetSysColor(TextColors[Item.Enabled]));
  905. // WinSCP: Align edit text with toolbar labels
  906. InflateRect(R, 0, -1);
  907. DrawText(DC, PChar(S), Length(S), R, DT_SINGLELINE or DT_NOPREFIX or Alignments[Item.Alignment]);
  908. SelectObject(DC, OldFnt);
  909. DeleteObject(Fnt);
  910. end;
  911. { if not IsToolbarStyle then
  912. begin
  913. R := ClientAreaRect;
  914. Self.GetEditRect(R);
  915. OffsetRect(R, -BoundsRect.Left, -BoundsRect.Top);
  916. Canvas.FrameRect(R);
  917. end; }
  918. end;
  919. function TTBXEditItemViewer.GetEditControlClass: TEditClass;
  920. begin
  921. Result := TTBXEdit;
  922. end;
  923. function TTBXEditItemViewer.ShowImage: Boolean;
  924. begin
  925. Result := TTBXEditItem(Item).ShowImage;
  926. end;
  927. function TTBXEditItemViewer.IsToolbarSize: Boolean;
  928. begin
  929. Result := inherited IsToolbarSize;
  930. Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX);
  931. end;
  932. function TTBXEditItemViewer.IsToolbarStyle: Boolean;
  933. begin
  934. Result := inherited IsToolbarStyle;
  935. Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX);
  936. end;
  937. function TTBXEditItemViewer.MeasureEditCaption: TSize;
  938. var
  939. DC: HDC;
  940. Fnt, OldFnt: HFont;
  941. DummyColor: TColor;
  942. TextMetric: TTextMetric;
  943. S: string;
  944. begin
  945. Result.cx := 0;
  946. Result.cy := 0;
  947. if Item is TTBXEditItem then
  948. begin
  949. S := StripAccelChars(TTBXEditItem(Item).EditCaption);
  950. if Length(S) > 0 then
  951. begin
  952. DummyColor := clWhite;
  953. DC := GetDC(0);
  954. Fnt := TTBXEditItem(Item).FontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, DummyColor);
  955. OldFnt := SelectObject(DC, Fnt);
  956. GetTextExtentPoint32(DC, PChar(S), Length(S), Result);
  957. GetTextMetrics(DC, TextMetric);
  958. Inc(Result.cy, TextMetric.tmExternalLeading);
  959. SelectObject(DC, OldFnt);
  960. DeleteObject(Fnt);
  961. ReleaseDC(0, DC);
  962. end;
  963. end;
  964. end;
  965. function TTBXEditItemViewer.MeasureTextHeight: Integer;
  966. var
  967. DC: HDC;
  968. Fnt, OldFnt: HFont;
  969. DummyColor: TColor;
  970. TextMetric: TTextMetric;
  971. begin
  972. Result := 0;
  973. if Item is TTBXEditItem then
  974. begin
  975. DummyColor := clWhite;
  976. DC := GetDC(0);
  977. Fnt := TTBXEditItem(Item).EditorFontSettings.CreateTransformedFont(TTBViewAccess(View).GetFont.Handle, DummyColor);
  978. OldFnt := SelectObject(DC, Fnt);
  979. Result := GetTextHeight(DC);
  980. GetTextMetrics(DC, TextMetric);
  981. Inc(Result, TextMetric.tmExternalLeading);
  982. SelectObject(DC, OldFnt);
  983. DeleteObject(Fnt);
  984. ReleaseDC(0, DC);
  985. end;
  986. end;
  987. function TTBXEditItemViewer.DoExecute: Boolean;
  988. begin
  989. if Item is TTBXEditItem then
  990. begin
  991. TTBXEditItem(Item).FLastEditChange := '';
  992. Result := inherited DoExecute;
  993. with TTBXEditItem(Item) do
  994. begin
  995. if FLastEditChange <> Text then DoChange(Text);
  996. FLastEditChange := '';
  997. end;
  998. end
  999. else Result := inherited DoExecute;
  1000. end;
  1001. //============================================================================//
  1002. {MP}
  1003. type
  1004. TTBXDropDownWindow = class(TTBXPopupWindow)
  1005. protected
  1006. procedure Cancel; override;
  1007. public
  1008. Owner: TTBXCustomDropDownItem;
  1009. end;
  1010. procedure TTBXDropDownWindow.Cancel;
  1011. begin
  1012. inherited;
  1013. Owner.DoCancel;
  1014. end;
  1015. {/MP}
  1016. //============================================================================//
  1017. { TTBXCustomDropDownItem }
  1018. constructor TTBXCustomDropDownItem.Create(AOwner: TComponent);
  1019. begin
  1020. inherited;
  1021. ItemStyle := ItemStyle + [tbisCombo, tbisSubmenu, tbisSubitemsEditable] - [tbisDontSelectFirst];
  1022. FAlwaysSelectFirst := True;
  1023. end;
  1024. function TTBXCustomDropDownItem.CreatePopup(const ParentView: TTBView;
  1025. const ParentViewer: TTBItemViewer; const PositionAsSubmenu,
  1026. SelectFirstItem, Customizing: Boolean; const APopupPoint: TPoint;
  1027. const Alignment: TTBPopupAlignment): TTBPopupWindow;
  1028. var
  1029. SelectFirst: Boolean;
  1030. begin
  1031. if AlwaysSelectFirst then SelectFirst := True
  1032. else SelectFirst := SelectFirstItem;
  1033. Result := inherited CreatePopup(ParentView, ParentViewer, PositionAsSubmenu,
  1034. SelectFirst, Customizing, APopupPoint, Alignment);
  1035. {MP}
  1036. (Result as TTBXDropDownWindow).Owner := Self;
  1037. end;
  1038. {MP}
  1039. procedure TTBXCustomDropDownItem.DoCancel;
  1040. begin
  1041. if Assigned(OnCancel) then
  1042. OnCancel(Self);
  1043. end;
  1044. function TTBXCustomDropDownItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  1045. begin
  1046. if not (tboUseEditWhenVertical in EditOptions) and (AView.Orientation = tbvoVertical) then
  1047. Result := TTBXItemViewer
  1048. else
  1049. Result := TTBXDropDownItemViewer;
  1050. end;
  1051. {MP}
  1052. function TTBXCustomDropDownItem.GetPopupWindowClass: TTBPopupWindowClass;
  1053. begin
  1054. Result := TTBXDropDownWindow;
  1055. end;
  1056. //----------------------------------------------------------------------------//
  1057. { TTBXDropDownItemViewer }
  1058. procedure TTBXDropDownItemViewer.GetCursor(const Pt: TPoint; var ACursor: HCURSOR);
  1059. begin
  1060. if not TTBXCustomDropDownItem(Item).DropDownList then inherited;
  1061. end;
  1062. procedure TTBXDropDownItemViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo);
  1063. const
  1064. CDisabled: array [Boolean] of Integer = (EBDS_DISABLED, 0);
  1065. CHot: array [Boolean] of Integer = (0, EBDS_HOT);
  1066. CPressed: array [Boolean] of Integer = (0, EBDS_PRESSED);
  1067. begin
  1068. inherited GetEditInfo(EditInfo, ItemInfo);
  1069. EditInfo.RightBtnInfo.ButtonType := EBT_DROPDOWN;
  1070. EditInfo.RightBtnInfo.ButtonState := CDisabled[ItemInfo.Enabled] or
  1071. CHot[ItemInfo.HoverKind = hkMouseHover] or CPressed[ItemInfo.Pushed];
  1072. end;
  1073. function TTBXDropDownItemViewer.GetIndentAfter: Integer;
  1074. begin
  1075. if IsToolbarStyle then Result := CurrentTheme.EditBtnWidth
  1076. else Result := GetSystemMetrics(SM_CXMENUCHECK) + 2;
  1077. end;
  1078. function TTBXDropDownItemViewer.HandleEditMessage(var Message: TMessage): Boolean;
  1079. begin
  1080. if Message.Msg = WM_KEYDOWN then
  1081. begin
  1082. if TWMKeyDown(Message).CharCode = VK_F4 then
  1083. begin
  1084. {TTBViewAccess(View).OpenChildPopup(True);} {vb-}
  1085. if (View.OpenViewer = Self) // WasAlreadyOpen {vb+}
  1086. then View.CloseChildPopups
  1087. else View.OpenChildPopup(True);
  1088. Result := True;
  1089. Exit;
  1090. end;
  1091. end;
  1092. Result := inherited HandleEditMessage(Message);
  1093. end;
  1094. function TTBXDropDownItemViewer.IsPtInButtonPart(X, Y: Integer): Boolean;
  1095. begin
  1096. Result := not (tbisSubmenu in TTBXCustomDropDownItem(Item).ItemStyle);
  1097. if TTBXCustomDropDownItem(Item).DropDownList then Result := False
  1098. else if (tbisCombo in TTBXCustomDropDownItem(Item).ItemStyle) then
  1099. Result := X < (BoundsRect.Right - BoundsRect.Left) - GetIndentAfter;
  1100. end;
  1101. procedure TTBXDropDownItemViewer.KeyDown(var Key: Word; Shift: TShiftState);
  1102. begin
  1103. if not TTBXCustomDropDownItem(Item).DropDownList then inherited;
  1104. end;
  1105. //============================================================================//
  1106. { TTBXComboBoxItem }
  1107. procedure TTBXComboBoxItem.AdjustImageIndex(const AText: string;
  1108. AIndex: Integer; var ImageIndex: Integer);
  1109. begin
  1110. if Assigned(FOnAdjustImageIndex) then FOnAdjustImageIndex(Self, AText, AIndex, ImageIndex);
  1111. end;
  1112. procedure TTBXComboBoxItem.AdjustImageIndexHandler(Sender: TTBXCustomList;
  1113. AItemIndex: Integer; var ImageIndex: Integer);
  1114. begin
  1115. AdjustImageIndex(FList.Strings[AItemIndex], AItemIndex, ImageIndex);
  1116. end;
  1117. constructor TTBXComboBoxItem.Create(AOwner: TComponent);
  1118. begin
  1119. inherited;
  1120. ItemStyle := ItemStyle - [tbisSubItemsEditable];
  1121. FAutoComplete := True;
  1122. FList := GetStringListClass.Create(Self);
  1123. FList.OnChange := ListChangeHandler;
  1124. FList.OnClick := ListClickHandler;
  1125. FList.OnAdjustImageIndex := AdjustImageIndexHandler;
  1126. MinListWidth := 64;
  1127. end;
  1128. function TTBXComboBoxItem.DoAutoComplete(var AText: string): Boolean;
  1129. var
  1130. I: Integer;
  1131. S, R: string;
  1132. TemplateL, MinL, L: Integer;
  1133. begin
  1134. Result := False;
  1135. if Length(AText) > 0 then
  1136. begin
  1137. { choose the shortest matching string from items }
  1138. TemplateL := Length(AText);
  1139. MinL := MaxInt;
  1140. SetLength(R, 0);
  1141. for I := 0 to FList.Strings.Count - 1 do
  1142. begin
  1143. S := FList.Strings[I];
  1144. L := Length(S);
  1145. if (L >= TemplateL) and (L < MinL) and StartsText(AText, S) then
  1146. begin
  1147. R := S;
  1148. MinL := L;
  1149. if MinL = TemplateL then Break;
  1150. end;
  1151. end;
  1152. Result := Length(R) > 0;
  1153. if Result then AText := R;
  1154. end;
  1155. end;
  1156. procedure TTBXComboBoxItem.DoListChange;
  1157. begin
  1158. { Update text in edit item. This will call OnChange automatically }
  1159. if (FList.ItemIndex >= 0) and (FList.ItemIndex < FList.Strings.Count) then
  1160. begin
  1161. IsChanging := True;
  1162. try
  1163. if Text <> FList.Strings[Flist.ItemIndex] then
  1164. begin
  1165. SetTextEx(FList.Strings[FList.ItemIndex], tcrList);
  1166. end;
  1167. finally
  1168. IsChanging := False;
  1169. end;
  1170. end;
  1171. end;
  1172. procedure TTBXComboBoxItem.DoListClick;
  1173. begin
  1174. if Assigned(FOnItemClick) then FOnItemClick(Self);
  1175. end;
  1176. procedure TTBXComboBoxItem.DoPopup(Sender: TTBCustomItem; FromLink: Boolean);
  1177. begin
  1178. inherited;
  1179. FList.ItemIndex := FList.Strings.IndexOf(Text);
  1180. end;
  1181. function TTBXComboBoxItem.GetImageIndex: Integer;
  1182. begin
  1183. if not CacheValid then
  1184. begin
  1185. CachedImageIndex := ImageIndex;
  1186. if ItemIndex >= 0 then CachedImageIndex := ItemIndex;
  1187. AdjustImageIndex(Text, -1, CachedImageIndex);
  1188. CacheValid := True;
  1189. end;
  1190. Result := CachedImageIndex;
  1191. end;
  1192. function TTBXComboBoxItem.GetItemIndex: Integer;
  1193. begin
  1194. Result := FList.ItemIndex;
  1195. end;
  1196. function TTBXComboBoxItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  1197. begin
  1198. if not (tboUseEditWhenVertical in EditOptions) and
  1199. (AView.Orientation = tbvoVertical) then
  1200. Result := TTBXItemViewer
  1201. else
  1202. Result := TTBXComboBoxItemViewer;
  1203. end;
  1204. function TTBXComboBoxItem.GetMaxVisibleItems: Integer;
  1205. begin
  1206. Result := FList.MaxVisibleItems;
  1207. end;
  1208. function TTBXComboBoxItem.GetMaxWidth: Integer;
  1209. begin
  1210. Result := FList.MaxWidth;
  1211. end;
  1212. function TTBXComboBoxItem.GetMinWidth: Integer;
  1213. begin
  1214. Result := FList.MinWidth;
  1215. end;
  1216. function TTBXComboBoxItem.GetOnClearItem: TTBXLPaintEvent;
  1217. begin
  1218. Result := FList.OnClearItem;
  1219. end;
  1220. function TTBXComboBoxItem.GetOnDrawItem: TTBXLPaintEvent;
  1221. begin
  1222. Result := FList.OnDrawItem;
  1223. end;
  1224. function TTBXComboBoxItem.GetOnMeasureHeight: TTBXLMeasureHeight;
  1225. begin
  1226. Result := FList.OnMeasureHeight;
  1227. end;
  1228. function TTBXComboBoxItem.GetOnMeasureWidth: TTBXLMeasureWidth;
  1229. begin
  1230. Result := FList.OnMeasureWidth;
  1231. end;
  1232. function TTBXComboBoxItem.GetShowListImages: Boolean;
  1233. begin
  1234. Result := FList.ShowImages;
  1235. end;
  1236. function TTBXComboBoxItem.GetStringListClass: TTBXStringListClass;
  1237. begin
  1238. Result := TTBXStringList;
  1239. end;
  1240. function TTBXComboBoxItem.GetStrings: TStrings;
  1241. begin
  1242. Result := FList.Strings;
  1243. end;
  1244. procedure TTBXComboBoxItem.HandleEditChange(Edit: TEdit);
  1245. begin
  1246. CacheValid := False;
  1247. inherited;
  1248. end;
  1249. procedure TTBXComboBoxItem.ListChangeHandler(Sender: TObject);
  1250. begin
  1251. CacheValid := False;
  1252. DoListChange;
  1253. end;
  1254. procedure TTBXComboBoxItem.ListClickHandler(Sender: TObject);
  1255. begin
  1256. CacheValid := False;
  1257. DoListClick;
  1258. end;
  1259. procedure TTBXComboBoxItem.Loaded;
  1260. begin
  1261. inherited;
  1262. if FList.Strings.IndexOf(Text) >= 0 then
  1263. begin
  1264. IsChanging := True;
  1265. try
  1266. FList.ItemIndex := FList.Strings.IndexOf(Text);
  1267. finally
  1268. IsChanging := False;
  1269. end;
  1270. end;
  1271. { MP Do not re-add on re-load (locale change) }
  1272. if not Assigned(FList.Parent) then
  1273. if not (csDesigning in ComponentState) then Add(FList);
  1274. end;
  1275. procedure TTBXComboBoxItem.SetItemIndex(Value: Integer);
  1276. begin
  1277. FList.ItemIndex := Value;
  1278. end;
  1279. procedure TTBXComboBoxItem.SetMaxVisibleItems(Value: Integer);
  1280. begin
  1281. FList.MaxVisibleItems := Value;
  1282. end;
  1283. procedure TTBXComboBoxItem.SetMaxWidth(Value: Integer);
  1284. begin
  1285. FList.MaxWidth := Value;
  1286. end;
  1287. procedure TTBXComboBoxItem.SetMinWidth(Value: Integer);
  1288. begin
  1289. FList.MinWidth := Value;
  1290. end;
  1291. procedure TTBXComboBoxItem.SetOnClearItem(Value: TTBXLPaintEvent);
  1292. begin
  1293. FList.OnClearItem := Value;
  1294. end;
  1295. procedure TTBXComboBoxItem.SetOnDrawItem(Value: TTBXLPaintEvent);
  1296. begin
  1297. FList.OnDrawItem := Value;
  1298. end;
  1299. procedure TTBXComboBoxItem.SetOnMeasureHeight(Value: TTBXLMeasureHeight);
  1300. begin
  1301. FList.OnMeasureHeight := Value;
  1302. end;
  1303. procedure TTBXComboBoxItem.SetOnMeasureWidth(Value: TTBXLMeasureWidth);
  1304. begin
  1305. FList.OnMeasureWidth := Value;
  1306. end;
  1307. procedure TTBXComboBoxItem.SetShowListImages(Value: Boolean);
  1308. begin
  1309. FList.ShowImages := Value;
  1310. end;
  1311. procedure TTBXComboBoxItem.SetStrings(Value: TStrings);
  1312. begin
  1313. FList.Strings := Value;
  1314. end;
  1315. //============================================================================//
  1316. { TTBXComboBoxItemViewer }
  1317. function TTBXComboBoxItemViewer.HandleEditMessage(var Message: TMessage): Boolean;
  1318. begin
  1319. if (Message.Msg = WM_KEYDOWN) then with TTBXComboBoxItem(Item) do
  1320. begin
  1321. case Message.wParam of
  1322. VK_UP:
  1323. begin
  1324. if ItemIndex > 0 then {vb+}
  1325. ItemIndex := ItemIndex- 1;
  1326. EditControl.Text := Text;
  1327. EditControl.SelectAll;
  1328. Result := True;
  1329. end;
  1330. VK_DOWN:
  1331. begin
  1332. if ItemIndex < Strings.Count- 1 then {vb+}
  1333. ItemIndex := ItemIndex+ 1;
  1334. EditControl.Text := Text;
  1335. EditControl.SelectAll;
  1336. Result := True;
  1337. end;
  1338. else
  1339. Result := inherited HandleEditMessage(Message);
  1340. end
  1341. end
  1342. else Result := inherited HandleEditMessage(Message);
  1343. end;
  1344. {MP}
  1345. function TTBXComboBoxItemViewer.StripTextHotkey: Boolean;
  1346. begin
  1347. Result := TTBXComboBoxItem(Item).DropDownList;
  1348. end;
  1349. //============================================================================//
  1350. { TTBXLabelItem }
  1351. constructor TTBXLabelItem.Create(AOwner: TComponent);
  1352. begin
  1353. inherited;
  1354. FFontSettings := TFontSettings.Create;
  1355. TFontSettingsAccess(FFontSettings).OnChange := FontSettingsChanged;
  1356. FShowAccelChar := True;
  1357. ItemStyle := ItemStyle - [tbisSelectable] + [tbisClicksTransparent, tbisStretch];
  1358. FSectionHeader := False;
  1359. end;
  1360. destructor TTBXLabelItem.Destroy;
  1361. begin
  1362. FFontSettings.Free;
  1363. inherited;
  1364. end;
  1365. procedure TTBXLabelItem.FontSettingsChanged(Sender: TObject);
  1366. begin
  1367. Change(True);
  1368. end;
  1369. function TTBXLabelItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  1370. begin
  1371. Result := TTBXLabelItemViewer;
  1372. end;
  1373. procedure TTBXLabelItem.SetCaption(const Value: TCaption);
  1374. begin
  1375. FCaption := Value;
  1376. Change(True);
  1377. end;
  1378. procedure TTBXLabelItem.SetFontSettings(Value: TFontSettings);
  1379. begin
  1380. FFontSettings := Value;
  1381. end;
  1382. {procedure TTBXLabelItem.SetFontSize(Value: TTBXFontSize);
  1383. begin
  1384. FFontSize := Value;
  1385. Change(True);
  1386. end; }
  1387. procedure TTBXLabelItem.SetMargin(Value: Integer);
  1388. begin
  1389. FMargin := Value;
  1390. Change(True);
  1391. end;
  1392. procedure TTBXLabelItem.SetOrientation(Value: TTBXLabelOrientation);
  1393. begin
  1394. FOrientation := Value;
  1395. Change(True);
  1396. end;
  1397. procedure TTBXLabelItem.SetShowAccelChar(Value: Boolean);
  1398. begin
  1399. FShowAccelChar := Value;
  1400. Change(True);
  1401. end;
  1402. {MP}
  1403. procedure TTBXLabelItem.SetFixedSize(Value: Integer);
  1404. begin
  1405. FFixedSize := Value;
  1406. Change(True);
  1407. end;
  1408. procedure TTBXLabelItem.SetSectionHeader(Value: Boolean);
  1409. begin
  1410. FSectionHeader := Value;
  1411. Change(True);
  1412. end;
  1413. procedure TTBXLabelItem.UpdateCaption(const Value: TCaption);
  1414. begin
  1415. FCaption := Value;
  1416. Change(False);
  1417. end;
  1418. //============================================================================//
  1419. { TTBXLabelItemViewer }
  1420. procedure TTBXLabelItemViewer.CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer);
  1421. var
  1422. DC: HDC;
  1423. S: string;
  1424. TextMetrics: TTextMetric;
  1425. RotatedFont, SaveFont: HFont;
  1426. Margins: TTBXMargins;
  1427. ImgList: TCustomImageList;
  1428. ImgHeight: Integer;
  1429. begin
  1430. Canvas.Font := TTBViewAccess(View).GetFont;
  1431. DoAdjustFont(Canvas.Font, 0);
  1432. S := GetCaptionText;
  1433. if Length(S) = 0 then S := '0';
  1434. DC := Canvas.Handle;
  1435. if IsToolbarStyle then
  1436. begin
  1437. AWidth := TTBXLabelItem(Item).Margin;
  1438. AHeight := AWidth;
  1439. if Length(S) > 0 then
  1440. begin
  1441. if GetIsHoriz then
  1442. begin
  1443. GetTextMetrics(DC, TextMetrics);
  1444. Inc(AHeight, TextMetrics.tmHeight);
  1445. Inc(AWidth, GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar));
  1446. end
  1447. else
  1448. begin
  1449. RotatedFont := CreateRotatedFont(DC);
  1450. SaveFont := SelectObject(DC, RotatedFont);
  1451. GetTextMetrics(DC, TextMetrics);
  1452. Inc(AWidth, TextMetrics.tmHeight);
  1453. Inc(AHeight, GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar));
  1454. SelectObject(DC, SaveFont);
  1455. DeleteObject(RotatedFont);
  1456. end;
  1457. end;
  1458. {MP}
  1459. with TTBXLabelItem(Item) do
  1460. if FFixedSize > 0 then
  1461. if GetIsHoriz then
  1462. AWidth := FFixedSize
  1463. else
  1464. AHeight := FFixedSize
  1465. end
  1466. else
  1467. begin
  1468. if Length(S) > 0 then
  1469. begin
  1470. GetTextMetrics(DC, TextMetrics);
  1471. AHeight := TextMetrics.tmHeight;
  1472. AWidth := GetTextWidth(DC, S, TTBXLabelItem(Item).ShowAccelChar);
  1473. end;
  1474. {MP}
  1475. with TTBXLabelItem(Item) do
  1476. begin
  1477. if FFixedSize > 0 then
  1478. AWidth := FFixedSize;
  1479. if SectionHeader then
  1480. begin
  1481. // the same as regular menu item
  1482. CurrentTheme.GetMargins(MID_MENUITEM, Margins);
  1483. Inc(AWidth, Margins.LeftWidth + Margins.RightWidth);
  1484. Inc(AWidth,
  1485. GetPopupMargin(Self) + CurrentTheme.MenuImageTextSpace +
  1486. CurrentTheme.MenuLeftCaptionMargin + CurrentTheme.MenuRightCaptionMargin);
  1487. // + make sure it's always bit indented compared to menu items
  1488. Inc(AWidth, 2 * 8);
  1489. ImgHeight := 16;
  1490. ImgList := GetImageList;
  1491. if ImgList <> nil then ImgHeight := ImgList.Height;
  1492. if AHeight < ImgHeight then AHeight := ImgHeight;
  1493. Inc(AHeight, Margins.TopHeight + Margins.BottomHeight);
  1494. Inc(AWidth, AHeight); { Note: maybe this should be controlled by the theme }
  1495. end;
  1496. end;
  1497. end;
  1498. if AWidth < 6 then AWidth := 6;
  1499. if AHeight < 6 then AHeight := 6;
  1500. with TTBXLabelItem(Item) do
  1501. begin
  1502. Inc(AWidth, Margin shl 1 + 1);
  1503. Inc(AHeight, Margin shl 1 + 1);
  1504. end;
  1505. end;
  1506. procedure TTBXLabelItemViewer.DoAdjustFont(AFont: TFont; StateFlags: Integer);
  1507. begin
  1508. if Item is TTBXLabelItem then
  1509. with TTBXLabelItem(Item) do
  1510. begin
  1511. FontSettings.Apply(AFont);
  1512. if Assigned(FOnAdjustFont) then FOnAdjustFont(Item, Self, AFont, StateFlags);
  1513. end;
  1514. end;
  1515. function TTBXLabelItemViewer.GetCaptionText: string;
  1516. var
  1517. P: Integer;
  1518. begin
  1519. Result := TTBXLabelItem(Item).Caption;
  1520. P := Pos(#9, Result);
  1521. if P <> 0 then SetLength(Result, P - 1);
  1522. end;
  1523. function TTBXLabelItemViewer.GetIsHoriz: Boolean;
  1524. begin
  1525. with TTBXLabelItem(Item) do
  1526. case Orientation of
  1527. tbxoHorizontal: Result := True;
  1528. tbxoVertical: Result := False;
  1529. else // tbxoAuto
  1530. Result := View.Orientation <> tbvoVertical;
  1531. end;
  1532. end;
  1533. function TTBXLabelItemViewer.IsToolbarSize: Boolean;
  1534. begin
  1535. Result := inherited IsToolbarSize;
  1536. Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX);
  1537. end;
  1538. function TTBXLabelItemViewer.IsToolbarStyle: Boolean;
  1539. begin
  1540. Result := inherited IsToolbarStyle;
  1541. Result := Result or ((GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX);
  1542. end;
  1543. procedure TTBXLabelItemViewer.Paint(const Canvas: TCanvas;
  1544. const ClientAreaRect: TRect; IsHoverItem, IsPushed, UseDisabledShadow: Boolean);
  1545. const
  1546. CEnabledStates: array [Boolean] of Integer = (ISF_DISABLED, 0);
  1547. CDesigning: array [Boolean] of Integer = (0, IO_DESIGNING);
  1548. CPrefixes: array [Boolean] of Integer = (DT_NOPREFIX, 0);
  1549. var
  1550. Fmt: Cardinal;
  1551. ItemInfo: TTBXItemInfo;
  1552. R: TRect;
  1553. begin
  1554. FillChar(ItemInfo, SizeOf(ItemInfo), 0);
  1555. ItemInfo.ViewType := GetViewType(View);
  1556. ItemInfo.ItemOptions := IO_TOOLBARSTYLE or CDesigning[csDesigning in Item.ComponentState];
  1557. ItemInfo.Enabled := Item.Enabled or View.Customizing;
  1558. ItemInfo.Pushed := False;
  1559. ItemInfo.Selected := False;
  1560. ItemInfo.ImageShown := False;
  1561. ItemInfo.ImageWidth := 0;
  1562. ItemInfo.ImageHeight := 0;
  1563. ItemInfo.HoverKind := hkNone;
  1564. ItemInfo.IsPopupParent := False;
  1565. ItemInfo.IsVertical := not GetIsHoriz;
  1566. Canvas.Font := TTBViewAccess(View).GetFont;
  1567. Canvas.Font.Color := CurrentTheme.GetItemTextColor(ItemInfo);
  1568. DoAdjustFont(Canvas.Font, CEnabledStates[ItemInfo.Enabled]);
  1569. Fmt := DT_SINGLELINE or DT_CENTER or DT_VCENTER or CPrefixes[TTBXLabelItem(Item).ShowAccelChar];
  1570. R := ClientAreaRect;
  1571. if TTBXLabelItem(Item).SectionHeader and (not IsToolbarStyle) then
  1572. begin
  1573. ItemInfo.PopupMargin := GetPopupMargin(Self);
  1574. CurrentTheme.PaintMenuItem(Canvas, R, ItemInfo);
  1575. Inc(R.Left, ItemInfo.PopupMargin + CurrentTheme.MenuLeftCaptionMargin - 1);
  1576. Canvas.Brush.Color := CurrentTheme.GetViewColor(VT_SECTIONHEADER);
  1577. Canvas.FillRect(R);
  1578. Assert(not ItemInfo.IsVertical);
  1579. Windows.DrawText(Canvas.Handle, PChar(GetCaptionText), Length(GetCaptionText), R, Fmt)
  1580. end
  1581. else
  1582. begin
  1583. Canvas.Brush.Style := bsClear;
  1584. CurrentTheme.PaintCaption(Canvas, R, ItemInfo, GetCaptionText, Fmt, ItemInfo.IsVertical);
  1585. end;
  1586. Canvas.Brush.Style := bsSolid;
  1587. end;
  1588. //============================================================================//
  1589. { TTBXColorItem }
  1590. constructor TTBXColorItem.Create(AOwner: TComponent);
  1591. begin
  1592. inherited;
  1593. FColor := clWhite;
  1594. end;
  1595. function TTBXColorItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  1596. begin
  1597. Result := TTBXColorItemViewer;
  1598. end;
  1599. procedure TTBXColorItem.SetColor(Value: TColor);
  1600. begin
  1601. if FColor <> Value then
  1602. begin
  1603. FColor := Value;
  1604. Change(False);
  1605. end;
  1606. end;
  1607. //============================================================================//
  1608. { TTBXColorItemViewer }
  1609. procedure TTBXColorItemViewer.DrawItemImage(Canvas: TCanvas; ARect: TRect; ItemInfo: TTBXItemInfo);
  1610. begin
  1611. with ItemInfo, Canvas do
  1612. begin
  1613. if TTBXColorItem(Item).Color <> clNone then
  1614. begin
  1615. if ((ItemOptions and IO_TOOLBARSTYLE) = 0) then InflateRect(ARect, -2, -2);
  1616. if Enabled then
  1617. begin
  1618. Brush.Color := clBtnShadow;
  1619. FrameRect(ARect);
  1620. InflateRect(ARect, -1, -1);
  1621. Brush.Color := TTBXColorItem(Item).Color;
  1622. FillRect(ARect);
  1623. end
  1624. else
  1625. begin
  1626. Inc(ARect.Right);
  1627. Inc(ARect.Bottom);
  1628. DrawEdge(Handle, ARect, BDR_SUNKENOUTER or BDR_RAISEDINNER, BF_RECT);
  1629. end;
  1630. end;
  1631. end;
  1632. end;
  1633. procedure TTBXColorItemViewer.DoPaintCaption(Canvas: TCanvas;
  1634. const ClientAreaRect: TRect; var CaptionRect: TRect;
  1635. IsTextRotated: Boolean; var PaintDefault: Boolean);
  1636. begin
  1637. if (GetViewType(View) and PVT_TOOLBOX) = PVT_TOOLBOX then
  1638. begin
  1639. { Center Caption }
  1640. OffsetRect(CaptionRect, -CaptionRect.Left, 0);
  1641. OffsetRect(CaptionRect, (ClientAreaRect.Right - CaptionRect.Right) div 2, 0);
  1642. end;
  1643. end;
  1644. function TTBXColorItemViewer.GetImageSize: TSize;
  1645. var
  1646. ImgList: TCustomImageList;
  1647. Size: Integer;
  1648. begin
  1649. ImgList := GetImageList;
  1650. if ImgList <> nil then
  1651. begin
  1652. Result.CX := ImgList.Width;
  1653. Result.CY := ImgList.Height;
  1654. if IsToolbarStyle then
  1655. begin
  1656. // we want to get 12x12 with 16x16 images,
  1657. // to match the imagelist-less branch below
  1658. Result.CX := MulDiv(Result.CX, 12, 16);
  1659. Result.CY := MulDiv(Result.CY, 12, 16);
  1660. end;
  1661. end
  1662. else
  1663. begin
  1664. // we do not want to get here
  1665. Assert(False);
  1666. if IsToolbarStyle then
  1667. begin
  1668. Size := 12;
  1669. end
  1670. else
  1671. begin
  1672. Size := 16;
  1673. end;
  1674. // do not have a canvas here to scale by text height
  1675. Size := MulDiv(Size, Screen.PixelsPerInch, USER_DEFAULT_SCREEN_DPI);
  1676. Result.CX := Size;
  1677. Result.CY := Size;
  1678. end;
  1679. end;
  1680. function TTBXColorItemViewer.GetImageShown: Boolean;
  1681. begin
  1682. Result := ((Item.DisplayMode in [nbdmDefault, nbdmImageAndText]) or
  1683. (IsToolbarStyle and (Item.DisplayMode = nbdmTextOnlyInMenus)));
  1684. end;
  1685. constructor TTBXColorItemViewer.Create(AView: TTBView; AItem: TTBCustomItem; AGroupLevel: Integer);
  1686. begin
  1687. inherited;
  1688. Wide := False;
  1689. end;
  1690. //============================================================================//
  1691. {$IFNDEF MPEXCLUDE}
  1692. { TTBXMRUList }
  1693. function TTBXMRUList.GetFirstKey:Integer;
  1694. begin
  1695. Result := FKeyShift;
  1696. end;
  1697. function TTBXMRUList.GetItemClass: TTBCustomItemClass;
  1698. begin
  1699. Result := TTBXCustomItem;
  1700. end;
  1701. procedure TTBXMRUList.SetItemCaptions;
  1702. var
  1703. I: Integer;
  1704. begin
  1705. inherited;
  1706. if Container is TTBXCustomItem then
  1707. for I := 0 to Items.Count - 1 do
  1708. TTBXCustomItem(Items[I]).FontSettings := TTBXCustomItem(Container).FontSettings;
  1709. end;
  1710. procedure TTBXMRUList.SetKeyShift(Value: Integer);
  1711. begin
  1712. if Value < 0 then Value := 0;
  1713. FKeyShift := Value;
  1714. SetItemCaptions;
  1715. end;
  1716. //============================================================================//
  1717. { TTBXMRUListItem }
  1718. constructor TTBXMRUListItem.Create(AOwner: TComponent);
  1719. begin
  1720. inherited;
  1721. ItemStyle := ItemStyle + [tbisEmbeddedGroup];
  1722. Caption := STBMRUListItemDefCaption[1] + 'TBX ' +
  1723. Copy(STBMRUListItemDefCaption, 2, Length(STBMRUListItemDefCaption) - 1);
  1724. end;
  1725. procedure TTBXMRUListItem.Notification(AComponent: TComponent;
  1726. Operation: TOperation);
  1727. begin
  1728. inherited;
  1729. if (AComponent = FMRUList) and (Operation = opRemove) then MRUList := nil;
  1730. end;
  1731. procedure TTBXMRUListItem.SetMRUList(Value: TTBMRUList);
  1732. begin
  1733. if FMRUList <> Value then
  1734. begin
  1735. FMRUList := Value;
  1736. if Assigned(Value) then
  1737. begin
  1738. Value.FreeNotification(Self);
  1739. LinkSubitems := TTBMRUListAccess(Value).Container;
  1740. end
  1741. else LinkSubitems := nil;
  1742. end;
  1743. end;
  1744. { TTBXCustomSpinEditItem }
  1745. function TTBXCustomSpinEditItem.CheckValue(const V: Extended): Extended;
  1746. begin
  1747. Result := V;
  1748. if FMaxValue <> FMinValue then
  1749. begin
  1750. if V < FMinValue then Result := FMinValue
  1751. else if V > FMaxValue then Result := FMaxValue;
  1752. end;
  1753. end;
  1754. procedure TTBXCustomSpinEditItem.ClickDown;
  1755. var
  1756. OldValue, NewValue: Extended;
  1757. begin
  1758. OldValue := GetValue;
  1759. if Snap then
  1760. NewValue := Ceil(OldValue / Increment - 1 - Increment * 0.0001) * Increment
  1761. else
  1762. NewValue := OldValue - FIncrement;
  1763. DoStep(-1, OldValue, NewValue);
  1764. SetValueEx(NewValue, tcrSpinButton);
  1765. end;
  1766. procedure TTBXCustomSpinEditItem.ClickUp;
  1767. var
  1768. OldValue, NewValue: Extended;
  1769. begin
  1770. OldValue := GetValue;
  1771. if Snap then
  1772. NewValue := Floor(OldValue / Increment + 1 + Increment * 0.0001) * Increment
  1773. else
  1774. NewValue := OldValue + FIncrement;
  1775. DoStep(+1, OldValue, NewValue);
  1776. SetValueEx(NewValue, tcrSpinButton);
  1777. end;
  1778. constructor TTBXCustomSpinEditItem.Create(AOwner: TComponent);
  1779. begin
  1780. inherited;
  1781. FAlignment := taRightJustify;
  1782. FDecimal := 2;
  1783. FIncrement := 1;
  1784. FSnap := True;
  1785. Text := '0';
  1786. end;
  1787. function TTBXCustomSpinEditItem.DoAcceptText(var NewText: string): Boolean;
  1788. var
  1789. V: Extended;
  1790. begin
  1791. if ParseValue(NewText, V) then
  1792. begin
  1793. NewText := GetAsText(V);
  1794. Result := True;
  1795. end
  1796. else Result := False;
  1797. end;
  1798. function TTBXCustomSpinEditItem.DoConvert(const APrefix, APostfix: string; var AValue: Extended): Boolean;
  1799. begin
  1800. Result := True;
  1801. if Assigned(FOnConvert) then FOnConvert(Self, APrefix, APostfix, AValue, Result);
  1802. end;
  1803. procedure TTBXCustomSpinEditItem.DoStep(Step: Integer; const OldValue: Extended; var NewValue: Extended);
  1804. begin
  1805. if Assigned(FOnStep) then FOnStep(Self, Step, OldValue, NewValue);
  1806. end;
  1807. procedure TTBXCustomSpinEditItem.DoTextChanged(Reason: Integer);
  1808. begin
  1809. if Reason = tcrEditControl then
  1810. SetValueEx(GetValue, tcrNumericProperty);
  1811. end;
  1812. function TTBXCustomSpinEditItem.DoTextToValue(const AText: string; out AValue: Extended): Boolean;
  1813. begin
  1814. Result := False;
  1815. if Assigned(FOnTextToValue) then FOnTextToValue(Self, AText, AValue, Result);
  1816. end;
  1817. procedure TTBXCustomSpinEditItem.DoValueChange(const V: Extended);
  1818. begin
  1819. if Assigned(FOnValueChange) then FOnValueChange(Self, V);
  1820. end;
  1821. procedure TTBXCustomSpinEditItem.DoValueToText(const NewValue: Extended; var NewText: string);
  1822. begin
  1823. if Assigned(FOnValueToText) then FOnValueToText(Self, NewValue, NewText);
  1824. end;
  1825. function TTBXCustomSpinEditItem.GetAsInteger: Integer;
  1826. begin
  1827. Result := Round(Value);
  1828. end;
  1829. function TTBXCustomSpinEditItem.GetAsText(AValue: Extended): string;
  1830. begin
  1831. AValue := CheckValue(AValue);
  1832. if ValueType = evtFloat then Result := FloatToStrF(AValue, ffFixed, 15, FDecimal)
  1833. else if ValueType = evtHex then Result := IntToHex(Round(AValue), 1)
  1834. else Result := IntToStr(Round(AValue));
  1835. if Length(Prefix) > 0 then
  1836. begin
  1837. if SpaceAfterPrefix then Result := ' ' + Result;
  1838. Result := Prefix + Result;
  1839. end;
  1840. if Length(Postfix) > 0 then
  1841. begin
  1842. if SpaceBeforePostfix then Result := Result + ' ';
  1843. Result := Result + Postfix;
  1844. end;
  1845. DoValueToText(AValue, Result);
  1846. end;
  1847. function TTBXCustomSpinEditItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  1848. begin
  1849. if not (tboUseEditWhenVertical in EditOptions) and
  1850. (AView.Orientation = tbvoVertical) then
  1851. Result := TTBXItemViewer
  1852. else
  1853. Result := TTBXSpinEditViewer;
  1854. end;
  1855. function TTBXCustomSpinEditItem.GetValue: Extended;
  1856. begin
  1857. if not ParseValue(Text, Result) then
  1858. Result := FLastGoodValue;
  1859. end;
  1860. function TTBXCustomSpinEditItem.IsIncrementStored: Boolean;
  1861. begin
  1862. Result := FIncrement <> 1;
  1863. end;
  1864. function TTBXCustomSpinEditItem.IsMaxValueStored: Boolean;
  1865. begin
  1866. Result := FMaxValue <> 0;
  1867. end;
  1868. function TTBXCustomSpinEditItem.IsMinValueStored: Boolean;
  1869. begin
  1870. Result := FMinValue <> 0;
  1871. end;
  1872. function TTBXCustomSpinEditItem.IsValueStored: Boolean;
  1873. begin
  1874. Result := GetValue <> 0;
  1875. end;
  1876. function TTBXCustomSpinEditItem.ParseValue(const S: string; out V: Extended): Boolean;
  1877. const
  1878. CWhiteSpace = [' ', #9];
  1879. CDigits = ['0'..'9'];
  1880. CHexDigits = CDigits + ['A'..'F'];
  1881. CInvalidUnitChars = [#0..#31, ' ', '*', '+', ',', '-', '.', '/', '0'..'9', '^'];
  1882. CInvalidHexUnitChars = CInvalidUnitChars + ['A'..'F'];
  1883. var
  1884. P: PChar;
  1885. Sign1: Integer;
  1886. Value1: Extended;
  1887. Value2: Extended;
  1888. Operator: Char;
  1889. PrefixString, PostfixString: string;
  1890. procedure SkipWhiteSpace;
  1891. begin
  1892. while P^ in CWhiteSpace do Inc(P);
  1893. end;
  1894. function GetInt: Integer;
  1895. begin
  1896. Result := 0;
  1897. while P^ in CDigits do
  1898. begin
  1899. Result := Result * 10 + (Integer(P^) - Integer('0'));
  1900. Inc(P);
  1901. end;
  1902. end;
  1903. function GetInt2: Extended;
  1904. begin
  1905. Result := 0;
  1906. while P^ in CDigits do
  1907. begin
  1908. Result := Result * 10 + (Integer(P^) - Integer('0'));
  1909. Inc(P);
  1910. end;
  1911. end;
  1912. function GetNumber(out PrefixString, PostfixString: string; out R: Extended): Boolean;
  1913. var
  1914. PStart: PChar;
  1915. Tmp: Integer;
  1916. ExponentSign, IR: Integer;
  1917. Count1, Count2: Integer;
  1918. E: Extended;
  1919. begin
  1920. R := 0;
  1921. Result := False;
  1922. { Read prefix }
  1923. PStart := P;
  1924. if ValueType <> evtHex then while not (P^ in CInvalidUnitChars) do Inc(P)
  1925. else while not (P^ in CInvalidHexUnitChars) do Inc(P);
  1926. SetString(PrefixString, PStart, P - PStart);
  1927. SkipWhiteSpace;
  1928. { Read value }
  1929. if ValueType in [evtFloat, evtInteger] then
  1930. begin
  1931. if (ValueType = evtInteger) and not (P^ in CDigits) then Exit;
  1932. { get the integer part }
  1933. PStart := P;
  1934. R := GetInt2;
  1935. Count1 := P - PStart;
  1936. if (ValueType = evtFloat) and (P^ = DecimalSeparator) then
  1937. begin
  1938. Inc(P);
  1939. PStart := P;
  1940. E := GetInt2;
  1941. R := R + E / IntPower(10, P - PStart);
  1942. Count2 := P - PStart;
  1943. end
  1944. else Count2 := 0;
  1945. if (Count1 = 0) and (Count2 = 0) then Exit; // '.' (or ',') is not a number
  1946. if (ValueType = evtFloat) and (P^ in ['e', 'E']) and (PChar(P + 1)^ in ['+', '-', '0'..'9']) then
  1947. begin
  1948. Inc(P);
  1949. ExponentSign := 1;
  1950. if P^ = '-' then
  1951. begin
  1952. ExponentSign := -1;
  1953. Inc(P);
  1954. end
  1955. else if P^ = '+' then Inc(P);
  1956. if not (P^ in CDigits) then Exit;
  1957. Tmp := GetInt;
  1958. if Tmp >= 5000 then Exit;
  1959. R := R * IntPower(10, Tmp * ExponentSign);
  1960. end;
  1961. end
  1962. else { evtHex }
  1963. begin
  1964. IR := 0;
  1965. if not (P^ in CHexDigits) then Exit;
  1966. while P^ in CHexDigits do
  1967. begin
  1968. IR := IR shl 4;
  1969. if P^ in CDigits then Inc(IR, Integer(P^) - Integer('0'))
  1970. else if P^ in ['a'..'f'] then Inc(IR, Integer(P^) - Integer('a') + 10)
  1971. else Inc(IR, Integer(P^) - Integer('A') + 10);
  1972. Inc(P);
  1973. end;
  1974. R := IR;
  1975. end;
  1976. SkipWhiteSpace;
  1977. { Read postfix }
  1978. PStart := P;
  1979. if ValueType <> evtHex then while not (P^ in CInvalidUnitChars) do Inc(P)
  1980. else while not (P^ in CInvalidHexUnitChars) do Inc(P);
  1981. SetString(PostfixString, PStart, P - PStart);
  1982. SkipWhiteSpace;
  1983. Result := True;
  1984. end;
  1985. begin
  1986. V := 0;
  1987. { Try text-to-value conversion for predefined "constants" }
  1988. Result := DoTextToValue(S, V);
  1989. if Result then Exit;
  1990. { Parse the string for values and expressions }
  1991. if Length(S) = 0 then Exit;
  1992. P := PChar(S);
  1993. SkipWhiteSpace;
  1994. { Read the sign }
  1995. Sign1 := 1;
  1996. if P^ = '-' then
  1997. begin
  1998. Sign1 := -1;
  1999. Inc(P);
  2000. SkipWhiteSpace;
  2001. end
  2002. else if P^ = '+' then
  2003. begin
  2004. Inc(P);
  2005. SkipWhiteSpace;
  2006. end;
  2007. { Read value }
  2008. if not GetNumber(PrefixString, PostfixString, Value1) then Exit;
  2009. if not DoConvert(PrefixString, PostfixString, Value1) then Exit;
  2010. Value1 := Value1 * Sign1;
  2011. V := Value1;
  2012. { Read operator }
  2013. if P^ in ['*', '+', '-', '/'] then
  2014. begin
  2015. Operator := P^;
  2016. Inc(P);
  2017. SkipWhiteSpace;
  2018. if not GetNumber(PrefixString, PostfixString, Value2) then Exit;
  2019. if not DoConvert(PrefixString, PostfixString, Value2) then Exit;
  2020. case Operator of
  2021. '*': V := V * Value2;
  2022. '+': V := V + Value2;
  2023. '-': V := V - Value2;
  2024. '/': if Value2 <> 0 then V := V / Value2 else Exit;
  2025. end;
  2026. end;
  2027. if P^ = #0 then Result := True;
  2028. end;
  2029. procedure TTBXCustomSpinEditItem.SetAsInteger(AValue: Integer);
  2030. begin
  2031. Value := AValue;
  2032. end;
  2033. procedure TTBXCustomSpinEditItem.SetDecimal(NewDecimal: TDecimal);
  2034. begin
  2035. if NewDecimal <> FDecimal then
  2036. begin
  2037. FDecimal := NewDecimal;
  2038. SetValueEx(GetValue, tcrNumericProperty);
  2039. end;
  2040. end;
  2041. procedure TTBXCustomSpinEditItem.SetIncrement(const NewIncrement: Extended);
  2042. begin
  2043. if NewIncrement <= 0 then
  2044. raise EPropertyError.Create('Increment should be a positive value');
  2045. FIncrement := NewIncrement;
  2046. end;
  2047. procedure TTBXCustomSpinEditItem.SetPostfix(const NewPostfix: string);
  2048. begin
  2049. if not ValidateUnits(NewPostfix) then
  2050. raise EPropertyError.Create('Invalid postfix');
  2051. FPostfix := NewPostfix;
  2052. SetValueEx(GetValue, tcrNumericProperty);
  2053. end;
  2054. procedure TTBXCustomSpinEditItem.SetPrefix(const NewPrefix: string);
  2055. begin
  2056. if not ValidateUnits(NewPrefix) then
  2057. raise EPropertyError.Create('Invalid prefix');
  2058. FPrefix := NewPrefix;
  2059. SetValueEx(GetValue, tcrNumericProperty);
  2060. end;
  2061. procedure TTBXCustomSpinEditItem.SetSpaceAfterPrefix(UseSpace: Boolean);
  2062. begin
  2063. FSpaceAfterPrefix := UseSpace;
  2064. SetValueEx(GetValue, tcrNumericProperty);
  2065. end;
  2066. procedure TTBXCustomSpinEditItem.SetSpaceBeforePostfix(UseSpace: Boolean);
  2067. begin
  2068. FSpaceBeforePostfix := UseSpace;
  2069. SetValueEx(GetValue, tcrNumericProperty);
  2070. end;
  2071. procedure TTBXCustomSpinEditItem.SetValue(NewValue: Extended);
  2072. begin
  2073. SetTextEx(GetAsText(NewValue), tcrNumericProperty);
  2074. if FLastGoodValue <> NewValue then
  2075. begin
  2076. FLastGoodValue := NewValue;
  2077. DoValueChange(NewValue);
  2078. end;
  2079. end;
  2080. procedure TTBXCustomSpinEditItem.SetValueEx(NewValue: Extended; Reason: Integer);
  2081. begin
  2082. SetTextEx(GetAsText(NewValue), Reason);
  2083. if FLastGoodValue <> NewValue then
  2084. begin
  2085. FLastGoodValue := NewValue;
  2086. DoValueChange(NewValue);
  2087. end;
  2088. end;
  2089. procedure TTBXCustomSpinEditItem.SetValueType(NewType: TSEValueType);
  2090. var
  2091. V: Extended;
  2092. begin
  2093. if NewType <> FValueType then
  2094. begin
  2095. V := GetValue;
  2096. FValueType := NewType;
  2097. SetValueEx(V, tcrNumericProperty);
  2098. if NewType in [evtInteger, evtHex] then FIncrement := Max(Round(FIncrement), 1);
  2099. end;
  2100. end;
  2101. function TTBXCustomSpinEditItem.ValidateUnits(const S: string): Boolean;
  2102. const
  2103. InvalidChars = [#0..#31, ' ', '*', '+', ',', '-', '.', '/', '0'..'9', '^'];
  2104. var
  2105. I: Integer;
  2106. begin
  2107. Result := False;
  2108. if Length(S) > 0 then
  2109. for I := 1 to Length(S) do
  2110. if S[I] in InvalidChars then Exit;
  2111. Result := True;
  2112. end;
  2113. { TTBXSpinEditViewer }
  2114. destructor TTBXSpinEditViewer.Destroy;
  2115. begin
  2116. FBtnTimer.Free;
  2117. inherited;
  2118. end;
  2119. procedure TTBXSpinEditViewer.GetEditInfo(out EditInfo: TTBXEditInfo; const ItemInfo: TTBXItemInfo);
  2120. const
  2121. CDisabled: array [Boolean] of Integer = (EBSS_DISABLED, 0);
  2122. CHot: array [Boolean] of Integer = (0, EBSS_HOT);
  2123. CUpDnState: array [TSEBtnState] of Integer = (0, EBSS_UP, EBSS_DOWN);
  2124. begin
  2125. inherited GetEditInfo(EditInfo, ItemInfo);
  2126. EditInfo.RightBtnInfo.ButtonType := EBT_SPIN;
  2127. EditInfo.RightBtnInfo.ButtonState := CDisabled[ItemInfo.Enabled] or
  2128. CHot[ItemInfo.HoverKind = hkMouseHover] or CUpDnState[FBtnState];
  2129. end;
  2130. function TTBXSpinEditViewer.GetIndentAfter: Integer;
  2131. begin
  2132. if IsToolbarStyle then Result := CurrentTheme.EditBtnWidth + 2
  2133. else Result := GetSystemMetrics(SM_CXMENUCHECK) + 2;
  2134. end;
  2135. function TTBXSpinEditViewer.HandleEditMessage(var Message: TMessage): Boolean;
  2136. var
  2137. Item: TTBXCustomSpinEditItem;
  2138. function Val: Extended;
  2139. begin
  2140. if not Item.ParseValue(EditControl.Text, Result) then Result := Item.FLastGoodValue;
  2141. end;
  2142. begin
  2143. Item := TTBXCustomSpinEditItem(Self.Item);
  2144. if Message.Msg = WM_CHAR then
  2145. case TWMChar(Message).CharCode of
  2146. VK_TAB:
  2147. begin
  2148. Item.Value := Val;
  2149. EditControl.Text := Item.Text;
  2150. end;
  2151. VK_RETURN:
  2152. begin
  2153. Item.Value := Val;
  2154. EditControl.Text := Item.Text;
  2155. end;
  2156. VK_ESCAPE:
  2157. begin
  2158. // Item.Value := Item.GetValue;
  2159. end;
  2160. end
  2161. else if Message.Msg = WM_KEYDOWN then
  2162. case TWMKeyDown(Message).CharCode of
  2163. VK_UP:
  2164. begin
  2165. Item.ClickUp;
  2166. EditControl.Text := Item.Text;
  2167. EditControl.SelectAll;
  2168. Result := True;
  2169. Exit;
  2170. end;
  2171. VK_DOWN:
  2172. begin
  2173. Item.ClickDown;
  2174. EditControl.Text := Item.Text;
  2175. EditControl.SelectAll;
  2176. Result := True;
  2177. Exit;
  2178. end;
  2179. end;
  2180. Result := inherited HandleEditMessage(Message);
  2181. end;
  2182. procedure TTBXSpinEditViewer.InvalidateButtons;
  2183. var
  2184. R: TRect;
  2185. begin
  2186. with TTBXSpinEditItem(Item) do
  2187. if Show and not IsRectEmpty(BoundsRect) then
  2188. begin
  2189. R := BoundsRect;
  2190. R.Left := R.Right - GetIndentAfter;
  2191. InvalidateRect(View.Window.Handle, @R, False);
  2192. Include(State, tbisInvalidated);
  2193. end;
  2194. end;
  2195. function TTBXSpinEditViewer.IsPtInButtonPart(X, Y: Integer): Boolean;
  2196. begin
  2197. Result := X <= (BoundsRect.Right - BoundsRect.Left) - GetIndentAfter;
  2198. end;
  2199. procedure TTBXSpinEditViewer.LosingCapture;
  2200. begin
  2201. FBtnTimer.Free;
  2202. FBtnTimer := nil;
  2203. inherited;
  2204. end;
  2205. procedure TTBXSpinEditViewer.MouseDown(Shift: TShiftState; X, Y: Integer; var MouseDownOnMenu: Boolean);
  2206. begin
  2207. if not Item.Enabled then Exit;
  2208. FBtnState := ebsNone;
  2209. if X >= BoundsRect.Right - BoundsRect.Left - GetIndentAfter then
  2210. begin
  2211. if Y < (BoundsRect.Bottom - BoundsRect.Top) div 2 then
  2212. begin
  2213. FBtnState := ebsUp;
  2214. TTBXSpinEditItem(Item).ClickUp;
  2215. end
  2216. else
  2217. begin
  2218. FBtnState := ebsDown;
  2219. TTBXSpinEditItem(Item).ClickDown;
  2220. end;
  2221. if FBtnTimer = nil then
  2222. begin
  2223. FBtnTimer := TTimer.Create(nil);
  2224. FBtnTimer.OnTimer := TimerHandler;
  2225. end;
  2226. FBtnTimer.Interval := SE_FIRSTINTERVAL;
  2227. FBtnTimer.Enabled := True;
  2228. end;
  2229. if FBtnState <> ebsNone then
  2230. begin
  2231. InvalidateButtons;
  2232. inherited;
  2233. View.SetCapture;
  2234. end
  2235. else inherited;
  2236. end;
  2237. procedure TTBXSpinEditViewer.MouseUp(X, Y: Integer; MouseWasDownOnMenu: Boolean);
  2238. begin
  2239. if FBtnState <> ebsNone then
  2240. begin
  2241. FBtnState := ebsNone;
  2242. FBtnTimer.Free;
  2243. FBtnTimer := nil;
  2244. InvalidateButtons;
  2245. end;
  2246. inherited;
  2247. end;
  2248. procedure TTBXSpinEditViewer.TimerHandler(Sender: TObject);
  2249. begin
  2250. FBtnTimer.Interval := SE_INTERVAL;
  2251. if FBtnState = ebsUp then TTBXSpinEditItem(Item).ClickUp
  2252. else if FBtnState = ebsDown then TTBXSpinEditItem(Item).ClickDown
  2253. else
  2254. begin
  2255. FBtnTimer.Free;
  2256. FBtnTimer := nil;
  2257. end;
  2258. end;
  2259. {$ENDIF}
  2260. end.