PageRenderTime 66ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Components/EhLib 4.2/Common/ToolCtrlsEh.pas

http://github.com/mitshel/tech-inv
Pascal | 1897 lines | 1560 code | 183 blank | 154 comment | 174 complexity | 10995667b0549dc887a299b27712be12 MD5 | raw file
Possible License(s): AGPL-3.0
  1. {*******************************************************}
  2. { }
  3. { EhLib v4.2 }
  4. { Tool controls }
  5. { (Build 4.2.05) }
  6. { }
  7. { Copyright (c) 2001-2006 by Dmitry V. Bolshakov }
  8. { }
  9. {*******************************************************}
  10. {$I EhLib.Inc}
  11. {$IFDEF EH_LIB_VCL}
  12. unit ToolCtrlsEh {$IFDEF CIL} platform {$ENDIF};
  13. {$ELSE}
  14. unit QToolCtrlsEh;
  15. {$ENDIF}
  16. interface
  17. {$IFDEF EH_LIB_VCL}
  18. uses
  19. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  20. {$IFDEF EH_LIB_5} Contnrs, ActnList, {$ENDIF}
  21. {$IFDEF EH_LIB_6} Variants, {$ENDIF}
  22. {$IFDEF CIL}
  23. EhLibVCLNET,
  24. {$ELSE}
  25. EhLibVCL,
  26. {$ENDIF}
  27. StdCtrls, Mask, Db, DBCtrls, Buttons, ExtCtrls, Menus, ComCtrls, CommCtrl,
  28. Imglist;
  29. {$ELSE}
  30. uses
  31. QGraphics, QControls, QForms, QDialogs, Variants, QStdCtrls, QMask,
  32. QDBCtrls, QButtons, QExtCtrls, QMenus, QComCtrls, QImglist,
  33. Db, SysUtils, Classes;
  34. {$ENDIF}
  35. const
  36. CM_IGNOREEDITDOWN = WM_USER + 102;
  37. type
  38. TLocateTextOptionEh = (ltoCaseInsensitiveEh, ltoAllFieldsEh, ltoMatchFormatEh, ltoIgnoteCurrentPosEh);
  39. TLocateTextOptionsEh = set of TLocateTextOptionEh;
  40. TLocateTextDirectionEh = (ltdUpEh, ltdDownEh, ltdAllEh);
  41. TLocateTextMatchingEh = (ltmAnyPartEh, ltmWholeEh, ltmFromBegingEh);
  42. TLocateTextTreeFindRangeEh = (lttInAllNodesEh, lttInExpandedNodesEh,
  43. lttInCurrentLevelEh, lttInCurrentNodeEh);
  44. IMemTableDataFieldValueListEh = interface
  45. ['{28F8194C-5FF3-42C4-87A6-8B3E06210FA6}']
  46. function GetValues: TStrings;
  47. end;
  48. IMemTableEh = interface
  49. ['{A8C3C87A-E556-4BDB-B8A7-5B33497D1624}']
  50. // property TreeViewMode: Boolean read GetTreeViewMode write SetTreeViewMode;
  51. function FetchRecords(Count: Integer): Integer;
  52. function GetInstantReadCurRowNum: Integer;
  53. function GetTreeNodeExpanded(RowNum: Integer): Boolean; overload;
  54. function GetTreeNodeExpanded: Boolean; overload;
  55. function GetTreeNodeHasChields: Boolean;
  56. function GetTreeNodeLevel: Integer;
  57. function GetPrevVisibleTreeNodeLevel: Integer;
  58. function GetNextVisibleTreeNodeLevel: Integer;
  59. function GetRecObject: TObject;
  60. function InstantReadIndexOfBookmark(Bookmark: TBookmarkStr): Integer;
  61. function InstantReadRowCount: Integer;
  62. function MemTableIsTreeList: Boolean;
  63. function ParentHasNextSibling(ParenLevel: Integer): Boolean;
  64. function SetToRec(Rec: TObject): Boolean;
  65. function SetTreeNodeExpanded(RowNum: Integer; Value: Boolean): Integer;
  66. function GetFieldValueList(FieldName: String): IMemTableDataFieldValueListEh;
  67. function MoveRecords(BookmarkList: TStrings; ToRecNo: Longint; TreeLevel: Integer; CheckOnly: Boolean): Boolean;
  68. procedure InstantReadEnter(RowNum: Integer);
  69. procedure InstantReadLeave;
  70. property InstantReadCurRowNum: Integer read GetInstantReadCurRowNum;
  71. // property TreeNodeCollapsed: Boolean read GetTreeNodeCollapsed write SetTreeNodeCollapsed;
  72. end;
  73. IComboEditEh = interface
  74. ['{B64255B5-386A-4524-8BC7-7F49DDB410F4}']
  75. procedure CloseUp(Accept: Boolean);
  76. end;
  77. TFieldsArrEh = array of TField;
  78. { Standard events }
  79. TButtonClickEventEh = procedure(Sender: TObject; var Handled: Boolean) of object;
  80. TButtonDownEventEh = procedure(Sender: TObject; TopButton: Boolean;
  81. var AutoRepeat: Boolean; var Handled: Boolean) of object;
  82. TCloseUpEventEh = procedure(Sender: TObject; Accept: Boolean) of object;
  83. TAcceptEventEh = procedure(Sender: TObject; var Accept: Boolean) of object;
  84. TNotInListEventEh = procedure(Sender: TObject; NewText: String;
  85. var RecheckInList: Boolean) of object;
  86. TUpdateDataEventEh = procedure(Sender: TObject; var Handled: Boolean) of object;
  87. { TBMListEh }
  88. TBMListEh = class
  89. private
  90. FCache: TBookmarkStr;
  91. FCacheFind: Boolean;
  92. FCacheIndex: Integer;
  93. FLinkActive:boolean;
  94. function GetCount: Integer;
  95. function GetCurrentRowSelected: Boolean;
  96. function GetItem(Index: Integer): TBookmarkStr;
  97. protected
  98. FList: TStringList;
  99. function Compare(const Item1, Item2: TBookmarkStr): Integer;
  100. function CurrentRow: TBookmarkStr;
  101. function GetDataSet:TDataSet; virtual; abstract;
  102. procedure Invalidate; virtual;
  103. procedure LinkActive(Value: Boolean);
  104. procedure RaiseBMListError(const S: string); virtual;
  105. procedure SetCurrentRowSelected(Value: Boolean); virtual;
  106. procedure StringsChanged(Sender: TObject); virtual;
  107. procedure UpdateState; virtual;
  108. public
  109. constructor Create;
  110. destructor Destroy; override;
  111. function Find(const Item: TBookmarkStr; var Index: Integer): Boolean;
  112. function IndexOf(const Item: TBookmarkStr): Integer;
  113. function Refresh: Boolean;
  114. procedure Clear; virtual;
  115. procedure Delete;
  116. procedure SelectAll;
  117. property Count: Integer read GetCount;
  118. property CurrentRowSelected: Boolean read GetCurrentRowSelected write SetCurrentRowSelected;
  119. property DataSet:TDataSet read GetDataSet;
  120. property Items[Index: Integer]: TBookmarkStr read GetItem; default;
  121. end;
  122. { TEditButtonControlEh }
  123. TEditButtonStyleEh = (ebsDropDownEh, ebsEllipsisEh, ebsGlyphEh, ebsUpDownEh,
  124. ebsPlusEh, ebsMinusEh);
  125. TEditButtonControlEh = class(TSpeedButton)
  126. private
  127. FActive: Boolean;
  128. FAlwaysDown: Boolean;
  129. FButtonNum: Integer;
  130. FNoDoClick: Boolean;
  131. FOnDown: TButtonDownEventEh;
  132. FStyle: TEditButtonStyleEh;
  133. FTimer: TTimer;
  134. function GetTimer: TTimer;
  135. procedure ResetTimer(Interval: Cardinal);
  136. procedure SetActive(const Value: Boolean);
  137. procedure SetAlwaysDown(const Value: Boolean);
  138. procedure SetStyle(const Value: TEditButtonStyleEh);
  139. procedure TimerEvent(Sender: TObject);
  140. procedure UpdateDownButtonNum(X, Y: Integer);
  141. protected
  142. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  143. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  144. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  145. procedure Paint; override;
  146. property Timer: TTimer read GetTimer;
  147. public
  148. procedure Click; override;
  149. procedure EditButtonDown(TopButton: Boolean; var AutoRepeat: Boolean);
  150. procedure SetState(NewState: TButtonState; IsActive: Boolean; ButtonNum: Integer);
  151. procedure SetWidthNoNotify(AWidth: Integer);
  152. property Active: Boolean read FActive write SetActive;
  153. property AlwaysDown: Boolean read FAlwaysDown write SetAlwaysDown;
  154. property Style: TEditButtonStyleEh read FStyle write SetStyle default ebsDropDownEh;
  155. property OnDown: TButtonDownEventEh read FOnDown write FOnDown;
  156. end;
  157. TSpeedButtonEh = class(TEditButtonControlEh)
  158. published
  159. property Active;
  160. property Style;
  161. end;
  162. TEditButtonControlLineRec = record
  163. ButtonLine: TShape;
  164. EditButtonControl: TEditButtonControlEh;
  165. end;
  166. TEditButtonControlList = array of TEditButtonControlLineRec;
  167. TEditButtonEh = class;
  168. TEditButtonActionLinkEh = class(TActionLink)
  169. protected
  170. FClient: TEditButtonEh;
  171. procedure AssignClient(AClient: TObject); override;
  172. function IsEnabledLinked: Boolean; override;
  173. function IsHintLinked: Boolean; override;
  174. function IsShortCutLinked: Boolean; override;
  175. function IsVisibleLinked: Boolean; override;
  176. procedure SetEnabled(Value: Boolean); override;
  177. procedure SetHint(const Value: string); override;
  178. procedure SetShortCut(Value: TShortCut); override;
  179. procedure SetVisible(Value: Boolean); override;
  180. end;
  181. TEditButtonActionLinkEhClass = class of TEditButtonActionLinkEh;
  182. { TEditButtonEh }
  183. TEditButtonEh = class(TCollectionItem)
  184. private
  185. FActionLink: TEditButtonActionLinkEh;
  186. FDropdownMenu: TPopupMenu;
  187. FEditControl: TWinControl;
  188. FEnabled: Boolean;
  189. FGlyph: TBitmap;
  190. FHint: String;
  191. FNumGlyphs: Integer;
  192. FOnButtonClick: TButtonClickEventEh;
  193. FOnButtonDown: TButtonDownEventEh;
  194. FOnChanged: TNotifyEvent;
  195. FShortCut: TShortCut;
  196. FStyle: TEditButtonStyleEh;
  197. FVisible: Boolean;
  198. FWidth: Integer;
  199. function GetAction: TBasicAction;
  200. function GetGlyph: TBitmap;
  201. function IsEnabledStored: Boolean;
  202. function IsHintStored: Boolean;
  203. function IsShortCutStored: Boolean;
  204. function IsVisibleStored: Boolean;
  205. procedure DoActionChange(Sender: TObject);
  206. procedure SetAction(const Value: TBasicAction);
  207. procedure SetEnabled(const Value: Boolean);
  208. procedure SetGlyph(const Value: TBitmap);
  209. procedure SetHint(const Value: String);
  210. procedure SetNumGlyphs(Value: Integer);
  211. procedure SetStyle(const Value: TEditButtonStyleEh);
  212. procedure SetVisible(const Value: Boolean);
  213. procedure SetWidth(const Value: Integer);
  214. protected
  215. function CreateEditButtonControl: TEditButtonControlEh; virtual;
  216. procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); dynamic;
  217. procedure Changed; overload;
  218. property ActionLink: TEditButtonActionLinkEh read FActionLink write FActionLink;
  219. public
  220. constructor Create(Collection: TCollection); overload; override;
  221. constructor Create(EditControl: TWinControl); reintroduce; overload;
  222. destructor Destroy; override;
  223. function GetActionLinkClass: TEditButtonActionLinkEhClass; dynamic;
  224. procedure Assign(Source: TPersistent); override;
  225. procedure Click(Sender: TObject; var Handled: Boolean); virtual;
  226. procedure InitiateAction; virtual;
  227. property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
  228. published
  229. property Action: TBasicAction read GetAction write SetAction;
  230. property DropdownMenu: TPopupMenu read FDropdownMenu write FDropdownMenu;
  231. property Enabled: Boolean read FEnabled write SetEnabled stored IsEnabledStored default True;
  232. property Glyph: TBitmap read GetGlyph write SetGlyph;
  233. property Hint: String read FHint write SetHint stored IsHintStored;
  234. property NumGlyphs: Integer read FNumGlyphs write SetNumGlyphs default 1;
  235. property ShortCut: TShortCut read FShortCut write FShortCut stored IsShortCutStored default scNone;
  236. //property ShortCut: TShortCut read FShortCut write FShortCut default 32808; //Menus.ShortCut(VK_DOWN, [ssAlt]);
  237. property Style: TEditButtonStyleEh read FStyle write SetStyle default ebsDropDownEh;
  238. property Visible: Boolean read FVisible write SetVisible stored IsVisibleStored default False;
  239. property Width: Integer read FWidth write SetWidth default 0;
  240. property OnClick: TButtonClickEventEh read FOnButtonClick write FOnButtonClick;
  241. property OnDown: TButtonDownEventEh read FOnButtonDown write FOnButtonDown;
  242. end;
  243. TEditButtonEhClass = class of TEditButtonEh;
  244. { TDropDownEditButtonEh }
  245. TDropDownEditButtonEh = class(TEditButtonEh)
  246. public
  247. constructor Create(Collection: TCollection); overload; override;
  248. constructor Create(EditControl: TWinControl); overload;
  249. published
  250. property ShortCut default 32808; //Menus.ShortCut(VK_DOWN, [ssAlt]);
  251. end;
  252. { TVisibleEditButtonEh }
  253. TVisibleEditButtonEh = class(TEditButtonEh)
  254. public
  255. constructor Create(Collection: TCollection); overload; override;
  256. constructor Create(EditControl: TWinControl); overload;
  257. published
  258. property ShortCut default 32808; //Menus.ShortCut(VK_DOWN, [ssAlt]);
  259. property Visible default True;
  260. end;
  261. { TEditButtonsEh }
  262. TEditButtonsEh = class(TCollection)
  263. private
  264. FOnChanged: TNotifyEvent;
  265. function GetEditButton(Index: Integer): TEditButtonEh;
  266. procedure SetEditButton(Index: Integer; Value: TEditButtonEh);
  267. protected
  268. FOwner: TPersistent;
  269. function GetOwner: TPersistent; override;
  270. procedure Update(Item: TCollectionItem); override;
  271. public
  272. constructor Create(Owner: TPersistent; EditButtonClass: TEditButtonEhClass);
  273. function Add: TEditButtonEh;
  274. property Items[Index: Integer]: TEditButtonEh read GetEditButton write SetEditButton; default;
  275. property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
  276. end;
  277. { TSpecRowEh }
  278. TSpecRowEh = class(TPersistent)
  279. private
  280. FCellsStrings: TStrings;
  281. FCellsText: String;
  282. FColor: TColor;
  283. FFont: TFont;
  284. FOnChanged: TNotifyEvent;
  285. FOwner: TPersistent;
  286. FSelected: Boolean;
  287. FShortCut: TShortCut;
  288. FShowIfNotInKeyList: Boolean;
  289. FUpdateCount: Integer;
  290. FValue: Variant;
  291. FVisible: Boolean;
  292. function GetCellText(Index: Integer): String;
  293. function GetColor: TColor;
  294. function GetFont: TFont;
  295. function IsColorStored: Boolean;
  296. function IsFontStored: Boolean;
  297. function IsValueStored: Boolean;
  298. procedure FontChanged(Sender: TObject);
  299. procedure SetCellsText(const Value: String);
  300. procedure SetColor(const Value: TColor);
  301. procedure SetFont(const Value: TFont);
  302. procedure SetShowIfNotInKeyList(const Value: Boolean);
  303. procedure SetValue(const Value: Variant);
  304. procedure SetVisible(const Value: Boolean);
  305. protected
  306. FColorAssigned: Boolean;
  307. FFontAssigned: Boolean;
  308. function GetOwner: TPersistent; override;
  309. procedure Changed;
  310. public
  311. constructor Create(Owner: TPersistent);
  312. destructor Destroy; override;
  313. function DefaultColor: TColor;
  314. function DefaultFont: TFont;
  315. function LocateKey(KeyValue: Variant): Boolean;
  316. procedure Assign(Source: TPersistent); override;
  317. procedure BeginUpdate;
  318. procedure EndUpdate;
  319. property CellText[Index: Integer]: String read GetCellText;
  320. property Selected: Boolean read FSelected write FSelected;
  321. property UpdateCount: Integer read FUpdateCount;
  322. property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
  323. published
  324. property CellsText: String read FCellsText write SetCellsText;
  325. property Color: TColor read GetColor write SetColor stored IsColorStored;
  326. property Font: TFont read GetFont write SetFont stored IsFontStored;
  327. property ShortCut: TShortCut read FShortCut write FShortCut default 32814; //Menus.ShortCut(VK_DOWN, [ssAlt]);
  328. property ShowIfNotInKeyList: Boolean read FShowIfNotInKeyList write SetShowIfNotInKeyList default True;
  329. property Value: Variant read FValue write SetValue stored IsValueStored;
  330. property Visible: Boolean read FVisible write SetVisible default False;
  331. end;
  332. { TSizeGripEh }
  333. TSizeGripPostion = (sgpTopLeft, sgpTopRight, sgpBottomRight, sgpBottomLeft);
  334. TSizeGripChangePosition = (sgcpToLeft, sgcpToRight, sgcpToTop, sgcpToBottom);
  335. TSizeGripEh = class(TCustomControl)
  336. private
  337. FInitScreenMousePos: TPoint;
  338. FInternalMove: Boolean;
  339. FOldMouseMovePos: TPoint;
  340. FParentRect: TRect;
  341. FParentResized: TNotifyEvent;
  342. FPosition: TSizeGripPostion;
  343. FTriangleWindow: Boolean;
  344. function GetVisible: Boolean;
  345. procedure SetPosition(const Value: TSizeGripPostion);
  346. procedure SetTriangleWindow(const Value: Boolean);
  347. procedure SetVisible(const Value: Boolean);
  348. procedure WMMove(var Message: TWMMove); message WM_MOVE;
  349. protected
  350. procedure CreateWnd; override;
  351. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  352. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  353. procedure Paint; override;
  354. procedure ParentResized; dynamic;
  355. public
  356. constructor Create(AOwner: TComponent); override;
  357. procedure ChangePosition(NewPosition: TSizeGripChangePosition);
  358. procedure UpdatePosition;
  359. procedure UpdateWindowRegion;
  360. property Position: TSizeGripPostion read FPosition write SetPosition default sgpBottomRight;
  361. property TriangleWindow: Boolean read FTriangleWindow write SetTriangleWindow default True;
  362. property Visible: Boolean read GetVisible write SetVisible;
  363. property OnParentResized: TNotifyEvent read FParentResized write FParentResized;
  364. end;
  365. const
  366. cm_SetSizeGripChangePosition = WM_USER + 100;
  367. { TPopupMonthCalendarEh }
  368. const
  369. CM_CLOSEUPEH = WM_USER + 101;
  370. type
  371. TPopupMonthCalendarEh = class(TMonthCalendar)
  372. private
  373. FBorderWidth: Integer;
  374. procedure CMCloseUpEh(var Message: TMessage); message CM_CLOSEUPEH;
  375. procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  376. procedure CMWantSpecialKey(var Message: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  377. procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  378. procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  379. procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
  380. procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
  381. protected
  382. function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
  383. function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
  384. function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;
  385. function MsgSetDateTime(Value: TSystemTime): Boolean; override;
  386. procedure CreateParams(var Params: TCreateParams); override;
  387. procedure CreateWnd; override;
  388. procedure DrawBorder; virtual;
  389. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  390. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  391. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  392. procedure PostCloseUp(Accept: Boolean);
  393. procedure UpdateBorderWidth;
  394. public
  395. constructor Create(AOwner: TComponent); override;
  396. property Color;
  397. property Ctl3D;
  398. end;
  399. TListGetImageIndexEventEh = procedure(Sender: TObject; ItemIndex: Integer; var ImageIndex: Integer) of object;
  400. { TPopupListboxEh }
  401. TPopupListboxEh = class(TCustomListbox)
  402. private
  403. FBorderWidth: Integer;
  404. FImageList: TCustomImageList;
  405. FMousePos: TPoint;
  406. FRowCount: Integer;
  407. FSearchText: String;
  408. FSearchTickCount: Longint;
  409. FSizeGrip: TSizeGripEh;
  410. FSizeGripResized: Boolean;
  411. FOnGetImageIndex: TListGetImageIndexEventEh;
  412. FExtItems: TStrings;
  413. function CheckNewSize(var NewWidth, NewHeight: Integer): Boolean;
  414. function GetBorderSize: Integer;
  415. function GetExtItems: TStrings;
  416. procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  417. procedure CMSetSizeGripChangePosition(var Message: TMessage); message cm_SetSizeGripChangePosition;
  418. procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
  419. procedure SetExtItems(Value: TStrings);
  420. procedure SetImageList(const Value: TCustomImageList);
  421. procedure SetRowCount(Value: Integer);
  422. procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
  423. procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
  424. procedure WMSize(var Message: TWMSize); message WM_SIZE;
  425. procedure WMWindowPosChanging(var Message: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING;
  426. protected
  427. function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
  428. function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;
  429. procedure CreateParams(var Params: TCreateParams); override;
  430. procedure CreateWnd; override;
  431. procedure DrawBorder; virtual;
  432. procedure DrawItem(Index: Integer; ARect: TRect; State: TOwnerDrawState); override;
  433. procedure KeyPress(var Key: Char); override;
  434. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  435. procedure UpdateBorderWidth;
  436. procedure SelfOnGetData(Control: TWinControl; Index: Integer; var Data: string); virtual;
  437. public
  438. constructor Create(Owner: TComponent); override;
  439. procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  440. function CanFocus: Boolean; {$IFDEF EH_LIB_5} override; {$ENDIF}
  441. function GetTextHeight: Integer;
  442. property Color;
  443. property Ctl3D;
  444. property Font;
  445. property ImageList: TCustomImageList read FImageList write SetImageList;
  446. property IntegralHeight;
  447. property ItemHeight;
  448. property RowCount: Integer read FRowCount write SetRowCount;
  449. property ExtItems: TStrings read GetExtItems write SetExtItems;
  450. property SizeGrip: TSizeGripEh read FSizeGrip;
  451. property SizeGripResized: Boolean read FSizeGripResized write FSizeGripResized;
  452. property OnMouseUp;
  453. property OnGetImageIndex: TListGetImageIndexEventEh read FOnGetImageIndex write FOnGetImageIndex;
  454. end;
  455. { TMRUList }
  456. TFilterMRUItemEventEh = procedure (Sender: TObject; var Accept: Boolean) of object;
  457. TSetDropDownEventEh = procedure (Sender: TObject) of object;
  458. TSetCloseUpEventEh = procedure (Sender: TObject; Accept: Boolean) of object;
  459. TMRUListEh = class(TPersistent)
  460. private
  461. FActive: Boolean;
  462. FAutoAdd: Boolean;
  463. FCaseSensitive: Boolean;
  464. FItems: TStrings;
  465. FLimit: Integer;
  466. FOnActiveChanged: TNotifyEvent;
  467. FOnFilterItem: TFilterMRUItemEventEh;
  468. FOnSetCloseUpEvent: TSetCloseUpEventEh;
  469. FOnSetDropDown: TSetDropDownEventEh;
  470. FOwner: TPersistent;
  471. FRows: Integer;
  472. FWidth: Integer;
  473. FCancelIfKeyInQueue: Boolean;
  474. procedure SetActive(const Value: Boolean);
  475. procedure SetItems(const Value: TStrings);
  476. procedure SetLimit(const Value: Integer);
  477. procedure SetRows(const Value: Integer);
  478. protected
  479. FDroppedDown: Boolean;
  480. procedure UpdateLimit;
  481. public
  482. constructor Create(AOwner: TPersistent);
  483. destructor Destroy; override;
  484. procedure Add(s: String);
  485. procedure Assign(Source: TPersistent); override;
  486. procedure CloseUp(Accept: Boolean); virtual;
  487. procedure DropDown; virtual;
  488. function FilterItemsTo(FilteredItems: TStrings; MaskText: String): Boolean;
  489. property DroppedDown: Boolean read FDroppedDown write FDroppedDown;
  490. property Width: Integer read FWidth write FWidth;
  491. property OnActiveChanged: TNotifyEvent read FOnActiveChanged write FOnActiveChanged;
  492. property OnSetCloseUp: TSetCloseUpEventEh read FOnSetCloseUpEvent write FOnSetCloseUpEvent;
  493. property OnSetDropDown: TSetDropDownEventEh read FOnSetDropDown write FOnSetDropDown;
  494. property OnFilterItem: TFilterMRUItemEventEh read FOnFilterItem write FOnFilterItem;
  495. property CancelIfKeyInQueue: Boolean read FCancelIfKeyInQueue write FCancelIfKeyInQueue default True;
  496. published
  497. property AutoAdd: Boolean read FAutoAdd write FAutoAdd default True;
  498. property Active: Boolean read FActive write SetActive default False;
  499. property CaseSensitive: Boolean read FCaseSensitive write FCaseSensitive default False;
  500. property Items: TStrings read FItems write SetItems;
  501. property Limit: Integer read FLimit write SetLimit default 100;
  502. property Rows: Integer read FRows write SetRows default 7;
  503. end;
  504. { TMRUListboxEh }
  505. TMRUListboxEh = class(TPopupListboxEh)
  506. private
  507. FScrollBar: TScrollBar;
  508. FScrollBarLockMove: Boolean;
  509. procedure CMChanged(var Message: TCMChanged); message CM_CHANGED;
  510. procedure CMMouseWheel(var Message: TCMMouseWheel); message CM_MOUSEWHEEL;
  511. procedure CMSetSizeGripChangePosition(var Message: TMessage); message cm_SetSizeGripChangePosition;
  512. procedure WMSize(var Message: TWMSize); message WM_SIZE;
  513. protected
  514. procedure CreateParams(var Params: TCreateParams); override;
  515. procedure ScrollBarScrolled(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
  516. procedure ScrollBarWindowProc(var Message: TMessage);
  517. public
  518. constructor Create(Owner: TComponent); override;
  519. procedure UpdateScrollBar;
  520. procedure UpdateScrollBarPos;
  521. property ParentCtl3D;
  522. property ScrollBar: TScrollBar read FScrollBar;
  523. property Sorted;
  524. property OnMouseUp;
  525. end;
  526. {$IFNDEF EH_LIB_5} // Delphi 4 doesn't have TObjectList but Delphi 8 required
  527. { TObjectList class }
  528. TObjectList = class(TList)
  529. private
  530. FOwnsObjects: Boolean;
  531. protected
  532. function GetItem(Index: Integer): TObject;
  533. procedure SetItem(Index: Integer; AObject: TObject);
  534. public
  535. constructor Create; overload;
  536. constructor Create(AOwnsObjects: Boolean); overload;
  537. function Add(AObject: TObject): Integer;
  538. function Remove(AObject: TObject): Integer;
  539. function IndexOf(AObject: TObject): Integer;
  540. function FindInstanceOf(AClass: TClass; AExact: Boolean = True; AStartAt: Integer = 0): Integer;
  541. procedure Insert(Index: Integer; AObject: TObject);
  542. property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
  543. property Items[Index: Integer]: TObject read GetItem write SetItem; default;
  544. end;
  545. {$ENDIF}
  546. {$IFNDEF EH_LIB_5}
  547. TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer;
  548. {$ENDIF}
  549. TStringListEh = class(TStringList)
  550. {$IFNDEF EH_LIB_6}
  551. private
  552. FCaseSensitive: Boolean;
  553. function CompareStrings(const S1, S2: string): Integer;
  554. procedure SetCaseSensitive(const Value: Boolean);
  555. public
  556. {$IFNDEF EH_LIB_5}
  557. procedure CustomSort(Compare: TStringListSortCompare);
  558. procedure QuickSort(L, R: Integer; SCompare: TStringListSortCompare);
  559. {$ENDIF}
  560. procedure Sort; override;
  561. property CaseSensitive: Boolean read FCaseSensitive write SetCaseSensitive;
  562. {$ENDIF}
  563. end;
  564. { TDataLinkEh }
  565. {$IFDEF CIL}
  566. TDataEventEh = procedure (Event: TDataEvent; Info: TObject) of object;
  567. {$ELSE}
  568. TDataEventEh = procedure (Event: TDataEvent; Info: Longint) of object;
  569. {$ENDIF}
  570. TDataLinkEh = class(TDataLink)
  571. private
  572. FOnDataEvent: TDataEventEh;
  573. protected
  574. {$IFDEF CIL}
  575. procedure DataEvent(Event: TDataEvent; Info: TObject); virtual;
  576. {$ELSE}
  577. procedure DataEvent(Event: TDataEvent; Info: Integer); override;
  578. {$ENDIF}
  579. public
  580. property OnDataEvent: TDataEventEh read FOnDataEvent write FOnDataEvent;
  581. end;
  582. { TDatasetFieldValueListEh }
  583. TDatasetFieldValueListEh = class(TInterfacedObject, IMemTableDataFieldValueListEh)
  584. private
  585. FValues: TStringList;
  586. FDataObsoleted: Boolean;
  587. FFieldName: String;
  588. FDataLink: TDataLinkEh;
  589. FDataSource: TDataSource;
  590. function GetValues: TStrings;
  591. procedure SetFieldName(const Value: String);
  592. procedure SetDataSet(const Value: TDataSet);
  593. function GetDataSet: TDataSet;
  594. protected
  595. procedure RefreshValues;
  596. {$IFDEF CIL}
  597. procedure DataSetEvent(Event: TDataEvent; Info: TObject); virtual;
  598. {$ELSE}
  599. procedure DataSetEvent(Event: TDataEvent; Info: Integer); virtual;
  600. {$ENDIF}
  601. public
  602. constructor Create;
  603. destructor Destroy; override;
  604. property FieldName: String read FFieldName write SetFieldName;
  605. property DataSet: TDataSet read GetDataSet write SetDataSet;
  606. property Values: TStrings read GetValues;
  607. end;
  608. TLocateTextEventEh = function (Sender: TObject;
  609. const FieldName: string; const Text: String; Options: TLocateTextOptionsEh;
  610. Direction: TLocateTextDirectionEh; Matching: TLocateTextMatchingEh;
  611. TreeFindRange: TLocateTextTreeFindRangeEh): Boolean of object;
  612. TDrawButtonControlStyleEh = (bcsDropDownEh, bcsEllipsisEh, bcsUpDownEh,
  613. bcsCheckboxEh, bcsPlusEh, bcsMinusEh);
  614. TTreeElementEh = (tehMinusUpDown, tehMinusUp, tehMinusDown,
  615. tehPlusUpDown, tehPlusUp, tehPlusDown,
  616. tehCrossUpDown, tehCrossUp, tehCrossDown,
  617. tehVLine);
  618. procedure PaintButtonControlEh(DC: HDC; ARect: TRect; ParentColor: TColor;
  619. Style: TDrawButtonControlStyleEh; DownButton: Integer;
  620. Flat, Active, Enabled: Boolean; State: TCheckBoxState);
  621. function GetDefaultFlatButtonWidth: Integer;
  622. var
  623. FlatButtonWidth: Integer;
  624. type
  625. TFieldTypes = set of TFieldType;
  626. const
  627. ftNumberFieldTypes: TFieldTypes = [ftSmallint, ftInteger, ftWord, ftFloat, ftCurrency,
  628. ftBCD{$IFDEF EH_LIB_6}, ftFMTBcd{$ENDIF}];
  629. procedure GetFieldsProperty(List: TList; DataSet: TDataSet;
  630. Control: TComponent; const FieldNames: String); overload;
  631. function GetFieldsProperty(DataSet: TDataSet; Control: TComponent;
  632. const FieldNames: String): TFieldsArrEh; overload;
  633. procedure DataSetSetFieldValues(DataSet: TDataSet; Fields: String; Value: Variant);
  634. function VarEquals(const V1, V2: Variant): Boolean;
  635. {$IFNDEF EH_LIB_6}
  636. type
  637. TVariantRelationship = (vrEqual, vrLessThan, vrGreaterThan, vrNotEqual);
  638. {$ENDIF}
  639. function DBVarCompareValue(const A, B: Variant): TVariantRelationship;
  640. var UseButtonsBitmapCache: Boolean = True;
  641. procedure ClearButtonsBitmapCache;
  642. procedure DrawImage(DC: HDC; ARect: TRect; Images: TCustomImageList;
  643. ImageIndex: Integer; Selected: Boolean);
  644. procedure DrawTreeElement(Canvas: TCanvas; ARect: TRect;
  645. TreeElement: TTreeElementEh; BackDot: Boolean; ScaleX, ScaleY: Double;
  646. RightToLeft: Boolean);
  647. function AlignDropDownWindowRect(MasterAbsRect: TRect; DropDownWin: TWinControl; Align: TDropDownAlign): TPoint;
  648. function AlignDropDownWindow(MasterWin, DropDownWin: TWinControl; Align: TDropDownAlign): TPoint;
  649. {$IFNDEF EH_LIB_5}
  650. function Supports(const Instance: IUnknown; const IID: TGUID; out Intf): Boolean; overload;
  651. function Supports(const Instance: TObject; const IID: TGUID; out Intf): Boolean; overload;
  652. {$ENDIF}
  653. var
  654. DefaultCheckBoxWidth, DefaultCheckBoxHeight: Integer;
  655. function AdjustCheckBoxRect(ClientRect: TRect; Alignment: TAlignment; Layout: TTextLayout): TRect;
  656. function IsDoubleClickMessage(OldPos, NewPos: TPoint; Interval: Longint): Boolean;
  657. function DefaultEditButtonHeight(EditButtonWidth: Integer; Flat: Boolean): Integer;
  658. function KillMouseUp(Control: TControl): Boolean; overload;
  659. function KillMouseUp(Control: TControl; Area: TRect): Boolean; overload;
  660. implementation
  661. uses DBConsts, Math,
  662. {$IFDEF EH_LIB_6} VDBConsts, Types, {$ENDIF}
  663. {$IFDEF EH_LIB_7} Themes, UxTheme, {$ENDIF}
  664. MultiMon;
  665. type
  666. TWinControlCracker = class(TWinControl) end;
  667. TControlCracker = class(TControl) end;
  668. {$IFNDEF EH_LIB_5}
  669. function Supports(const Instance: IUnknown; const IID: TGUID; out Intf): Boolean; overload;
  670. begin
  671. Result := (Instance <> nil) and (Instance.QueryInterface(IID, Intf) = 0);
  672. end;
  673. function Supports(const Instance: TObject; const IID: TGUID; out Intf): Boolean; overload;
  674. var
  675. LUnknown: IUnknown;
  676. begin
  677. Result := (Instance <> nil) and
  678. ((Instance.GetInterface(IUnknown, LUnknown) and Supports(LUnknown, IID, Intf)) or
  679. Instance.GetInterface(IID, Intf));
  680. end;
  681. {$ENDIF}
  682. function IsDoubleClickMessage(OldPos, NewPos: TPoint; Interval: Longint): Boolean;
  683. begin
  684. Result := (Interval <= Longint(GetDoubleClickTime)) and
  685. (Abs(OldPos.X - NewPos.X) <= GetSystemMetrics(SM_CXDOUBLECLK)) and
  686. (Abs(OldPos.Y - NewPos.Y) <= GetSystemMetrics(SM_CYDOUBLECLK));
  687. end;
  688. procedure GetCheckSize;
  689. begin
  690. with TBitmap.Create do
  691. try
  692. Handle := LoadBitmapEh(0, OBM_CHECKBOXES);
  693. DefaultCheckBoxWidth := Width div 4;
  694. DefaultCheckBoxHeight := Height div 3;
  695. finally
  696. Free;
  697. end;
  698. end;
  699. function AdjustCheckBoxRect(ClientRect: TRect; Alignment: TAlignment; Layout: TTextLayout): TRect;
  700. var
  701. CheckWidth, CheckHeight: Integer;
  702. begin
  703. if (ClientRect.Right - ClientRect.Left) > DefaultCheckBoxWidth
  704. then CheckWidth := DefaultCheckBoxWidth
  705. else CheckWidth := ClientRect.Right - ClientRect.Left;
  706. if (ClientRect.Bottom - ClientRect.Top) > DefaultCheckBoxHeight
  707. then CheckHeight := DefaultCheckBoxHeight
  708. else CheckHeight := ClientRect.Bottom - ClientRect.Top;
  709. Result := ClientRect;
  710. if (ClientRect.Right - ClientRect.Left) > DefaultCheckBoxWidth then
  711. case Alignment of
  712. taRightJustify: Result.Left := Result.Right - CheckWidth;
  713. taCenter: Result.Left := Result.Left + (ClientRect.Right - ClientRect.Left) shr 1 - CheckWidth shr 1;
  714. end;
  715. Result.Right := Result.Left + CheckWidth;
  716. if (ClientRect.Bottom - ClientRect.Top) > DefaultCheckBoxHeight then
  717. case Layout of
  718. tlBottom: Result.Top := Result.Bottom - CheckWidth;
  719. tlCenter: Result.Top := Result.Top + (ClientRect.Bottom - ClientRect.Top) shr 1 - CheckHeight shr 1;
  720. end;
  721. Result.Bottom := Result.Top + CheckHeight;
  722. end;
  723. procedure DrawCheck(DC: HDC; R: TRect; AState: TCheckBoxState; AEnabled, AFlat, ADown, AActive: Boolean);
  724. var
  725. DrawState, oldRgn: Integer;
  726. DrawRect: TRect;
  727. // OldBrushColor: TColor;
  728. // OldBrushStyle: TBrushStyle;
  729. // OldPenColor: TColor;
  730. Rgn, SaveRgn: HRgn;
  731. {$IFDEF EH_LIB_7}
  732. ElementDetails: TThemedElementDetails;
  733. {$ENDIF}
  734. // Brush,SaveBrush: HBRUSH;
  735. begin
  736. SaveRgn := 0;
  737. oldRgn := 0;
  738. DrawRect := R;
  739. with DrawRect do
  740. if (Right - Left) > (Bottom - Top) then
  741. begin
  742. Left := Left + ((Right - Left) - (Bottom - Top)) div 2;
  743. Right := Left + (Bottom - Top);
  744. end else if (Right - Left) < (Bottom - Top) then
  745. begin
  746. Top := Top + ((Bottom - Top) - (Right - Left)) div 2;
  747. Bottom := Top + (Right - Left);
  748. end;
  749. case AState of
  750. cbChecked:
  751. DrawState := DFCS_BUTTONCHECK or DFCS_CHECKED;
  752. cbUnchecked:
  753. DrawState := DFCS_BUTTONCHECK;
  754. else // cbGrayed
  755. DrawState := DFCS_BUTTON3STATE or DFCS_CHECKED;
  756. end;
  757. if not AEnabled then
  758. DrawState := DrawState or DFCS_INACTIVE;
  759. if ADown then
  760. DrawState := DrawState or DFCS_PUSHED;
  761. // with Canvas do
  762. // begin
  763. if AFlat then
  764. begin
  765. { Remember current clipping region }
  766. SaveRgn := CreateRectRgn(0, 0, 0, 0);
  767. oldRgn := GetClipRgn(DC, SaveRgn);
  768. { Clip 3d-style checkbox to prevent flicker }
  769. with DrawRect do
  770. Rgn := CreateRectRgn(Left + 1, Top + 1, Right - 1, Bottom - 1);
  771. SelectClipRgn(DC, Rgn);
  772. DeleteObject(Rgn);
  773. end;
  774. if AFlat then InflateRect(DrawRect, 1, 1);
  775. {$IFDEF EH_LIB_7}
  776. if ThemeServices.ThemesEnabled then
  777. begin
  778. case AState of
  779. cbChecked:
  780. if AEnabled then
  781. ElementDetails := ThemeServices.GetElementDetails(tbCheckBoxCheckedNormal)
  782. else
  783. ElementDetails := ThemeServices.GetElementDetails(tbCheckBoxCheckedDisabled);
  784. cbUnchecked:
  785. if AEnabled then
  786. ElementDetails := ThemeServices.GetElementDetails(tbCheckBoxUncheckedNormal)
  787. else
  788. ElementDetails := ThemeServices.GetElementDetails(tbCheckBoxUncheckedDisabled)
  789. else // cbGrayed
  790. if AEnabled then
  791. ElementDetails := ThemeServices.GetElementDetails(tbCheckBoxMixedNormal)
  792. else
  793. ElementDetails := ThemeServices.GetElementDetails(tbCheckBoxMixedDisabled);
  794. end;
  795. ThemeServices.DrawElement(DC, ElementDetails, R);
  796. end
  797. else
  798. {$ENDIF}
  799. DrawFrameControl(DC, DrawRect, DFC_BUTTON, DrawState);
  800. if AFlat then
  801. begin
  802. //SelectClipRgn(Handle, SaveRgn);
  803. if oldRgn = 0 then
  804. SelectClipRgn(DC, 0)
  805. else
  806. SelectClipRgn(DC, SaveRgn);
  807. DeleteObject(SaveRgn);
  808. { Draw flat rectangle in-place of clipped 3d checkbox above }
  809. InflateRect(DrawRect, -1, -1);
  810. if AActive
  811. then FrameRect(DC, DrawRect, GetSysColorBrush(COLOR_BTNFACE))
  812. else FrameRect(DC, DrawRect, GetSysColorBrush(COLOR_BTNSHADOW));
  813. { Caller drow in flat mode
  814. InflateRect(DrawRect, 1, 1);
  815. if AActive
  816. then DrawEdge(DC, DrawRect, BDR_SUNKENOUTER, BF_RECT)
  817. else FrameRect(DC, DrawRect, GetCurrentObject(DC, OBJ_BRUSH));}
  818. end;
  819. // end;
  820. end;
  821. const
  822. DownFlags: array[Boolean] of Integer = (0, DFCS_PUSHED {? or DFCS_FLAT});
  823. FlatFlags: array[Boolean] of Integer = (0, DFCS_FLAT);
  824. EnabledFlags: array[Boolean] of Integer = (DFCS_INACTIVE, 0);
  825. IsDownFlags: array[Boolean] of Integer = (DFCS_SCROLLUP, DFCS_SCROLLDOWN);
  826. PressedFlags: array[Boolean] of Integer = (EDGE_RAISED, EDGE_SUNKEN);
  827. procedure DrawEllipsisButton(DC: HDC; ARect: TRect; Enabled, Active, Flat, Pressed: Boolean);
  828. var
  829. InterP, PWid, W, H: Integer;
  830. ElRect: TRect;
  831. Brush, SaveBrush: HBRUSH;
  832. {$IFDEF EH_LIB_7}
  833. Button: TThemedButton;
  834. ToolButton: TThemedToolBar;
  835. Details: TThemedElementDetails;
  836. {$ENDIF}
  837. begin
  838. ElRect := ARect;
  839. {$IFDEF EH_LIB_7}
  840. if ThemeServices.ThemesEnabled then
  841. begin
  842. if not Enabled then
  843. Button := tbPushButtonDisabled
  844. else
  845. if Pressed then
  846. Button := tbPushButtonPressed
  847. else
  848. if Active
  849. then Button := tbPushButtonHot
  850. else Button := tbPushButtonNormal;
  851. ToolButton := ttbToolbarDontCare;
  852. if Flat then
  853. begin
  854. case Button of
  855. tbPushButtonDisabled:
  856. Toolbutton := ttbButtonDisabled;
  857. tbPushButtonPressed:
  858. Toolbutton := ttbButtonPressed;
  859. tbPushButtonHot:
  860. Toolbutton := ttbButtonHot;
  861. tbPushButtonNormal:
  862. Toolbutton := ttbButtonNormal;
  863. end;
  864. end;
  865. if ToolButton = ttbToolbarDontCare then
  866. begin
  867. Details := ThemeServices.GetElementDetails(Button);
  868. ThemeServices.DrawElement(DC, Details, ARect);
  869. // ARect := ThemeServices.ContentRect(DC, Details, ARect);
  870. InflateRect(ElRect, -2, -2);
  871. end else
  872. begin
  873. Details := ThemeServices.GetElementDetails(ToolButton);
  874. ThemeServices.DrawElement(DC, Details, ARect);
  875. InflateRect(ElRect, -1, -1)
  876. // ARect := ThemeServices.ContentRect(DC, Details, ARect);
  877. end;
  878. end else
  879. {$ENDIF}
  880. begin
  881. Brush := GetSysColorBrush(COLOR_BTNFACE);
  882. if Flat then
  883. begin
  884. Windows.FillRect(DC, ElRect, Brush);
  885. InflateRect(ElRect, -1, -1)
  886. end else
  887. begin
  888. DrawEdge(DC, ElRect, PressedFlags[Pressed], BF_RECT or BF_MIDDLE);
  889. InflateRect(ElRect, -2, -2);
  890. //Windows.FillRect(DC, ElRect, Brush);
  891. end;
  892. end;
  893. InterP := 2;
  894. PWid := 2;
  895. W := ElRect.Right - ElRect.Left; //+ Ord(not Active and Flat);
  896. if W < 12 then InterP := 1;
  897. if W < 8 then PWid := 1;
  898. W := ElRect.Left + W div 2 - PWid div 2 + Ord(Pressed); //- Ord(not Active and Flat);
  899. H := ElRect.Top + (ElRect.Bottom - ElRect.Top) div 2 - PWid div 2 + Ord(Pressed);
  900. if not Enabled then
  901. begin
  902. Inc(W); Inc(H);
  903. Brush := GetSysColorBrush(COLOR_BTNHILIGHT);
  904. SaveBrush := SelectObject(DC, Brush);
  905. PatBlt(DC, W, H, PWid, PWid, PATCOPY);
  906. PatBlt(DC, W - InterP - PWid, H, PWid, PWid, PATCOPY);
  907. PatBlt(DC, W + InterP + PWid, H, PWid, PWid, PATCOPY);
  908. Dec(W); Dec(H);
  909. SelectObject(DC, SaveBrush);
  910. Brush := GetSysColorBrush(COLOR_BTNSHADOW);
  911. end else
  912. Brush := GetSysColorBrush(COLOR_BTNTEXT);
  913. SaveBrush := SelectObject(DC, Brush);
  914. PatBlt(DC, W, H, PWid, PWid, PATCOPY);
  915. PatBlt(DC, W - InterP - PWid, H, PWid, PWid, PATCOPY);
  916. PatBlt(DC, W + InterP + PWid, H, PWid, PWid, PATCOPY);
  917. SelectObject(DC, SaveBrush);
  918. end;
  919. procedure DrawPlusMinusButton(DC: HDC; ARect: TRect; Enabled, Active, Flat, Pressed, Plus: Boolean);
  920. var PWid, PHet, W, H, PlusInd, MinWH: Integer;
  921. ElRect: TRect;
  922. Brush, SaveBrush: HBRUSH;
  923. {$IFDEF EH_LIB_7}
  924. Button: TThemedButton;
  925. ToolButton: TThemedToolBar;
  926. Details: TThemedElementDetails;
  927. {$ENDIF}
  928. begin
  929. ElRect := ARect;
  930. {$IFDEF EH_LIB_7}
  931. if ThemeServices.ThemesEnabled then
  932. begin
  933. if not Enabled then
  934. Button := tbPushButtonDisabled
  935. else
  936. if Pressed then
  937. Button := tbPushButtonPressed
  938. else
  939. if Active
  940. then Button := tbPushButtonHot
  941. else Button := tbPushButtonNormal;
  942. ToolButton := ttbToolbarDontCare;
  943. if Flat then
  944. begin
  945. case Button of
  946. tbPushButtonDisabled:
  947. Toolbutton := ttbButtonDisabled;
  948. tbPushButtonPressed:
  949. Toolbutton := ttbButtonPressed;
  950. tbPushButtonHot:
  951. Toolbutton := ttbButtonHot;
  952. tbPushButtonNormal:
  953. Toolbutton := ttbButtonNormal;
  954. end;
  955. end;
  956. if ToolButton = ttbToolbarDontCare then
  957. begin
  958. Details := ThemeServices.GetElementDetails(Button);
  959. ThemeServices.DrawElement(DC, Details, ARect);
  960. // ARect := ThemeServices.ContentRect(DC, Details, ARect);
  961. InflateRect(ElRect, -2, -2);
  962. end else
  963. begin
  964. Details := ThemeServices.GetElementDetails(ToolButton);
  965. ThemeServices.DrawElement(DC, Details, ARect);
  966. InflateRect(ElRect, -1, -1)
  967. // ARect := ThemeServices.ContentRect(DC, Details, ARect);
  968. end;
  969. end else
  970. {$ENDIF}
  971. begin
  972. Brush := GetSysColorBrush(COLOR_BTNFACE);
  973. if Flat then
  974. begin
  975. Windows.FillRect(DC, ElRect, Brush);
  976. InflateRect(ElRect, -1, -1)
  977. end else
  978. begin
  979. DrawEdge(DC, ElRect, PressedFlags[Pressed], BF_RECT or BF_MIDDLE);
  980. InflateRect(ElRect, -2, -2);
  981. Windows.FillRect(DC, ElRect, Brush);
  982. end;
  983. end;
  984. MinWH := ElRect.Right - ElRect.Left; //+ Ord(not Active and Flat);
  985. if ElRect.Bottom - ElRect.Top < MinWH then
  986. MinWH := ElRect.Bottom - ElRect.Top;
  987. PWid := MinWH * 4 div 7;
  988. if PWid = 0 then PWid := 1;
  989. PHet := PWid div 3;
  990. if PHet = 0 then PHet := 1;
  991. if Flat then Dec(PWid);
  992. if PWid mod 2 <> MinWH mod 2 then Inc(PWid);
  993. if Plus and (PWid mod 2 <> PHet mod 2) then
  994. if (MinWH < 12) then Inc(PWid) else Dec(PWid);
  995. PlusInd := PWid div 2 - PHet div 2;
  996. W := ElRect.Left + (ElRect.Right - ElRect.Left - PWid) div 2; //- Ord(not Active and Flat);
  997. //if W * 2 + PWid > (ElRect.Right - ElRect.Left) then Dec(W);
  998. Inc(W, Ord(Pressed));
  999. H := ElRect.Top + (ElRect.Bottom - ElRect.Top - PHet) div 2 + Ord(Pressed);
  1000. if not Enabled then
  1001. begin
  1002. Inc(W); Inc(H);
  1003. Brush := GetSysColorBrush(COLOR_BTNHILIGHT);
  1004. SaveBrush := SelectObject(DC, Brush);
  1005. PatBlt(DC, W, H, PWid, PHet, PATCOPY);
  1006. if Plus then PatBlt(DC, W + PlusInd, H - PlusInd, PHet, PWid, PATCOPY);
  1007. Dec(W); Dec(H);
  1008. SelectObject(DC, SaveBrush);
  1009. Brush := GetSysColorBrush(COLOR_BTNSHADOW);
  1010. end else
  1011. Brush := GetSysColorBrush(COLOR_BTNTEXT);
  1012. SaveBrush := SelectObject(DC, Brush);
  1013. PatBlt(DC, W, H, PWid, PHet, PATCOPY);
  1014. if Plus then PatBlt(DC, W + PlusInd, H - PlusInd, PHet, PWid, PATCOPY);
  1015. SelectObject(DC, SaveBrush);
  1016. end;
  1017. procedure DrawDropDownButton(DC: HDC; ARect: TRect; Enabled, Flat, Active, Down: Boolean);
  1018. var
  1019. Flags: Integer;
  1020. {$IFDEF EH_LIB_7}
  1021. Details: TThemedElementDetails;
  1022. {$ENDIF}
  1023. // Rgn, SaveRgn: HRGN;
  1024. // r: Integer;
  1025. // IsClip: Boolean;
  1026. begin
  1027. {$IFDEF EH_LIB_7}
  1028. if ThemeServices.ThemesEnabled then
  1029. begin
  1030. if not Enabled then
  1031. Details := ThemeServices.GetElementDetails(tcDropDownButtonDisabled)
  1032. else
  1033. if Down then
  1034. Details := ThemeServices.GetElementDetails(tcDropDownButtonPressed)
  1035. else
  1036. if Active
  1037. then Details := ThemeServices.GetElementDetails(tcDropDownButtonHot)
  1038. else Details := ThemeServices.GetElementDetails(tcDropDownButtonNormal);
  1039. { with Details do
  1040. GetThemeBackgroundRegion(ThemeServices.Theme[Element], DC, Part, State, ARect, Rgn);
  1041. IsClip := False;
  1042. SaveRgn := 0;
  1043. r := 0;
  1044. if Rgn <> 0 then
  1045. begin
  1046. IsClip := True;
  1047. SaveRgn := CreateRectRgn(0, 0, 0, 0);
  1048. r := GetClipRgn(DC, SaveRgn);
  1049. SelectClipRgn(DC, Rgn);
  1050. DeleteObject(Rgn);
  1051. end;}
  1052. ThemeServices.DrawElement(DC, Details, ARect);
  1053. { if IsClip = True then
  1054. begin
  1055. if r = 0
  1056. then SelectClipRgn(DC, 0)
  1057. else SelectClipRgn(DC, SaveRgn);
  1058. DeleteObject(SaveRgn);
  1059. end;}
  1060. end else
  1061. {$ENDIF}
  1062. begin
  1063. Flags := DownFlags[Down] or FlatFlags[Flat] or EnabledFlags[Enabled];
  1064. DrawFrameControl(DC, ARect, DFC_SCROLL, Flags or DFCS_SCROLLCOMBOBOX);
  1065. end;
  1066. end;
  1067. procedure DrawUpDownButton(DC: HDC; ARect: TRect; Enabled, Flat, Active, Down, DownDirection: Boolean);
  1068. var
  1069. Flags: Integer;
  1070. {$IFDEF EH_LIB_7}
  1071. Details: TThemedElementDetails;
  1072. {$ENDIF}
  1073. begin
  1074. {$IFDEF EH_LIB_7}
  1075. if ThemeServices.ThemesEnabled then
  1076. begin
  1077. if DownDirection then
  1078. if not Enabled then
  1079. Details := ThemeServices.GetElementDetails(tsDownDisabled)
  1080. else
  1081. if Down then
  1082. Details := ThemeServices.GetElementDetails(tsDownPressed)
  1083. else
  1084. if Active
  1085. then Details := ThemeServices.GetElementDetails(tsDownHot)
  1086. else Details := ThemeServices.GetElementDetails(tsDownNormal)
  1087. else
  1088. if not Enabled then
  1089. Details := ThemeServices.GetElementDetails(tsUpDisabled)
  1090. else
  1091. if Down then
  1092. Details := ThemeServices.GetElementDetails(tsUpPressed)
  1093. else
  1094. if Active
  1095. then Details := ThemeServices.GetElementDetails(tsUpHot)
  1096. else Details := ThemeServices.GetElementDetails(tsUpNormal);
  1097. ThemeServices.DrawElement(DC, Details, ARect);
  1098. end else
  1099. {$ENDIF}
  1100. begin
  1101. Flags := DownFlags[Down] or FlatFlags[Flat] or EnabledFlags[Enabled];
  1102. DrawFrameControl(DC, ARect, DFC_SCROLL, Flags or IsDownFlags[DownDirection]);
  1103. end;
  1104. end;
  1105. procedure DrawOneButton(DC: HDC; Style: TDrawButtonControlStyleEh;
  1106. ARect: TRect; Enabled, Flat, Active, Down, DownDirection: Boolean);
  1107. var
  1108. Rgn, SaveRgn: HRgn;
  1109. r: Integer;
  1110. IsClipRgn: Boolean;
  1111. DRect: TRect;
  1112. // Brush: HBRUSH;
  1113. begin
  1114. DRect := ARect;
  1115. // LPtoDP(DC, DRect, 2);
  1116. WindowsLPtoDP(DC, DRect);
  1117. {$IFDEF EH_LIB_7}
  1118. IsClipRgn := Flat and Active and not ThemeServices.ThemesEnabled;
  1119. {$ELSE}
  1120. IsClipRgn := Flat and Active;
  1121. {$ENDIF}
  1122. r := 0; SaveRgn := 0;
  1123. if IsClipRgn then
  1124. begin
  1125. SaveRgn := CreateRectRgn(0, 0, 0, 0);
  1126. r := GetClipRgn(DC, SaveRgn);
  1127. with DRect do
  1128. Rgn := CreateRectRgn(Left + 1, Top + 1, Right - 1, Bottom - 1);
  1129. SelectClipRgn(DC, Rgn);
  1130. DeleteObject(Rgn);
  1131. end;
  1132. if Flat {$IFDEF EH_LIB_7} and not ThemeServices.ThemesEnabled {$ENDIF} then
  1133. if not Active {and not (Style=bcsUpDownEh)}
  1134. then InflateRect(ARect, 2, 2)
  1135. else InflateRect(ARect, 1, 1);
  1136. case Style of
  1137. bcsDropDownEh: DrawDropDownButton(DC, ARect, Enabled, Flat, Active, Down);
  1138. bcsEllipsisEh: DrawEllipsisButton(DC, ARect, Enabled, Active, Flat, Down);
  1139. bcsUpDownEh: DrawUpDownButton(DC, ARect, Enabled, Flat, Active, Down, DownDirection);
  1140. bcsMinusEh, bcsPlusEh: DrawPlusMinusButton(DC, ARect, Enabled, Active, Flat, Down, bcsPlusEh = Style);
  1141. end;
  1142. if Flat then
  1143. if not Active {and not (Style=bcsUpDownEh)}
  1144. then InflateRect(ARect, -2, -2)
  1145. else InflateRect(ARect, -1, -1);
  1146. if IsClipRgn then
  1147. begin
  1148. if r = 0
  1149. then SelectClipRgn(DC, 0)
  1150. else SelectClipRgn(DC, SaveRgn);
  1151. DeleteObject(SaveRgn);
  1152. if Down
  1153. then DrawEdge(DC, ARect, BDR_SUNKENOUTER, BF_RECT)
  1154. else DrawEdge(DC, ARect, BDR_RAISEDINNER, BF_RECT)
  1155. end;
  1156. end;
  1157. type
  1158. PPoints = ^TPoints;
  1159. TPoints = array[0..0] of TPoint;
  1160. TButtonBitmapInfoEh = record
  1161. Size: TPoint;
  1162. BitmapType: TDrawButtonControlStyleEh;
  1163. Flat: Boolean;
  1164. Pressed: Boolean;
  1165. Active: Boolean;
  1166. Enabled: Boolean;
  1167. DownDirect: Boolean;
  1168. CheckState: TCheckBoxState;
  1169. end;
  1170. function CompareButtonBitmapInfo(Info1, Info2: TButtonBitmapInfoEh): Boolean;
  1171. begin
  1172. Result := (Info1.Size.X = Info2.Size.X) and (Info1.Size.Y = Info2.Size.Y)
  1173. and (Info1.BitmapType = Info2.BitmapType)
  1174. and (Info1.Flat = Info2.Flat)
  1175. and (Info1.Pressed = Info2.Pressed)
  1176. and (Info1.Active = Info2.Active)
  1177. and (Info1.Enabled = Info2.Enabled)
  1178. and (Info1.DownDirect = Info2.DownDirect)
  1179. and (Info1.CheckState = Info2.CheckState);
  1180. end;
  1181. type
  1182. { TButtonsBitmapCache }
  1183. TButtonBitmapInfoBitmapEh = class(TObject)
  1184. public
  1185. BitmapInfo: TButtonBitmapInfoEh;
  1186. Bitmap: TBitmap;
  1187. end;
  1188. // PButtonBitmapInfoBitmapEh = ^TButtonBitmapInfoBitmapEh;
  1189. TButtonsBitmapCache = class(TObjectList)
  1190. private
  1191. function Get(Index: Integer): TButtonBitmapInfoBitmapEh;
  1192. // procedure Put(Index: Integer; const Value: PButtonBitmapInfoBitmapEh);
  1193. public
  1194. constructor Create; overload;
  1195. procedure Clear; override;
  1196. function GetButtonBitmap(ButtonBitmapInfo: TButtonBitmapInfoEh): TBitmap;
  1197. property Items[Index: Integer]: TButtonBitmapInfoBitmapEh read Get {write Put}; default;
  1198. end;
  1199. var ButtonsBitmapCache: TButtonsBitmapCache;
  1200. procedure ClearButtonsBitmapCache;
  1201. begin
  1202. ButtonsBitmapCache.Clear;
  1203. end;
  1204. function RectSize(ARect: TRect): TSize;
  1205. begin
  1206. Result.cx := ARect.Right - ARect.Left;
  1207. Result.cy := ARect.Bottom - ARect.Top;
  1208. end;
  1209. procedure PaintButtonControlEh(DC: HDC; ARect: TRect; ParentColor: TColor;
  1210. Style: TDrawButtonControlStyleEh; DownButton: Integer;
  1211. Flat, Active, Enabled: Boolean; State: TCheckBoxState);
  1212. var
  1213. Rgn, SaveRgn: HRgn;
  1214. HalfRect, DRect: TRect;
  1215. ASize: TSize;
  1216. r: Integer;
  1217. Brush: HBRUSH;
  1218. IsClipRgn: Boolean;
  1219. BitmapInfo: TButtonBitmapInfoEh;
  1220. Bitmap: TBitmap;
  1221. begin
  1222. SaveRgn := 0; r := 0;
  1223. // FillChar(BitmapInfo, Sizeof(BitmapInfo), #0);
  1224. BitmapInfo.BitmapType := Style;
  1225. BitmapInfo.Flat := Flat;
  1226. if Style = bcsCheckboxEh then
  1227. begin
  1228. ASize := RectSize(ARect);
  1229. if ASize.cx < ASize.cy then
  1230. begin
  1231. ARect.Top := ARect.Top + (ASize.cy - ASize.cx) div 2;
  1232. ARect.Bottom := ARect.Bottom - (ASize.cy - ASize.cx) div 2 - (ASize.cy - ASize.cx) mod 2;
  1233. end else if ASize.cx > ASize.cy then
  1234. begin
  1235. ARect.Left := ARect.Left + (ASize.cx - ASize.cy) div 2;
  1236. ARect.Right := ARect.Right - (ASize.cx - ASize.cy) div 2 - (ASize.cx - ASize.cy) mod 2;
  1237. end;
  1238. if Flat then InflateRect(ARect, -1, -1);
  1239. if UseButtonsBitmapCache then
  1240. begin
  1241. BitmapInfo.Size := Point(ARect.Right - ARect.Left, ARect.Bottom - ARect.Top);
  1242. BitmapInfo.CheckState := State;
  1243. BitmapInfo.Pressed := DownButton <> 0;
  1244. BitmapInfo.Active := Active;
  1245. BitmapInfo.Enabled := Enabled;
  1246. Bitmap := ButtonsBitmapCache.GetButtonBitmap(BitmapInfo);
  1247. StretchBlt(DC, ARect.Left, ARect.Top, ARect.Right - ARect.Left,
  1248. ARect.Bottom - ARect.Top, Bitmap.Canvas.Handle, 0, 0,
  1249. Bitmap.Width, Bitmap.Height, cmSrcCopy);
  1250. end else
  1251. DrawCheck(DC, ARect, State, Enabled, Flat, DownButton <> 0, Active);
  1252. if Flat then
  1253. begin
  1254. InflateRect(ARect, 1, 1);
  1255. if Active then
  1256. DrawEdge(DC, ARect, BDR_SUNKENOUTER, BF_RECT)
  1257. else
  1258. begin
  1259. // FrameRect(DC, ARect, GetCurrentObject(DC, OBJ_BRUSH));
  1260. Brush := CreateSolidBrush(ColorToRGB(ParentColor));
  1261. FrameRect(DC, ARect, Brush);
  1262. DeleteObject(Brush);
  1263. end;
  1264. end;
  1265. end else
  1266. begin
  1267. BitmapInfo.Active := Active;
  1268. BitmapInfo.Enabled := Enabled;
  1269. {$IFDEF EH_LIB_7}
  1270. IsClipRgn := Flat and not Active and not ThemeServices.ThemesEnabled;
  1271. {$ELSE}
  1272. IsClipRgn := Flat and not Active;
  1273. {$ENDIF}
  1274. if IsClipRgn then
  1275. begin
  1276. DRect := ARect;
  1277. WindowsLPtoDP(DC, DRect);
  1278. InflateRect(ARect, -1, -1);
  1279. if not UseButtonsBitmapCache then
  1280. begin
  1281. SaveRgn := CreateRectRgn(0, 0, 0, 0);
  1282. r := GetClipRgn(DC, SaveRgn);
  1283. with DRect do
  1284. Rgn := CreateRectRgn(Left + 1, Top + 1, Right - 1, Bottom - 1);
  1285. SelectClipRgn(DC, Rgn);
  1286. DeleteObject(Rgn);
  1287. end;
  1288. end;
  1289. if Style = bcsUpDownEh then
  1290. begin
  1291. if IsClipRgn then InflateRect(ARect, 1, 1);
  1292. HalfRect := ARect;
  1293. with HalfRect do
  1294. Bottom := Top + (Bottom - Top) div 2;
  1295. if IsClipRgn then InflateRect(HalfRect, -1, -1);
  1296. if UseButtonsBitmapCache then
  1297. begin
  1298. BitmapInfo.Size := Point(HalfRect.Right - HalfRect.Left, HalfRect.Bottom - HalfRect.Top);
  1299. BitmapInfo.Pressed := DownButton = 1;
  1300. BitmapInfo.DownDirect := False;
  1301. Bitmap := ButtonsBitmapCache.GetButtonBitmap(BitmapInfo);
  1302. StretchBlt(DC, HalfRect.Left, HalfRect.Top, HalfRect.Right - HalfRect.Left,
  1303. HalfRect.Bottom - HalfRect.Top, Bitmap.Canvas.Handle, 0, 0,
  1304. Bitmap.Width, Bitmap.Height, cmSrcCopy);
  1305. end else
  1306. DrawOneButton(DC, Style, HalfRect, Enabled, Flat, Active, DownButton = 1, False);
  1307. if IsClipRgn then InflateRect(HalfRect, 1, 1);
  1308. HalfRect.Bottom := ARect.Bottom;
  1309. with HalfRect do
  1310. Top := Bottom - (Bottom - Top) div 2;
  1311. if IsClipRgn then InflateRect(HalfRect, -1, -1);
  1312. if UseButtonsBitmapCache then
  1313. begin
  1314. BitmapInfo.Size := Point(HalfRect.Right - HalfRect.Left, HalfRect.Bottom - HalfRect.Top);
  1315. BitmapInfo.Pressed := DownButton = 2;
  1316. BitmapInfo.DownDirect := True;
  1317. Bitmap := ButtonsBitmapCache.GetButtonBitmap(BitmapInfo);
  1318. StretchBlt(DC, HalfRect.Left, HalfRect.Top, HalfRect.Right - HalfRect.Left,
  1319. HalfRect.Bottom - HalfRect.Top, Bitmap.Canvas.Handle, 0, 0,
  1320. Bitmap.Width, Bitmap.Height, cmSrcCopy);
  1321. end else
  1322. DrawOneButton(DC, Style, HalfRect, Enabled, Flat, Active, DownButton = 2, True);
  1323. if IsClipRgn
  1324. then InflateRect(ARect, -1, -1);
  1325. if ((ARect.Bottom - ARect.Top) mod 2 = 1) or (IsClipRgn) then
  1326. begin
  1327. HalfRect := ARect;
  1328. HalfRect.Top := (HalfRect.Bottom + HalfRect.Top) div 2;
  1329. HalfRect.Bottom := HalfRect.Top;
  1330. if (ARect.Bottom - ARect.Top) mod 2 = 1 then Inc(HalfRect.Bottom);
  1331. if IsClipRgn then InflateRect(HalfRect, 0, 1);
  1332. Brush := CreateSolidBrush(ColorToRGB(ParentColor));
  1333. FillRect(DC, HalfRect, Brush);
  1334. DeleteObject(Brush);
  1335. end;
  1336. end else if UseButtonsBitmapCache then
  1337. begin
  1338. BitmapInfo.Size := Point(ARect.Right - ARect.Left, ARect.Bottom - ARect.Top);
  1339. BitmapInfo.Pressed := DownButton <> 0;
  1340. Bitmap := ButtonsBitmapCache.GetButtonBitmap(BitmapInfo);
  1341. StretchBlt(DC, ARect.Left, ARect.Top, ARect.Right - ARect.Left,
  1342. ARect.Bottom - ARect.Top, Bitmap.Canvas.Handle, 0, 0,
  1343. Bitmap.Width, Bitmap.Height, cmSrcCopy);
  1344. end else
  1345. DrawOneButton(DC, Style, ARect, Enabled, Flat, Active, DownButton <> 0, True);
  1346. if IsClipRgn then
  1347. begin
  1348. InflateRect(ARect, 1, 1);
  1349. if not UseButtonsBitmapCache then
  1350. begin
  1351. if r = 0
  1352. then SelectClipRgn(DC, 0)
  1353. else SelectClipRgn(DC, SaveRgn);
  1354. DeleteObject(SaveRgn);
  1355. end;
  1356. Brush := CreateSolidBrush(ColorToRGB(ParentColor));
  1357. FrameRect(DC, ARect, Brush);
  1358. DeleteObject(Brush);
  1359. end;
  1360. end;
  1361. end;
  1362. function GetDefaultFlatButtonWidth: Integer;
  1363. var
  1364. DC: HDC;
  1365. SysMetrics: TTextMetric;
  1366. begin
  1367. DC := GetDC(0);
  1368. GetTextMetrics(DC, SysMetrics);
  1369. ReleaseDC(0, DC);
  1370. Result := Round(SysMetrics.tmHeight / 3 * 2);
  1371. if Result mod 2 = 0 then Inc(Result);
  1372. if Result > GetSystemMetrics(SM_CXVSCROLL)
  1373. then Result := GetSystemMetrics(SM_CXVSCROLL);
  1374. end;
  1375. function DefaultEditButtonHeight(EditButtonWidth: Integer; Flat: Boolean): Integer;
  1376. begin
  1377. if Flat
  1378. then Result := Round(EditButtonWidth * 3 / 2)
  1379. else Result := EditButtonWidth;
  1380. end;
  1381. //{$DEBUGINFO OFF}
  1382. function VarEquals(const V1, V2: Variant): Boolean;
  1383. var
  1384. i: Integer;
  1385. begin
  1386. Result := not (VarIsArray(V1) xor VarIsArray(V2));
  1387. if not Result then Exit;
  1388. Result := False;
  1389. try
  1390. if VarIsArray(V1) and VarIsArray(V2) and
  1391. (VarArrayDimCount(V1) = VarArrayDimCount(V2)) and
  1392. (VarArrayLowBound(V1, 1) = VarArrayLowBound(V2, 1)) and
  1393. (VarArrayHighBound(V1, 1) = VarArrayHighBound(V2, 1))
  1394. then
  1395. for i := VarArrayLowBound(V1, 1) to VarArrayHighBound(V1, 1) do
  1396. begin
  1397. Result := V1[i] = V2[i];
  1398. if not Result then Exit;
  1399. end
  1400. else
  1401. begin
  1402. Result := not (VarIsEmpty(V1) xor VarIsEmpty(V2));
  1403. if not Result
  1404. then Exit
  1405. else Result := (V1 = V2);
  1406. end;
  1407. except
  1408. end;
  1409. end;
  1410. //{$DEBUGINFO ON}
  1411. {$IFNDEF EH_LIB_6}
  1412. function VarCompareValue(const A, B: Variant): TVariantRelationship;
  1413. const
  1414. CTruth: array [Boolean] of TVariantRelationship = (vrNotEqual, vrEqual);
  1415. var
  1416. LA, LB: TVarData;
  1417. begin
  1418. LA := TVarData(A);
  1419. LB := TVarData(B);
  1420. if LA.VType = varEmpty then
  1421. Result := CTruth[LB.VType = varEmpty]
  1422. else if LA.VType = varNull then
  1423. Result := CTruth[LB.VType = varNull]
  1424. else if LB.VType in [varEmpty, varNull] then
  1425. Result := vrNotEqual
  1426. else if A = B then
  1427. Result := vrEqual
  1428. else if A < B then
  1429. Result := vrLessThan
  1430. else
  1431. Result := vrGreaterThan;
  1432. end;
  1433. {$ENDIF}
  1434. function DBVarCompareOneValue(const A, B: Variant): TVariantRelationship;
  1435. begin
  1436. if VarIsNull(A) and VarIsNull(B) then
  1437. Result := vrEqual
  1438. else if VarIsNull(A) then
  1439. Result := vrLessThan
  1440. else if VarIsNull(B) then
  1441. Result := vrGreaterThan
  1442. else Result := VarCompareValue(A, B);
  1443. end;
  1444. function DBVarCompareValue(const A, B: Variant): TVariantRelationship;
  1445. var
  1446. i: Integer;
  1447. IsComparable: Boolean;
  1448. begin
  1449. Result := vrNotEqual;
  1450. IsComparable := not (VarIsArray(A) xor VarIsArray(B));
  1451. if not IsComparable then Exit;
  1452. if VarIsArray(A) and VarIsArray(B) and
  1453. (VarArrayDimCount(A) = VarArrayDimCount(B)) and
  1454. (VarArrayLowBound(A, 1) = VarArrayLowBound(B, 1)) and
  1455. (VarArrayHighBound(A, 1) = VarArrayHighBound(B, 1))
  1456. then
  1457. for i := VarArrayLowBound(A, 1) to VarArrayHighBound(A, 1) do
  1458. begin
  1459. Result := DBVarCompareOneValue(A[i], B[i]);
  1460. if Result <> vrEqual then Exit;
  1461. end
  1462. else
  1463. Result := DBVarCompareOneValue(A, B);
  1464. end;
  1465. function GetRGBColor(Value: TColor): DWORD;
  1466. begin
  1467. Result := ColorToRGB(Value);
  1468. case Result of
  1469. clNone: Result := CLR_NONE;
  1470. clDefault: Result := CLR_DEFAULT;
  1471. end;
  1472. end;
  1473. procedure DrawImage(DC: HDC; ARect: TRect; Images: TCustomImageList;
  1474. ImageIndex: Integer; Selected: Boolean);
  1475. const
  1476. ImageTypes: array[TImageType] of Longint = (0, ILD_MASK);
  1477. ImageSelTypes: array[Boolean] of Longint = (0, ILD_SELECTED);
  1478. var CheckedRect, AUnionRect: TRect;
  1479. OldRectRgn, RectRgn: HRGN;
  1480. r, x, y: Integer;
  1481. procedure DrawIm;
  1482. var ABlendColor: TColor;
  1483. begin
  1484. with Images do
  1485. if HandleAllocated then
  1486. begin
  1487. if Selected then ABlendColor := clHighlight
  1488. else ABlendColor := BlendColor;
  1489. ImageList_DrawEx(Handle, ImageIndex, DC, x, y, 0, 0,
  1490. GetRGBColor(BkColor), GetRGBColor(ABlendColor),
  1491. ImageTypes[ImageType] or ImageSelTypes[Selected]);
  1492. end;
  1493. end;
  1494. begin
  1495. with Images do
  1496. begin
  1497. x := (ARect.Right + ARect.Left - Images.Width) div 2;
  1498. y := (ARect.Bottom + ARect.Top - Images.Height) div 2;
  1499. CheckedRect := Rect(X, Y, X + Images.Width, Y + Images.Height);
  1500. UnionRect(AUnionRect, CheckedRect, ARect);
  1501. if EqualRect(AUnionRect, ARect) then // ARect containt image
  1502. DrawIm
  1503. else
  1504. begin // Need clip
  1505. OldRectRgn := CreateRectRgn(0, 0, 0, 0);
  1506. r := GetClipRgn(DC, OldRectRgn);
  1507. RectRgn := CreateRectRgn(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
  1508. SelectClipRgn(DC, RectRgn);
  1509. DeleteObject(RectRgn);
  1510. DrawIm;
  1511. if r = 0
  1512. then SelectClipRgn(DC, 0)
  1513. else SelectClipRgn(DC, OldRectRgn);
  1514. DeleteObject(OldRectRgn);
  1515. end;
  1516. end;
  1517. end;
  1518. function AlignDropDownWindowRect(MasterAbsRect: TRect; DropDownWin: TWinControl; Align: TDropDownAlign): TPoint;
  1519. var
  1520. P: TPoint;
  1521. Y: Integer;
  1522. WorkArea: TRect;
  1523. MonInfo: TMonitorInfo;
  1524. begin
  1525. P := MasterAbsRect.TopLeft;
  1526. Y := P.Y + (MasterAbsRect.Bottom - MasterAbsRect.Top);
  1527. MonInfo.cbSize := SizeOf(MonInfo);
  1528. {$IFDEF CIL}
  1529. GetMonitorInfo(MonitorFromRect(MasterAbsRect, MONITOR_DEFAULTTONEAREST), MonInfo);
  1530. {$ELSE}
  1531. GetMonitorInfo(MonitorFromRect(@MasterAbsRect, MONITOR_DEFAULTTONEAREST), @MonInfo);
  1532. {$ENDIF}
  1533. WorkArea := MonInfo.rcWork;
  1534. // SystemParametersInfo(SPI_GETWORKAREA, 0, Pointer(@WorkArea), 0);
  1535. if ((Y + DropDownWin.Height > WorkArea.Bottom) and (P.Y - DropDownWin.Height >= WorkArea.Top)) or
  1536. ((P.Y - DropDownWin.Height < WorkArea.Top) and (WorkArea.Bottom - Y < P.Y - WorkArea.Top))
  1537. then
  1538. begin
  1539. if P.Y - DropDownWin.Height < WorkArea.Top then
  1540. DropDownWin.Height := P.Y - WorkArea.Top;
  1541. Y := P.Y - DropDownWin.Height;
  1542. DropDownWin.Perform(cm_SetSizeGripChangePosition, Ord(sgcpToTop), 0);
  1543. end else
  1544. begin
  1545. if Y + DropDownWin.Height > WorkArea.Bottom then
  1546. DropDownWin.Height := WorkArea.Bottom - Y;
  1547. DropDownWin.Perform(cm_SetSizeGripChangePosition, Ord(sgcpToBottom), 0);
  1548. end;
  1549. case Align of
  1550. daRight: Dec(P.X, DropDownWin.Width - (MasterAbsRect.Right - MasterAbsRect.Left));
  1551. daCenter: Dec(P.X, (DropDownWin.Width - (MasterAbsRect.Right - MasterAbsRect.Left)) div 2);
  1552. end;
  1553. if (DropDownWin.Width > WorkArea.Right - WorkArea.Left) then
  1554. DropDownWin.Width := WorkArea.Right - WorkArea.Left;
  1555. if (P.X + DropDownWin.Width > WorkArea.Right) then
  1556. begin
  1557. P.X := WorkArea.Right - DropDownWin.Width;
  1558. DropDownWin.Perform(cm_SetSizeGripChangePosition, Ord(sgcpToLeft), 0);
  1559. end
  1560. else if P.X < WorkArea.Left then
  1561. begin
  1562. P.X := WorkArea.Left;
  1563. DropDownWin.Perform(cm_SetSizeGripChangePosition, Ord(sgcpToRight), 0);
  1564. end else if Align = daRight then
  1565. DropDownWin.Perform(cm_SetSizeGripChangePosition, Ord(sgcpToLeft), 0)
  1566. else
  1567. DropDownWin.Perform(cm_SetSizeGripChangePosition, Ord(sgcpToRight), 0);
  1568. Result := Point(P.X, Y);
  1569. end;
  1570. function AlignDropDownWindow(MasterWin, DropDownWin: TWinControl; Align: TDropDownAlign): TPoint;
  1571. var
  1572. MasterAbsRect: TRect;
  1573. begin
  1574. MasterAbsRect.TopLeft := MasterWin.Parent.ClientToScreen(Point(MasterWin.Left, MasterWin.Top));
  1575. MasterAbsRect.Bottom := MasterAbsRect.Top + MasterWin.Height;
  1576. MasterAbsRect.Right := MasterAbsRect.Left + MasterWin.Width;
  1577. Result := AlignDropDownWindowRect(MasterAbsRect, DropDownWin, Align);
  1578. end;
  1579. type
  1580. TIntArray = array[0..16384] of Integer;
  1581. PIntArray = ^TIntArray;
  1582. procedure DrawDotLine(Canvas: TCanvas; FromPoint: TPoint; ALength: Integer;
  1583. Along: Boolean; BackDot: Boolean);
  1584. var
  1585. Points: array of TPoint;
  1586. StrokeList: array of DWORD;
  1587. DotWidth, DotCount, I: Integer;
  1588. begin
  1589. // Canvas.Pen.Style
  1590. if Along then
  1591. begin
  1592. if ((FromPoint.X mod 2) <> (FromPoint.Y mod 2)) xor BackDot then
  1593. begin
  1594. Inc(FromPoint.X);
  1595. Dec(ALength);
  1596. end;
  1597. end else
  1598. begin
  1599. if ((FromPoint.X mod 2) <> (FromPoint.Y mod 2)) xor BackDot then
  1600. begin
  1601. Inc(FromPoint.Y);
  1602. Dec(ALength);
  1603. end;
  1604. end;
  1605. DotWidth := Canvas.Pen.Width;
  1606. DotCount := ALength div (2 * DotWidth);
  1607. if DotCount < 0 then Exit;
  1608. if ALength mod 2 <> 0 then
  1609. Inc(DotCount);
  1610. SetLength(Points, DotCount * 2); // two points per stroke
  1611. SetLength(StrokeList, DotCount);
  1612. for I := 0 to DotCount - 1 do
  1613. StrokeList[I] := 2;
  1614. if Along then
  1615. for I := 0 to DotCount - 1 do
  1616. begin
  1617. Points[I * 2] := Point(FromPoint.X, FromPoint.Y);
  1618. Points[I * 2 + 1] := Point(FromPoint.X + 1, FromPoint.Y);
  1619. Inc(FromPoint.X, (2 * DotWidth));
  1620. end
  1621. else
  1622. for I := 0 to DotCount - 1 do
  1623. begin
  1624. Points[I * 2] := Point(FromPoint.X, FromPoint.Y);
  1625. Points[I * 2 + 1] := Point(FromPoint.X, FromPoint.Y + 1);
  1626. Inc(FromPoint.Y, (2 * DotWidth));
  1627. end;
  1628. {$IFDEF CIL}
  1629. PolyPolyLine(Canvas.Handle, Points, StrokeList, DotCount);
  1630. {$ELSE}
  1631. PolyPolyLine(Canvas.Handle, PIntArray(Points)^, PIntArray(StrokeList)^, DotCount);
  1632. {$ENDIF}
  1633. end;
  1634. procedure DrawTreeElement(Canvas: TCanvas; ARect: TRect;
  1635. TreeElement: TTreeElementEh; BackDot: Boolean; ScaleX, ScaleY: Double;
  1636. RightToLeft: Boolean);
  1637. var
  1638. ABoxRect: TRect;
  1639. // ABoxRectWidth: Integer;
  1640. ACenter: TPoint;
  1641. X1, X2, X4, Y1, Y2, Y4: Integer;
  1642. begin
  1643. ACenter.X := (ARect.Right + ARect.Left) div 2;
  1644. ACenter.Y := (ARect.Bottom + ARect.Top) div 2;
  1645. X1 := Trunc(ScaleX);
  1646. X2 := Trunc(ScaleX*2);
  1647. X4 := Trunc(ScaleX*4);
  1648. Y1 := Trunc(ScaleY);
  1649. Y2 := Trunc(ScaleY*2);
  1650. Y4 := Trunc(ScaleY*4);
  1651. with Canvas do
  1652. begin
  1653. ABoxRect := Rect(ACenter.X-X4, ACenter.Y-Y4, ACenter.X+X4+1, ACenter.Y+Y4+1);
  1654. // ABoxRectWidth := ABoxRect.Right - ABoxRect.Left;
  1655. if TreeElement in [tehMinusUpDown .. tehPlusDown] then
  1656. begin
  1657. Brush.Color := clWindow;
  1658. Pen.Color := clBtnShadow;
  1659. Pen.Style := psSolid;
  1660. if RightToLeft
  1661. then Rectangle(ABoxRect.Left-1, ABoxRect.Top, ABoxRect.Right-1, ABoxRect.Bottom)
  1662. else Rectangle(ABoxRect.Left, ABoxRect.Top, ABoxRect.Right, ABoxRect.Bottom);
  1663. Pen.Color := clWindowText;
  1664. MoveTo(ABoxRect.Left + X2, ACenter.Y);
  1665. LineTo(ABoxRect.Right - X2, ACenter.Y);
  1666. if TreeElement in [tehPlusUpDown, tehPlusUp, tehPlusDown] then
  1667. begin
  1668. MoveTo(ACenter.X, ABoxRect.Top + Y2);
  1669. LineTo(ACenter.X, ABoxRect.Bottom - Y2);
  1670. end;
  1671. Pen.Color := clBtnShadow;
  1672. DrawDotLine(Canvas, Point(ABoxRect.Right + X1, ACenter.Y),
  1673. (ARect.Right - ABoxRect.Right), True, False);
  1674. if TreeElement in [tehMinusUpDown, tehMinusUp, tehPlusUpDown, tehPlusUp] then
  1675. DrawDotLine(Canvas, Point(ACenter.X, ARect.Top), (ABoxRect.Top - ARect.Top), False, BackDot);
  1676. if TreeElement in [tehMinusUpDown, tehMinusDown, tehPlusUpDown, tehPlusDown] then
  1677. DrawDotLine(Canvas, Point(ACenter.X, ABoxRect.Bottom + Y1),
  1678. (ARect.Bottom - ABoxRect.Bottom), False, BackDot);
  1679. end else
  1680. begin
  1681. Pen.Style := psSolid;
  1682. Pen.Color := clBtnShadow;
  1683. if TreeElement in [tehCrossUpDown, tehVLine] then
  1684. DrawDotLine(Canvas, Point(ACenter.X, ARect.Top),
  1685. (ARect.Bottom - ARect.Top), False, BackDot);
  1686. if TreeElement in [tehCrossUpDown, tehCrossUp, tehCrossDown] then
  1687. DrawDotLine(Canvas, Point(ACenter.X, ACenter.Y), (ARect.Right - ACenter.X), True, False);
  1688. if TreeElement in [tehCrossDown] then
  1689. DrawDotLine(Canvas, Point(ACenter.X, ACenter.Y), (ARect.Bottom - ACenter.Y), False, BackDot);
  1690. if TreeElement in [tehCrossUp] then
  1691. DrawDotLine(Canvas, Point(ACenter.X, ARect.Top), (ACenter.Y - ARect.Top), False, BackDot);
  1692. end;
  1693. end;
  1694. end;
  1695. { TButtonsBitmapCache }
  1696. function TButtonsBitmapCache.GetButtonBitmap(ButtonBitmapInfo: TButtonBitmapInfoEh): TBitmap;
  1697. var
  1698. i: Integer;
  1699. BitmapInfoBitmap: TButtonBitmapInfoBitmapEh;
  1700. begin
  1701. if ButtonBitmapInfo.Size.X < 0 then ButtonBitmapInfo.Size.X := 0;
  1702. if ButtonBitmapInfo.Size.Y < 0 then ButtonBitmapInfo.Size.Y := 0;
  1703. for i := 0 to Count - 1 do
  1704. if CompareButtonBitmapInfo(ButtonBitmapInfo, Items[i].BitmapInfo) then
  1705. begin
  1706. Result := Items[i].Bitmap;
  1707. Exit;
  1708. end;
  1709. BitmapInfoBitmap := TButtonBitmapInfoBitmapEh.Create;
  1710. Add(BitmapInfoBitmap);
  1711. BitmapInfoBitmap.BitmapInfo := ButtonBitmapInfo;
  1712. BitmapInfoBitmap.Bitmap := TBitmap.Create;
  1713. BitmapInfoBitmap.Bitmap.Width := ButtonBitmapInfo.Size.X;
  1714. BitmapInfoBitmap.B