|
@@ -0,0 +1,238 @@
|
|
|
|
|
+unit BCListBoxEx;
|
|
|
|
|
+
|
|
|
|
|
+{$mode delphi}
|
|
|
|
|
+
|
|
|
|
|
+interface
|
|
|
|
|
+
|
|
|
|
|
+uses
|
|
|
|
|
+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
|
|
|
|
|
+ LCLType;
|
|
|
|
|
+
|
|
|
|
|
+type
|
|
|
|
|
+ TBCListBoxEx = class(TCustomControl)
|
|
|
|
|
+ private
|
|
|
|
|
+ mousepos: TPoint;
|
|
|
|
|
+ scrolly: integer;
|
|
|
|
|
+ fitems: TStringList;
|
|
|
|
|
+ itemselected: integer;
|
|
|
|
|
+ itemheight: integer;
|
|
|
|
|
+ lastitem: integer;
|
|
|
|
|
+ invalidatecount: integer;
|
|
|
|
|
+ scrollwidth: integer;
|
|
|
|
|
+ function GetItemRect(index: integer): TRect;
|
|
|
|
|
+ function GetItemVertically(y: integer): integer;
|
|
|
|
|
+ procedure ScrollToItemTop();
|
|
|
|
|
+ procedure ScrollToItemBottom();
|
|
|
|
|
+ procedure ScrollToItem(index: integer);
|
|
|
|
|
+ function ItemIsVisible(index: integer): boolean;
|
|
|
|
|
+ protected
|
|
|
|
|
+ procedure Click; override;
|
|
|
|
|
+ procedure KeyDown(var Key: word; Shift: TShiftState); override;
|
|
|
|
|
+ procedure MouseMove(Shift: TShiftState; X, Y: integer); override;
|
|
|
|
|
+ function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): boolean; override;
|
|
|
|
|
+ function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): boolean; override;
|
|
|
|
|
+ procedure Paint; override;
|
|
|
|
|
+ public
|
|
|
|
|
+ constructor Create(AOwner: TComponent); override;
|
|
|
|
|
+ destructor Destroy; override;
|
|
|
|
|
+ published
|
|
|
|
|
+ property Align;
|
|
|
|
|
+ property Items: TStringList read Fitems;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+procedure Register;
|
|
|
|
|
+
|
|
|
|
|
+implementation
|
|
|
|
|
+
|
|
|
|
|
+procedure Register;
|
|
|
|
|
+begin
|
|
|
|
|
+ RegisterComponents('BGRA Controls', [TBCListBoxEx]);
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TBCListBoxEx.Click;
|
|
|
|
|
+var
|
|
|
|
|
+ tempitem: integer;
|
|
|
|
|
+begin
|
|
|
|
|
+ tempitem := GetItemVertically(mousepos.Y);
|
|
|
|
|
+ if tempitem <> itemselected then
|
|
|
|
|
+ begin
|
|
|
|
|
+ itemselected := tempitem;
|
|
|
|
|
+ Invalidate;
|
|
|
|
|
+ end;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+constructor TBCListBoxEx.Create(AOwner: TComponent);
|
|
|
|
|
+begin
|
|
|
|
|
+ inherited Create(AOwner);
|
|
|
|
|
+ scrolly := 0;
|
|
|
|
|
+ itemheight := 150;
|
|
|
|
|
+ scrollwidth := 20;
|
|
|
|
|
+ lastitem := -1;
|
|
|
|
|
+ invalidatecount := 0;
|
|
|
|
|
+ itemselected := -1;
|
|
|
|
|
+ fitems := TStringList.Create;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+destructor TBCListBoxEx.Destroy;
|
|
|
|
|
+begin
|
|
|
|
|
+ items.Free;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TBCListBoxEx.KeyDown(var Key: word; Shift: TShiftState);
|
|
|
|
|
+var
|
|
|
|
|
+ tempitem: integer;
|
|
|
|
|
+begin
|
|
|
|
|
+ case key of
|
|
|
|
|
+ vk_down:
|
|
|
|
|
+ begin
|
|
|
|
|
+ tempitem := itemselected + 1;
|
|
|
|
|
+ if (tempitem < items.Count) then
|
|
|
|
|
+ begin
|
|
|
|
|
+ itemselected := tempitem;
|
|
|
|
|
+ if not ItemIsVisible(itemselected) then
|
|
|
|
|
+ ScrollToItemBottom();
|
|
|
|
|
+ if not ItemIsVisible(itemselected) then
|
|
|
|
|
+ ScrollToItem(itemselected);
|
|
|
|
|
+ Invalidate;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+ vk_up:
|
|
|
|
|
+ begin
|
|
|
|
|
+ tempitem := itemselected - 1;
|
|
|
|
|
+ if (tempitem >= 0) then
|
|
|
|
|
+ begin
|
|
|
|
|
+ itemselected := tempitem;
|
|
|
|
|
+ if not ItemIsVisible(itemselected) then
|
|
|
|
|
+ ScrollToItemTop();
|
|
|
|
|
+ if not ItemIsVisible(itemselected) then
|
|
|
|
|
+ ScrollToItem(itemselected);
|
|
|
|
|
+ Invalidate;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TBCListBoxEx.MouseMove(Shift: TShiftState; X, Y: integer);
|
|
|
|
|
+var
|
|
|
|
|
+ tempitem: integer;
|
|
|
|
|
+begin
|
|
|
|
|
+ mousepos := Point(x, y);
|
|
|
|
|
+ tempitem := GetItemVertically(mousepos.Y);
|
|
|
|
|
+ if tempitem <> lastitem then
|
|
|
|
|
+ begin
|
|
|
|
|
+ lastitem := tempitem;
|
|
|
|
|
+ Invalidate;
|
|
|
|
|
+ end;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+function TBCListBoxEx.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): boolean;
|
|
|
|
|
+var
|
|
|
|
|
+ r: TRect;
|
|
|
|
|
+begin
|
|
|
|
|
+ result := False;
|
|
|
|
|
+ r := GetItemRect(items.Count - 1);
|
|
|
|
|
+ if (r.Bottom >= Height) then
|
|
|
|
|
+ begin
|
|
|
|
|
+ result := True;
|
|
|
|
|
+ scrolly := scrolly - itemheight;
|
|
|
|
|
+ Invalidate;
|
|
|
|
|
+ end;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+function TBCListBoxEx.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): boolean;
|
|
|
|
|
+var
|
|
|
|
|
+ lastscroll: integer;
|
|
|
|
|
+begin
|
|
|
|
|
+ result := False;
|
|
|
|
|
+ lastscroll := scrolly;
|
|
|
|
|
+ scrolly := scrolly + itemheight;
|
|
|
|
|
+ if (scrolly > 0) then
|
|
|
|
|
+ scrolly := 0;
|
|
|
|
|
+ if scrolly <> lastscroll then
|
|
|
|
|
+ begin
|
|
|
|
|
+ result := True;
|
|
|
|
|
+ Invalidate;
|
|
|
|
|
+ end;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TBCListBoxEx.Paint;
|
|
|
|
|
+var
|
|
|
|
|
+ i: integer;
|
|
|
|
|
+ r: TRect;
|
|
|
|
|
+ style: TTextStyle;
|
|
|
|
|
+ start: integer;
|
|
|
|
|
+begin
|
|
|
|
|
+ style.Alignment := taCenter;
|
|
|
|
|
+ style.Layout := tlCenter;
|
|
|
|
|
+ start := -1;
|
|
|
|
|
+
|
|
|
|
|
+ for i := trunc(abs(scrolly) / itemheight) to items.Count - 1 do
|
|
|
|
|
+ begin
|
|
|
|
|
+ r := GetItemRect(i);
|
|
|
|
|
+
|
|
|
|
|
+ if (r.Top < Height) then
|
|
|
|
|
+ begin
|
|
|
|
|
+ if start = -1 then
|
|
|
|
|
+ start := i;
|
|
|
|
|
+ Canvas.Brush.Color := clGreen;
|
|
|
|
|
+ if (GetItemVertically(mousepos.Y) = i) then
|
|
|
|
|
+ canvas.Brush.Color := clMoneyGreen;
|
|
|
|
|
+ if (itemselected = i) then
|
|
|
|
|
+ canvas.Brush.Color := clBlue;
|
|
|
|
|
+ Canvas.Rectangle(r);
|
|
|
|
|
+ Canvas.Font.Color := clWhite;
|
|
|
|
|
+ Canvas.TextRect(r, 0, 0, items[i], style);
|
|
|
|
|
+ Caption := IntToStr(start) + '..' + IntToStr(i);
|
|
|
|
|
+ end
|
|
|
|
|
+ else
|
|
|
|
|
+ break;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ Canvas.Brush.Color := clGray;
|
|
|
|
|
+ Canvas.Rectangle(Width - scrollwidth, 0, Width, Height);
|
|
|
|
|
+
|
|
|
|
|
+ Canvas.Font.Color := clRed;
|
|
|
|
|
+ Canvas.TextOut(10, 10, IntToStr(invalidatecount));
|
|
|
|
|
+ Inc(invalidatecount);
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+function TBCListBoxEx.GetItemRect(index: integer): TRect;
|
|
|
|
|
+begin
|
|
|
|
|
+ Result := Rect(0, (index * itemheight) + scrolly, Width - scrollwidth,
|
|
|
|
|
+ (index * itemheight) + scrolly + itemheight);
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+function TBCListBoxEx.GetItemVertically(y: integer): integer;
|
|
|
|
|
+var
|
|
|
|
|
+ i: integer;
|
|
|
|
|
+begin
|
|
|
|
|
+ i := trunc(abs(scrolly) / itemheight);
|
|
|
|
|
+ Result := i + trunc(y / itemheight);
|
|
|
|
|
+ if (Result > items.Count) or (Result < 0) then
|
|
|
|
|
+ Result := -1;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TBCListBoxEx.ScrollToItemTop();
|
|
|
|
|
+begin
|
|
|
|
|
+ scrolly := scrolly + itemheight;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TBCListBoxEx.ScrollToItemBottom();
|
|
|
|
|
+begin
|
|
|
|
|
+ scrolly := scrolly - itemheight;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TBCListBoxEx.ScrollToItem(index: integer);
|
|
|
|
|
+begin
|
|
|
|
|
+ scrolly := -itemheight * index;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+function TBCListBoxEx.ItemIsVisible(index: integer): boolean;
|
|
|
|
|
+var
|
|
|
|
|
+ r: TRect;
|
|
|
|
|
+begin
|
|
|
|
|
+ r := GetItemRect(index);
|
|
|
|
|
+ Result := Rect(0, 0, Width, Height).Contains(r);
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+end.
|