unit CCScrollBar;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,ccGeneral;
type
  TCCScrollBarPressedStatus=(ccsbpsNo,ccsbpsLeftButton,ccsbpsRightButton,ccsbpsSchieber,ccsbpsLeftBackground,ccsbpsRightBackground);
  TCCScrollBarOrientierung=(ccsboHorizontal,ccsboVertikal);
  TCCScrollBarDrawTeil=set of (ccsbdtLeftButton,ccsbdtSchieber,ccsbdtRightButton);
  TCCVirtualScrollBar=class(TCCVirtualComponent)
  protected
    pressed_ccsbps:TCCScrollBarPressedStatus;
    forientierung_ccsbo:TCCScrollBarOrientierung;
    FMaxValue_i,FPosition_i,ClickPos_i:integer;
    FButtonGroese_i:integer;
    FPageSize_i:integer;
    FLargeMove_i,FSmallMove_i:integer;
    FChangeFunc:TNotifyEvent;
  public
    PagePos_i:integer;
    { Public-Deklarationen}
    constructor create(aowner:TCCComponent);override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer);override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
    procedure KeyDown(var Key: Word; Shift: TShiftState);override;
    procedure DrawTeil(const teil_ccsbdt:TCCScrollBarDrawTeil);
    procedure WndProc(var Message: TMessage);override;
    procedure setPosition(const pos:integer);
    procedure setMaxValue(const pos:integer);
    procedure setButtonGroese(const pos:integer);
    procedure setPageSize(const pos:integer);
    procedure PaintPixeledRect(const StartX_i,x1,y1,x2,y2:integer;const c1,c2:Tcolor);
    procedure UpdatePagePos;
    procedure paint;override;
  published
    { Published-Deklarationen }
    property MaxValue:integer read FMaxValue_i write setMaxValue;
    property Position:integer read FPosition_i write setPosition;
    property Orientierung:TCCScrollBarOrientierung read FOrientierung_ccsbo write FOrientierung_ccsbo ;
    property ButtonGroese:integer read FButtonGroese_i write setButtonGroese;
    property PageSize:integer read FPageSize_i write setPageSize;
//    property TimerGeschwindigkeit:integer read FTimerUpdate_i write FTimerUpdate_i;
    property LargeMove:integer read FLargeMove_i write FLargeMove_i;
    property SmallMove:integer read FSmallMove_i write FSmallMove_i;
    property OnChange:TNotifyEvent read FChangeFunc write FChangeFunc;
  end;
  TCCScrollBar = class(TCCComponent)
  private
    { Private-Deklarationen}
  protected
    { Protected-Deklarationen}
    virtscrollbar_ccvsb:TCCVirtualScrollBar;
    FTimerUpdate_i:integer;
    FChangeFunc:TNotifyEvent;
  public
    { Public-Deklarationen}
    constructor create(aowner:TComponent); override;
    destructor destroy;override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
    procedure KeyDown(var Key: Word; Shift: TShiftState);override;
    procedure Paint;override;
   // procedure DrawTeil(const teil_ccsbdt:TCCScrollBarDrawTeil);
    procedure WndProc(var Message: TMessage);override;
    procedure CreateWnd;override;
//    procedure setPosition(const pos:integer);
    procedure setTimerUpdate(const geschwindigkeit:integer);
    procedure DoChange(sender: TObject);
  published
    { Published-Deklarationen }
    property ScrollBarInformationen:TCCVirtualScrollBar read virtscrollbar_ccvsb write virtscrollbar_ccvsb;
    property TimerGeschwindigkeit:integer read FTimerUpdate_i write setTimerUpdate;
    property OnChange:TNotifyEvent read FChangeFunc write FChangeFunc;
  end;

procedure Register;

implementation
function min(const a,b:integer):integer;
begin
  if a<b then result:=a
  else result:=b;
