home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d56 / RMCTL.ZIP / rmListControl.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-22  |  16KB  |  623 lines

  1. {================================================================================
  2. Copyright (C) 1997-2001 Mills Enterprise
  3.  
  4. Unit     : rmListControl
  5. Purpose  : This unit was created for use in the rmDiff controls and has been
  6.            found to be usefull in other areas.  Basically it's a listbox with
  7.            a few interesting properties.
  8. Date     : 06-24-2000
  9. Author   : Ryan J. Mills
  10. Version  : 1.80
  11. ================================================================================}
  12.  
  13. unit rmListControl;
  14.  
  15. interface
  16.  
  17. {$I CompilerDefines.INC}
  18.  
  19. uses
  20.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  21.   StdCtrls, ExtCtrls;
  22.  
  23. type
  24.   TFormatDrawingEvent = procedure(Sender:TObject; Canvas: TCanvas; Selected: boolean; var str: string) of object;
  25.   TScrollEvent = procedure(Sender:TObject; ScrollBar:integer) of object;
  26.  
  27.   TrmListControl = class(TCustomControl)
  28.   private
  29.     { Private declarations }
  30.     fItems: TStringList;
  31.     fIndex: integer;
  32.     fTopIndex: integer;
  33.     fLongest: integer;
  34.     fxPos: integer;
  35.     fOnScroll: TScrollEvent;
  36.     fFormatDrawing: TFormatDrawingEvent;
  37.     fShowFocusRect: boolean;
  38.     fShowHScrollBars: boolean;
  39.     fShowVScrollBars: boolean;
  40.  
  41.     procedure SetItems(const Value: TStringList);
  42.     function vLines: integer;
  43.     procedure ItemsChanged(Sender: TObject);
  44.     function LLLength: integer;
  45.     procedure setIndex(const Value: integer);
  46.  
  47.     procedure UpdateVScrollBar;
  48.     procedure UpdateHScrollBar;
  49.     procedure ScrollToVisible;
  50.  
  51.     function GetHScrollPos: integer;
  52.     function GetVScrollPos: integer;
  53.     procedure SetHScrollPos(const Value: integer);
  54.     procedure SetVScrollPos(const Value: integer);
  55.  
  56.     procedure cmFOCUSCHANGED(var MSG: TMessage); message CM_FOCUSCHANGED;
  57.     procedure cmFontChanged(var Msg:TMessage); message cm_fontchanged;
  58.     procedure wmSize(var MSG: TWMSize); message wm_size;
  59.     procedure wmEraseBKGrnd(var msg: tmessage); message wm_erasebkgnd;
  60.     procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
  61.     procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
  62.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  63.     procedure SetShowFocusRect(const Value: boolean);
  64.     procedure SetShowVScrollBars(const Value: boolean);
  65.     procedure SetShowHScrollBars(const Value: boolean);
  66.     function GetHScrollSize: integer;
  67.     function GetVScrollSize: integer;
  68.     procedure SetTopIndex(const Value: integer);
  69.   protected
  70.     procedure paint; override;
  71.     procedure CreateParams(var Params: TCreateParams); override;
  72.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  73.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  74.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  75.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
  76.     property InternalTopIndex : integer read fTopIndex write SetTopIndex;
  77.   public
  78.     { Public declarations }
  79.     constructor create(aowner: TComponent); override;
  80.     destructor destroy; override;
  81.     property Items: TStringList read fItems write SetItems;
  82.     property ItemIndex: integer read fIndex write setIndex default 0;
  83.     property VScrollPos: integer read GetVScrollPos write SetVScrollPos;
  84.     property HScrollPos: integer read GetHScrollPos write SetHScrollPos;
  85.     property VScrollSize: integer read GetVScrollSize;
  86.     property HScrollSize: integer read GetHScrollSize;
  87.   published
  88.     property Align;
  89.     property Font;
  90.     property ShowVScrollBars: boolean read fShowVScrollBars write SetShowVScrollBars default true;
  91.     property ShowHScrollBars: boolean read fShowHScrollBars write SetShowHScrollBars default true;
  92.     property ShowFocusRect: boolean read fShowFocusRect write SetShowFocusRect default true;
  93.     property OnScroll: TScrollEvent read fOnScroll write fOnScroll;
  94.     property OnFormatDrawing: TFormatDrawingEvent read fFormatDrawing write fFormatDrawing;
  95.   end;
  96.  
  97. implementation
  98.  
  99. uses Math, rmlibrary;
  100.  
  101. { TrmListControl }
  102.  
  103. constructor TrmListControl.create(aowner: TComponent);
  104. begin
  105.   inherited;
  106.  
  107.   ControlStyle := controlstyle + [csopaque];
  108.   height := 200;
  109.   width := 400;
  110.   fLongest :=-1;
  111.   fIndex := 0;
  112.   fTopIndex := 0;
  113.   fItems := TStringList.Create;
  114.   fItems.OnChange := ItemsChanged;
  115.   fXPos := 0;
  116.   fShowFocusRect := true;
  117.   fShowVScrollBars := true;
  118.   fShowHScrollBars := true;
  119. end;
  120.  
  121. procedure TrmListControl.CreateParams(var Params: TCreateParams);
  122. begin
  123.   inherited;
  124.   if fShowVScrollBars then
  125.     Params.style := Params.style or WS_VSCROLL;
  126.  
  127.   if fShowHScrollBars then
  128.     Params.style := Params.style or WS_HSCROLL;
  129. end;
  130.  
  131. destructor TrmListControl.destroy;
  132. begin
  133.   fItems.free;
  134.   inherited;
  135. end;
  136.  
  137. function TrmListControl.GetHScrollPos: integer;
  138. var
  139.   wScrollInfo: TScrollInfo;
  140. begin
  141.   if fShowHScrollBars then
  142.   begin
  143.     with wScrollInfo do
  144.     begin
  145.       cbSize := sizeof(TScrollInfo);
  146.       fMask := SIF_POS;
  147.     end;
  148.  
  149.     if GetScrollInfo(Handle, SB_HORZ, wScrollInfo) then
  150.       result := wScrollInfo.nPos
  151.     else
  152.       result := 0;
  153.   end
  154.   else
  155.     result := fxPos;
  156. end;
  157.  
  158. function TrmListControl.GetVScrollPos: integer;
  159. var
  160.   wScrollInfo: TScrollInfo;
  161. begin
  162.   if fShowVScrollBars then
  163.   begin
  164.     with wScrollInfo do
  165.     begin
  166.       cbSize := sizeof(TScrollInfo);
  167.       fMask := SIF_POS;
  168.     end;
  169.  
  170.     if GetScrollInfo(Handle, SB_VERT, wScrollInfo) then
  171.       result := wScrollInfo.nPos
  172.     else
  173.       result := 0;
  174.   end
  175.   else
  176.     result := InternalTopIndex;
  177. end;
  178.  
  179. procedure TrmListControl.ItemsChanged(Sender: TObject);
  180. begin
  181.   fIndex := 0;
  182.   InternalTopIndex := 0;
  183.  
  184.   UpdateVScrollBar;
  185.   UpdateHScrollBar;
  186.   Invalidate;
  187. end;
  188.  
  189. function TrmListControl.LLLength: integer;
  190. var
  191.   loop: integer;
  192. begin
  193.   if (fLongest = -1) and (fItems.count > 0) then
  194.   begin
  195.     for loop := 0 to fItems.count - 1 do
  196.       fLongest := Max(fLongest, Canvas.TextWidth(fItems[loop]));
  197.   end;
  198.   result := fLongest;
  199. end;
  200.  
  201. procedure TrmListControl.paint;
  202. var
  203.   lcount, loop: integer;
  204.   wRect: TRect;
  205.   wstr: string;
  206. begin
  207.   Canvas.brush.Color := clWindow;
  208.   wRect := rect(0, 0, ClientWidth, Canvas.textheight('X'));
  209.   if fitems.count > 0 then
  210.   begin
  211.     lcount := vLines;
  212.     if lcount + InternalTopIndex > fitems.Count then
  213.       lcount := fitems.count - InternalTopIndex;
  214.     loop := InternalTopIndex;
  215.     while loop < InternalTopIndex + lcount do
  216.     begin
  217.       if loop = fIndex then
  218.       begin
  219.         if Focused then
  220.         begin
  221.            Canvas.brush.Color := clHighlight;
  222.            Canvas.Font.color := clHighlightText;
  223.         end
  224.         else
  225.         begin
  226.            Canvas.brush.Color := clBtnFace;
  227.            Canvas.Font.color := clWindowText;
  228.         end;
  229.       end;
  230.  
  231.       wstr := fItems[loop];
  232.  
  233.       if Assigned(fFormatDrawing) then
  234.         fFormatDrawing(Self, Canvas, (loop = fIndex), wstr);
  235.  
  236.       Canvas.TextRect(wRect, -HScrollPos, wRect.top, wstr);
  237.  
  238.       if Focused and fShowFocusRect and (loop = fIndex) then
  239.         Canvas.DrawFocusRect(wRect);
  240.  
  241.       offsetrect(wrect, 0, canvas.textheight('X'));
  242.  
  243.       Canvas.brush.Color := clWindow;
  244.       Canvas.Font.color := clWindowText;
  245.  
  246.       inc(loop);
  247.     end;
  248.   end;
  249.   wRect.Bottom := ClientHeight;
  250.   Canvas.FillRect(wRect);
  251. end;
  252.  
  253. procedure TrmListControl.ScrollToVisible;
  254. begin
  255.   if (InternalTopIndex < fIndex) then
  256.   begin
  257.     if (InternalTopIndex + (vLines - 1) < fIndex) then
  258.       InternalTopIndex := (fIndex - (vLines - 1));
  259.   end
  260.   else if fIndex < InternalTopIndex then
  261.     InternalTopIndex := fIndex;
  262.  
  263.   if InternalTopIndex < 0 then
  264.   begin
  265.     InternalTopIndex := 0;
  266.     fIndex := 0;
  267.   end;
  268. end;
  269.  
  270. procedure TrmListControl.SetHScrollPos(const Value: integer);
  271. var
  272.   wScrollInfo: TScrollInfo;
  273. begin
  274.   if fShowHScrollBars then
  275.   begin
  276.     with wScrollInfo do
  277.     begin
  278.       cbSize := sizeof(TScrollInfo);
  279.       fMask := SIF_POS;
  280.       nPos := Value;
  281.     end;
  282.  
  283.     fxPos := SetScrollInfo(Handle, SB_HORZ, wScrollInfo, true);
  284.   end
  285.   else
  286.     fxPos := SetInRange(Value, 0, HScrollSize);
  287.   Invalidate;
  288. end;
  289.  
  290. procedure TrmListControl.setIndex(const Value: integer);
  291. begin
  292.   if fitems.count > 0 then
  293.   begin
  294.      fIndex := SetInRange(Value, 0, fItems.count-1);
  295.      ScrollToVisible;
  296.      Invalidate;
  297.   end;
  298. end;
  299.  
  300. procedure TrmListControl.SetItems(const Value: TStringList);
  301. begin
  302.   fItems.assign(Value);
  303. end;
  304.  
  305. procedure TrmListControl.SetVScrollPos(const Value: integer);
  306. var
  307.   wScrollInfo: TScrollInfo;
  308. begin
  309.   if fShowVScrollBars then
  310.   begin
  311.     with wScrollInfo do
  312.     begin
  313.       cbSize := sizeof(TScrollInfo);
  314.       fMask := SIF_POS or SIF_DISABLENOSCROLL;
  315.       nMin := 0;
  316.       nMax := 0;
  317.       nPos := Value;
  318.     end;
  319.  
  320.     InternalTopIndex := SetScrollInfo(Handle, SB_VERT, wScrollInfo, true);
  321.   end
  322.   else
  323.   begin
  324.     InternalTopIndex := SetInRange(value, 0, VScrollSize);
  325.   end;
  326.   Invalidate;
  327. end;
  328.  
  329. procedure TrmListControl.UpdateVScrollBar;
  330. var
  331.   wScrollInfo: TScrollInfo;
  332. begin
  333.   if csloading in componentstate then exit;
  334.   if csDestroying in ComponentState then exit;
  335.  
  336.   InternalTopIndex := SetInRange(InternalTopIndex, 0, VScrollSize);
  337.  
  338.   if fShowVScrollBars then
  339.   begin
  340.     with wScrollInfo do
  341.     begin
  342.       cbSize := sizeof(TScrollInfo);
  343.       fMask := SIF_POS or SIF_RANGE or SIF_DISABLENOSCROLL;
  344.       nMin := 0;
  345.       nMax := VScrollSize;
  346.       nPos := InternalTopIndex;
  347.     end;
  348.  
  349.     SetScrollInfo(Handle, SB_VERT, wScrollInfo, True);
  350.     InternalTopIndex := VScrollPos;
  351.   end;
  352.   
  353.   if assigned(fOnScroll) then
  354.     fOnScroll(self, SB_VERT);
  355. end;
  356.  
  357. procedure TrmListControl.UpdateHScrollBar;
  358. var
  359.   wScrollInfo: TScrollInfo;
  360. begin
  361.   if csloading in componentstate then exit;
  362.   if csDestroying in ComponentState then exit;
  363.  
  364.   fxPos := SetInRange(fxPos, 0, HScrollSize);
  365.  
  366.   if fShowHScrollBars then
  367.   begin
  368.     with wScrollInfo do
  369.     begin
  370.       cbSize := sizeof(TScrollInfo);
  371.       fMask := SIF_POS or SIF_RANGE or SIF_DISABLENOSCROLL;
  372.       nMin := 0;
  373.       nMax := HScrollSize;
  374.       nPos := fxPos;
  375.     end;
  376.  
  377.     SetScrollInfo(Handle, SB_HORZ, wScrollInfo, True);
  378.     fxPos := HScrollPos;
  379.   end;
  380.  
  381.   if assigned(fOnScroll) then
  382.     fOnScroll(self, SB_HORZ);
  383. end;
  384.  
  385.  
  386. function TrmListControl.vLines: integer;
  387. begin
  388.   result := ClientHeight div canvas.TextHeight('X');
  389. end;
  390.  
  391. procedure TrmListControl.wmEraseBKGrnd(var msg: tmessage);
  392. begin
  393.   msg.result := 1;
  394. end;
  395.  
  396. procedure TrmListControl.WMHScroll(var Msg: TWMHScroll);
  397. begin
  398.   inherited;
  399.   case Msg.ScrollCode of
  400.     SB_BOTTOM: fxPos := LLLength - clientwidth;
  401.     SB_LINEDOWN: inc(fxPos, canvas.TextWidth('X'));
  402.     SB_LINEUP: dec(fxPos, canvas.TextWidth('X'));
  403.     SB_TOP: fxPos := 0;
  404.     SB_PAGEDOWN: inc(fxPos, (LLLength - clientwidth) div 2);
  405.     SB_PAGEUP: dec(fxPos, (LLLength - clientwidth) div 2);
  406.     SB_THUMBPOSITION: fxPos := Msg.Pos;
  407.     SB_THUMBTRACK: fxPos := Msg.Pos;
  408.   else
  409.     exit;
  410.   end;
  411.  
  412.   UpdateHScrollBar;
  413.   Invalidate;
  414. end;
  415.  
  416. procedure TrmListControl.wmSize(var MSG: TWMSize);
  417. begin
  418.   UpdatevScrollBar;
  419.   UpdateHScrollBar;
  420.   inherited;
  421. end;
  422.  
  423. procedure TrmListControl.WMVScroll(var Msg: TWMVScroll);
  424. begin
  425.   inherited;
  426.   case Msg.ScrollCode of
  427.     SB_BOTTOM: InternalTopIndex := fItems.Count - vLines;
  428.     SB_LINEDOWN: InternalTopIndex := InternalTopIndex+1;
  429.     SB_LINEUP: InternalTopIndex := InternalTopIndex-1;
  430.     SB_TOP: InternalTopIndex := 0;
  431.     SB_PAGEDOWN: InternalTopIndex := InternalTopIndex+vLines;
  432.     SB_PAGEUP: InternalTopIndex := InternalTopIndex-vLines;
  433.     SB_THUMBPOSITION: InternalTopIndex := Msg.Pos;
  434.     SB_THUMBTRACK: InternalTopIndex := Msg.Pos;
  435.   else
  436.     exit;
  437.   end;
  438.  
  439.   UpdateVScrollBar;
  440.   Invalidate;
  441. end;
  442.  
  443. procedure TrmListControl.WMGetDlgCode(var Message: TWMGetDlgCode);
  444. begin
  445.   Message.Result := DLGC_WANTARROWS;
  446. end;
  447.  
  448. procedure TrmListControl.KeyDown(var Key: Word; Shift: TShiftState);
  449. begin
  450.   inherited;
  451.  
  452.   case key of
  453.     vk_end:
  454.       begin
  455.         if shift = [] then
  456.           fIndex := fItems.count - 1;
  457.       end;
  458.     vk_DOWN:
  459.       begin
  460.         if shift = [] then
  461.           inc(fIndex);
  462.       end;
  463.     vk_up:
  464.       begin
  465.         if shift = [] then
  466.           dec(fIndex);
  467.       end;
  468.     vk_home:
  469.       begin
  470.         if shift = [] then
  471.           fIndex := 0;
  472.       end;
  473.     VK_Right:
  474.       begin
  475.         if shift = [] then
  476.           inc(fxPos)
  477.         else if shift = [ssCTRL] then
  478.           fxPos := LLLength - ClientWidth;
  479.       end;
  480.     VK_LEFT:
  481.       begin
  482.         if shift = [] then
  483.           dec(fxPos)
  484.         else if shift = [ssCTRL] then
  485.           fxPos := 0;
  486.       end;
  487.     vk_next:
  488.       begin
  489.         if shift = [] then
  490.           inc(fIndex, vLines - 1);
  491.       end;
  492.     vk_prior:
  493.       begin
  494.         if shift = [] then
  495.           Dec(fIndex, vLines - 1);
  496.       end;
  497.   else
  498.     exit;
  499.   end;
  500.  
  501.   fIndex := SetInRange(fIndex, 0, fItems.count-1);
  502.   ScrollToVisible;
  503.   UpdateVScrollBar;
  504.   UpdateHScrollBar;
  505.  
  506.   Invalidate;
  507. end;
  508.  
  509. procedure TrmListControl.cmFOCUSCHANGED(var MSG: TMessage);
  510. begin
  511.   inherited;
  512.   invalidate;
  513. end;
  514.  
  515. procedure TrmListControl.MouseDown(Button: TMouseButton;
  516.   Shift: TShiftState; X, Y: Integer);
  517. var
  518.   wLine: integer;
  519. begin
  520.   inherited;
  521.   if Button = mbLeft then
  522.   begin
  523.     if CanFocus then
  524.       setfocus;
  525.     wLine := InternalTopIndex + (y div Canvas.TextHeight('X'));
  526.     if wLine < fItems.count then
  527.     begin
  528.       fIndex := wLine;
  529.       ScrollToVisible;
  530.       UpdateVScrollBar;
  531.       invalidate;
  532.     end;
  533.   end;
  534. end;
  535.  
  536. procedure TrmListControl.MouseMove(Shift: TShiftState; X, Y: Integer);
  537. var
  538.   wLine: integer;
  539. begin
  540.   inherited;
  541.   if focused and (Shift = [ssLeft]) then
  542.   begin
  543.     wLine := InternalTopIndex + (y div Canvas.TextHeight('X'));
  544.     if wLine < fItems.count then
  545.     begin
  546.       fIndex := wLine;
  547.       ScrollToVisible;
  548.       UpdateVScrollBar;
  549.       invalidate;
  550.     end;
  551.   end;
  552. end;
  553.  
  554. procedure TrmListControl.SetShowFocusRect(const Value: boolean);
  555. begin
  556.   if fShowFocusRect <> Value then
  557.   begin
  558.     fShowFocusRect := Value;
  559.     invalidate;
  560.   end;
  561. end;
  562.  
  563. procedure TrmListControl.SetShowVScrollBars(const Value: boolean);
  564. begin
  565.   if fShowVScrollBars <> Value then
  566.   begin
  567.     fShowVScrollBars := Value;
  568.     recreatewnd;
  569.   end;
  570. end;
  571.  
  572. function TrmListControl.GetHScrollSize: integer;
  573. begin
  574.   if LLLength - ClientWidth < 0 then
  575.     result := 0
  576.   else
  577.     result := (LLLength - ClientWidth);
  578. end;
  579.  
  580. function TrmListControl.GetVScrollSize: integer;
  581. begin
  582.   if fItems.Count - vLines < 0 then
  583.     result := 0
  584.   else
  585.     result := (fItems.Count - vLines);
  586. end;
  587.  
  588. procedure TrmListControl.SetShowHScrollBars(const Value: boolean);
  589. begin
  590.   if fShowHScrollBars <> Value then
  591.   begin
  592.     fShowHScrollBars := Value;
  593.     recreatewnd;
  594.   end;
  595. end;
  596.  
  597. procedure TrmListControl.cmFontChanged(var Msg: TMessage);
  598. begin
  599.    inherited;
  600.    Canvas.font.Assign(font);
  601. end;
  602.  
  603. function TrmListControl.DoMouseWheel(Shift: TShiftState;
  604.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  605. var
  606.    wdata : integer;
  607. begin
  608.    inherited DoMouseWheel(Shift, WheelDelta, MousePos);
  609.    result := true;
  610.    wData := (WheelDelta div canvas.textheight('X'));
  611.    InternalTopIndex := SetInRange(vScrollPos + wData, 0, VScrollSize);
  612.    UpdateVScrollBar;
  613.    invalidate;
  614. end;
  615.  
  616. procedure TrmListControl.SetTopIndex(const Value: integer);
  617. begin
  618.   fTopIndex := Value;
  619. end;
  620.  
  621. end.
  622.  
  623.