bclistboxex.pas 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. unit BCListBoxEx;
  2. {$mode delphi}
  3. interface
  4. uses
  5. Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
  6. LCLType;
  7. type
  8. TBCListBoxEx = class(TCustomControl)
  9. private
  10. mousepos: TPoint;
  11. scrolly: integer;
  12. fitems: TStringList;
  13. itemselected: integer;
  14. itemheight: integer;
  15. lastitem: integer;
  16. invalidatecount: integer;
  17. scrollwidth: integer;
  18. function GetItemRect(index: integer): TRect;
  19. function GetItemVertically(y: integer): integer;
  20. procedure ScrollToItemTop();
  21. procedure ScrollToItemBottom();
  22. procedure ScrollToItem(index: integer);
  23. function ItemIsVisible(index: integer): boolean;
  24. protected
  25. procedure Click; override;
  26. procedure KeyDown(var Key: word; Shift: TShiftState); override;
  27. procedure MouseMove(Shift: TShiftState; X, Y: integer); override;
  28. function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): boolean; override;
  29. function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): boolean; override;
  30. procedure Paint; override;
  31. public
  32. constructor Create(AOwner: TComponent); override;
  33. destructor Destroy; override;
  34. published
  35. property Align;
  36. property Items: TStringList read Fitems;
  37. end;
  38. procedure Register;
  39. implementation
  40. procedure Register;
  41. begin
  42. RegisterComponents('BGRA Controls', [TBCListBoxEx]);
  43. end;
  44. procedure TBCListBoxEx.Click;
  45. var
  46. tempitem: integer;
  47. begin
  48. tempitem := GetItemVertically(mousepos.Y);
  49. if tempitem <> itemselected then
  50. begin
  51. itemselected := tempitem;
  52. Invalidate;
  53. end;
  54. end;
  55. constructor TBCListBoxEx.Create(AOwner: TComponent);
  56. begin
  57. inherited Create(AOwner);
  58. scrolly := 0;
  59. itemheight := 150;
  60. scrollwidth := 20;
  61. lastitem := -1;
  62. invalidatecount := 0;
  63. itemselected := -1;
  64. fitems := TStringList.Create;
  65. end;
  66. destructor TBCListBoxEx.Destroy;
  67. begin
  68. items.Free;
  69. end;
  70. procedure TBCListBoxEx.KeyDown(var Key: word; Shift: TShiftState);
  71. var
  72. tempitem: integer;
  73. begin
  74. case key of
  75. vk_down:
  76. begin
  77. tempitem := itemselected + 1;
  78. if (tempitem < items.Count) then
  79. begin
  80. itemselected := tempitem;
  81. if not ItemIsVisible(itemselected) then
  82. ScrollToItemBottom();
  83. if not ItemIsVisible(itemselected) then
  84. ScrollToItem(itemselected);
  85. Invalidate;
  86. end;
  87. end;
  88. vk_up:
  89. begin
  90. tempitem := itemselected - 1;
  91. if (tempitem >= 0) then
  92. begin
  93. itemselected := tempitem;
  94. if not ItemIsVisible(itemselected) then
  95. ScrollToItemTop();
  96. if not ItemIsVisible(itemselected) then
  97. ScrollToItem(itemselected);
  98. Invalidate;
  99. end;
  100. end;
  101. end;
  102. end;
  103. procedure TBCListBoxEx.MouseMove(Shift: TShiftState; X, Y: integer);
  104. var
  105. tempitem: integer;
  106. begin
  107. mousepos := Point(x, y);
  108. tempitem := GetItemVertically(mousepos.Y);
  109. if tempitem <> lastitem then
  110. begin
  111. lastitem := tempitem;
  112. Invalidate;
  113. end;
  114. end;
  115. function TBCListBoxEx.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): boolean;
  116. var
  117. r: TRect;
  118. begin
  119. result := False;
  120. r := GetItemRect(items.Count - 1);
  121. if (r.Bottom >= Height) then
  122. begin
  123. result := True;
  124. scrolly := scrolly - itemheight;
  125. Invalidate;
  126. end;
  127. end;
  128. function TBCListBoxEx.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): boolean;
  129. var
  130. lastscroll: integer;
  131. begin
  132. result := False;
  133. lastscroll := scrolly;
  134. scrolly := scrolly + itemheight;
  135. if (scrolly > 0) then
  136. scrolly := 0;
  137. if scrolly <> lastscroll then
  138. begin
  139. result := True;
  140. Invalidate;
  141. end;
  142. end;
  143. procedure TBCListBoxEx.Paint;
  144. var
  145. i: integer;
  146. r: TRect;
  147. style: TTextStyle;
  148. start: integer;
  149. begin
  150. style.Alignment := taCenter;
  151. style.Layout := tlCenter;
  152. start := -1;
  153. for i := trunc(abs(scrolly) / itemheight) to items.Count - 1 do
  154. begin
  155. r := GetItemRect(i);
  156. if (r.Top < Height) then
  157. begin
  158. if start = -1 then
  159. start := i;
  160. Canvas.Brush.Color := clGreen;
  161. if (GetItemVertically(mousepos.Y) = i) then
  162. canvas.Brush.Color := clMoneyGreen;
  163. if (itemselected = i) then
  164. canvas.Brush.Color := clBlue;
  165. Canvas.Rectangle(r);
  166. Canvas.Font.Color := clWhite;
  167. Canvas.TextRect(r, 0, 0, items[i], style);
  168. Caption := IntToStr(start) + '..' + IntToStr(i);
  169. end
  170. else
  171. break;
  172. end;
  173. Canvas.Brush.Color := clGray;
  174. Canvas.Rectangle(Width - scrollwidth, 0, Width, Height);
  175. Canvas.Font.Color := clRed;
  176. Canvas.TextOut(10, 10, IntToStr(invalidatecount));
  177. Inc(invalidatecount);
  178. end;
  179. function TBCListBoxEx.GetItemRect(index: integer): TRect;
  180. begin
  181. Result := Rect(0, (index * itemheight) + scrolly, Width - scrollwidth,
  182. (index * itemheight) + scrolly + itemheight);
  183. end;
  184. function TBCListBoxEx.GetItemVertically(y: integer): integer;
  185. var
  186. i: integer;
  187. begin
  188. i := trunc(abs(scrolly) / itemheight);
  189. Result := i + trunc(y / itemheight);
  190. if (Result > items.Count) or (Result < 0) then
  191. Result := -1;
  192. end;
  193. procedure TBCListBoxEx.ScrollToItemTop();
  194. begin
  195. scrolly := scrolly + itemheight;
  196. end;
  197. procedure TBCListBoxEx.ScrollToItemBottom();
  198. begin
  199. scrolly := scrolly - itemheight;
  200. end;
  201. procedure TBCListBoxEx.ScrollToItem(index: integer);
  202. begin
  203. scrolly := -itemheight * index;
  204. end;
  205. function TBCListBoxEx.ItemIsVisible(index: integer): boolean;
  206. var
  207. r: TRect;
  208. begin
  209. r := GetItemRect(index);
  210. Result := Rect(0, 0, Width, Height).Contains(r);
  211. end;
  212. end.