end;
constructor TCCVirtualScrollBar.create(aowner:TCCComponent);
begin
  inherited;
  FButtonGroese_i:=18;
  FMaxValue_i:=100;
  FPageSize_i:=15;
  FSmallMove_i:=1;
  FLargeMove_i:=5;
  PagePos_i:=FButtonGroese_i;
//  UpdatePagePos;
 // ButtonGroese:=16;
end;
procedure TCCVirtualScrollBar.UpdatePagePos;
begin
  if MaxValue=0 then MaxValue:=100;
  if control<>nil then
    if Orientierung=ccsboHorizontal then
      PagePos_i:=(Position * (width-ButtonGroese shl 1-PageSize)) div MaxValue+ButtonGroese
     else
      PagePos_i:=(Position * (height-ButtonGroese shl 1-PageSize)) div MaxValue+ButtonGroese;
end;
procedure TCCVirtualScrollBar.KeyDown(var Key: Word; Shift: TShiftState);
begin
  case key of
    vk_left,vk_up: Position:=Position-SmallMove;
    VK_RIGHT,vk_down: Position:=Position+SmallMove;
    VK_PRIOR: Position:=Position-LargeMove;
    VK_NEXT: Position:=Position+LargeMove;
  end;
//  inherited;
end;
procedure TCCVirtualScrollBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if (x<left) or (y<top) or (x>left+width) or (y>top+height) then
    exit;
  if Orientierung=ccsboHorizontal then begin
    if (x-left<ButtonGroese) then begin
      pressed_ccsbps:=ccsbpsLeftButton;
      Position:=Position-SmallMove;
     end else if (x-left>width-ButtonGroese) then begin
      pressed_ccsbps:=ccsbpsRightButton;
      Position:=Position+SmallMove;
     end else if (x-left>PagePos_i)and(x-left<PagePos_i+PageSize) then begin
      pressed_ccsbps:=ccsbpsSchieber;
      ClickPos_i:=x-PagePos_i;
     end else if (x-left<PagePos_i) then begin
      pressed_ccsbps:=ccsbpsLeftBackground;
      ClickPos_i:=x;
    //  Position:=Position-LargeMove;
     end else if (x-left>PagePos_i+ButtonGroese) then begin
      pressed_ccsbps:=ccsbpsRightBackground;
//    Position:=Position+LargeMove;
      ClickPos_i:=x;
     end else
      pressed_ccsbps:=ccsbpsNo;
  end else begin
    if (y-top<ButtonGroese) then begin
      pressed_ccsbps:=ccsbpsLeftButton;
      Position:=Position-SmallMove;
     end else if (y-top>height-ButtonGroese) then begin
      pressed_ccsbps:=ccsbpsRightButton;
      Position:=Position+SmallMove;
     end else if (y-top>PagePos_i)and(y-top<PagePos_i+PageSize) then begin
      pressed_ccsbps:=ccsbpsSchieber;
      ClickPos_i:=y-PagePos_i;
     end else if (y-top<PagePos_i) then begin
      pressed_ccsbps:=ccsbpsLeftBackground;
      ClickPos_i:=y;
    //  Position:=Position-LargeMove;
     end else if (y-top>PagePos_i+ButtonGroese) then begin
      pressed_ccsbps:=ccsbpsRightBackground;
//    Position:=Position+LargeMove;
      ClickPos_i:=y;
     end else
      pressed_ccsbps:=ccsbpsNo;
  end;
  control.SetFocus;
  DrawTeil([ccsbdtLeftButton,ccsbdtSchieber,ccsbdtRightButton]);
