IEComboBox.pas 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. unit IEComboBox;
  2. {==================================================================
  3. Components TIECustomCombobox / Version 1.4 / January 2000
  4. TIEComboBox
  5. TIEDriveBox
  6. ==================================================================
  7. Description:
  8. ============
  9. TIECustomComboBox is a combobox with variable width of the dropdown list and
  10. provides the additional event OnCloseUp.
  11. TIEComboBox publishes the properties of the class TIECustomComboBox including
  12. the property Align wich might be was forgotten by Borland.
  13. TIEDriveComboBox realizes a selection control for the aviable drives of
  14. the system with icons. The drive icons are taken from the system image
  15. list.
  16. Author:
  17. =======
  18. (c) Ingo Eckel 1999
  19. Sodener Weg 38
  20. 65812 Bad Soden
  21. Germany
  22. For detailed documentation and history see the documentation in TIEDriveComboBox.htm.
  23. V1.3:
  24. - Property DisplayStyle changed.
  25. {==================================================================}
  26. {Required compiler options:}
  27. {$A+,B-,X+,H+,P+}
  28. interface
  29. uses
  30. StdCtrls, Controls, Messages, Types, Classes, Graphics;
  31. const
  32. IconWidth = 16;
  33. type
  34. TIECloseUpEvent = procedure (Sender: TObject; Canceled: Boolean) of object;
  35. // =======================================================================
  36. // Class TIECustomComboBox
  37. // =======================================================================
  38. TIECustomComboBox = class(TCustomComboBox)
  39. private
  40. FDropDownFixedWidth: Integer;
  41. FOnCloseUp: TIECloseUpEvent;
  42. FCanceled: Boolean;
  43. function GetTopIndex: Integer;
  44. procedure SetTopIndex(Value: Integer);
  45. procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  46. protected
  47. procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;
  48. function GetItemImage(Index: Integer): Integer; virtual;
  49. function GetItemIndent(Index: Integer): Integer; virtual;
  50. function GetItemText(Index: Integer): string;
  51. function GetItemTextEx(Index: Integer; ForList: Boolean): string; virtual;
  52. procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
  53. procedure DoCloseUp(Canceled: Boolean); virtual;
  54. procedure DropDown; override;
  55. function GetMaxItemWidth: Integer;
  56. procedure ResetItemHeight;
  57. public
  58. constructor Create(AOwner: TComponent); override;
  59. function GetTextWidth(Str: string): Integer;
  60. procedure DoPreloadImages;
  61. property ItemImage[Index: Integer]: Integer read GetItemImage;
  62. property ItemIndent[Index: Integer]: Integer read GetItemIndent;
  63. property ItemText[Index: Integer]: string read GetItemText;
  64. property TopIndex: Integer read GetTopIndex write SetTopIndex;
  65. property DropDownFixedWidth: Integer read FDropDownFixedWidth write FDropDownFixedWidth default 0;
  66. property OnCloseUp: TIECloseUpEvent read FOnCloseUp write FOnCloseUp;
  67. published
  68. end;
  69. // =======================================================================
  70. // Class TIEComboBox
  71. // =======================================================================
  72. TIEComboBox = class(TIECustomComboBox)
  73. published
  74. property DropDownFixedWidth;
  75. property OnCloseUp;
  76. property Style; {Must be published before Items}
  77. property Align;
  78. property Anchors;
  79. property BiDiMode;
  80. property Color;
  81. property Constraints;
  82. property Ctl3D;
  83. property DragCursor;
  84. property DragKind;
  85. property DragMode;
  86. property DropDownCount;
  87. property Enabled;
  88. property Font;
  89. property ImeMode;
  90. property ImeName;
  91. property ItemHeight;
  92. property Items;
  93. property MaxLength;
  94. property ParentBiDiMode;
  95. property ParentColor;
  96. property ParentCtl3D;
  97. property ParentFont;
  98. property ParentShowHint;
  99. property PopupMenu;
  100. property ShowHint;
  101. property Sorted;
  102. property TabOrder;
  103. property TabStop;
  104. property Text;
  105. property Visible;
  106. property OnChange;
  107. property OnClick;
  108. property OnDblClick;
  109. property OnDragDrop;
  110. property OnDragOver;
  111. property OnDrawItem;
  112. property OnDropDown;
  113. property OnEndDock;
  114. property OnEndDrag;
  115. property OnEnter;
  116. property OnExit;
  117. property OnKeyDown;
  118. property OnKeyPress;
  119. property OnKeyUp;
  120. property OnMeasureItem;
  121. property OnStartDock;
  122. property OnStartDrag;
  123. end;
  124. function GetItemHeight(Font: TFont): Integer;
  125. procedure Register;
  126. implementation
  127. uses
  128. SysUtils, Forms, Dialogs, Imglist, ShellAPI, CommCtrl, Math, Windows, PasTools;
  129. procedure Register;
  130. begin
  131. RegisterComponents('DriveDir', [TIEComboBox]);
  132. end;
  133. // =======================================================================
  134. // Class TIECustomComboBox
  135. // =======================================================================
  136. constructor TIECustomComboBox.Create(AOwner: TComponent);
  137. begin
  138. inherited Create(AOwner);
  139. FCanceled := True;
  140. end; {TIECustomComboBox.Create}
  141. procedure TIECustomComboBox.CMFontChanged(var Message: TMessage);
  142. begin
  143. inherited;
  144. ResetItemHeight;
  145. RecreateWnd;
  146. end; {CMFontChanged}
  147. procedure TIECustomComboBox.DoCloseUp(Canceled: Boolean);
  148. begin
  149. if Assigned(FOnCloseUp) then
  150. FOnCloseUp(Self, Canceled);
  151. end; { DoCloseUp }
  152. procedure TIECustomComboBox.DropDown;
  153. var
  154. ItemWidth: Integer;
  155. begin
  156. {Check to see if DropDownFixed Width > 0. Then just set the
  157. width of the list box. Otherwise, loop through the items
  158. and set the width of the list box to 8 pixels > than the
  159. widest string to buffer the right side. Anything less than
  160. 8 for some reason touches the end of the item on high-res
  161. monitor settings.}
  162. if (FDropDownFixedWidth > 0) then
  163. Self.Perform(CB_SETDROPPEDWIDTH, FDropDownFixedWidth, 0)
  164. else
  165. begin
  166. // The same code is in THistoryComboBox.DropDown
  167. ItemWidth := GetMaxItemWidth + ScaleByPixelsPerInch(8, Self);
  168. if Items.Count > DropDownCount then
  169. Inc(ItemWidth, GetSystemMetricsForControl(Self, SM_CXVSCROLL));
  170. Self.Perform(CB_SETDROPPEDWIDTH, ItemWidth, 0);
  171. end;
  172. inherited DropDown;
  173. end; {TIECustomComboBox.DropDown}
  174. function TIECustomComboBox.GetTextWidth(Str: string): Integer;
  175. var
  176. DC: HDC;
  177. SaveFont: HFont;
  178. Size: TSize;
  179. begin
  180. DC := GetDC(0);
  181. try
  182. SaveFont := SelectObject(DC, Font.Handle);
  183. GetTextExtentPoint32(DC, PChar(Str), Length(Str), Size);
  184. Result := Size.Cx;
  185. SelectObject(DC, SaveFont);
  186. finally
  187. ReleaseDC(0, DC);
  188. end;
  189. end; {TIECustomComboBox.GetTextWidth}
  190. function TIECustomComboBox.GetMaxItemWidth: Integer;
  191. var
  192. DC: HDC;
  193. SaveFont: HFont;
  194. Size: TSize;
  195. Index: Integer;
  196. begin
  197. Result := 0;
  198. DC := GetDC(0);
  199. try
  200. SaveFont := SelectObject(DC, Font.Handle);
  201. for Index := 0 to Items.Count - 1 do
  202. begin
  203. GetTextExtentPoint32(DC, PChar(ItemText[Index]), Length(ItemText[Index]), Size);
  204. Inc(Size.Cx, ItemIndent[Index]);
  205. if Size.Cx > Result then Result := Size.Cx;
  206. end;
  207. SelectObject(DC, SaveFont);
  208. finally
  209. ReleaseDC(0, DC);
  210. end;
  211. end; {TIECustomComboBox.GetMaxItemWidth}
  212. function TIECustomComboBox.GetTopIndex: Integer;
  213. begin
  214. Result := Perform(CB_GETTOPINDEX, 0, 0);
  215. end; {TIECustomComboBox.GetTopIndex}
  216. {$HINTS OFF}
  217. procedure TIECustomComboBox.DoPreloadImages;
  218. var
  219. Index, Dummy: Integer;
  220. begin
  221. for Index := 0 to Items.Count-1 do
  222. Dummy := ItemImage[Index];
  223. end;
  224. {$HINTS ON}
  225. procedure TIECustomComboBox.ResetItemHeight;
  226. var
  227. AHeight: Integer;
  228. Begin
  229. AHeight := Max(GetItemHeight(Font), 10) + 2;
  230. inherited ItemHeight := AHeight;
  231. if HandleAllocated then
  232. begin
  233. {Set height of list items:}
  234. SendMessage(Handle, CB_SETITEMHEIGHT, 0, Max(AHeight, 12));
  235. {Set height of selection field:}
  236. SendMessage(Handle, CB_SETITEMHEIGHT, -1, AHeight);
  237. {Set height of delphi-control:}
  238. Height := AHeight;
  239. end;
  240. end;
  241. procedure TIECustomComboBox.SetTopIndex(Value: Integer);
  242. begin
  243. if Value <> TopIndex then
  244. Perform(CB_SETTOPINDEX, Value, 0);
  245. end; {TIECustomComboBox.SetTopIndex}
  246. procedure TIECustomComboBox.CNCommand(var Message: TWMCommand);
  247. begin
  248. inherited;
  249. case Message.NotifyCode of
  250. CBN_CLOSEUP:
  251. DoCloseUp(FCanceled);
  252. CBN_SELENDCANCEL:
  253. FCanceled := True;
  254. CBN_SELENDOK:
  255. FCanceled := False;
  256. end;
  257. end; {TIECustomComboBox.CNCommand}
  258. function GetItemHeight(Font: TFont): Integer;
  259. var
  260. DC: HDC;
  261. SaveFont: HFont;
  262. Metrics: TTextMetric;
  263. begin
  264. DC := GetDC(0);
  265. try
  266. SaveFont := SelectObject(DC, Font.Handle);
  267. GetTextMetrics(DC, Metrics);
  268. SelectObject(DC, SaveFont);
  269. finally
  270. ReleaseDC(0, DC);
  271. end;
  272. Result := Metrics.tmHeight;
  273. end; {GetItemHeight}
  274. procedure TIECustomComboBox.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState);
  275. var
  276. Text: string;
  277. InList: Boolean;
  278. begin
  279. inherited;
  280. if Style = csOwnerDrawFixed then
  281. with Canvas do
  282. begin
  283. FillRect(Rect);
  284. Pen.Color := clWindowText;
  285. // Rect.Top = 3 when we draw selected item in component rect (not in dropdown)
  286. InList := (Rect.Top <> 3);
  287. Text := GetItemTextEx(Index, InList);
  288. if InList then Rect.Left := Rect.Left + ItemIndent[Index];
  289. Rect.Left := Rect.Left + 2;
  290. DrawText(Canvas.Handle, PChar(Text), Length(Text), Rect,
  291. DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX));
  292. end;
  293. end;
  294. function TIECustomComboBox.GetItemImage(Index: Integer): Integer;
  295. begin
  296. Result := -1;
  297. end;
  298. function TIECustomComboBox.GetItemIndent(Index: Integer): Integer;
  299. begin
  300. Result := 0;
  301. end;
  302. function TIECustomComboBox.GetItemText(Index: Integer): string;
  303. begin
  304. Result := GetItemTextEx(Index, True);
  305. end;
  306. function TIECustomComboBox.GetItemTextEx(Index: Integer; ForList: Boolean): string;
  307. begin
  308. Result := Items[Index];
  309. end;
  310. initialization
  311. end.