bcbuttonfocus.pas 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918
  1. // SPDX-License-Identifier: LGPL-3.0-linking-exception
  2. { Customizable component which using BGRABitmap for drawing. Control mostly rendered
  3. using framework.
  4. Functionality:
  5. - Gradients
  6. - Double gradients
  7. - Rounding
  8. - Drop down list
  9. - Glyph
  10. - States (normal, hover, clicked)
  11. - Caption with shadow
  12. - Full alpha and antialias support
  13. originally written in 2012 by Krzysztof Dibowski dibowski at interia.pl
  14. }
  15. {******************************* CONTRIBUTOR(S) ******************************
  16. - Edivando S. Santos Brasil | [email protected]
  17. (Compatibility with delphi VCL 11/2018)
  18. ***************************** END CONTRIBUTOR(S) *****************************}
  19. unit BCButtonFocus;
  20. {$I bgracontrols.inc}
  21. interface
  22. uses
  23. Classes, {$IFDEF FPC}LCLType, LResources, LMessages,{$ENDIF} Controls, Dialogs,
  24. ActnList, ImgList, Menus, // MORA
  25. Buttons, Graphics, types,
  26. {$IFNDEF FPC}Windows, Messages, BGRAGraphics, GraphType, FPImage, {$ENDIF}
  27. BGRABitmap, BGRABitmapTypes, BCTypes, Forms, BCBasectrls, BCThemeManager;
  28. {off $DEFINE DEBUG}
  29. type
  30. TBCButtonFocusMemoryUsage = (bmuLowF, bmuMediumF, bmuHighF);
  31. TBCButtonFocusState = class;
  32. TBCButtonFocusStyle = (bbtButtonF, bbtDropDownF);
  33. TOnAfterRenderBCButtonFocus = procedure(Sender: TObject; const ABGRA: TBGRABitmap;
  34. AState: TBCButtonFocusState; ARect: TRect) of object;
  35. TBCButtonFocusPropertyData = (pdNoneF, pdUpdateSizeF);
  36. // MORA: DropDown styles
  37. TBCButtonFocusDropDownStyle = (
  38. bdsSeparateF, // DropDown is a separate button (default)
  39. bdsCommonF // DropDown is same as main button
  40. );
  41. TBCButtonFocusDropDownPosition = (
  42. bdpLeftF, // default
  43. bdpBottomF);
  44. { TBCButtonFocusState }
  45. TBCButtonFocusState = class(TBCProperty)
  46. private
  47. FBackground: TBCBackground;
  48. FBorder: TBCBorder;
  49. FFontEx: TBCFont;
  50. procedure OnChangeFont({%H-}Sender: TObject; {%H-}AData: PtrInt);
  51. procedure OnChangeChildProperty({%H-}Sender: TObject; AData: PtrInt);
  52. procedure SetBackground(AValue: TBCBackground);
  53. procedure SetBorder(AValue: TBCBorder);
  54. procedure SetFontEx(const AValue: TBCFont);
  55. public
  56. constructor Create(AControl: TControl); override;
  57. destructor Destroy; override;
  58. procedure Assign(Source: TPersistent); override;
  59. published
  60. property Background: TBCBackground read FBackground write SetBackground;
  61. property Border: TBCBorder read FBorder write SetBorder;
  62. property FontEx: TBCFont read FFontEx write SetFontEx;
  63. end;
  64. { TCustomBCButtonFocus }
  65. TCustomBCButtonFocus = class(TBCStyleCustomControl)
  66. private
  67. { Private declarations }
  68. {$IFDEF INDEBUG}
  69. FRenderCount: integer;
  70. {$ENDIF}
  71. FDropDownArrowSize: integer;
  72. FDropDownWidth: integer;
  73. FFlipArrow: boolean;
  74. FActiveButt: TBCButtonFocusStyle;
  75. FBGRANormal, FBGRAHover, FBGRAClick: TBGRABitmapEx;
  76. FGlyphAlignment: TBCAlignment;
  77. FGlyphOldPlacement: boolean;
  78. FInnerMargin: single;
  79. FMemoryUsage: TBCButtonFocusMemoryUsage;
  80. FOnPaintButton: TNotifyEvent;
  81. FPreserveGlyphOnAssign: boolean;
  82. FRounding: TBCRounding;
  83. FRoundingDropDown: TBCRounding;
  84. FStateClicked: TBCButtonFocusState;
  85. FStateHover: TBCButtonFocusState;
  86. FStateNormal: TBCButtonFocusState;
  87. FDown: boolean;
  88. FGlyph: TBitmap;
  89. FGlyphMargin: integer;
  90. FButtonState: TBCMouseState;
  91. FDownButtonState: TBCMouseState;
  92. FOnAfterRenderBCButton: TOnAfterRenderBCButtonFocus;
  93. FOnButtonClick: TNotifyEvent;
  94. FStaticButton: boolean;
  95. FStyle: TBCButtonFocusStyle;
  96. FGlobalOpacity: byte;
  97. FTextApplyGlobalOpacity: boolean;
  98. AutoSizeExtraY: integer;
  99. AutoSizeExtraX: integer;
  100. FLastBorderWidth: integer;
  101. // MORA
  102. FClickOffset: boolean;
  103. FDropDownArrow: boolean;
  104. FDropDownMenu: TPopupMenu;
  105. FDropDownMenuVisible: boolean;
  106. FDropDownClosingTime: TDateTime;
  107. FDropDownPosition: TBCButtonFocusDropDownPosition;
  108. FDropDownStyle: TBCButtonFocusDropDownStyle;
  109. FImageChangeLink: TChangeLink;
  110. FImageIndex: integer;
  111. FImages: TCustomImageList;
  112. FSaveDropDownClosed: TNotifyEvent;
  113. FShowCaption: boolean;
  114. procedure AssignDefaultStyle;
  115. procedure CalculateGlyphSize(out NeededWidth, NeededHeight: integer);
  116. procedure DropDownClosed(Sender: TObject);
  117. procedure RenderAll(ANow: boolean = False);
  118. function GetButtonRect: TRect;
  119. function GetDropDownWidth(AFull: boolean = True): integer;
  120. function GetDropDownRect(AFull: boolean = True): TRect;
  121. procedure SeTBCButtonStateClicked(const AValue: TBCButtonFocusState);
  122. procedure SeTBCButtonStateHover(const AValue: TBCButtonFocusState);
  123. procedure SeTBCButtonStateNormal(const AValue: TBCButtonFocusState);
  124. procedure SetClickOffset(AValue: boolean);
  125. procedure SetDown(AValue: boolean);
  126. procedure SetDropDownArrow(AValue: boolean);
  127. procedure SetDropDownArrowSize(AValue: integer);
  128. procedure SetDropDownPosition(AValue: TBCButtonFocusDropDownPosition);
  129. procedure SetDropDownWidth(AValue: integer);
  130. procedure SetFlipArrow(AValue: boolean);
  131. procedure SetGlyph(const AValue: TBitmap);
  132. procedure SetGlyphAlignment(AValue: TBCAlignment);
  133. procedure SetGlyphMargin(const AValue: integer);
  134. procedure SetGlyphOldPlacement(AValue: boolean);
  135. procedure SetImageIndex(AValue: integer);
  136. procedure SetImages(AValue: TCustomImageList);
  137. procedure SetInnerMargin(AValue: single);
  138. procedure SetMemoryUsage(AValue: TBCButtonFocusMemoryUsage);
  139. procedure SetRounding(AValue: TBCRounding);
  140. procedure SetRoundingDropDown(AValue: TBCRounding);
  141. procedure SetShowCaption(AValue: boolean);
  142. procedure SetStaticButton(const AValue: boolean);
  143. procedure SetStyle(const AValue: TBCButtonFocusStyle);
  144. procedure SetGlobalOpacity(const AValue: byte);
  145. procedure SetTextApplyGlobalOpacity(const AValue: boolean);
  146. procedure UpdateSize;
  147. procedure OnChangeGlyph({%H-}Sender: TObject);
  148. procedure OnChangeState({%H-}Sender: TObject; AData: PtrInt);
  149. procedure ImageListChange(ASender: TObject);
  150. function GetGlyph: TBitmap;
  151. protected
  152. { Protected declarations }
  153. procedure LimitMemoryUsage;
  154. procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
  155. {%H-}WithThemeSpace: boolean); override;
  156. class function GetControlClassDefaultSize: TSize; override;
  157. procedure Click; override;
  158. procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  159. X, Y: integer); override;
  160. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override;
  161. procedure MouseEnter; override;
  162. procedure MouseLeave; override;
  163. procedure MouseMove(Shift: TShiftState; X, Y: integer); override;
  164. procedure SetEnabled(Value: boolean); override;
  165. procedure TextChanged; override;
  166. procedure KeyDown(var Key: word; Shift: TShiftState); override;
  167. procedure KeyUp(var Key: word; Shift: TShiftState); override;
  168. protected
  169. // MORA
  170. procedure ActionChange(Sender: TObject; CheckDefaults: boolean); override;
  171. function GetActionLinkClass: TControlActionLinkClass; override;
  172. procedure Notification(AComponent: TComponent; Operation: TOperation);
  173. override;
  174. procedure Render(ABGRA: TBGRABitmapEx; AState: TBCButtonFocusState); virtual;
  175. procedure RenderState(ABGRA: TBGRABitmapEx; AState: TBCButtonFocusState;
  176. const ARect: TRect; ARounding: TBCRounding); virtual;
  177. property ClickOffset: boolean read FClickOffset write SetClickOffset default False;
  178. property DropDownArrow: boolean
  179. read FDropDownArrow write SetDropDownArrow default False;
  180. property DropDownMenu: TPopupMenu read FDropDownMenu write FDropDownMenu;
  181. property DropDownStyle: TBCButtonFocusDropDownStyle
  182. read FDropDownStyle write FDropDownStyle default bdsSeparateF;
  183. property DropDownPosition: TBCButtonFocusDropDownPosition
  184. read FDropDownPosition write SetDropDownPosition default bdpLeftF;
  185. property Images: TCustomImageList read FImages write SetImages;
  186. property ImageIndex: integer read FImageIndex write SetImageIndex default -1;
  187. property ShowCaption: boolean read FShowCaption write SetShowCaption default True;
  188. protected
  189. {$IFDEF INDEBUG}
  190. function GetDebugText: string; override;
  191. {$ENDIF}
  192. function GetStyleExtension: string; override;
  193. procedure DrawControl; override;
  194. procedure RenderControl; override;
  195. protected
  196. procedure WMSetFocus(var Message: {$IFDEF FPC}TLMSetFocus{$ELSE}TWMSetFocus{$ENDIF}); message {$IFDEF FPC}LM_SETFOCUS{$ELSE}WM_SETFOCUS{$ENDIF};
  197. procedure WMKillFocus(var Message: {$IFDEF FPC}TLMKillFocus{$ELSE}TWMKillFocus{$ENDIF}); message {$IFDEF FPC}LM_KILLFOCUS{$ELSE}WM_KILLFOCUS{$ENDIF};
  198. procedure UpdateFocus(AFocused: boolean);
  199. property AutoSizeExtraVertical: integer read AutoSizeExtraY;
  200. property AutoSizeExtraHorizontal: integer read AutoSizeExtraX;
  201. property StateNormal: TBCButtonFocusState read FStateNormal write SeTBCButtonStateNormal;
  202. property StateHover: TBCButtonFocusState read FStateHover write SeTBCButtonStateHover;
  203. property StateClicked: TBCButtonFocusState read FStateClicked
  204. write SeTBCButtonStateClicked;
  205. property Down: boolean read FDown write SetDown default False;
  206. property DropDownWidth: integer read FDropDownWidth write SetDropDownWidth;
  207. property DropDownArrowSize: integer read FDropDownArrowSize
  208. write SetDropDownArrowSize;
  209. property FlipArrow: boolean read FFlipArrow write SetFlipArrow default False;
  210. property Glyph: TBitmap read GetGlyph write SetGlyph;
  211. property GlyphMargin: integer read FGlyphMargin write SetGlyphMargin default 5;
  212. property GlyphAlignment: TBCAlignment read FGlyphAlignment write SetGlyphAlignment default bcaCenter;
  213. property GlyphOldPlacement: boolean read FGlyphOldPlacement write SetGlyphOldPlacement default true;
  214. property Style: TBCButtonFocusStyle read FStyle write SetStyle default bbtButtonF;
  215. property StaticButton: boolean
  216. read FStaticButton write SetStaticButton default False;
  217. property GlobalOpacity: byte read FGlobalOpacity write SetGlobalOpacity;
  218. property Rounding: TBCRounding read FRounding write SetRounding;
  219. property RoundingDropDown: TBCRounding read FRoundingDropDown
  220. write SetRoundingDropDown;
  221. property TextApplyGlobalOpacity: boolean
  222. read FTextApplyGlobalOpacity write SetTextApplyGlobalOpacity;
  223. property OnAfterRenderBCButton: TOnAfterRenderBCButtonFocus
  224. read FOnAfterRenderBCButton write FOnAfterRenderBCButton;
  225. property OnButtonClick: TNotifyEvent read FOnButtonClick write FOnButtonClick;
  226. property MemoryUsage: TBCButtonFocusMemoryUsage read FMemoryUsage write SetMemoryUsage;
  227. property InnerMargin: single read FInnerMargin write SetInnerMargin;
  228. property OnPaintButton: TNotifyEvent read FOnPaintButton write FOnPaintButton;
  229. property PreserveGlyphOnAssign: boolean read FPreserveGlyphOnAssign write FPreserveGlyphOnAssign default True;
  230. public
  231. { Constructor }
  232. constructor Create(AOwner: TComponent); override;
  233. { Destructor }
  234. destructor Destroy; override;
  235. { Assign the properties from Source to this instance }
  236. procedure Assign(Source: TPersistent); override;
  237. { Set dropdown size and autosize extra padding }
  238. procedure SetSizeVariables(newDropDownWidth, newDropDownArrowSize,
  239. newAutoSizeExtraVertical, newAutoSizeExtraHorizontal: integer);
  240. { Called by EndUpdate }
  241. procedure UpdateControl; override;
  242. public
  243. {$IFDEF FPC}
  244. { Save all published settings to file }
  245. procedure SaveToFile(AFileName: string);
  246. { Load and assign all published settings from file }
  247. procedure LoadFromFile(AFileName: string);
  248. { Assign the properties from AFileName to this instance }
  249. procedure AssignFromFile(AFileName: string);
  250. {$ENDIF}
  251. { Used by SaveToFile/LoadFromFile }
  252. procedure OnFindClass({%H-}Reader: TReader; const AClassName: string;
  253. var ComponentClass: TComponentClass);
  254. end;
  255. TBCButtonFocus = class(TCustomBCButtonFocus)
  256. private
  257. FBCThemeManager: TBCThemeManager;
  258. procedure SetFBCThemeManager(AValue: TBCThemeManager);
  259. published
  260. property Action;
  261. property Align;
  262. property Anchors;
  263. { Click to edit the style. Available when editing only. If you want to stream the style from a file at runtime please use LoadFromFile and SaveToFile methods. }
  264. property AssignStyle;
  265. property AutoSize;
  266. { The style of the button when pressed. }
  267. property StateClicked;
  268. { The style of the button when hovered. }
  269. property StateHover;
  270. { The default style of the button. }
  271. property StateNormal;
  272. property BorderSpacing;
  273. property Caption;
  274. property Color;
  275. property Constraints;
  276. { Set to True to change the button to always show a StateClicked style that will not change when button is clicked or hovered. }
  277. property Down;
  278. { The width of the dropdown arrow area. }
  279. property DropDownWidth;
  280. { The size of the dropdown arrow. }
  281. property DropDownArrowSize;
  282. property Enabled;
  283. { Changes the direction of the arrow. Default: False. }
  284. property FlipArrow;
  285. { Set the opacity that will be applied to the whole button. Default: 255. }
  286. property GlobalOpacity;
  287. { The glyph icon. }
  288. property Glyph;
  289. property GlyphAlignment;
  290. property GlyphOldPlacement;
  291. property PreserveGlyphOnAssign;
  292. { The margin of the glyph icon. }
  293. property GlyphMargin;
  294. property Hint;
  295. property InnerMargin;
  296. { Called when the button finish the render. Use it to add your own drawings to the button. }
  297. property OnAfterRenderBCButton;
  298. { Called when the button part is clicked, not the dropdown. }
  299. property OnButtonClick;
  300. property OnClick;
  301. property OnDblClick;
  302. property OnMouseDown;
  303. property OnMouseEnter;
  304. property OnMouseLeave;
  305. property OnMouseMove;
  306. property OnMouseUp;
  307. property OnMouseWheel;
  308. property OnMouseWheelDown;
  309. property OnMouseWheelUp;
  310. property ParentColor;
  311. property PopupMenu;
  312. { Change the style of the rounded corners of the button. }
  313. property Rounding;
  314. { Change the style of the rounded corners of the dropdown part of the button. }
  315. property RoundingDropDown;
  316. { Set to True to change the button to always show a StateNormal style that will not change when button is clicked or hovered. }
  317. property StaticButton;
  318. property ShowHint;
  319. { The style of button that will be used. bbtButton or bbtDropDownF. }
  320. property Style;
  321. { Apply the global opacity to rendered text. Default: False. }
  322. property TextApplyGlobalOpacity;
  323. property Visible;
  324. { -ToDo: Unused property? }
  325. property ClickOffset;
  326. { Show the dropdown arrow. }
  327. property DropDownArrow;
  328. { The dropdown menu that will be displayed when the button is pressed. }
  329. property DropDownMenu;
  330. { The kind of dropdown that will be used. bdsSeparate will show the dropdown down the dropdown arrow side. bdsCommon will show the dropdown down the whole button. }
  331. property DropDownStyle;
  332. { The position of the dropdown arrow. }
  333. property DropDownPosition;
  334. { The image list that holds an image to be used with the button ImageIndex property. }
  335. property Images;
  336. { The index of the image that will be used for the button as glyph icon if glyph property is not set. }
  337. property ImageIndex;
  338. { Show caption or hides it. Default: True. }
  339. property ShowCaption;
  340. { Limit memory usage by selecting one of the options. Default: bmuHighF. }
  341. property MemoryUsage;
  342. { The unique name of the control in the form. }
  343. property Name;
  344. { TabStop }
  345. property TabOrder;
  346. property TabStop;
  347. property ThemeManager: TBCThemeManager read FBCThemeManager write SetFBCThemeManager;
  348. property OnPaintButton;
  349. end;
  350. { TBCButtonFocusActionLink }
  351. TBCButtonFocusActionLink = class(TControlActionLink)
  352. protected
  353. procedure AssignClient(AClient: TObject); override;
  354. procedure SetChecked(Value: boolean); override;
  355. procedure SetImageIndex(Value: integer); override;
  356. public
  357. function IsCheckedLinked: boolean; override;
  358. function IsImageIndexLinked: boolean; override;
  359. end;
  360. {$IFDEF FPC}procedure Register;{$ENDIF}
  361. implementation
  362. uses {$IFDEF FPC}LCLIntf, PropEdits, LCLProc, GraphPropEdits,{$ENDIF} Math, BCTools, SysUtils;
  363. const
  364. DropDownReopenDelay = 0.2/(24*60*60);
  365. {$IFDEF FPC}//#
  366. type
  367. TBCButtonImageIndexPropertyEditor = class(TImageIndexPropertyEditor)
  368. protected
  369. function GetImageList: TCustomImageList; override;
  370. end;
  371. function TBCButtonImageIndexPropertyEditor.GetImageList: TCustomImageList;
  372. var
  373. Component: TPersistent;
  374. begin
  375. Component := GetComponent(0);
  376. if Component is TCustomBCButtonFocus then
  377. Result := TCustomBCButtonFocus(Component).Images
  378. else
  379. Result := nil;
  380. end;
  381. {$ENDIF}
  382. { TBCButtonFocus }
  383. procedure TBCButtonFocus.SetFBCThemeManager(AValue: TBCThemeManager);
  384. begin
  385. if FBCThemeManager=AValue then Exit;
  386. FBCThemeManager:=AValue;
  387. end;
  388. {$IFDEF FPC}
  389. procedure Register;
  390. begin
  391. RegisterComponents('BGRA Button Controls', [TBCButtonFocus]);
  392. {$IFDEF FPC}
  393. RegisterPropertyEditor(TypeInfo(integer), TBCButtonFocus,
  394. 'ImageIndex', TBCButtonImageIndexPropertyEditor);
  395. {$ENDIF}
  396. end;
  397. {$ENDIF}
  398. { TBCButtonFocusActionLink }
  399. procedure TBCButtonFocusActionLink.AssignClient(AClient: TObject);
  400. begin
  401. inherited AssignClient(AClient);
  402. FClient := AClient as TCustomBCButtonFocus;
  403. end;
  404. procedure TBCButtonFocusActionLink.SetChecked(Value: boolean);
  405. begin
  406. if IsCheckedLinked then
  407. TCustomBCButtonFocus(FClient).Down := Value;
  408. end;
  409. procedure TBCButtonFocusActionLink.SetImageIndex(Value: integer);
  410. begin
  411. if IsImageIndexLinked then
  412. TCustomBCButtonFocus(FClient).ImageIndex := Value;
  413. end;
  414. function TBCButtonFocusActionLink.IsCheckedLinked: boolean;
  415. begin
  416. Result := inherited IsCheckedLinked and (TCustomBCButtonFocus(FClient).Down =
  417. (Action as TCustomAction).Checked);
  418. end;
  419. function TBCButtonFocusActionLink.IsImageIndexLinked: boolean;
  420. begin
  421. Result := inherited IsImageIndexLinked and
  422. (TCustomBCButtonFocus(FClient).ImageIndex = (Action as TCustomAction).ImageIndex);
  423. end;
  424. { TBCButtonFocusState }
  425. procedure TBCButtonFocusState.SetFontEx(const AValue: TBCFont);
  426. begin
  427. if FFontEx = AValue then
  428. exit;
  429. FFontEx.Assign(AValue);
  430. Change;
  431. end;
  432. procedure TBCButtonFocusState.OnChangeFont(Sender: TObject; AData: PtrInt);
  433. begin
  434. Change(PtrInt(pdUpdateSizeF));
  435. end;
  436. procedure TBCButtonFocusState.OnChangeChildProperty(Sender: TObject; AData: PtrInt);
  437. begin
  438. Change(AData);
  439. end;
  440. procedure TBCButtonFocusState.SetBackground(AValue: TBCBackground);
  441. begin
  442. if FBackground = AValue then
  443. Exit;
  444. FBackground.Assign(AValue);
  445. Change;
  446. end;
  447. procedure TBCButtonFocusState.SetBorder(AValue: TBCBorder);
  448. begin
  449. if FBorder = AValue then
  450. Exit;
  451. FBorder.Assign(AValue);
  452. Change;
  453. end;
  454. constructor TBCButtonFocusState.Create(AControl: TControl);
  455. begin
  456. FBackground := TBCBackground.Create(AControl);
  457. FBorder := TBCBorder.Create(AControl);
  458. FFontEx := TBCFont.Create(AControl);
  459. FBackground.OnChange := OnChangeChildProperty;
  460. FBorder.OnChange := OnChangeChildProperty;
  461. FFontEx.OnChange := OnChangeFont;
  462. inherited Create(AControl);
  463. end;
  464. destructor TBCButtonFocusState.Destroy;
  465. begin
  466. FBackground.Free;
  467. FBorder.Free;
  468. FFontEx.Free;
  469. inherited Destroy;
  470. end;
  471. procedure TBCButtonFocusState.Assign(Source: TPersistent);
  472. begin
  473. if Source is TBCButtonFocusState then
  474. begin
  475. FBackground.Assign(TBCButtonFocusState(Source).FBackground);
  476. FBorder.Assign(TBCButtonFocusState(Source).FBorder);
  477. FFontEx.Assign(TBCButtonFocusState(Source).FFontEx);
  478. Change(PtrInt(pdUpdateSizeF));
  479. end
  480. else
  481. inherited Assign(Source);
  482. end;
  483. { TCustomBCButtonFocus }
  484. procedure TCustomBCButtonFocus.AssignDefaultStyle;
  485. begin
  486. FRounding.RoundX := 12;
  487. FRounding.RoundY := 12;
  488. // Normal
  489. with StateNormal do
  490. begin
  491. Border.Style := bboNone;
  492. FontEx.Color := RGBToColor(230, 230, 255);
  493. FontEx.Style := [fsBold];
  494. FontEx.Shadow := True;
  495. FontEx.ShadowOffsetX := 1;
  496. FontEx.ShadowOffsetY := 1;
  497. FontEx.ShadowRadius := 2;
  498. Background.Gradient1EndPercent := 60;
  499. Background.Style := bbsGradient;
  500. // Gradient1
  501. with Background.Gradient1 do
  502. begin
  503. EndColor := RGBToColor(64, 64, 128);
  504. StartColor := RGBToColor(0, 0, 64);
  505. end;
  506. // Gradient2
  507. with Background.Gradient2 do
  508. begin
  509. EndColor := RGBToColor(0, 0, 64);
  510. GradientType := gtRadial;
  511. Point1XPercent := 50;
  512. Point1YPercent := 100;
  513. Point2YPercent := 0;
  514. StartColor := RGBToColor(64, 64, 128);
  515. end;
  516. end;
  517. // Hover
  518. with StateHover do
  519. begin
  520. Border.Style := bboNone;
  521. FontEx.Color := RGBToColor(255, 255, 255);
  522. FontEx.Style := [fsBold];
  523. FontEx.Shadow := True;
  524. FontEx.ShadowOffsetX := 1;
  525. FontEx.ShadowOffsetY := 1;
  526. FontEx.ShadowRadius := 2;
  527. Background.Gradient1EndPercent := 100;
  528. Background.Style := bbsGradient;
  529. // Gradient1
  530. with Background.Gradient1 do
  531. begin
  532. EndColor := RGBToColor(0, 64, 128);
  533. GradientType := gtRadial;
  534. Point1XPercent := 50;
  535. Point1YPercent := 100;
  536. Point2YPercent := 0;
  537. StartColor := RGBToColor(0, 128, 255);
  538. end;
  539. end;
  540. // Clicked
  541. with StateClicked do
  542. begin
  543. Border.Style := bboNone;
  544. FontEx.Color := RGBToColor(230, 230, 255);
  545. FontEx.Style := [fsBold];
  546. FontEx.Shadow := True;
  547. FontEx.ShadowOffsetX := 1;
  548. FontEx.ShadowOffsetY := 1;
  549. FontEx.ShadowRadius := 2;
  550. Background.Gradient1EndPercent := 100;
  551. Background.Style := bbsGradient;
  552. // Gradient1
  553. with Background.Gradient1 do
  554. begin
  555. EndColor := RGBToColor(0, 0, 64);
  556. GradientType := gtRadial;
  557. Point1XPercent := 50;
  558. Point1YPercent := 100;
  559. Point2YPercent := 0;
  560. StartColor := RGBToColor(0, 64, 128);
  561. end;
  562. end;
  563. end;
  564. procedure TCustomBCButtonFocus.CalculateGlyphSize(out NeededWidth, NeededHeight: integer);
  565. begin
  566. if Assigned(FGlyph) and not FGlyph.Empty then
  567. begin
  568. NeededWidth := FGlyph.Width;
  569. NeededHeight := FGlyph.Height;
  570. end
  571. else
  572. if Assigned(FImages) then
  573. begin
  574. NeededWidth := FImages.Width;
  575. NeededHeight := FImages.Height;
  576. end
  577. else
  578. begin
  579. NeededHeight := 0;
  580. NeededWidth := 0;
  581. end;
  582. end;
  583. procedure TCustomBCButtonFocus.RenderAll(ANow: boolean);
  584. begin
  585. if (csCreating in ControlState) or IsUpdating or (FBGRANormal = nil) then
  586. Exit;
  587. if ANow then
  588. begin
  589. Render(FBGRANormal, FStateNormal);
  590. Render(FBGRAHover, FStateHover);
  591. Render(FBGRAClick, FStateClicked);
  592. end
  593. else
  594. begin
  595. FBGRANormal.NeedRender := True;
  596. FBGRAHover.NeedRender := True;
  597. FBGRAClick.NeedRender := True;
  598. end;
  599. end;
  600. function TCustomBCButtonFocus.GetButtonRect: TRect;
  601. begin
  602. Result := GetClientRect;
  603. if FStyle = bbtDropDownF then
  604. case FDropDownPosition of
  605. bdpBottomF:
  606. Dec(Result.Bottom, GetDropDownWidth(False));
  607. else
  608. // bdpLeft:
  609. Dec(Result.Right, GetDropDownWidth(False));
  610. end;
  611. end;
  612. function TCustomBCButtonFocus.GetDropDownWidth(AFull: boolean): integer;
  613. begin
  614. Result := FDropDownWidth + (ifthen(AFull, 2, 1) * FStateNormal.FBorder.Width);
  615. end;
  616. function TCustomBCButtonFocus.GetGlyph: TBitmap;
  617. begin
  618. Result := FGlyph as TBitmap;
  619. end;
  620. function TCustomBCButtonFocus.GetDropDownRect(AFull: boolean): TRect;
  621. begin
  622. Result := GetClientRect;
  623. case FDropDownPosition of
  624. bdpBottomF:
  625. Result.Top := Result.Bottom - GetDropDownWidth(AFull);
  626. else
  627. // bdpLeft:
  628. Result.Left := Result.Right - GetDropDownWidth(AFull);
  629. end;
  630. end;
  631. procedure TCustomBCButtonFocus.Render(ABGRA: TBGRABitmapEx; AState: TBCButtonFocusState);
  632. function GetActualGlyph: TBitmap;
  633. begin
  634. if Assigned(FGlyph) and not FGlyph.Empty then result := FGlyph else
  635. if Assigned(FImages) and (FImageIndex > -1) and (FImageIndex < FImages.Count) then
  636. begin
  637. result := TBitmap.Create;
  638. {$IFDEF FPC}
  639. FImages.GetBitmap(FImageIndex, result);
  640. {$ELSE}
  641. FImages.GetBitmapRaw(FImageIndex, result);
  642. {$ENDIF}
  643. end else exit(nil);
  644. end;
  645. procedure RenderGlyph(ARect: TRect; AGlyph: TBitmap);
  646. begin
  647. if ARect.IsEmpty or (AGlyph = nil) then exit;
  648. ABGRA.PutImage(ARect.Left, ARect.Top, AGlyph, dmLinearBlend);
  649. end;
  650. var
  651. r, r_a, r_g: TRect;
  652. g: TBitmap;
  653. actualCaption: TCaption;
  654. begin
  655. if (csCreating in ControlState) or IsUpdating then
  656. Exit;
  657. ABGRA.NeedRender := False;
  658. { Refreshing size }
  659. ABGRA.SetSize(Width, Height);
  660. { Clearing previous paint }
  661. ABGRA.Fill(BGRAPixelTransparent);
  662. { Basic body }
  663. r := GetButtonRect;
  664. RenderState(ABGRA, AState, r, FRounding);
  665. if not GlyphOldPlacement then
  666. r.Inflate(-round(InnerMargin),-round(InnerMargin));
  667. { Calculating rect }
  668. CalculateBorderRect(AState.Border, r);
  669. if FStyle = bbtDropDownF then
  670. begin
  671. r_a := GetDropDownRect;
  672. RenderState(ABGRA, AState, r_a, FRoundingDropDown);
  673. CalculateBorderRect(AState.Border, r_a);
  674. // Click offset for arrow
  675. if FClickOffset and (AState = FStateClicked) then
  676. r_a.Offset(1,1);
  677. if FFlipArrow then
  678. RenderArrow(TBGRABitmap(ABGRA), r_a, FDropDownArrowSize, badUp,
  679. AState.FontEx.Color)
  680. else
  681. RenderArrow(TBGRABitmap(ABGRA), r_a, FDropDownArrowSize, badDown,
  682. AState.FontEx.Color);
  683. end;
  684. // Click offset for text and glyph
  685. if FClickOffset and (AState = FStateClicked) then
  686. r.Offset(1,1);
  687. // DropDown arrow
  688. if FDropDownArrow and (FStyle <> bbtDropDownF) then
  689. begin
  690. r_a := r;
  691. r_a.Left := r_a.Right - FDropDownWidth;
  692. if FFlipArrow then
  693. RenderArrow(TBGRABitmap(ABGRA), r_a, FDropDownArrowSize, badUp,
  694. AState.FontEx.Color)
  695. else
  696. RenderArrow(TBGRABitmap(ABGRA), r_a, FDropDownArrowSize, badDown,
  697. AState.FontEx.Color);
  698. Dec(R.Right, FDropDownWidth);
  699. end;
  700. g := GetActualGlyph;
  701. if FShowCaption then actualCaption := self.Caption else actualCaption := '';
  702. r_g := ComputeGlyphPosition(r, g, GlyphAlignment, GlyphMargin, actualCaption, AState.FontEx, GlyphOldPlacement);
  703. if FTextApplyGlobalOpacity then
  704. begin
  705. { Drawing text }
  706. RenderText(r, AState.FontEx, actualCaption, ABGRA, Enabled);
  707. RenderGlyph(r_g, g);
  708. { Set global opacity }
  709. ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
  710. end
  711. else
  712. begin
  713. { Set global opacity }
  714. ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
  715. { Drawing text }
  716. RenderText(r, AState.FontEx, actualCaption, ABGRA, Enabled);
  717. RenderGlyph(r_g, g);
  718. end;
  719. if g <> FGlyph then g.Free;
  720. { Convert to gray if not enabled }
  721. if not Enabled then ABGRA.InplaceGrayscale;
  722. if Assigned(FOnAfterRenderBCButton) then
  723. FOnAfterRenderBCButton(Self, ABGRA, AState, r);
  724. {$IFDEF INDEBUG}
  725. FRenderCount := FRenderCount +1;
  726. {$ENDIF}
  727. end;
  728. procedure TCustomBCButtonFocus.RenderState(ABGRA: TBGRABitmapEx;
  729. AState: TBCButtonFocusState; const ARect: TRect; ARounding: TBCRounding);
  730. begin
  731. RenderBackgroundAndBorder(ARect, AState.FBackground, TBGRABitmap(ABGRA),
  732. ARounding, AState.FBorder, FInnerMargin);
  733. end;
  734. procedure TCustomBCButtonFocus.OnChangeGlyph(Sender: TObject);
  735. begin
  736. RenderControl;
  737. UpdateSize;
  738. Invalidate;
  739. end;
  740. procedure TCustomBCButtonFocus.OnChangeState(Sender: TObject; AData: PtrInt);
  741. begin
  742. RenderControl;
  743. if (TBCButtonFocusPropertyData(AData) = pdUpdateSizeF) or
  744. (FStateNormal.Border.Width <> FLastBorderWidth) then
  745. UpdateSize;
  746. Invalidate;
  747. end;
  748. procedure TCustomBCButtonFocus.ImageListChange(ASender: TObject);
  749. begin
  750. if ASender = Images then
  751. begin
  752. RenderControl;
  753. Invalidate;
  754. end;
  755. end;
  756. procedure TCustomBCButtonFocus.LimitMemoryUsage;
  757. begin
  758. {$IFNDEF FPC}//# //@ IN DELPHI NEEDRENDER NEDD TO BE TRUE. IF FALSE COMPONENT IN BGRANORMAL BE BLACK AFTER INVALIDATE.
  759. if Assigned(FBGRAHover) then FBGRANormal.NeedRender := True;
  760. if Assigned(FBGRAHover) then FBGRAHover.NeedRender := True;
  761. if Assigned(FBGRAClick) then FBGRAClick.NeedRender := True;
  762. {$ENDIF}
  763. if (FMemoryUsage = bmuLowF) and Assigned(FBGRANormal) then FBGRANormal.Discard;
  764. if (FMemoryUsage <> bmuHighF) then
  765. begin
  766. if Assigned(FBGRAHover) then FBGRAHover.Discard;
  767. if Assigned(FBGRAClick) then FBGRAClick.Discard;
  768. end;
  769. end;
  770. procedure TCustomBCButtonFocus.SeTBCButtonStateClicked(const AValue: TBCButtonFocusState);
  771. begin
  772. if FStateClicked = AValue then
  773. exit;
  774. FStateClicked.Assign(AValue);
  775. RenderControl;
  776. Invalidate;
  777. end;
  778. procedure TCustomBCButtonFocus.SeTBCButtonStateHover(const AValue: TBCButtonFocusState);
  779. begin
  780. if FStateHover = AValue then
  781. exit;
  782. FStateHover.Assign(AValue);
  783. RenderControl;
  784. Invalidate;
  785. end;
  786. procedure TCustomBCButtonFocus.SeTBCButtonStateNormal(const AValue: TBCButtonFocusState);
  787. begin
  788. if FStateNormal = AValue then
  789. exit;
  790. FStateNormal.Assign(AValue);
  791. RenderControl;
  792. Invalidate;
  793. end;
  794. procedure TCustomBCButtonFocus.SetClickOffset(AValue: boolean);
  795. begin
  796. if FClickOffset = AValue then
  797. Exit;
  798. FClickOffset := AValue;
  799. RenderControl;
  800. end;
  801. procedure TCustomBCButtonFocus.SetDown(AValue: boolean);
  802. begin
  803. if FDown = AValue then
  804. exit;
  805. FDown := AValue;
  806. if FDown then
  807. FButtonState := msClicked
  808. else
  809. FButtonState := msNone;
  810. RenderControl;
  811. Invalidate;
  812. end;
  813. procedure TCustomBCButtonFocus.SetDropDownArrow(AValue: boolean);
  814. begin
  815. if FDropDownArrow = AValue then
  816. Exit;
  817. FDropDownArrow := AValue;
  818. RenderControl;
  819. Invalidate;
  820. end;
  821. procedure TCustomBCButtonFocus.SetDropDownArrowSize(AValue: integer);
  822. begin
  823. if FDropDownArrowSize = AValue then
  824. Exit;
  825. FDropDownArrowSize := AValue;
  826. RenderControl;
  827. Invalidate;
  828. end;
  829. procedure TCustomBCButtonFocus.SetDropDownPosition(AValue: TBCButtonFocusDropDownPosition);
  830. begin
  831. if FDropDownPosition = AValue then
  832. Exit;
  833. FDropDownPosition := AValue;
  834. if FStyle <> bbtDropDownF then
  835. Exit;
  836. RenderControl;
  837. UpdateSize;
  838. Invalidate;
  839. end;
  840. procedure TCustomBCButtonFocus.SetDropDownWidth(AValue: integer);
  841. begin
  842. if FDropDownWidth = AValue then
  843. Exit;
  844. FDropDownWidth := AValue;
  845. RenderControl;
  846. UpdateSize;
  847. Invalidate;
  848. end;
  849. procedure TCustomBCButtonFocus.SetFlipArrow(AValue: boolean);
  850. begin
  851. if FFlipArrow = AValue then
  852. Exit;
  853. FFlipArrow := AValue;
  854. RenderControl;
  855. Invalidate;
  856. end;
  857. procedure TCustomBCButtonFocus.SetGlyph(const AValue: TBitmap);
  858. begin
  859. if (FGlyph <> nil) and (FGlyph = AValue) then
  860. exit;
  861. FGlyph.Assign(AValue);
  862. RenderControl;
  863. UpdateSize;
  864. Invalidate;
  865. end;
  866. procedure TCustomBCButtonFocus.SetGlyphAlignment(AValue: TBCAlignment);
  867. begin
  868. if FGlyphAlignment=AValue then Exit;
  869. FGlyphAlignment:=AValue;
  870. RenderControl;
  871. UpdateSize;
  872. Invalidate;
  873. end;
  874. procedure TCustomBCButtonFocus.SetGlyphMargin(const AValue: integer);
  875. begin
  876. if FGlyphMargin = AValue then
  877. exit;
  878. FGlyphMargin := AValue;
  879. RenderControl;
  880. UpdateSize;
  881. Invalidate;
  882. end;
  883. procedure TCustomBCButtonFocus.SetGlyphOldPlacement(AValue: boolean);
  884. begin
  885. if FGlyphOldPlacement=AValue then Exit;
  886. FGlyphOldPlacement:=AValue;
  887. RenderControl;
  888. UpdateSize;
  889. Invalidate;
  890. end;
  891. procedure TCustomBCButtonFocus.SetImageIndex(AValue: integer);
  892. begin
  893. if FImageIndex = AValue then
  894. Exit;
  895. FImageIndex := AValue;
  896. RenderControl;
  897. Invalidate;
  898. end;
  899. procedure TCustomBCButtonFocus.SetImages(AValue: TCustomImageList);
  900. begin
  901. if FImages = AValue then
  902. Exit;
  903. FImages := AValue;
  904. RenderControl;
  905. UpdateSize;
  906. Invalidate;
  907. end;
  908. procedure TCustomBCButtonFocus.SetInnerMargin(AValue: single);
  909. begin
  910. if FInnerMargin=AValue then Exit;
  911. FInnerMargin:=AValue;
  912. RenderControl;
  913. UpdateSize;
  914. Invalidate;
  915. end;
  916. procedure TCustomBCButtonFocus.SetMemoryUsage(AValue: TBCButtonFocusMemoryUsage);
  917. begin
  918. if FMemoryUsage=AValue then Exit;
  919. FMemoryUsage:=AValue;
  920. LimitMemoryUsage;
  921. end;
  922. procedure TCustomBCButtonFocus.SetRounding(AValue: TBCRounding);
  923. begin
  924. if FRounding = AValue then
  925. Exit;
  926. FRounding.Assign(AValue);
  927. RenderControl;
  928. Invalidate;
  929. end;
  930. procedure TCustomBCButtonFocus.SetRoundingDropDown(AValue: TBCRounding);
  931. begin
  932. if FRoundingDropDown = AValue then
  933. Exit;
  934. FRoundingDropDown.Assign(AValue);
  935. RenderControl;
  936. Invalidate;
  937. end;
  938. procedure TCustomBCButtonFocus.SetShowCaption(AValue: boolean);
  939. begin
  940. if FShowCaption = AValue then
  941. Exit;
  942. FShowCaption := AValue;
  943. RenderControl;
  944. UpdateSize;
  945. Invalidate;
  946. end;
  947. procedure TCustomBCButtonFocus.SetStaticButton(const AValue: boolean);
  948. begin
  949. if FStaticButton = AValue then
  950. exit;
  951. FStaticButton := AValue;
  952. RenderControl;
  953. Invalidate;
  954. end;
  955. procedure TCustomBCButtonFocus.SetStyle(const AValue: TBCButtonFocusStyle);
  956. begin
  957. if FStyle = AValue then
  958. exit;
  959. FStyle := AValue;
  960. RenderControl;
  961. UpdateSize;
  962. Invalidate;
  963. end;
  964. procedure TCustomBCButtonFocus.UpdateSize;
  965. begin
  966. InvalidatePreferredSize;
  967. AdjustSize;
  968. end;
  969. procedure TCustomBCButtonFocus.CalculatePreferredSize(
  970. var PreferredWidth, PreferredHeight: integer; WithThemeSpace: boolean);
  971. var
  972. // AWidth: integer;
  973. gh,gw: integer;
  974. actualCaption: TCaption;
  975. horizAlign, relHorizAlign: TAlignment;
  976. vertAlign, relVertAlign: TTextLayout;
  977. glyphHorzMargin, glyphVertMargin: integer;
  978. tw, th, availW: integer;
  979. begin
  980. gh := 0;
  981. gw := 0;
  982. if (Parent = nil) or (not Parent.HandleAllocated) then
  983. Exit;
  984. { if WidthIsAnchored then
  985. AWidth := Width
  986. else
  987. AWidth := 10000;}
  988. FLastBorderWidth := FStateNormal.Border.Width;
  989. CalculateGlyphSize(gw, gh);
  990. if GlyphOldPlacement then
  991. begin
  992. { if WidthIsAnchored then
  993. AWidth := Width
  994. else
  995. AWidth := 10000;}
  996. PreferredWidth := 0;
  997. PreferredHeight := 0;
  998. if FShowCaption then
  999. CalculateTextSize(Caption, FStateNormal.FontEx, PreferredWidth, PreferredHeight);
  1000. // Extra pixels for DropDown
  1001. if Style = bbtDropDownF then
  1002. if FDropDownPosition in [bdpBottomF] then
  1003. Inc(PreferredHeight, GetDropDownWidth)
  1004. else
  1005. Inc(PreferredWidth, GetDropDownWidth);
  1006. if (Style = bbtButtonF) and FDropDownArrow then
  1007. Inc(PreferredWidth, FDropDownArrowSize);// GetDropDownWidth);
  1008. //if (FGlyph <> nil) and (not FGlyph.Empty) then
  1009. if (gw > 0) and (gh > 0) then
  1010. begin
  1011. //if Caption = '' then
  1012. if PreferredWidth = 0 then
  1013. begin
  1014. Inc(PreferredWidth, gw{ - AutoSizeExtraY * 2});
  1015. Inc(PreferredHeight, gh);
  1016. end
  1017. else
  1018. begin
  1019. Inc(PreferredWidth, gw + FGlyphMargin);
  1020. if gh > PreferredHeight then
  1021. PreferredHeight := gh;
  1022. end;
  1023. end;
  1024. // Extra pixels for AutoSize
  1025. Inc(PreferredWidth, AutoSizeExtraX);
  1026. Inc(PreferredHeight, AutoSizeExtraY);
  1027. end else
  1028. begin
  1029. if ShowCaption then actualCaption := Caption else actualCaption := '';
  1030. PreferredWidth := round(InnerMargin);
  1031. PreferredHeight := round(InnerMargin);
  1032. case FStyle of
  1033. bbtDropDownF:
  1034. case FDropDownPosition of
  1035. bdpBottomF: inc(PreferredHeight, GetDropDownWidth(False));
  1036. else{bdpLeft} inc(PreferredWidth, GetDropDownWidth(False));
  1037. end;
  1038. else{bbtButton} if FDropDownArrow then
  1039. inc(PreferredWidth, FDropDownWidth);
  1040. end;
  1041. inc(PreferredWidth, FStateNormal.Border.Width);
  1042. inc(PreferredHeight, FStateNormal.Border.Width);
  1043. if actualCaption='' then
  1044. begin
  1045. inc(PreferredWidth,gw);
  1046. inc(PreferredHeight,gh);
  1047. if gw>0 then inc(PreferredWidth, GlyphMargin*2);
  1048. if gh>0 then inc(PreferredHeight, GlyphMargin*2);
  1049. end else
  1050. begin
  1051. GetGlyphActualLayout(actualCaption, FStateNormal.FontEx, GlyphAlignment, GlyphMargin,
  1052. horizAlign, vertAlign, relHorizAlign, relVertAlign, glyphHorzMargin, glyphVertMargin);
  1053. availW := 65535;
  1054. if (Align in [alTop,alBottom]) and (Parent <> nil) then
  1055. availW := Parent.ClientWidth - PreferredWidth;
  1056. CalculateTextSizeEx(actualCaption, FStateNormal.FontEx, tw, th, availW);
  1057. if (tw<>0) and FStateNormal.FontEx.WordBreak then inc(tw);
  1058. if vertAlign<>relVertAlign then
  1059. begin
  1060. inc(PreferredWidth, max(gw+2*GlyphMargin,tw));
  1061. inc(PreferredHeight, GlyphMargin+gh+th);
  1062. end
  1063. else
  1064. begin
  1065. inc(PreferredWidth, GlyphMargin+gw+tw);
  1066. inc(PreferredHeight, max(gh+2*GlyphMargin,th));
  1067. end;
  1068. end;
  1069. end;
  1070. // Extra pixels for AutoSize
  1071. Inc(PreferredWidth, AutoSizeExtraX);
  1072. Inc(PreferredHeight, AutoSizeExtraY);
  1073. end;
  1074. class function TCustomBCButtonFocus.GetControlClassDefaultSize: TSize;
  1075. begin
  1076. Result.CX := 123;
  1077. Result.CY := 33;
  1078. end;
  1079. procedure TCustomBCButtonFocus.Click;
  1080. begin
  1081. if (FActiveButt = bbtDropDownF) and Assigned(FOnButtonClick) then
  1082. begin
  1083. FOnButtonClick(Self);
  1084. Exit;
  1085. end;
  1086. inherited Click;
  1087. end;
  1088. procedure TCustomBCButtonFocus.DropDownClosed(Sender: TObject);
  1089. begin
  1090. if Assigned(FSaveDropDownClosed) then
  1091. FSaveDropDownClosed(Sender);
  1092. {$IFDEF FPC}
  1093. if Assigned(FDropDownMenu) then
  1094. FDropDownMenu.OnClose := FSaveDropDownClosed;
  1095. {$ENDIF}
  1096. // MORA: DropDownMenu is still visible if mouse is over control
  1097. FDropDownMenuVisible := {$IFNDEF FPC}BGRAGraphics.{$ENDIF}PtInRect(ClientRect, ScreenToClient(Mouse.CursorPos));
  1098. FDropDownClosingTime := Now;
  1099. end;
  1100. procedure TCustomBCButtonFocus.MouseDown(Button: TMouseButton; Shift: TShiftState;
  1101. X, Y: integer);
  1102. var
  1103. ClientToScreenPoint : TPoint;
  1104. begin
  1105. inherited MouseDown(Button, Shift, X, Y);
  1106. if csDesigning in ComponentState then
  1107. exit;
  1108. if CanFocus() then SetFocus();
  1109. if (Button = mbLeft) and Enabled {and (not (FButtonState = msClicked)) } then
  1110. begin
  1111. case FActiveButt of
  1112. bbtButtonF:
  1113. if not (FButtonState = msClicked) then
  1114. begin
  1115. FButtonState := msClicked;
  1116. if FDropDownStyle = bdsCommonF then
  1117. FDownButtonState := msClicked
  1118. else
  1119. FDownButtonState := msNone;
  1120. Invalidate;
  1121. end;
  1122. bbtDropDownF:
  1123. if not (FDownButtonState = msClicked) then
  1124. begin
  1125. if FDropDownStyle = bdsCommonF then
  1126. FButtonState := msClicked
  1127. else
  1128. FButtonState := msNone;
  1129. FDownButtonState := msClicked;
  1130. Invalidate;
  1131. end;
  1132. end;
  1133. // Old
  1134. {FButtonState := msClicked;
  1135. Invalidate;}
  1136. // MORA: Show DropDown menu
  1137. if FDropDownMenuVisible or (Now < FDropDownClosingTime+DropDownReopenDelay) then
  1138. FDropDownMenuVisible := False // Prevent redropping
  1139. else
  1140. if ((FActiveButt = bbtDropDownF) or (FStyle = bbtButtonF)) and
  1141. (FDropDownMenu <> nil) and Enabled then
  1142. begin
  1143. ClientToScreenPoint := ClientToScreen(Point(0, Height));
  1144. with ClientToScreenPoint do
  1145. begin
  1146. // normal button
  1147. if FStyle = bbtButtonF then
  1148. begin
  1149. x := x + Width * integer(FDropDownMenu.Alignment = paRight);
  1150. if FFlipArrow then
  1151. y := y -Height;
  1152. end
  1153. else
  1154. // dropdown button
  1155. begin
  1156. if FDropDownPosition = bdpBottomF then
  1157. begin
  1158. x := x + Width * integer(FDropDownMenu.Alignment = paRight);
  1159. if FFlipArrow then
  1160. y := y -(FDropDownWidth + (FStateNormal.FBorder.Width * 2));
  1161. end
  1162. else
  1163. begin
  1164. if FFlipArrow then
  1165. y := y -Height;
  1166. if FDropDownStyle = bdsSeparateF then
  1167. x := x + Width - (FDropDownWidth + (FStateNormal.FBorder.Width * 2)) *
  1168. integer(FDropDownMenu.Alignment <> paRight)
  1169. else
  1170. x := x + Width * integer(FDropDownMenu.Alignment = paRight);
  1171. end;
  1172. end;
  1173. FDropDownMenuVisible := True;
  1174. {$IFDEF FPC}
  1175. FSaveDropDownClosed := FDropDownMenu.OnClose;
  1176. FDropDownMenu.OnClose := DropDownClosed;
  1177. {$ENDIF}
  1178. FDropDownMenu.PopUp(x, y);
  1179. end;
  1180. end;
  1181. end;
  1182. end;
  1183. procedure TCustomBCButtonFocus.MouseUp(Button: TMouseButton; Shift: TShiftState;
  1184. X, Y: integer);
  1185. {var
  1186. p: TPoint;}
  1187. begin
  1188. inherited MouseUp(Button, Shift, X, Y);
  1189. if csDesigning in ComponentState then
  1190. exit;
  1191. if (Button = mbLeft) and Enabled {and (FButtonState = msClicked)} then
  1192. begin
  1193. case FActiveButt of
  1194. bbtButtonF:
  1195. if FButtonState = msClicked then
  1196. begin
  1197. FButtonState := msHover;
  1198. if FDropDownStyle = bdsCommonF then
  1199. FDownButtonState := msHover
  1200. else
  1201. FDownButtonState := msNone;
  1202. Invalidate;
  1203. end;
  1204. bbtDropDownF:
  1205. if FDownButtonState = msClicked then
  1206. begin
  1207. FDownButtonState := msHover;
  1208. if FDropDownStyle = bdsCommonF then
  1209. FButtonState := msHover
  1210. else
  1211. FButtonState := msNone;
  1212. Invalidate;
  1213. end;
  1214. end;
  1215. // Old
  1216. {FButtonState := msHover;
  1217. Invalidate;}
  1218. end;
  1219. //if (FActiveButt = bbtDropDownF) and (PopupMenu <> nil) and Enabled then
  1220. //begin
  1221. // if FFlipArrow then
  1222. // p := ClientToScreen(Point(Width - FDropDownWidth - (FStateNormal.FBorder.Width * 2),
  1223. // {PopupMenu.Height} -1))
  1224. // else
  1225. // p := ClientToScreen(Point(Width - FDropDownWidth - (FStateNormal.FBorder.Width * 2), Height + 1));
  1226. // PopupMenu.PopUp(p.x, p.y);
  1227. //end;
  1228. end;
  1229. procedure TCustomBCButtonFocus.MouseEnter;
  1230. begin
  1231. if csDesigning in ComponentState then
  1232. exit;
  1233. case FActiveButt of
  1234. bbtButtonF:
  1235. begin
  1236. if FDown then
  1237. FButtonState := msClicked
  1238. else
  1239. FButtonState := msHover;
  1240. if FDropDownStyle = bdsSeparateF then
  1241. FDownButtonState := msNone
  1242. else
  1243. FDownButtonState := msHover;
  1244. end;
  1245. bbtDropDownF:
  1246. begin
  1247. if FDown then
  1248. FButtonState := msClicked
  1249. else
  1250. if FDropDownStyle = bdsSeparateF then
  1251. FButtonState := msNone
  1252. else
  1253. FButtonState := msHover;
  1254. FDownButtonState := msHover;
  1255. end;
  1256. end;
  1257. Invalidate;
  1258. // Old
  1259. {FButtonState := msHover;
  1260. Invalidate;}
  1261. {$IFDEF FPC}
  1262. inherited MouseEnter;
  1263. {$ENDIF}
  1264. end;
  1265. procedure TCustomBCButtonFocus.MouseLeave;
  1266. begin
  1267. if csDesigning in ComponentState then
  1268. exit;
  1269. if FDown then
  1270. begin
  1271. FButtonState := msClicked;
  1272. FActiveButt := bbtButtonF;
  1273. end
  1274. else
  1275. FButtonState := msNone;
  1276. FDownButtonState := msNone;
  1277. Invalidate;
  1278. {$IFDEF FPC} //#
  1279. inherited MouseLeave;
  1280. {$ENDIF}
  1281. end;
  1282. procedure TCustomBCButtonFocus.MouseMove(Shift: TShiftState; X, Y: integer);
  1283. function IsOverDropDown: boolean;
  1284. begin
  1285. with GetButtonRect do
  1286. case FDropDownPosition of
  1287. bdpBottomF:
  1288. Result := Y > Bottom;
  1289. else
  1290. Result := X > GetButtonRect.Right;
  1291. end;
  1292. end;
  1293. begin
  1294. inherited MouseMove(Shift, X, Y);
  1295. if FStyle = bbtButtonF then
  1296. FActiveButt := bbtButtonF
  1297. else
  1298. begin
  1299. // Calling invalidate only when active button changed. Otherwise, we leave
  1300. // this for LCL. This reduce paint call
  1301. if (FActiveButt = bbtButtonF) and IsOverDropDown then
  1302. begin
  1303. FActiveButt := bbtDropDownF;
  1304. if FDropDownStyle <> bdsCommonF then // Don't need invalidating
  1305. begin
  1306. FDownButtonState := msHover;
  1307. if FDown then
  1308. FButtonState := msClicked
  1309. else
  1310. FButtonState := msNone;
  1311. Invalidate;
  1312. end;
  1313. end
  1314. else
  1315. if (FActiveButt = bbtDropDownF) and not IsOverDropDown then
  1316. begin
  1317. FActiveButt := bbtButtonF;
  1318. if FDropDownStyle <> bdsCommonF then // Don't need invalidating
  1319. begin
  1320. if FDown then
  1321. FButtonState := msClicked
  1322. else
  1323. FButtonState := msHover;
  1324. FDownButtonState := msNone;
  1325. Invalidate;
  1326. end;
  1327. end;
  1328. end;
  1329. end;
  1330. procedure TCustomBCButtonFocus.SetEnabled(Value: boolean);
  1331. begin
  1332. inherited SetEnabled(Value);
  1333. RenderControl;
  1334. Invalidate;
  1335. end;
  1336. procedure TCustomBCButtonFocus.TextChanged;
  1337. begin
  1338. {$IFDEF FPC}
  1339. inherited TextChanged;
  1340. {$ENDIF}
  1341. RenderControl;
  1342. UpdateSize;
  1343. Invalidate;
  1344. end;
  1345. procedure TCustomBCButtonFocus.KeyDown(var Key: word; Shift: TShiftState);
  1346. begin
  1347. inherited KeyDown(Key, Shift);
  1348. if (Key = VK_SPACE) or (Key = VK_RETURN) then
  1349. MouseDown(mbLeft, [], 0, 0);
  1350. end;
  1351. procedure TCustomBCButtonFocus.KeyUp(var Key: word; Shift: TShiftState);
  1352. begin
  1353. if (Key = VK_SPACE) or (Key = VK_RETURN) then
  1354. begin
  1355. MouseLeave;
  1356. Self.Click;
  1357. end;
  1358. inherited KeyUp(Key, Shift);
  1359. end;
  1360. procedure TCustomBCButtonFocus.ActionChange(Sender: TObject; CheckDefaults: boolean);
  1361. var
  1362. NewAction: TCustomAction;
  1363. begin
  1364. inherited ActionChange(Sender, CheckDefaults);
  1365. if Sender is TCustomAction then
  1366. begin
  1367. NewAction := TCustomAction(Sender);
  1368. if (not CheckDefaults) or (not Down) then
  1369. Down := NewAction.Checked;
  1370. if (not CheckDefaults) or (ImageIndex < 0) then
  1371. ImageIndex := NewAction.ImageIndex;
  1372. end;
  1373. end;
  1374. function TCustomBCButtonFocus.GetActionLinkClass: TControlActionLinkClass;
  1375. begin
  1376. Result := TBCButtonFocusActionLink;
  1377. end;
  1378. procedure TCustomBCButtonFocus.Notification(AComponent: TComponent; Operation: TOperation);
  1379. begin
  1380. inherited Notification(AComponent, Operation);
  1381. if (AComponent = FImages) and (Operation = opRemove) then
  1382. Images := nil;
  1383. end;
  1384. procedure TCustomBCButtonFocus.UpdateControl;
  1385. begin
  1386. RenderControl;
  1387. inherited UpdateControl; // indalidate
  1388. end;
  1389. {$IFDEF FPC}
  1390. procedure TCustomBCButtonFocus.SaveToFile(AFileName: string);
  1391. var
  1392. AStream: TMemoryStream;
  1393. begin
  1394. AStream := TMemoryStream.Create;
  1395. try
  1396. WriteComponentAsTextToStream(AStream, Self);
  1397. AStream.SaveToFile(AFileName);
  1398. finally
  1399. AStream.Free;
  1400. end;
  1401. end;
  1402. procedure TCustomBCButtonFocus.LoadFromFile(AFileName: string);
  1403. var
  1404. AStream: TMemoryStream;
  1405. begin
  1406. AStream := TMemoryStream.Create;
  1407. try
  1408. AStream.LoadFromFile(AFileName);
  1409. ReadComponentFromTextStream(AStream, TComponent(Self), OnFindClass);
  1410. finally
  1411. AStream.Free;
  1412. end;
  1413. end;
  1414. procedure TCustomBCButtonFocus.AssignFromFile(AFileName: string);
  1415. var
  1416. AStream: TMemoryStream;
  1417. AButton: TBCButtonFocus;
  1418. begin
  1419. AButton := TBCButtonFocus.Create(nil);
  1420. AStream := TMemoryStream.Create;
  1421. try
  1422. AStream.LoadFromFile(AFileName);
  1423. ReadComponentFromTextStream(AStream, TComponent(AButton), OnFindClass);
  1424. Assign(AButton);
  1425. finally
  1426. AStream.Free;
  1427. AButton.Free;
  1428. end;
  1429. end;
  1430. {$ENDIF}
  1431. procedure TCustomBCButtonFocus.OnFindClass(Reader: TReader; const AClassName: string;
  1432. var ComponentClass: TComponentClass);
  1433. begin
  1434. if CompareText(AClassName, 'TBCButton') = 0 then
  1435. ComponentClass := TBCButtonFocus;
  1436. end;
  1437. {$IFDEF INDEBUG}
  1438. function TCustomBCButtonFocus.GetDebugText: string;
  1439. begin
  1440. Result := 'R: ' + IntToStr(FRenderCount);
  1441. end;
  1442. {$ENDIF}
  1443. procedure TCustomBCButtonFocus.DrawControl;
  1444. var
  1445. bgra: TBGRABitmapEx;
  1446. begin
  1447. // If style is without dropdown button or state of each button
  1448. // is the same (possible only for msNone) or static button then
  1449. // we can draw whole BGRABitmap
  1450. if (FStyle = bbtButtonF) or (FButtonState = FDownButtonState) or FStaticButton then
  1451. begin
  1452. // Main button
  1453. if FStaticButton then
  1454. bgra := FBGRANormal
  1455. else
  1456. if FDown then
  1457. bgra := FBGRAClick
  1458. else
  1459. case FButtonState of
  1460. msNone: bgra := FBGRANormal;
  1461. msHover: bgra := FBGRAHover;
  1462. msClicked: bgra := FBGRAClick;
  1463. end;
  1464. if {%H-}bgra.NeedRender then
  1465. Render(bgra, TBCButtonFocusState(bgra.CustomData));
  1466. bgra.Draw(Self.Canvas, 0, 0, False);
  1467. end
  1468. // Otherwise we must draw part of state for each button
  1469. else
  1470. begin
  1471. // The active button must be draw as last because right edge of button and
  1472. // left edge of dropdown are overlapping each other, so we must draw edge
  1473. // for current state of active button
  1474. case FActiveButt of
  1475. bbtButtonF:
  1476. begin
  1477. // Drop down button
  1478. case FDownButtonState of
  1479. msNone: bgra := FBGRANormal;
  1480. msHover: bgra := FBGRAHover;
  1481. msClicked: bgra := FBGRAClick;
  1482. end;
  1483. if bgra.NeedRender then
  1484. Render(bgra, TBCButtonFocusState(bgra.CustomData));
  1485. bgra.DrawPart(GetDropDownRect, Self.Canvas, GetDropDownRect.Left,
  1486. GetDropDownRect.Top, False);
  1487. // Main button
  1488. if FDown then
  1489. bgra := FBGRAClick
  1490. else
  1491. case FButtonState of
  1492. msNone: bgra := FBGRANormal;
  1493. msHover: bgra := FBGRAHover;
  1494. msClicked: bgra := FBGRAClick;
  1495. end;
  1496. if bgra.NeedRender then
  1497. Render(bgra, TBCButtonFocusState(bgra.CustomData));
  1498. bgra.DrawPart(GetButtonRect, Self.Canvas, 0, 0, False);
  1499. end;
  1500. bbtDropDownF:
  1501. begin
  1502. // Main button
  1503. if FDown then
  1504. bgra := FBGRAClick
  1505. else
  1506. case FButtonState of
  1507. msNone: bgra := FBGRANormal;
  1508. msHover: bgra := FBGRAHover;
  1509. msClicked: bgra := FBGRAClick;
  1510. end;
  1511. if bgra.NeedRender then
  1512. Render(bgra, TBCButtonFocusState(bgra.CustomData));
  1513. bgra.DrawPart(GetButtonRect, Self.Canvas, 0, 0, False);
  1514. // Drop down button
  1515. case FDownButtonState of
  1516. msNone: bgra := FBGRANormal;
  1517. msHover: bgra := FBGRAHover;
  1518. msClicked: bgra := FBGRAClick;
  1519. end;
  1520. if bgra.NeedRender then
  1521. Render(bgra, TBCButtonFocusState(bgra.CustomData));
  1522. bgra.DrawPart(GetDropDownRect, Self.Canvas, GetDropDownRect.Left,
  1523. GetDropDownRect.Top, False);
  1524. end;
  1525. end;
  1526. end;
  1527. if Assigned(FOnPaintButton) then
  1528. FOnPaintButton(Self);
  1529. LimitMemoryUsage;
  1530. end;
  1531. procedure TCustomBCButtonFocus.RenderControl;
  1532. begin
  1533. inherited RenderControl;
  1534. RenderAll;
  1535. end;
  1536. procedure TCustomBCButtonFocus.WMSetFocus(var Message: {$IFDEF FPC}TLMSetFocus{$ELSE}TWMSetFocus{$ENDIF});
  1537. begin
  1538. inherited;
  1539. UpdateFocus(True);
  1540. end;
  1541. procedure TCustomBCButtonFocus.WMKillFocus(var Message: {$IFDEF FPC}TLMKillFocus{$ELSE}TWMKillFocus{$ENDIF});
  1542. begin
  1543. inherited;
  1544. if Message.FocusedWnd <> Handle then
  1545. UpdateFocus(False);
  1546. end;
  1547. procedure TCustomBCButtonFocus.UpdateFocus(AFocused: boolean);
  1548. var
  1549. lForm: TCustomForm;
  1550. begin
  1551. lForm := GetParentForm(Self);
  1552. if lForm = nil then
  1553. exit;
  1554. {$IFDEF FPC}//#
  1555. if AFocused then
  1556. ActiveDefaultControlChanged(lForm.ActiveControl)
  1557. else
  1558. ActiveDefaultControlChanged(nil);
  1559. {$ENDIF}
  1560. Invalidate;
  1561. end;
  1562. procedure TCustomBCButtonFocus.SetGlobalOpacity(const AValue: byte);
  1563. begin
  1564. if FGlobalOpacity = AValue then
  1565. exit;
  1566. FGlobalOpacity := AValue;
  1567. RenderControl;
  1568. Invalidate;
  1569. end;
  1570. procedure TCustomBCButtonFocus.SetTextApplyGlobalOpacity(const AValue: boolean);
  1571. begin
  1572. if FTextApplyGlobalOpacity = AValue then
  1573. exit;
  1574. FTextApplyGlobalOpacity := AValue;
  1575. RenderControl;
  1576. Invalidate;
  1577. end;
  1578. constructor TCustomBCButtonFocus.Create(AOwner: TComponent);
  1579. begin
  1580. inherited Create(AOwner);
  1581. ControlStyle := ControlStyle + [csParentBackground];
  1582. {$IFDEF INDEBUG}
  1583. FRenderCount := 0;
  1584. {$ENDIF}
  1585. FMemoryUsage := bmuHighF;
  1586. {$IFDEF FPC}
  1587. DisableAutoSizing;
  1588. Include(FControlState, csCreating);
  1589. {$ELSE} //#
  1590. {$ENDIF}
  1591. //{$IFDEF WINDOWS}
  1592. // default sizes under different dpi settings
  1593. //SetSizeVariables(ScaleX(8,96), ScaleX(16,96), ScaleY(8,96), ScaleX(24,96));
  1594. //{$ELSE}
  1595. // default sizes
  1596. SetSizeVariables(16, 8, 8, 24);
  1597. //{$ENDIF}
  1598. BeginUpdate;
  1599. try
  1600. with GetControlClassDefaultSize do
  1601. SetInitialBounds(0, 0, CX, CY);
  1602. ControlStyle := ControlStyle + [csAcceptsControls];
  1603. FBGRANormal := TBGRABitmapEx.Create(Width, Height, BGRAPixelTransparent);
  1604. FBGRAHover := TBGRABitmapEx.Create(Width, Height, BGRAPixelTransparent);
  1605. FBGRAClick := TBGRABitmapEx.Create(Width, Height, BGRAPixelTransparent);
  1606. ParentColor := False;
  1607. Color := clNone;
  1608. FStateNormal := TBCButtonFocusState.Create(Self);
  1609. FStateHover := TBCButtonFocusState.Create(Self);
  1610. FStateClicked := TBCButtonFocusState.Create(Self);
  1611. FStateNormal.OnChange := OnChangeState;
  1612. FStateHover.OnChange := OnChangeState;
  1613. FStateClicked.OnChange := OnChangeState;
  1614. FRounding := TBCRounding.Create(Self);
  1615. FRounding.OnChange := OnChangeState;
  1616. FRoundingDropDown := TBCRounding.Create(Self);
  1617. FRoundingDropDown.OnChange := OnChangeState;
  1618. { Connecting bitmaps with states property to easy call and access }
  1619. FBGRANormal.CustomData := PtrInt(FStateNormal);
  1620. FBGRAHover.CustomData := PtrInt(FStateHover);
  1621. FBGRAClick.CustomData := PtrInt(FStateClicked);
  1622. FButtonState := msNone;
  1623. FDownButtonState := msNone;
  1624. FFlipArrow := False;
  1625. FGlyph := TBitmap.Create;
  1626. FGlyph.OnChange := OnChangeGlyph;
  1627. FGlyphMargin := 5;
  1628. FGlyphAlignment:= bcaCenter;
  1629. FGlyphOldPlacement:= true;
  1630. FStyle := bbtButtonF;
  1631. FStaticButton := False;
  1632. FActiveButt := bbtButtonF;
  1633. FGlobalOpacity := 255;
  1634. FTextApplyGlobalOpacity := False;
  1635. //FStates := [];
  1636. FDown := False;
  1637. { Default style }
  1638. AssignDefaultStyle;
  1639. FImageChangeLink := TChangeLink.Create;
  1640. FImageChangeLink.OnChange := ImageListChange;
  1641. FImageIndex := -1;
  1642. FShowCaption := True;
  1643. FPreserveGlyphOnAssign := True;
  1644. finally
  1645. {$IFDEF FPC}
  1646. Exclude(FControlState, csCreating);
  1647. EnableAutoSizing;
  1648. {$ELSE} //#
  1649. {$ENDIF}
  1650. EndUpdate;
  1651. end;
  1652. end;
  1653. destructor TCustomBCButtonFocus.Destroy;
  1654. begin
  1655. FImageChangeLink.Free;
  1656. FStateNormal.Free;
  1657. FStateHover.Free;
  1658. FStateClicked.Free;
  1659. FBGRANormal.Free;
  1660. FBGRAHover.Free;
  1661. FBGRAClick.Free;
  1662. FreeAndNil(FGlyph);
  1663. FRounding.Free;
  1664. FRoundingDropDown.Free;
  1665. inherited Destroy;
  1666. end;
  1667. procedure TCustomBCButtonFocus.Assign(Source: TPersistent);
  1668. begin
  1669. if Source is TCustomBCButtonFocus then
  1670. begin
  1671. if not PreserveGlyphOnAssign then
  1672. Glyph := TCustomBCButtonFocus(Source).Glyph;
  1673. FGlyphMargin := TCustomBCButtonFocus(Source).FGlyphMargin;
  1674. FStyle := TCustomBCButtonFocus(Source).FStyle;
  1675. FFlipArrow := TCustomBCButtonFocus(Source).FFlipArrow;
  1676. FStaticButton := TCustomBCButtonFocus(Source).FStaticButton;
  1677. FGlobalOpacity := TCustomBCButtonFocus(Source).FGlobalOpacity;
  1678. FTextApplyGlobalOpacity := TCustomBCButtonFocus(Source).FTextApplyGlobalOpacity;
  1679. FStateNormal.Assign(TCustomBCButtonFocus(Source).FStateNormal);
  1680. FStateHover.Assign(TCustomBCButtonFocus(Source).FStateHover);
  1681. FStateClicked.Assign(TCustomBCButtonFocus(Source).FStateClicked);
  1682. FDropDownArrowSize := TCustomBCButtonFocus(Source).FDropDownArrowSize;
  1683. FDropDownWidth := TCustomBCButtonFocus(Source).FDropDownWidth;
  1684. AutoSizeExtraX := TCustomBCButtonFocus(Source).AutoSizeExtraX;
  1685. AutoSizeExtraY := TCustomBCButtonFocus(Source).AutoSizeExtraY;
  1686. FDown := TCustomBCButtonFocus(Source).FDown;
  1687. FRounding.Assign(TCustomBCButtonFocus(Source).FRounding);
  1688. FRoundingDropDown.Assign(TCustomBCButtonFocus(Source).FRoundingDropDown);
  1689. RenderControl;
  1690. Invalidate;
  1691. UpdateSize;
  1692. end
  1693. else
  1694. inherited Assign(Source);
  1695. end;
  1696. procedure TCustomBCButtonFocus.SetSizeVariables(newDropDownWidth,
  1697. newDropDownArrowSize, newAutoSizeExtraVertical, newAutoSizeExtraHorizontal: integer);
  1698. begin
  1699. FDropDownArrowSize := newDropDownArrowSize;
  1700. FDropDownWidth := newDropDownWidth;
  1701. AutoSizeExtraY := newAutoSizeExtraVertical;
  1702. AutoSizeExtraX := newAutoSizeExtraHorizontal;
  1703. if csCreating in ControlState then
  1704. Exit;
  1705. RenderControl;
  1706. UpdateSize;
  1707. Invalidate;
  1708. end;
  1709. function TCustomBCButtonFocus.GetStyleExtension: string;
  1710. begin
  1711. Result := 'bcbtn';
  1712. end;
  1713. end.