//  inherited;
end;
procedure TCCVirtualScrollBar.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
  if (x<left) or (y<top) or (x>left+width) or (y>top+height) then begin
    if pressed_ccsbps=ccsbpsNo then
      exit;
    pressed_ccsbps:=ccsbpsNo;
    drawTeil([ccsbdtLeftButton,ccsbdtRightButton,ccsbdtSchieber]);
    exit;
  end;
  if Orientierung=ccsboHorizontal then begin
    if (x>left+ButtonGroese)and(x<left+width-ButtonGroese)and(ssLeft in shift)and(pressed_ccsbps=ccsbpsSchieber) then
      Position:=-(ButtonGroese-x+ClickPos_i)* MaxValue div (width-ButtonGroese shl 1-PageSize);
    if (x<left+ButtonGroese)and(ssLeft in shift)and(pressed_ccsbps=ccsbpsNo) then begin
      pressed_ccsbps:=ccsbpsLeftButton;
      drawTeil([ccsbdtLeftButton]);
    end else if (x>left+width-ButtonGroese)and(ssLeft in shift)and(pressed_ccsbps=ccsbpsNo) then begin
      pressed_ccsbps:=ccsbpsRightButton;
      drawTeil([ccsbdtRightButton]);
    end else if ((x>left+ButtonGroese))and(ssLeft in shift)and(pressed_ccsbps=ccsbpsLeftButton) then begin
      pressed_ccsbps:=ccsbpsNo;
      drawTeil([ccsbdtLeftButton]);
    end else if ((x<left+width-ButtonGroese))and(ssLeft in shift)and(pressed_ccsbps=ccsbpsRightButton) then begin
      pressed_ccsbps:=ccsbpsNo;
      drawTeil([ccsbdtRightButton]);
    end;
  end else begin
    if (y>top+ButtonGroese)and(y<top+height-ButtonGroese)and(ssLeft in shift)and(pressed_ccsbps=ccsbpsSchieber) then
      Position:=-(ButtonGroese-y+ClickPos_i)* MaxValue div (height-ButtonGroese shl 1-PageSize);
    if (y<top+ButtonGroese)and(ssLeft in shift)and(pressed_ccsbps=ccsbpsNo) then begin
      pressed_ccsbps:=ccsbpsLeftButton;
      drawTeil([ccsbdtLeftButton]);
    end else if (y>top+height-ButtonGroese)and(ssLeft in shift)and(pressed_ccsbps=ccsbpsNo) then begin
      pressed_ccsbps:=ccsbpsRightButton;
      drawTeil([ccsbdtRightButton]);
    end else if ((y>top+ButtonGroese))and(ssLeft in shift)and(pressed_ccsbps=ccsbpsLeftButton) then begin
      pressed_ccsbps:=ccsbpsNo;
      drawTeil([ccsbdtLeftButton]);
    end else if ((y<top+height-ButtonGroese))and(ssLeft in shift)and(pressed_ccsbps=ccsbpsRightButton) then begin
      pressed_ccsbps:=ccsbpsNo;
      drawTeil([ccsbdtRightButton]);
    end;
  end;
//  inherited;
end;
procedure TCCVirtualScrollBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  pressed_ccsbps:=ccsbpsNo;
  control.refresh;
//  inherited;
end;
procedure TCCVirtualScrollBar.PaintPixeledRect(const StartX_i,x1,y1,x2,y2:integer;const c1,c2:Tcolor);
  procedure PaintDiagonale(StartX_i,StartY_i,ZielX_i:integer);
  var size:integer;
  begin
    if StartX_i<x1 then begin
      StartY_i:=StartY_i+x1-StartX_i;
      StartX_i:=x1;
    end;
    if StartY_i<y1 then begin
      StartX_i:=StartX_i+y1-StartY_i;
      StartY_i:=y1;
    end;
    size:=ZielX_i-StartX_i;
    if StartY_i+size >y2 then begin
      size:=y2-StartY_i;
    end;
    control.Canvas.MoveTo(StartX_i+left,StartY_i+top);
    control.Canvas.LineTo(StartX_i+left+size,StartY_i+top+size)
  end;
var i:integer;
begin
control.canvas.pen.Color:=c1;
for i:=(y1-x2+StartX_i)div 2 to (y2) div 2 do
  PaintDiagonale(StartX_i,i*2,x2);
control.canvas.pen.Color:=c2;
for i:=(y1-x2+StartX_i)div 2 to (y2) div 2 do
  PaintDiagonale(StartX_i,i*2+1,x2);
