TBXExtItems.pas 76 KB

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