end;
procedure TCCVirtualScrollBar.DrawTeil(const teil_ccsbdt:TCCScrollBarDrawTeil);
var c1_xf,c2_xf:TColor;
    x,y,PagePosMod2_i:integer;
begin
  if control=nil then exit;
//  with control do begin
    control.canvas.brush.style:=bsClear;
    control.drawLowerButtonRect(left,top,width+left,height+top,false);
    if control.DarstellungsOptionen=nil then exit;
    if orientierung=ccsboHorizontal then begin
      control.canvas.brush.style:=bsSolid;
      //Linken Button zeichnen
      if ccsbdtLeftButton in teil_ccsbdt then
        if pressed_ccsbps=ccsbpsLeftButton then
          control.drawLowerButtonRect(1+left,1+top,ButtonGroese-1+left,height-1+top,true)
         else
          control.DrawUpperRect(1+left,1+top,ButtonGroese-1+left,height-1+top,true);
      //Rechten Button zeichnen
      if ccsbdtRightButton in teil_ccsbdt then
        if pressed_ccsbps=ccsbpsRightButton then
          control.drawLowerButtonRect(width-ButtonGroese+1+left,1+top,width-1+left,height-1+top,true)
         else
          control.DrawUpperRect(width-ButtonGroese+1+left,1+top,width-1+left,height-1+top,true);
      //Mitte zeichnen
      if ccsbdtSchieber in teil_ccsbdt then begin
        if MaxValue=0 then maxvalue:=100;
        if PageSize=0 then maxvalue:=15;
        control.drawUpperRect(PagePos_i+left,1+top,PagePos_i+PageSize+left,height-1+top,true);

        c1_xf:=control.DarstellungsOptionen.getColorFromWindowColorKey(COLOR_SCROLLBAR);
        c2_xf:=control.DarstellungsOptionen.getAlternativColorFromWindowColorKey(COLOR_SCROLLBAR,1);
        control.canvas.brush.color:=control.DarstellungsOptionen.getAlternativColorFromWindowColorKey(COLOR_SCROLLBAR,2);
        if pressed_ccsbps=ccsbpsLeftBackground then
          control.canvas.FillRect(rect(ButtonGroese-1+left,1+top,PagePos_i+left,height-1+top))
         else
          PaintPixeledRect(ButtonGroese-1+left,ButtonGroese-1+left,1+top,PagePos_i+left,height-1+top,c1_xf,c2_xf);
        if pressed_ccsbps=ccsbpsRightBackground then
          control.canvas.FillRect(rect(PagePos_i+PageSize+left,1+top,width-ButtonGroese+left,height-1+top))
         else
          PaintPixeledRect(1,PagePos_i+PageSize+left,1+top,width-ButtonGroese+left,height-1+top,c1_xf,c2_xf);
      end;
      control.canvas.brush.Style:=bsClear;
      control.Canvas.font.Color:=control.DarstellungsOptionen.getColorFromWindowColorKey(COLOR_BTNTEXT);
      control.Canvas.font.Name:='Marlett';
      control.Canvas.font.size:=10;
      if ccsbdtLeftButton in teil_ccsbdt then
        control.canvas.TextOut(ButtonGroese div 4+left,(height-control.canvas.TextHeight('3')) div 2+top,'3');
      if ccsbdtRightButton in teil_ccsbdt then
        control.canvas.TextOut(width-ButtonGroese+ButtonGroese div 4+left,(height-control.canvas.TextHeight('4')) div 2+top,'4');
    end else begin
      control.canvas.brush.style:=bsSolid;
      if ccsbdtLeftButton in teil_ccsbdt then
        if pressed_ccsbps=ccsbpsLeftButton then
          control.drawLowerButtonRect(1+left,1+top,width-1+left,ButtonGroese-1+top,true)
         else
          control.DrawUpperRect(1+left,1+top,width-1+left,ButtonGroese-1+top,true);
      if ccsbdtRightButton in teil_ccsbdt then
        if pressed_ccsbps=ccsbpsRightButton then
          control.drawLowerButtonRect(1+left,height-ButtonGroese+1+top,width-1+left,height-1+top,true)
         else
          control.DrawUpperRect(1+left,height-ButtonGroese+1+top,width-1+left,height-1+top,true);
      if ccsbdtSchieber in teil_ccsbdt then begin
        if MaxValue=0 then maxvalue:=100;
        if PageSize=0 then maxvalue:=15;
//      PagePos_i:=(Position * (width-ButtonGroese shl 1-PageSize)) div MaxValue+ButtonGroese;
        control.drawUpperRect(1+left,PagePos_i+top,width-1+left,PagePos_i+PageSize+top,true);

        c1_xf:=control.DarstellungsOptionen.getColorFromWindowColorKey(COLOR_SCROLLBAR);
        c2_xf:=control.DarstellungsOptionen.getAlternativColorFromWindowColorKey(COLOR_SCROLLBAR,1);
        control.canvas.brush.color:=control.DarstellungsOptionen.getAlternativColorFromWindowColorKey(COLOR_SCROLLBAR,2);
        if pressed_ccsbps=ccsbpsLeftBackground then
          control.canvas.FillRect(rect(1+left,ButtonGroese-1+top,width-1+left,PagePos_i++top))
         else
          PaintPixeledRect(1+left,1+left,ButtonGroese-1+top,width-1+left,PagePos_i++top,c1_xf,c2_xf);
        if pressed_ccsbps=ccsbpsRightBackground then
          control.canvas.FillRect(rect(1+left,PagePos_i+PageSize+top,width-1+left,height-ButtonGroese+top))
         else
          PaintPixeledRect(1,1+left,PagePos_i+PageSize+top,width-1+left,height-ButtonGroese+top,c1_xf,c2_xf);

      end;
      control.canvas.brush.Style:=bsClear;
      control.canvas.font.Color:=control.DarstellungsOptionen.getColorFromWindowColorKey(COLOR_BTNTEXT);
      control.canvas.font.Name:='Marlett';
      control.canvas.font.size:=10;
      if ccsbdtLeftButton in teil_ccsbdt then
        control.canvas.TextOut((width-control.canvas.Textwidth('5')) div 2+left,ButtonGroese div 4+top,'5');
      if ccsbdtRightButton in teil_ccsbdt then
        control.canvas.TextOut((width-control.canvas.Textwidth('6')) div 2+left,height-ButtonGroese+ButtonGroese div 4+top,'6');
    end;
    control.canvas.brush.style:=bsClear;
  //  drawLowerRect(0,0,width,height,false);
//  end;
end;

procedure TCCVirtualScrollBar.paint;
begin
  inherited;
  DrawTeil([ccsbdtLeftButton,ccsbdtSchieber,ccsbdtRightButton]);
end;
procedure TCCVirtualScrollBar.WndProc(var Message: TMessage);
begin
  case Message.Msg of
    WM_MOUSEWHEEL: begin
                     position:=position-TWMMouseWheel(message).WheelDelta div 30;
                     DrawTeil([ccsbdtSchieber]);
                   end;
    WM_TIMER: begin
                if (pressed_ccsbps=ccsbpsLeftBackground) and (((ClickPos_i<PagePos_i+left)and(Orientierung=ccsboHorizontal))or((ClickPos_i<PagePos_i+top)and(Orientierung=ccsboVertikal))) then
                  Position:=Position-LargeMove
                else if (pressed_ccsbps=ccsbpsRightBackground)and (((ClickPos_i>PagePos_i+PageSize+left)and(Orientierung=ccsboHorizontal))or((ClickPos_i>PagePos_i+PageSize+top)and(Orientierung=ccsboVertikal)))  then
                  Position:=Position+LargeMove
                else if pressed_ccsbps=ccsbpsLeftButton then
                  Position:=Position-SmallMove
                else if pressed_ccsbps=ccsbpsRightButton then
                  Position:=Position+SmallMove
                else
                  exit;
                DrawTeil([ccsbdtSchieber]);
              end;
    else inherited;
  end;
end;
procedure TCCVirtualScrollBar.setPosition(const pos:integer);
begin
  if pos<0 then FPosition_i:=0
  else if pos>MaxValue then FPosition_i:=MaxValue
  else FPosition_i:=pos;
  UpdatePagePos;
  if assigned(FChangeFunc) then
    FChangeFunc(control);
  DrawTeil([ccsbdtSchieber]);;
end;
procedure TCCVirtualScrollBar.setMaxValue(const pos:integer);
begin
  if pos<1  then FMaxValue_i:=1
  else FMaxValue_i:=pos;
  UpdatePagePos;
  DrawTeil([ccsbdtSchieber]);
end;
procedure TCCVirtualScrollBar.setButtonGroese(const pos:integer);
begin
  if pos<1  then FButtonGroese_i:=1
  else FButtonGroese_i:=pos;
  UpdatePagePos;
  DrawTeil([ccsbdtSchieber,ccsbdtLeftButton,ccsbdtRightButton]);
end;
procedure TCCVirtualScrollBar.setPageSize(const pos:integer);
begin
  if pos<1  then FPageSize_i:=1
  else FPageSize_i:=pos;
  UpdatePagePos;
  DrawTeil([ccsbdtSchieber]);
end;

constructor TCCScrollBar.create(aowner:TComponent);
begin
  inherited create(aowner);
  Width:=200;
  height:=18;
  virtscrollbar_ccvsb:=TCCVirtualScrollBar.create(self);
  TabStop:=true;
  FTimerUpdate_i:=175;
  virtscrollbar_ccvsb.OnChange:=DoChange;
 // ButtonGroese:=16;
end;
procedure TCCScrollBar.DoChange(sender: TObject);
begin
  if assigned(FChangeFunc) then
    FChangeFunc(sender);
end;
procedure TCCScrollBar.KeyDown(var Key: Word; Shift: TShiftState);
begin
  virtscrollbar_ccvsb.KeyDown(key,shift);
  inherited;
end;
procedure TCCScrollBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  virtscrollbar_ccvsb.MouseDown(button,shift,x,y);
  inherited;
end;
procedure TCCScrollBar.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
  virtscrollbar_ccvsb.MouseMove(shift,x,y);
  inherited;
end;
procedure TCCScrollBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  virtscrollbar_ccvsb.MouseUp(button,shift,x,y);
  inherited;
end;
procedure TCCScrollBar.Paint;
begin
  virtscrollbar_ccvsb.DrawTeil([ccsbdtLeftButton,ccsbdtSchieber,ccsbdtRightButton]);
  inherited;
end;
procedure TCCScrollBar.WndProc(var Message: TMessage);
begin
  case Message.Msg of
    WM_ERASEBKGND:Message.Msg:=1000;
    WM_GETDLGCODE: TWMGetDlgCode(message).Result:=DLGC_WANTARROWS;
    else begin
      if assigned(virtscrollbar_ccvsb) then virtscrollbar_ccvsb.WndProc(message);
      inherited;
    end;
  end;
end;
procedure TCCScrollBar.CreateWnd;
begin
  inherited;
  SetTimer(handle,1,175,nil);
end;
procedure TCCScrollBar.setTimerUpdate(const geschwindigkeit:integer);
begin
  if HandleAllocated then
    settimer(handle,1,geschwindigkeit,nil);
end;
{procedure TCCScrollBar.setPosition(const pos:integer);
begin
  virtscrollbar_ccvsb.setPosition(pos);
end;}
destructor TCCScrollBar.destroy;
begin
  virtscrollbar_ccvsb.free;
  inherited;
end;
procedure Register;
begin
  RegisterComponents('Custom Controls', [TCCScrollBar]);
end;

end.

