unit SRVImagesScroll;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls,
  ImgList, SRVSBar, SRVSkinManager, SRVControl, SRVHint, SRVTabSet, RVStyle;

type
  TSRVImagesScroll = class;
  {-----------------------------------------------------------------------}
  TSRVCloseImageScrollEvent = procedure(Sender: TSRVImagesScroll; ItemIndex : Integer;
    var CanClose : Boolean) of object;
  {-----------------------------------------------------------------------}
  TSRVImageScrollMoveEvent = procedure(Sender: TSRVImagesScroll; NewImageIndex, OldImageIndex : Integer) of object;
  {-----------------------------------------------------------------------}
  TSRVDrawImageScrollEvent = procedure(Sender: TSRVImagesScroll; Canvas : TCanvas;
    ARect, PaintRect : TRect; State : TSRVDrawStates; var DoDefault : Boolean) of object;
  {-----------------------------------------------------------------------}
  TSRVDrawImageScrollItemEvent = procedure(Sender: TSRVImagesScroll; Canvas : TCanvas;
    ARect, PaintRect : TRect; ItemIndex : Integer; State : TSRVDrawStates;
    var DoDefault : Boolean) of object;
  {-----------------------------------------------------------------------}
  TSRVTypeHint = (srvthBottomMouse, srvthMouseMove, srvthMouseStop, srvthBottomPicture);
  {-----------------------------------------------------------------------}
  TSRVImageScrollKind = (srvbkHorizontal, srvbkVertical);
  {-----------------------------------------------------------------------}
  TSRVScrollerPosition = (srvpsBegin, srvpsEnd);
  {-----------------------------------------------------------------------}
  {ImageScrollItem in collection ImagesScroll }
  TSRVImageScrollItem = class(TCollectionItem)
  private
    FOwner : TCollection;
  protected
    FTag: Longint;
    FSkinSchemeIndex : Integer;
    FSkinFontIndex : Integer;
    FEnabled : Boolean;
    FVisible : Boolean;
    FName : String;
    FLink : String;
    FHint : String;
    FShowHint : Boolean;
    FImageIndex : Integer;
    FSelectImageIndex : Integer;

    procedure SetSkinSchemeIndex(const Value : Integer);
    procedure SetSkinFontIndex(const Value : Integer);
    procedure SetEnabled(const Value : Boolean);
    procedure SetVisible(const Value : Boolean);
    procedure SetImageIndex(const Value : Integer);
    procedure SetSelectImageIndex(const Value : Integer);
  public
    BoundsRect : TRect;
    constructor Create(Collection: TCollection); override;
    function GetOwner: TPersistent; override;
    procedure Assign(Source: TPersistent); override;
    function GetDisplayName: string; override;
    procedure Repaint;
  published
    property SkinSchemeIndex : Integer read FSkinSchemeIndex write SetSkinSchemeIndex default -1;
    property SkinFontIndex : Integer read FSkinFontIndex write SetSkinFontIndex default -1;
    property ImageIndex : Integer read FImageIndex write SetImageIndex default -1;
    property SelectImageIndex : Integer read FSelectImageIndex write SetSelectImageIndex default -1;
    property Hint : String read FHint write FHint;
    property Link : String read FLink write FLink;
    property Name : String read FName write FName;
    property Tag: Longint read FTag write FTag default 0;
    property Enabled : Boolean read FEnabled write SetEnabled default True;
    property Visible : Boolean read FVisible write SetVisible default True;
    property ShowHint : Boolean read FShowHint write FShowHint default True;
  end;
  {-----------------------------------------------------------------------}
  {Collection items}
  TSRVImageScrollCollection = class(TCollection)
  private
    FOwner: TPersistent;
    function GetItem(Index: Integer): TSRVImageScrollItem;
    procedure SetItem(Index: Integer; const Value: TSRVImageScrollItem);
  public
    constructor Create(ItemClass: TCollectionItemClass; Owner: TPersistent);
    function GetOwner: TPersistent; override;
    procedure AssignTo(Dest: TPersistent); override;
    property Items[Index: Integer]: TSRVImageScrollItem read GetItem write SetItem; default;
  end;

  {-----------------------------------------------------------------------}
  TSRVImagesScroll = class(TSRVCustomControl)
  private
    { Private declarations }
    IsMouseDown : Boolean;
    IsKeyDown : Boolean;
    IsFocus : Boolean;
    IsByse : Boolean;
    FInMouse : Boolean;

    FIsItemMouseDown : Integer;
    FIsItemMouseHot : Integer;
    FIsCloseMouseDown : Integer;
    FIsCloseMouseHot : Integer;
    dPosItemMoving : Integer;

    kdCharCode : Integer;
    FocusFrame : Integer;
  protected
    { Protected declarations }
    RScroller : TRect;
    FScrollBar : TSRVScrollBar;
    LockUpdate : Integer;
    FKind : TSRVImageScrollKind;
    FIndent : Integer;
    FItemWidth : Integer;
    FItemHeight : Integer;
    FSpacings : Integer;
    FMargins : TSRVMargins;
    FHintMargins : TSRVMargins;
    FCloseButton : TSRVCloseButton;
    FItems : TSRVImageScrollCollection;
    FItemIndex : Integer;
    FRestrictMove : Boolean;
    FScrollOffs : Integer;
    FScrollingDelay : Integer;
    FSkinSchemeIndex : Integer;
    FScrollBarSkinSchemeIndex : Integer;
    FItemSkinSchemeIndex : Integer;
    FButtonSkinSchemeIndex : Integer;
    FImageList : TCustomImageList;
    FDoubleBuffered : Boolean;
    FItemColor : TColor;
    FItemDownColor : TColor;
    FItemSelectedColor : TColor;
    FItemHotColor : TColor;
    FItemBorderColor : TColor;
    FItemBorderStyle : TPenStyle;

    FScrollerPosition : TSRVScrollerPosition;
    FCursorInPicture : TCursor;
    FTypeHint : TSRVTypeHint;
    FSRVHint : TSRVHint;
    FCanMoveImages : Boolean;
    FMovingItemIndex : Integer;
    FIsMovingItem : Boolean;

    FScrollItemIndex : Integer;
    IsScrollShow : Boolean;

    FOnImageScrollMove : TSRVImageScrollMoveEvent;
    FOnChange: TNotifyEvent;
    FOnCloseImageScroll : TSRVCloseImageScrollEvent;
    FOnDrawBorder : TSRVDrawImageScrollEvent;
    FOnDrawBackground : TSRVDrawImageScrollEvent;
    FOnDrawImageScroll : TSRVDrawImageScrollItemEvent;
    FOnDrawCloseButton : TSRVDrawImageScrollItemEvent;

    procedure SetSkinManager(Value : TSRVSkinManager); override;
    procedure SetScrollBarSkinSchemeIndex(Value : Integer);
    procedure SetItemSkinSchemeIndex(Value : Integer);
    procedure SetButtonSkinSchemeIndex(Value : Integer);

    procedure SetItemWidth(Value : Integer);
    procedure SetItemHeight(Value : Integer);
    procedure SetItems(const Value : TSRVImageScrollCollection);
    procedure SetKind(Value : TSRVImageScrollKind);
    procedure SetScrollerPosition(Value : TSRVScrollerPosition);
    procedure SetSRVHint(Value : TSRVHint);
    procedure SetSmallChange(Value : Integer);
    procedure SetLargeChange(Value : Integer);
    procedure SetImageList(const Value : TCustomImageList);
    procedure SetDoubleBuffered(Value: Boolean);
    procedure SetItemColor(const Value: TColor);
    procedure SetItemDownColor(const Value: TColor);
    procedure SetItemSelectedColor(const Value: TColor);
    procedure SetItemHotColor(const Value: TColor);
    procedure SetItemBorderColor(const Value: TColor);
    procedure SetItemBorderStyle(const Value: TPenStyle);

    procedure CalculateImagesScroll(FirstItemIndex : Integer);
    function  GetShowImageScrollCount : Integer;
    procedure SetSpacings(Value : Integer);
    procedure SetIndent(Value : Integer);
    procedure SetItemIndex(Value : Integer);
    procedure SetDecButtonWidth(Value : Integer);
    procedure SetIncButtonWidth(Value : Integer);
    procedure SetScrollBarHeight(Value : Integer);

    function  GetScrollBarSchemeIndex : Integer;
    procedure SetScrollBarSchemeIndex(Value : Integer);
    procedure SetMargins(const Value : TSRVMargins);
    procedure SetHintMargins(const Value : TSRVMargins);
    procedure SetCloseButton(const Value : TSRVCloseButton);

    function  GetFirstItemIndex : Integer;
    function  GetLastItemIndex : Integer;

    procedure Notification(AComponent: TComponent; Operation: TOperation); override;

    procedure DrawBorder(ACanvas : TCanvas; ARect : TRect);
    procedure DrawBG(ACanvas : TCanvas; ARect : TRect);
    procedure DrawImageScrollItem(ACanvas : TCanvas; ItemIndex : Integer; ARect : TRect);
    procedure DrawCloseButton(ACanvas : TCanvas; ItemIndex : Integer; ARect : TRect);

    function  GetSmallChange : Integer;
    function  GetLargeChange : Integer;
    function  GetDecButtonWidth: Integer;
    function  GetIncButtonWidth: Integer;
    function  GetScrollBarHeight: Integer;
    function  GetClientWidth: Integer;
    function  GetClientHeight: Integer;
    function  GetClientRect: TRect; reintroduce;
    function  GetMaxScrollPos: Integer;
    procedure SetHMax(Value: Integer);
    procedure HookOnScroll(Sender: TObject; ScrollCode: TScrollCode;
      var ScrollPos: Integer);
    procedure WMRepaintControl(var Message: TMessage); message WM_REPAINT_CONTROL;
    procedure WMTimer(var Message: TMessage); message WM_TIMER;
    procedure WMKeyDown(var Message: TWMKey); message WM_KEYDOWN;
    procedure WMKeyUp(var Message: TWMKey); message WM_KEYUP;
    procedure WMMouseDown(var Message: TWMMouse); message WM_LBUTTONDOWN;
    procedure WMMouseUp(var Message: TWMMouse); message WM_LBUTTONUP;
    procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure WMEraseBkgnd(var Message: TWMPaint); message WM_ERASEBKGND;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Resize; override;

    function  GetImagesScrollRect : TRect;
    function  IsItemVisible(ItemIndex : Integer; IsFullVisible : Boolean) : Boolean;
    function  GetItemRect(ItemIndex : Integer) : TRect;
    function  GetCloseAtItemIndex(ItemIndex : Integer) : TRect;
    function  GetItemIndexAtPos(X, Y : Integer) : Integer;
    procedure ScrollToItem(ItemIndex : Integer);
    function  DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;

{    function  GetImageScrollTextRect(ItemIndex : Integer) : TRect;
}
    procedure BeginUpdate;
    procedure EndUpdate;
    procedure Paint; override;
    procedure Invalidate; override;
    property  Canvas;
    property  InMouse : Boolean read FInMouse;
    property  IsItemMouseHot : Integer read FIsItemMouseHot;
    property  IsCloseMouseHot : Integer read FIsCloseMouseHot;
    property  IsCloseMouseDown : Integer read FIsCloseMouseDown;
    property  IsItemMouseDown : Integer read FIsItemMouseDown;
    property  MovingItemIndex : Integer read FMovingItemIndex;
    property  IsMovingItem : Boolean read FIsMovingItem;
    property  FirstItemIndex : Integer read GetFirstItemIndex;
    property  LastItemIndex : Integer read GetLastItemIndex;
    property  ScrollOffs : Integer read FScrollOffs write FScrollOffs;
    property  ClientRect: TRect read GetClientRect;
    property  ClientWidth: Integer read GetClientWidth;
    property  ClientHeight: Integer read GetClientHeight;
  published
    { Published declarations }
    property  ItemWidth : Integer read FItemWidth write SetItemWidth default 80;
    property  ItemHeight : Integer read FItemHeight write SetItemHeight default 40;
    property  Items : TSRVImageScrollCollection read FItems write SetItems;
    property  SmallChange : Integer read GetSmallChange write SetSmallChange;
    property  LargeChange : Integer read GetLargeChange write SetLargeChange;
    property  DecButtonWidth : Integer read GetDecButtonWidth write SetDecButtonWidth default 0;
    property  IncButtonWidth : Integer read GetIncButtonWidth write SetIncButtonWidth default 0;
    property  ScrollBarHeight : Integer read GetScrollBarHeight write SetScrollBarHeight;
    property  Margins : TSRVMargins read FMargins write SetMargins;
    property  HintMargins : TSRVMargins read FHintMargins write SetHintMargins;
    property  ItemIndex : Integer read FItemIndex write SetItemIndex default -1;
    property  ScrollingDelay : Integer read FScrollingDelay write FScrollingDelay default 100;
    property  CanMoveImages : Boolean read FCanMoveImages
      write FCanMoveImages default True;
    property  CloseButton : TSRVCloseButton read FCloseButton write SetCloseButton;
    property  Kind : TSRVImageScrollKind read FKind write SetKind default srvbkHorizontal;
    property  Spacings : Integer read FSpacings write SetSpacings default 10;
    property  Indent : Integer read FIndent write SetIndent default 10;
    property  RestrictMove : Boolean read FRestrictMove write FRestrictMove default False;
    property  ScrollerPosition : TSRVScrollerPosition read FScrollerPosition write SetScrollerPosition default srvpsEnd;
    property  SkinManager;
    property  SkinSchemeIndex;
    property  ScrollBarSkinSchemeIndex : Integer read FScrollBarSkinSchemeIndex write SetScrollBarSkinSchemeIndex default 0;
    property  ItemSkinSchemeIndex : Integer read FItemSkinSchemeIndex write SetItemSkinSchemeIndex default 0;
    property  ButtonSkinSchemeIndex : Integer read FButtonSkinSchemeIndex write SetButtonSkinSchemeIndex default 0;
    property  ImageList : TCustomImageList read FImageList write SetImageList;
    property  DoubleBuffered: Boolean read FDoubleBuffered write SetDoubleBuffered default False;
    property  ItemColor : TColor read FItemColor write SetItemColor default clBtnFace;
    property  ItemDownColor : TColor read FItemDownColor write SetItemDownColor default clInactiveCaption;
    property  ItemSelectedColor : TColor read FItemSelectedColor write SetItemSelectedColor default clHighlight;
    property  ItemHotColor : TColor read FItemHotColor write SetItemHotColor default clBtnShadow;
    property  ItemBorderColor : TColor read FItemBorderColor write SetItemBorderColor default clBtnShadow;
    property  ItemBorderStyle : TPenStyle read FItemBorderStyle write SetItemBorderStyle default psSolid;

    property  SRVHint : TSRVHint read FSRVHint write SetSRVHint;
    property  TabStop;
    property  Align;
    property  Anchors;
    property  Color;
    property  Constraints;
    property  Cursor;
    property  Enabled;
    property  Font;
    property  Hint;
    property  ShowHint;
    property  PopupMenu;
    property  Width;
    property  Height;
    property  Left;
    property  Top;

    property  OnMouseMove;
    property  OnMouseDown;
    property  OnMouseUp;
    property  OnKeyUp;
    property  OnKeyDown;
    property  OnEnter;
    property  OnExit;
    property  OnClick;
    property  OnChange: TNotifyEvent read FOnChange write FOnChange;
    property  OnItemMove : TSRVImageScrollMoveEvent
      read FOnImageScrollMove write FOnImageScrollMove;
    property  OnCloseItem : TSRVCloseImageScrollEvent
      read FOnCloseImageScroll write FOnCloseImageScroll;
    property  OnDrawBorder : TSRVDrawImageScrollEvent
      read FOnDrawBorder write FOnDrawBorder;
    property  OnDrawBackground : TSRVDrawImageScrollEvent
      read FOnDrawBackground write FOnDrawBackground;
    property  OnDrawItem : TSRVDrawImageScrollItemEvent
      read FOnDrawImageScroll write FOnDrawImageScroll;
    property  OnDrawCloseButton : TSRVDrawImageScrollItemEvent
      read FOnDrawCloseButton write FOnDrawCloseButton;
  end;

implementation

uses Math;

{---------------------------  TSRVImageScrollItem  --------------------------}
constructor TSRVImageScrollItem.Create(Collection: TCollection);
begin
  inherited;

    FOwner := Collection;
    FName := 'ImageScrollItem' + IntToStr(Collection.Count);
    FTag := 0;
    FSkinSchemeIndex := -1;
    FSkinFontIndex := -1;
    FImageIndex := -1;
    FSelectImageIndex := -1;
    FEnabled := True;
    FVisible := True;
    FLink := '';
    FHint := '';
    FShowHint := True;

    Repaint;
end;

{-----------------------------------------------------------------------}
function TSRVImageScrollItem.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollItem.Assign(Source: TPersistent);
var
     nProperty : TSRVImageScrollItem;
begin
  if Source = nil then Exit;
  nProperty := TSRVImageScrollItem(Source);

  FSkinSchemeIndex := nProperty.FSkinSchemeIndex;
  FSkinFontIndex := nProperty.FSkinFontIndex;
  FImageIndex := nProperty.FImageIndex;
  FSelectImageIndex := nProperty.FSelectImageIndex;
  FName := nProperty.FName;
  FLink := nProperty.FLink;
  FHint := nProperty.FHint;
  FEnabled := nProperty.FEnabled;
  FVisible := nProperty.FVisible;
  FShowHint := nProperty.FShowHint;
  FTag := nProperty.FTag;
end;

{-----------------------------------------------------------------------}
function TSRVImageScrollItem.GetDisplayName: string;
begin
  Result := FName;
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollItem.Repaint;
begin
  If Assigned(FOwner) and Assigned(TSRVImageScrollCollection(FOwner).FOwner) then
    TSRVImagesScroll(TSRVImageScrollCollection(FOwner).GetOwner).Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollItem.SetSkinSchemeIndex(const Value : Integer);
begin
  If FSkinSchemeIndex <> Value then begin
    FSkinSchemeIndex := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollItem.SetSkinFontIndex(const Value : Integer);
begin
  If FSkinFontIndex <> Value then begin
    FSkinFontIndex := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollItem.SetImageIndex(const Value : Integer);
begin
  If FImageIndex <> Value then begin
    FImageIndex := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollItem.SetSelectImageIndex(const Value : Integer);
begin
  If FSelectImageIndex <> Value then begin
    FSelectImageIndex := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollItem.SetEnabled(const Value : Boolean);
begin
  If FEnabled <> Value then begin
    FEnabled := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollItem.SetVisible(const Value : Boolean);
begin
  If FVisible <> Value then begin
    FVisible := Value;
    Repaint;
  end;
end;

{---------------------------  TSRVImageScrollCollection  ---------------------------}
{ Constructor }
constructor TSRVImageScrollCollection.Create(ItemClass: TCollectionItemClass;
                                     Owner: TPersistent);
begin
  inherited Create(ItemClass);
    FOwner := Owner;
end;

{------------------------------------------------------------------------------}
procedure TSRVImageScrollCollection.AssignTo(Dest: TPersistent);
var
     i: Integer;
begin
  if Dest is TStrings then begin
    TStrings(Dest).Clear;
    for i:=0 to Count-1 do
      TStrings(Dest).Add(TSRVImageScrollItem(Items[i]).Name);
  end else
    inherited AssignTo(Dest);
end;

{-----------------------------------------------------------------------}
function TSRVImageScrollCollection.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

{-----------------------------------------------------------------------}
function TSRVImageScrollCollection.GetItem(Index: Integer): TSRVImageScrollItem;
begin
  Result := TSRVImageScrollItem(inherited GetItem(Index));
end;

{-----------------------------------------------------------------------}
procedure TSRVImageScrollCollection.SetItem(Index: Integer;
  const Value: TSRVImageScrollItem);
begin
  inherited SetItem(Index, Value);
end;

{---------------------------  TSRVImagesScroll -----------------------------}
{ Constructor }
constructor TSRVImagesScroll.Create(AOwner: TComponent);
begin
  inherited;
    ControlStyle := ControlStyle + [csOpaque] - [csFramed] + [csReplicatable];

    FCanMoveImages := True;
    FItemWidth := 80;
    FItemHeight := 40;
    FItems := TSRVImageScrollCollection.Create(TSRVImageScrollItem, Self);
    FScrollerPosition := srvpsEnd;
    FMargins := TSRVMargins.Create(Self);
    FMargins.SetMargins(0, 0, 0, 0);
    FHintMargins := TSRVMargins.Create(Self);
    FHintMargins.SetMargins(0, 0, 0, 0);
    FCloseButton := TSRVCloseButton.Create(Self);
    FItemIndex := -1;
    FKind := srvbkHorizontal;
    FSpacings := 10;
    FIndent := 10;
    FRestrictMove := False;
    FSkinManager := nil;
    FSkinSchemeIndex := 0;
    FScrollBarSkinSchemeIndex := 0;
    FItemSkinSchemeIndex := 0;
    FButtonSkinSchemeIndex := 0;
    FCursorInPicture := crJump;
    FSRVHint := nil;
    FImageList := nil;
    inherited DoubleBuffered := False;
    FDoubleBuffered := False;
    FItemColor := clBtnFace;
    FItemDownColor := clInactiveCaption;
    FItemSelectedColor := clHighlight;
    FItemHotColor := clBtnShadow;
    FItemBorderColor := clBtnShadow;
    FItemBorderStyle := psSolid;
//    FTypeHint := srvthMouseMove;
    FTypeHint := srvthBottomPicture;
//    FTypeHint := srvthBottomMouse;
//    FTypeHint := srvthMouseStop;

    // *********************************************
    FScrollBar := TSRVScrollBar.Create(nil);
    FScrollBar.Parent := Self;
    FScrollBar.Kind := sbHorizontal;
    FScrollBar.Height := GetSystemMetrics(SM_CYHSCROLL);
    FScrollBar.Align := alBottom;
    FScrollBar.SmallChange := 1;
    FScrollBar.LargeChange := 10;
    FScrollBar.TabStop := False;
    FScrollBar.OnScroll := HookOnScroll;
    FScrollBar.Enabled := FALSE;
    FScrollBar.Visible := TRUE;

    RScroller := FScrollBar.BoundsRect;
    FScrollItemIndex := 0;
    FScrollOffs := 0;
    IsScrollShow := False;
    LockUpdate := 0;

    FScrollingDelay := 100;
    FocusFrame := 0;

    IsMouseDown := False;
    IsKeyDown := False;
    IsFocus := False;
    IsByse := False;

    FIsCloseMouseDown := -1;
    FIsItemMouseDown := -1;
    FMovingItemIndex := -1;
    FIsMovingItem := False;

    FIsCloseMouseHot := -1;
    FIsItemMouseHot := -1;

    TabStop := True;

    Width := 200;
    Height := FItemHeight + FScrollBar.Height + FMargins.Top + FMargins.Bottom;
end;

{-----------------------------------------------------------------------}
destructor TSRVImagesScroll.Destroy;
begin
    FItems.Destroy;
    FMargins.Destroy;
    FHintMargins.Destroy;
    FCloseButton.Destroy;
    FScrollBar.Free;
  inherited;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.Resize;
begin
  inherited;
    SetHMax(GetMaxScrollPos);
    FScrollBar.Change;
    FScrollBar.Position := FScrollBar.Position;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (AComponent = FImageList) then
    FImageList := nil;

  if (Operation = opRemove) and (AComponent = FSkinManager) then
    FSkinManager := nil;

  if (Operation = opRemove) and (AComponent = FSRVHint) then
    FSRVHint := nil;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetSkinManager(Value : TSRVSkinManager);
begin
  If Value <> FSkinManager then begin
    FScrollBar.SkinManager := Value;
    inherited SetSkinManager(Value);
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetScrollBarSkinSchemeIndex(Value : Integer);
begin
  If FScrollBarSkinSchemeIndex <> Value then begin
    FScrollBarSkinSchemeIndex := Value;
    FScrollBar.SkinSchemeIndex := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemSkinSchemeIndex(Value : Integer);
begin
  If FItemSkinSchemeIndex <> Value then begin
    FItemSkinSchemeIndex := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetButtonSkinSchemeIndex(Value : Integer);
begin
  If FButtonSkinSchemeIndex <> Value then begin
    FButtonSkinSchemeIndex := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetScrollBarHeight: Integer;
begin
  if FKind = srvbkHorizontal then
    Result := FScrollBar.Height
  else
    Result := FScrollBar.Width;
end;

{-----------------------------------------------------------------------}

procedure TSRVImagesScroll.SetScrollBarHeight(Value : Integer);
begin
  if FKind = srvbkHorizontal then begin
    If FScrollBar.Height <> Value then
      FScrollBar.Height := Value;
  end else
    If FScrollBar.Width <> Value then
      FScrollBar.Width := Value;
 Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetSmallChange(Value : Integer);
begin
  FScrollBar.SmallChange := Value;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetLargeChange(Value : Integer);
begin
  FScrollBar.LargeChange := Value;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetSmallChange : Integer;
begin
  Result := FScrollBar.SmallChange;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetLargeChange : Integer;
begin
  Result := FScrollBar.LargeChange;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetDecButtonWidth: Integer;
begin
  Result := FScrollBar.DecButtonWidth;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetIncButtonWidth: Integer;
begin
  Result := FScrollBar.IncButtonWidth;
end;

{-----------------------------------------------------------------------}

procedure TSRVImagesScroll.SetDecButtonWidth(Value : Integer);
begin
  If FScrollBar.DecButtonWidth <> Value then begin
    FScrollBar.DecButtonWidth := Value;
    Repaint;
  end;
end;
{-----------------------------------------------------------------------}

procedure TSRVImagesScroll.SetIncButtonWidth(Value : Integer);
begin
  If FScrollBar.IncButtonWidth <> Value then begin
    FScrollBar.IncButtonWidth := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemWidth(Value : Integer);
begin
  If FItemWidth <> Value then begin
    FScrollOffs := 0;
    CalculateImagesScroll(0);
    FItemWidth := Value;
    Repaint;
  end;

end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemHeight(Value : Integer);
begin
  If FItemHeight <> Value then begin
    FScrollOffs := 0;
    CalculateImagesScroll(0);
    FItemHeight := Value;
    Repaint;
  end;

end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItems(const Value : TSRVImageScrollCollection);
begin
  If Value <> nil then begin
    FItems.Assign(Value);
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetKind(Value : TSRVImageScrollKind);
begin
  FKind := Value;
  if Value = srvbkHorizontal then begin
    FScrollBar.Kind := sbHorizontal;
    if FScrollerPosition = srvpsBegin then
      FScrollBar.Align := alTop
    else
      FScrollBar.Align := alBottom;
    FScrollBar.Height := GetSystemMetrics(SM_CYHSCROLL);
    RScroller := FScrollBar.BoundsRect;
  end else begin
    FScrollBar.Kind := sbVertical;
    if FScrollerPosition = srvpsBegin then
      FScrollBar.Align := alLeft
    else
      FScrollBar.Align := alRight;
    FScrollBar.Width := GetSystemMetrics(SM_CXHSCROLL);
    RScroller := FScrollBar.BoundsRect;
  end;
  CalculateImagesScroll(0);
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.CalculateImagesScroll(FirstItemIndex : Integer);
var
     BI  : TSRVImageScrollItem;
     MaxSB, XPos, YPos, Offs, L, i : Integer;
     R : TRect;
begin
  RScroller := FScrollBar.BoundsRect;

  If FKind = srvbkHorizontal then begin
    L := FItemWidth;
    IsScrollShow := L * GetShowImageScrollCount > ClientWidth;
  end else begin
    L := FItemHeight;
    IsScrollShow := L * GetShowImageScrollCount > ClientHeight;
  end;

  If not IsScrollShow then
    SetRectEmpty(RScroller);

  FirstItemIndex := Max(Min(FirstItemIndex, FItems.Count), 0);

  If FirstItemIndex > 0 then
    if FKind = srvbkHorizontal then
      Offs := TSRVImageScrollItem(FItems.Items[FirstItemIndex-1]).BoundsRect.Right
    else
      Offs := TSRVImageScrollItem(FItems.Items[FirstItemIndex-1]).BoundsRect.Bottom
  else
    Offs := 0;
  Offs := Offs + FIndent;

  R := GetImagesScrollRect;
  XPos := (R.Right + R.Left - FItemWidth) div 2;
  YPos := (R.Bottom + R.Top - FItemHeight) div 2;
  // пересчет позиции ImagesScroll
  If (FItems.Count > 0) then
  for i:=FirstItemIndex to FItems.Count-1 do begin
    BI := TSRVImageScrollItem(FItems.Items[i]);
    If BI.Visible then begin
      if FKind = srvbkHorizontal then begin
        BI.BoundsRect := Bounds(Offs, YPos, FItemWidth, FItemHeight);
        Offs := Offs + FItemWidth + FSpacings;
      end else begin
        BI.BoundsRect := Bounds(XPos, Offs, FItemWidth, FItemHeight);
        Offs := Offs + FItemHeight + FSpacings;
      end;
    end;
  end;

  if FKind = srvbkHorizontal then
    IsScrollShow := Offs >= ClientWidth
  else
    IsScrollShow := Offs >= ClientHeight;

  MaxSB := GetMaxScrollPos;
  If (MaxSB <> FScrollBar.Max) then
    SetHMax(MaxSB);
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetShowImageScrollCount : Integer;
var
     i : Integer;
begin
  Result := 0;
  for i:= 0 to FItems.Count-1 do
    if TSRVImageScrollItem(FItems.Items[i]).Visible then
      Inc(Result);
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetIndent(Value : Integer);
begin
  FIndent := Value;
  CalculateImagesScroll(0);
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetSpacings(Value : Integer);
begin
  FSpacings := Value;
  CalculateImagesScroll(0);
  Repaint;
end;

{------------------------------------------------------------------------------}
function  TSRVImagesScroll.GetScrollBarSchemeIndex : Integer;
begin
  Result := FScrollBar.SkinSchemeIndex;
end;

{------------------------------------------------------------------------------}
procedure TSRVImagesScroll.SetScrollBarSchemeIndex(Value : Integer);
begin
  FScrollBar.SkinSchemeIndex := Value;
  Repaint;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetFirstItemIndex : Integer;
var
     i : Integer;
begin
  Result := -1;
  for i:=0 to FItems.Count-1 do
    If IsItemVisible(i, False) then begin
      Result := i;
      Break;
    end;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetLastItemIndex : Integer;
var
     i : Integer;
begin
  Result := -1;
  for i:= FItems.Count-1 downto 0 do
    If IsItemVisible(i, False) then begin
      Result := i;
      Break;
    end;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.IsItemVisible(ItemIndex : Integer; IsFullVisible : Boolean) : Boolean;
var
     BI  : TSRVImageScrollItem;
     R, tmp : TRect;
begin
  Result := False;
  If (ItemIndex < 0) or (ItemIndex >= FItems.Count) then
    Exit;

  BI := TSRVImageScrollItem(FItems.Items[ItemIndex]);
  if BI.Visible then begin
    R := BI.BoundsRect;
    if FKind = srvbkHorizontal then
      OffsetRect(R, FScrollOffs, 0)
    else
      OffsetRect(R, 0, FScrollOffs);
    Result := IntersectRect(tmp, R, GetImagesScrollRect);
    If IsFullVisible and Result then
      Result := EqualRect(tmp, R);
  end;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetImagesScrollRect : TRect;
begin
  Result := inherited ClientRect;
//  If IsScrollShow then
    If FKind = srvbkHorizontal then
      case FScrollerPosition of
        srvpsBegin: Result.Top := FScrollBar.BoundsRect.Bottom;
        srvpsEnd: Result.Bottom := FScrollBar.BoundsRect.Top;
      end
    else
      case FScrollerPosition of
        srvpsBegin: Result.Left := FScrollBar.BoundsRect.Right;
        srvpsEnd: Result.Right := FScrollBar.BoundsRect.Left;
      end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetScrollerPosition(Value : TSRVScrollerPosition);
begin
  FScrollerPosition := Value;

  if FKind = srvbkHorizontal then
    if FScrollerPosition = srvpsBegin then
      FScrollBar.Align := alTop
    else
      FScrollBar.Align := alBottom
  else if Value = srvpsBegin then
    FScrollBar.Align := alLeft
  else
    FScrollBar.Align := alRight;

  FScrollOffs := 0;
  CalculateImagesScroll(0);
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemIndex(Value : Integer);
begin
  If Value <> FItemIndex then begin
    FItemIndex := Value;
    If Value = -1 then
      FScrollOffs := 0
    else If (Value < 0) or (Value >= FItems.Count) then begin
      FItemIndex := Value;
      ScrollToItem(Value);
    end;

    Repaint;
    If Assigned(FOnChange) then
      OnChange(Self);
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetSRVHint(Value : TSRVHint);
begin
  If Value <> FSRVHint then begin
    FSRVHint := Value;
  end;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetItemRect(ItemIndex : Integer) : TRect;
begin
  Result := Rect(-1, -1, -1, -1);
  If (ItemIndex < 0) or (ItemIndex >= FItems.Count) then
    Exit;

  if TSRVImageScrollItem(FItems.Items[ItemIndex]).Visible then begin
    Result := TSRVImageScrollItem(FItems.Items[ItemIndex]).BoundsRect;
    if FKind = srvbkHorizontal then
      OffsetRect(Result, FScrollOffs, 0)
    else
      OffsetRect(Result, 0, FScrollOffs);
  end;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetCloseAtItemIndex(ItemIndex : Integer) : TRect;
var
     BR : TRect;
     sp, XPos, YPos : Integer;
begin
  SetRectEmpty(Result);
  If (ItemIndex < 0) or (ItemIndex >= FItems.Count) then
    Exit;

  BR := GetItemRect(ItemIndex);

  XPos := 0;
  YPos := 0;
    // XPos
    case FCloseButton.HorizontalAlign of
      srvthaLeft: XPos := BR.Left + FCloseButton.IndentX;
      srvthaCenter: XPos := ((BR.Left + BR.Right - FCloseButton.Width) div 2) + FCloseButton.IndentX;
      srvthaRight: XPos := BR.Right - FCloseButton.IndentX - FCloseButton.Width;
    end;
    // YPos
    case FCloseButton.VerticalAlign of
      srvtvaTop: YPos := BR.Top + FCloseButton.IndentY;
      srvtvaCenter: YPos := ((BR.Top + BR.Bottom - FCloseButton.Height) div 2) + FCloseButton.IndentY;
      srvtvaBottom: YPos := BR.Bottom - FCloseButton.IndentY - FCloseButton.Height;
    end;

  If FSpacings < 0 then sp := FSpacings
  else sp := 0;

  SetRectEmpty(Result);
  If ((XPos < BR.Left) or (XPos + FCloseButton.Width > BR.Right + sp)) and
     (FKind = srvbkHorizontal) and
     (BR.Right - BR.Left + sp > FCloseButton.Width) then
    Result := Bounds((BR.Right + BR.Left + sp - FCloseButton.Width) div 2, YPos,
                     FCloseButton.Width, FCloseButton.Height)
  else If ((YPos < BR.Top) or (YPos + FCloseButton.Height > BR.Bottom + sp)) and
     (FKind = srvbkVertical) and
     (BR.Bottom - BR.Top + sp > FCloseButton.Height) then
    Result := Bounds(XPos, (BR.Bottom + BR.Top + sp - FCloseButton.Height) div 2,
                     FCloseButton.Width, FCloseButton.Height)
  else If ((FKind = srvbkHorizontal) and
           (BR.Right - BR.Left + sp > FCloseButton.Width)) or
          ((FKind = srvbkVertical) and
           (BR.Bottom - BR.Top + sp > FCloseButton.Height)) then
    IntersectRect(Result, BR, Bounds(XPos, YPos, FCloseButton.Width, FCloseButton.Height));
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.GetItemIndexAtPos(X, Y : Integer) : Integer;
var
     BI  : TSRVImageScrollItem;
     R : TRect;
     i : Integer;
begin
  Result := -1;
  for i:= 0 to FItems.Count-1 do begin
    BI := TSRVImageScrollItem(FItems.Items[i]);
    if BI.Visible then begin
      R := BI.BoundsRect;
      if FKind = srvbkHorizontal then
        OffsetRect(R, FScrollOffs, 0)
      else
        OffsetRect(R, 0, FScrollOffs);
      If PtInRect(R, Point(X, Y)) then begin
        Result := i;
        Break;
      end;
    end;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.ScrollToItem(ItemIndex : Integer);
var
     R : TRect;
begin
  If (FItems.Count = 0) then
    Exit;
  ItemIndex := Max(Min(ItemIndex, FItems.Count-1), 0);

  If TSRVImageScrollItem(FItems.Items[ItemIndex]).Visible and
     not IsItemVisible(ItemIndex, True) then begin
    R := TSRVImageScrollItem(FItems.Items[ItemIndex]).BoundsRect;

    if FKind = srvbkHorizontal then
      If R.Left + FScrollOffs < 0 then
        FScrollOffs := GetImagesScrollRect.Left - R.Left
      else
        FScrollOffs := Max(GetImagesScrollRect.Right - R.Right, GetImagesScrollRect.Left - R.Left)
    else
      If R.Top + FScrollOffs < 0 then
        FScrollOffs := GetImagesScrollRect.Top - R.Top
      else
        FScrollOffs := Max(GetImagesScrollRect.Bottom - R.Bottom, GetImagesScrollRect.Top - R.Top)
  end;

  Repaint;
end;

{-----------------------------------------------------------------------}
function  TSRVImagesScroll.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean;
var
     ImageScrollOffs : Integer;
begin
  Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);

  ImageScrollOffs := 0;
  If WheelDelta > 0 then
    ImageScrollOffs := FirstItemIndex - 1
  else If WheelDelta < 0 then
    ImageScrollOffs := LastItemIndex + 1;
  If ImageScrollOffs <> 0 then
    ScrollToItem(ImageScrollOffs);
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetMargins(const Value : TSRVMargins);
begin
  If Value <> nil then begin
    FMargins.Assign(Value);
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetHintMargins(const Value : TSRVMargins);
begin
  If Value <> nil then begin
    FHintMargins.Assign(Value);
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetCloseButton(const Value : TSRVCloseButton);
begin
  If Value <> nil then begin
    FCloseButton.Assign(Value);
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}

procedure TSRVImagesScroll.WMTimer(var Message: TMessage);
var
     ImageScrollOffs : Integer;
begin
  If IsByse then
    Exit;

  IsByse := True;
  ImageScrollOffs := 0;

  If IsKeyDown and (Message.WParam = 3) then begin
    If (kdCharCode = VK_LEFT) or (kdCharCode = VK_UP) then
      ImageScrollOffs := FirstItemIndex - 1
    Else If (kdCharCode = VK_RIGHT) or (kdCharCode = VK_DOWN) then
      ImageScrollOffs := LastItemIndex + 1
    Else If (kdCharCode = VK_HOME) then
      ImageScrollOffs := 0
    Else If (kdCharCode = VK_END) then
      ImageScrollOffs := FItems.Count-1;
    ScrollToItem(ImageScrollOffs);
  end else If not IsMouseDown and not IsKeyDown and IsFocus and (Message.WParam = 1) then begin
//    Repaint;
//    FocusFrame := (FocusFrame + 1) mod 2;
  end;
  IsByse := False;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.WMKeyDown(var Message: TWMKey);
begin
  inherited;

  IsKeyDown := True;

  kdCharCode := Message.CharCode;
  if (FScrollingDelay <> 0) and Visible then
    if SetTimer(WindowHandle, 3, FScrollingDelay, nil) = 0 then
      raise EOutOfResources.Create('Out of resource for installing timer');
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.WMKeyUp(var Message: TWMKey);
begin
  inherited;

  IsKeyDown := False;
  KillTimer(WindowHandle, 3);
  If TabStop and Visible and not IsFocus then
    SetFocus;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.WMMouseDown(var Message: TWMMouse);
var
     InRect : Boolean;
     p : TPoint;
     L : Integer;
begin
  inherited;

    If TabStop and Visible and not Focused then
      SetFocus;

    FIsCloseMouseDown := -1;
    FIsItemMouseDown := -1;
    IsMouseDown := True;
    FMovingItemIndex := -1;
    FIsMovingItem := False;
    p := Point(Message.XPos, Message.YPos);
    L := GetItemIndexAtPos(p.x, p.y);

    If (Message.Keys and MK_RBUTTON) <> 0 then begin
      if Assigned(FSRVHint) then
        FSRVHint.HideHint;
      FIsItemMouseDown := L;
      if Assigned(PopupMenu) then begin
        PopupMenu.PopupComponent := Self;
        PopupMenu.Popup(p.x, p.y);
      end;
      Repaint;
      Exit;
    end;

    InRect := IsScrollShow and PtInRect(RScroller, p);
    If InRect and ParentSRV then begin
      // in scrollbar
      FScrollBar.MouseOffX_ := FScrollBar.Left + Round((ScreenOffX - FScrollBar.ClientToScreen(Point(0, 0)).x) / ScaleX);
      FScrollBar.MouseOffY_ := FScrollBar.Top + Round((ScreenOffY - FScrollBar.ClientToScreen(Point(0, 0)).y) / ScaleY);
      Message.XPos := p.x - FScrollBar.Left;
      Message.YPos := p.y - FScrollBar.Top;
      with TMessage(Message) do
        PostMessage(FScrollBar.Handle, Msg, WParam, LParam);
      Repaint;
      Exit;
    end else begin
      If FCloseButton.Visible and (L <> -1) and PtInRect(GetCloseAtItemIndex(L), p) and
         ((FCloseButton.Visibility <> srvcbvActive) or
          (FCloseButton.Visibility = srvcbvActive) and (L = ItemIndex)) and
          (FCloseButton.AllowCloseLastTab or
           (not FCloseButton.AllowCloseLastTab and (FItems.Count > 1)))  then
        FIsCloseMouseDown := L
      else
        FIsCloseMouseDown := -1;
      FIsCloseMouseHot := FIsCloseMouseDown;

      if (L <> -1) and (FIsCloseMouseDown = -1) then  begin
        If FCanMoveImages then begin
          FMovingItemIndex := L;
          If FKind = srvbkHorizontal then
            dPosItemMoving := p.x - TSRVImageScrollItem(FItems.Items[FMovingItemIndex]).BoundsRect.Left - FScrollOffs
          else
            dPosItemMoving := p.y - TSRVImageScrollItem(FItems.Items[FMovingItemIndex]).BoundsRect.Top - FScrollOffs;
        end;

        if (ItemIndex <> L) then begin
          FIsItemMouseDown := L;
          ItemIndex := L;

          If Assigned(OnClick) then
            OnClick(Self);
        end;
      end;
    end;

  SetCapture(Handle);
  Repaint;

  if (FScrollingDelay <> 0) and Visible then
    if SetTimer(WindowHandle, 2, FScrollingDelay, nil) = 0 then
      raise EOutOfResources.Create('Out of resource for installing timer');
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.WMMouseUp(var Message: TWMMouse);
var
     IsCanClose : Boolean;
begin
    If (Message.Keys and MK_RBUTTON) = 0 then begin

    KillTimer(WindowHandle, 2);
    ReleaseCapture();

    If (FCloseButton.Visible and (FIsCloseMouseDown <> -1) and
       (FIsCloseMouseDown = FIsCloseMouseHot)) and
       (FCloseButton.AllowCloseLastTab or
        (not FCloseButton.AllowCloseLastTab and (FItems.Count > 1))) then begin

      IsCanClose := True;
      If Assigned(FOnCloseImageScroll) then
        FOnCloseImageScroll(Self, FIsCloseMouseDown, IsCanClose);

      If IsCanClose then begin
        FItems[FIsCloseMouseDown].Free;
        CalculateImagesScroll(FIsCloseMouseDown);

        If (GetLastItemIndex = FItems.Count-1) and
           ((GetFirstItemIndex > 0) or not IsItemVisible(0, True)) then
          if ((FKind = srvbkHorizontal) and
              (GetItemRect(GetLastItemIndex).Right + FItemWidth <= GetImagesScrollRect.Right)) or
             ((FKind = srvbkVertical) and
              (GetItemRect(GetLastItemIndex).Bottom + FItemHeight <= GetImagesScrollRect.Bottom)) then begin
          FScrollOffs := 0;
          ScrollToItem(FItems.Count-1);
        end;

        If FIsCloseMouseDown = ItemIndex then
          ItemIndex := Min(FIsCloseMouseDown, FItems.Count - 1);
      end;
    end;

    end;

  inherited;

    IsMouseDown := False;
    FIsCloseMouseDown := -1;
    FIsItemMouseDown := -1;
    FMovingItemIndex := -1;
    FIsMovingItem := False;

    Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.WMMouseMove(var Message: TWMMouseMove);
var
     InRect : Boolean;
     p : TPoint;
     ARect, R1, R2 : TRect;
     MouseOffX_, MouseOffY_ : Integer;

  // ищем TabIndex на которую перетаскивает текущая вкладка (горизонтальная)
  procedure MoveImageH;
  var
       i : Integer;
       tmp : TSRVImageScrollItem;
  begin
    If (R1.Left < R2.Left) then begin
      for i:= GetFirstItemIndex to Min(GetLastItemIndex, FMovingItemIndex-1) do
        If (i <> FMovingItemIndex) and IsItemVisible(i, False) and
           (((GetItemRect(i).Left + GetItemRect(i).Right) div 2) >= R1.Left) then begin
          tmp := FItems.Items[FMovingItemIndex];
          TSRVImageScrollItem(FItems.Insert(i)).Assign(tmp);
          FItems[FMovingItemIndex + 1].Free;
          CalculateImagesScroll(0);
          If Assigned(FOnImageScrollMove) then
            FOnImageScrollMove(Self, i, FMovingItemIndex);
          FMovingItemIndex := i;
          FItemIndex := FMovingItemIndex;
          Break;
        end;
    end else If (R1.Left > R2.Left) then begin
      for i:= Max(GetFirstItemIndex, FMovingItemIndex+1) to GetLastItemIndex do
        If (i <> FMovingItemIndex) and IsItemVisible(i, False) and
           (((GetItemRect(i).Left + GetItemRect(i).Right) div 2) <= R1.Right) then begin
          tmp := FItems.Items[MovingItemIndex];
          TSRVImageScrollItem(FItems.Insert(i+1)).Assign(tmp);
          FItems[FMovingItemIndex].Free;
          CalculateImagesScroll(0);
          If Assigned(FOnImageScrollMove) then
            FOnImageScrollMove(Self, i, FMovingItemIndex);
          FMovingItemIndex := i;
          FItemIndex := FMovingItemIndex;
          Break;
        end;
    end;
  end;

  // ищем ImageIndex на которую перетаскивает текущая вкладка (вертикальная)
  procedure MoveImageV;
  var
       i : Integer;
       tmp : TSRVImageScrollItem;
  begin
    If (R1.Top < R2.Top) then begin
      for i:= GetFirstItemIndex to Min(GetLastItemIndex, FMovingItemIndex-1) do
        If (i <> FMovingItemIndex) and IsItemVisible(i, False) and
           (((GetItemRect(i).Top + GetItemRect(i).Bottom) div 2) >= R1.Top) then begin
          tmp := FItems.Items[FMovingItemIndex];
          TSRVImageScrollItem(FItems.Insert(i)).Assign(tmp);
          FItems[FMovingItemIndex + 1].Free;
          CalculateImagesScroll(0);
          If Assigned(FOnImageScrollMove) then
            FOnImageScrollMove(Self, i, FMovingItemIndex);
          FMovingItemIndex := i;
          FItemIndex := FMovingItemIndex;
          Break;
        end;
    end else If (R1.Top > R2.Top) then begin
      for i:= Max(GetFirstItemIndex, FMovingItemIndex+1) to GetLastItemIndex do
        If (i <> FMovingItemIndex) and IsItemVisible(i, False) and
           (((GetItemRect(i).Top + GetItemRect(i).Bottom) div 2) <= R1.Bottom) then begin
          tmp := FItems.Items[MovingItemIndex];
          TSRVImageScrollItem(FItems.Insert(i+1)).Assign(tmp);
          FItems[FMovingItemIndex].Free;
          CalculateImagesScroll(0);
          If Assigned(FOnImageScrollMove) then
            FOnImageScrollMove(Self, i, FMovingItemIndex);
          FMovingItemIndex := i;
          FItemIndex := FMovingItemIndex;
          Break;
        end;
    end;
  end;

begin
  inherited;

    if (FIsItemMouseDown >= FItems.Count) or
       (FIsCloseMouseDown >= FItems.Count) or
       (FMovingItemIndex >= FItems.Count) then begin
      IsMouseDown := False;
      FIsCloseMouseDown := -1;
      FIsItemMouseDown := -1;
      FMovingItemIndex := -1;
      FIsMovingItem := False;
    end;

    p := Point(Message.XPos, Message.YPos);
    If ParentSRV and (GetCapture() = Handle) then begin
      MouseOffX_ := Round((ScreenOffX - ClientToScreen(Point(0, 0)).x) / ScaleX);
      MouseOffY_ := Round((ScreenOffY - ClientToScreen(Point(0, 0)).y) / ScaleY);
      p.x := Round(p.x / ScaleX) - MouseOffX_;
      p.y := Round(p.y / ScaleY) - MouseOffY_;
    end;

    If IsMouseDown and FCanMoveImages and (FMovingItemIndex >= 0) then begin
      FIsMovingItem := True;
      R1 := TSRVImageScrollItem(FItems.Items[FMovingItemIndex]).BoundsRect;
      if (FKind = srvbkHorizontal) then
        OffsetRect(R1, FScrollOffs, 0)
      else
        OffsetRect(R1, 0, FScrollOffs);
      R2 := R1;
      if (FKind = srvbkHorizontal) then begin
        OffsetRect(R1, -R1.Left, 0);
        If RestrictMove then begin
          OffsetRect(R1, Max(p.x - dPosItemMoving, GetImagesScrollRect.Left), 0);
          If R1.Right > GetImagesScrollRect.Right then
            OffsetRect(R1, GetImagesScrollRect.Right - R1.Right, 0);
        end else
          OffsetRect(R1, p.x - dPosItemMoving, 0);
        MoveImageH;
      end else begin
        OffsetRect(R1, 0, -R1.Top);
        If RestrictMove then begin
          OffsetRect(R1, 0, Max(p.y - dPosItemMoving, GetImagesScrollRect.Top));
          If R1.Bottom > GetImagesScrollRect.Bottom then
            OffsetRect(R1, 0, GetImagesScrollRect.Bottom - R1.Bottom);
        end else
          OffsetRect(R1, 0, p.y - dPosItemMoving);
        MoveImageV;
      end;

      if (FKind = srvbkHorizontal) then
        OffsetRect(R1, -FScrollOffs, 0)
      else
        OffsetRect(R1, 0, -FScrollOffs);
      TSRVImageScrollItem(FItems.Items[MovingItemIndex]).BoundsRect := R1;
      Repaint;
      Exit;
    end;

    FIsCloseMouseHot := -1;
    FIsItemMouseHot := -1;

    InRect := IsScrollShow and PtInRect(RScroller, p);
    If InRect and ParentSRV then begin
      // in scrollbar
      FScrollBar.MouseOffX_ := FScrollBar.Left + Round((ScreenOffX - FScrollBar.ClientToScreen(Point(0, 0)).x) / ScaleX);
      FScrollBar.MouseOffY_ := FScrollBar.Top + Round((ScreenOffY - FScrollBar.ClientToScreen(Point(0, 0)).y) / ScaleY);
      Message.XPos := p.x - FScrollBar.Left;
      Message.YPos := p.y - FScrollBar.Top;
      with TMessage(Message) do
        PostMessage(FScrollBar.Handle, Msg, WParam, LParam);
      Repaint;
      Exit;
    end else begin
      If not IsByse and ParentSRV and FScrollBar.InMouse then begin
        IsByse := True;
        with Message do
          SendMessage(FScrollBar.Handle, CM_MOUSELEAVE, 0, 0);
        IsByse := False;
      end;

      FIsItemMouseHot := GetItemIndexAtPos(p.x, p.y);
      If (FIsItemMouseHot <> -1) and PtInRect(GetCloseAtItemIndex(FIsItemMouseHot), p) then
        FIsCloseMouseHot := FIsItemMouseHot
      else
        FIsCloseMouseHot := -1;

      If (FIsCloseMouseHot = -1) and (FIsItemMouseHot >= 0) and
         Assigned(FSRVHint) and
         TSRVImageScrollItem(FItems.Items[FIsItemMouseHot]).ShowHint then begin
        p := ClientToScreen(p);
        If (FTypeHint = srvthMouseMove) then begin
          FSRVHint.FromMouseDeltaX := 0;
          FSRVHint.FromMouseDeltaY := 0;
          FSRVHint.HintLeft := p.X;
          FSRVHint.HintTop := p.Y;
          FSRVHint.ShowInMousePos := True;
        end;

        If (FSRVHint.Tag <> FIsItemMouseHot) then begin

        FSRVHint.Tag := FIsItemMouseHot;
        FSRVHint.Caption := 'Банер №' + Inttostr(FIsItemMouseHot+1);
{        FSRVHint.RichView1.Clear;
  If FIsItemMouseHot = 0 then begin
  FSRVHint.RichView1.AddNL('Some text styles can be chosen as hypertext styles. ',0,0);
  FSRVHint.RichView1.AddNLTag('Like this one.',4,-1, 100);
  FSRVHint.RichView1.AddNL(' You can have as many hypertext styles as you want.  ',0,-1);
  FSRVHint.RichView1.AddNLTag('Here is one more.',5,-1,  200);
  FSRVHint.RichView1.AddNL('Images from Image Lists also can be hypertext: ',0,0);
  FSRVHint.RichView1.AddHotspotExTag('Pen Image', 0,1, FSRVHint.ImageList1, -1, 300);
  FSRVHint.RichView1.AddNL(' Such images are called "hotspots".',0,-1);
  end;

        FSRVHint.lblCaption.Caption := 'Банер №' + Inttostr(FIsItemMouseHot+1);
        FSRVHint.RichView1.Add(TSRVImageScrollItem(FItems.Items[FIsItemMouseHot]).Hint, 0);
//        FSRVHint.RichView1.LoadRVF('readme.rvf');
//        FSRVHint.RichView1.AddNL('Type a word and press Ctrl+Space for suggestions',0,0);
        FSRVHint.RichView1.Format;}

        FSRVHint.Text := TSRVImageScrollItem(FItems.Items[FIsItemMouseHot]).Hint;

        ARect := GetItemRect(FIsItemMouseHot);
        with ClientToScreen(Point(0,0)) do
          OffsetRect(ARect, x, y);

        case FTypeHint of
          srvthBottomMouse:
            begin
              FSRVHint.FromMouseDeltaX := 0;
              FSRVHint.FromMouseDeltaY := 22;
              FSRVHint.ShowInMousePos := True;
            end;
          srvthMouseStop:
            begin
              FSRVHint.FromMouseDeltaX := 0;
              FSRVHint.FromMouseDeltaY := 0;
              FSRVHint.ShowInMousePos := True;
            end;
          srvthBottomPicture:
            begin
              FSRVHint.HintLeft := Max(ARect.Left, Max(ClientToScreen(Point(0, 0)).X, 0));
              FSRVHint.HintTop := ARect.Bottom;
              FSRVHint.ShowInMousePos := False;
            end;
        end;

{$IFDEF RICHVIEWDEF6}
        FSRVHint.HintLeft := Min(FSRVHint.HintLeft, Screen.WorkAreaRect.Right - FSRVHint.Width);
        FSRVHint.HintTop := Min(FSRVHint.HintTop, Screen.WorkAreaRect.Bottom - FSRVHint.Height);
{$ELSE}
        FSRVHint.HintLeft := Min(FSRVHint.HintLeft, Screen.DesktopLeft + Screen.DesktopWidth - FSRVHint.Width);
        FSRVHint.HintTop := Min(FSRVHint.HintTop, Screen.DesktopTop + Screen.DesktopHeight - FSRVHint.Height);
{$ENDIF}
        FSRVHint.HintBounds := ARect;
        FSRVHint.ShowHint;
        end;
      end else if Assigned(FSRVHint) then begin
        FSRVHint.HideHint;
        FSRVHint.Tag := -1;
      end;
    end;

    If (FIsItemMouseHot >= 0) and (FIsCloseMouseHot = -1) then
      Cursor := FCursorInPicture
    else
      Cursor := crDefault;

    Repaint;
  inherited;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.CMMouseEnter(var Message: TMessage);
begin
    FIsItemMouseHot := -1;
    FInMouse := True;

    if Assigned(FSRVHint) and not FSRVHint.InMouse then begin
      FSRVHint.HideHintWithDelay(FSRVHint.CloseDelay);
      FSRVHint.Tag := -1;
    end;

    Repaint;
  inherited;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.CMMouseLeave(var Message: TMessage);
begin
  If IsByse and ParentSRV then
    Exit;

  inherited;

  If not IsByse and ParentSRV and FScrollBar.InMouse then begin
    IsByse := True;
    with Message do
      SendMessage(FScrollBar.Handle, CM_MOUSELEAVE, 0, 0);
    IsByse := False;
  end;

  FInMouse := False;
  if Assigned(FSRVHint) then begin
    FSRVHint.HideHint;
    FSRVHint.Tag := -1;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.Paint;
var
     i : Integer;
     b : TBitmap;
     ACanvas : TCanvas;
begin
  if LockUpdate <> 0 then
    exit;

  BeginUpdate;
  If not IsMouseDown or not FCanMoveImages or (FMovingItemIndex = -1) then
    CalculateImagesScroll(0);

  If FDoubleBuffered then begin
    b := TBitmap.Create;
    if ParentSRV then begin
      b.Width := Width;
      b.Height := Height;
    end else begin
      b.Width := ClientWidth;
      b.Height := ClientHeight;
    end;
    ACanvas := b.Canvas;
  end else begin
    ACanvas := Canvas;
    b := nil;
  end;

  DrawBG(ACanvas, ClientRect);
  for i:= GetFirstItemIndex to GetLastItemIndex do
    If i <> ItemIndex then
      DrawImageScrollItem(ACanvas, i, ClientRect);
  DrawImageScrollItem(ACanvas, ItemIndex, ClientRect);

  DrawBorder(ACanvas, ClientRect);

  FScrollBar.ParentSRV := ParentSRV;
  FScrollBar.Printing := Printing;
  FScrollBar.ScaleX := ScaleX;
  FScrollBar.ScaleY := ScaleY;
  FScrollBar.ScreenOffX := ScreenOffX;
  FScrollBar.ScreenOffY := ScreenOffY;
  FScrollBar.CanvasOffX := CanvasOffX + FScrollBar.Left;
  FScrollBar.CanvasOffY := CanvasOffY + FScrollBar.Top;

  If FDoubleBuffered then begin
    Canvas.Lock;
    with GetImagesScrollRect do
      Canvas.Draw(Left, Top, b);
    Canvas.Unlock;
    b.Free;
  end;

  LockUpdate := LockUpdate - 1;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.DrawBG(ACanvas : TCanvas; ARect : TRect);
var
     DoDefault : Boolean;
begin
  DoDefault := True;
  If Assigned(FOnDrawBackground) then
    FOnDrawBackground(Self, ACanvas, ClientRect, ARect,
      GetState(IsFocus, IsMouseDown, IsFocus, Enabled), DoDefault);

  If not DoDefault then
    Exit;

  DrawBoxBG(ACanvas, ClientRect, FSkinManager, SkinSchemeIndex, FKind = srvbkHorizontal,
    FInMouse, IsMouseDown, Enabled, IsFocus, FocusFrame, Color);
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.DrawBorder(ACanvas : TCanvas; ARect : TRect);
var
     DoDefault : Boolean;
begin
  DoDefault := True;
  If Assigned(FOnDrawBorder) then
    FOnDrawBorder(Self, ACanvas, ClientRect, ARect,
      GetState(IsFocus, IsMouseDown, IsFocus, Enabled), DoDefault);

  If not DoDefault then
    Exit;

 DrawBoxBorder(ACanvas, ClientRect, FSkinManager, SkinSchemeIndex, FKind = srvbkHorizontal,
   FInMouse, IsMouseDown, Enabled, IsFocus, FocusFrame);
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.DrawImageScrollItem(ACanvas : TCanvas; ItemIndex : Integer; ARect : TRect);
var
     BI : TSRVImageScrollItem;
     R, RI : TRect;
     DoDefault, isDrawSkin, isFlag, isDown : Boolean;
     W, H, ImageIndex : Integer;
     scaleW, scaleH : Single;
begin
  If (ItemIndex < 0) or (ItemIndex >= FItems.Count) then
    Exit;

  BI := FItems[ItemIndex];
  R := BI.BoundsRect;
  if FKind = srvbkHorizontal then
    OffsetRect(R, FScrollOffs, 0)
  else
    OffsetRect(R, 0, FScrollOffs);

  DoDefault := True;
  isFlag := not IsMouseDown and (ItemIndex = FIsItemMouseHot);
  isDown := (ItemIndex = Self.ItemIndex) or (ItemIndex = FIsItemMouseDown);
  If Assigned(FOnDrawImageScroll) then
    FOnDrawImageScroll(Self, ACanvas, R, ARect, ItemIndex,
      GetState(isFlag, isDown, IsFocus, Enabled and BI.Enabled), DoDefault);

  If not DoDefault then begin
    DrawCloseButton(ACanvas, ItemIndex, ARect);
    Exit;
  end;

  isDrawSkin :=
    DrawBoxBG(ACanvas, R, FSkinManager, BI.SkinSchemeIndex, FKind = srvbkHorizontal,
      isFlag, isDown, Enabled and BI.Enabled, IsFocus, FocusFrame, clBtnFace);

  If not isDrawSkin then begin
    ACanvas.Brush.Color := FItemColor;
    if FIsItemMouseDown = ItemIndex then
      ACanvas.Brush.Color := FItemDownColor
    else If FItemIndex = ItemIndex then
      ACanvas.Brush.Color := FItemSelectedColor
    else If not IsMouseDown and (FIsItemMouseHot = ItemIndex) then
      ACanvas.Brush.Color := FItemHotColor;

    If ACanvas.Brush.Color <> clNone then begin
      ACanvas.Pen.Color := ACanvas.Brush.Color;
      ACanvas.Pen.Style := psSolid;
      ACanvas.Brush.Style := bsSolid;
      ACanvas.FillRect(R);
    end;

    // draw image
    If Assigned(ImageList) then begin
      If isFlag and (BI.FSelectImageIndex > -1) then
        ImageIndex := BI.FSelectImageIndex
      else
        ImageIndex := BI.FImageIndex;

      If ImageIndex > -1 then begin
        W := R.Right - R.Left;
        H := R.Bottom - R.Top;
        scaleW := W / ImageList.Width;
        scaleH := H / ImageList.Height;
        If (scaleW < scaleH) then
          RI := Bounds(R.Left, R.Top + Round(H - ImageList.Height * scaleW) div 2, W, Round(ImageList.Height * scaleW))
        else
          RI := Bounds(R.Left + Round(W - ImageList.Width * scaleH) div 2, R.Top, Round(ImageList.Width * scaleH), H);
        ImageList.Draw(ACanvas, RI.Left, RI.Top, ImageIndex);
      end;
    end;

    // bounds
    ACanvas.Pen.Color := FItemBorderColor;
    ACanvas.Pen.Style := FItemBorderStyle;
    If FItemBorderColor <> clNone then
    if (FItemIndex = ItemIndex) then begin
      ACanvas.Brush.Style := bsClear;
      with R do
        ACanvas.Rectangle(Left + 3, Top + 2, Right - 3, Bottom - 2);
    end else begin
      ACanvas.Brush.Style := bsClear;
      with R do
        ACanvas.Rectangle(Left, Top, Right, Bottom);
{      if FKind = srvbkHorizontal then begin
        If ItemIndex > 0 then begin
          ACanvas.MoveTo(R.Left, R.Top);
          ACanvas.LineTo(R.Left, R.Bottom);
        end;
        If ItemIndex = FItems.Count-1 then begin
          ACanvas.MoveTo(R.Right-1 + (Spacings div 2), R.Top);
          ACanvas.LineTo(R.Right-1 + (Spacings div 2), R.Bottom);
        end;
      end else begin
        If ItemIndex > 0 then begin
          ACanvas.MoveTo(R.Left, R.Top);
          ACanvas.LineTo(R.Right, R.Top);
        end;
        If ItemIndex = FItems.Count-1 then begin
          ACanvas.MoveTo(R.Left, R.Bottom-1 + (Spacings div 2));
          ACanvas.LineTo(R.Right, R.Bottom-1 + (Spacings div 2));
        end;
      end;}
    end;
  end;

  DrawCloseButton(ACanvas, ItemIndex, ARect);

  DrawBoxBorder(ACanvas, R, FSkinManager, BI.SkinSchemeIndex, FKind = srvbkHorizontal,
    isFlag, isDown, Enabled and BI.Enabled, IsFocus, FocusFrame);
end;

procedure DrawButton(ACanvas : TCanvas; R : TRect; IsDown : Boolean);
begin
    ACanvas.Brush.Style := bsClear;
    ACanvas.Pen.Style := psSolid;

    if IsDown then
      ACanvas.Pen.Color := clBtnShadow
    else
      ACanvas.Pen.Color := clBtnHighlight;
    with R do
      ACanvas.Rectangle(Left, Top, Right, Bottom);

    if IsDown then
      ACanvas.Pen.Color := clBtnHighlight
    else
      ACanvas.Pen.Color := clBtnShadow;
    with R do
      ACanvas.Rectangle(Left+1, Top+1, Right, Bottom);

    ACanvas.Brush.Style := bsSolid;
    ACanvas.Pen.Style := psClear;
    ACanvas.Brush.Color := clBtnFace;
    if IsDown then
      ACanvas.Brush.Color := clScrollBar;

    with R do
      ACanvas.Rectangle(Left+1, Top+1, Right-1, Bottom-1);
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.DrawCloseButton(ACanvas : TCanvas; ItemIndex : Integer; ARect : TRect);
var
     R : TRect;
     DoDefault, isDrawSkin, isFlag, isDown : Boolean;
begin
  If not FCloseButton.Visible or
     (ItemIndex < 0) or (ItemIndex >= FItems.Count) then
    Exit;
  If ((FCloseButton.Visibility = srvcbvHot) and (ItemIndex <> FIsCloseMouseHot) and
      (ItemIndex <> FIsCloseMouseDown) and (ItemIndex <> FIsItemMouseHot)) or
     ((FCloseButton.Visibility = srvcbvActive) and (ItemIndex<> Self.ItemIndex)) or
     (not FCloseButton.AllowCloseLastTab and (FItems.Count = 1)) then
    Exit;

  R := GetCloseAtItemIndex(ItemIndex);
  if IsRectEmpty(R) then
    Exit;

  DoDefault := True;
  isFlag := not IsMouseDown and (ItemIndex = FIsCloseMouseHot);
  isDown := IsMouseDown and (ItemIndex = FIsCloseMouseDown) and (ItemIndex = FIsCloseMouseHot);
  If Assigned(FOnDrawCloseButton) then
    FOnDrawCloseButton(Self, ACanvas, R, ARect, ItemIndex,
      GetState(isFlag, isDown, IsFocus, Enabled and FItems[ItemIndex].Enabled), DoDefault);

  If not DoDefault then
    Exit;

  isDrawSkin :=
    DrawBoxBG(ACanvas, R, FSkinManager, FButtonSkinSchemeIndex, FKind = srvbkHorizontal,
      isFlag, isDown, Enabled and FItems[ItemIndex].Enabled, IsFocus, FocusFrame, clBtnShadow);

  If not isDrawSkin then begin
    DrawButton(ACanvas, R, ItemIndex = FIsCloseMouseDown);

    ACanvas.Pen.Style := psSolid;
    ACanvas.Pen.Width := 2;
    ACanvas.Pen.Color := clBlack;

    ACanvas.MoveTo(R.Left+2, R.Top+2);
    ACanvas.LineTo(R.Right-4, R.Bottom-4);

    ACanvas.MoveTo(R.Right-4, R.Top+2);
    ACanvas.LineTo(R.Left+2, R.Bottom-4);

    ACanvas.Pen.Width := 1;
  end;

  DrawBoxBorder(ACanvas, R, FSkinManager, FButtonSkinSchemeIndex, FKind = srvbkHorizontal,
      isFlag, isDown, Enabled and FItems[ItemIndex].Enabled, IsFocus, FocusFrame);
end;

{------------------------------------------------------------------------------}
procedure TSRVImagesScroll.SetHMax(Value: Integer);
begin
  FScrollBar.PageSize := 0;
  FScrollBar.Max := Value;
  if FKind = srvbkHorizontal then
    FScrollBar.PageSize := Min(ClientWidth, Value)
  else
    FScrollBar.PageSize := Min(ClientHeight, Value);
end;

{------------------------------------------------------------------------------}
function TSRVImagesScroll.GetMaxScrollPos: Integer;
var
     isEnable : Boolean;
begin
  if FKind = srvbkHorizontal then begin
    Result := FIndent + (FItemWidth + FSpacings) * GetShowImageScrollCount;
    Result := Math.Max(Result - 1, 0);
    IsEnable := ClientWidth < Result;
    If ClientWidth >= Result Then begin
      SetHMax(0);
      Result := 0;
    end;
  end else begin
    Result := FIndent + (FItemHeight + FSpacings) * GetShowImageScrollCount;
    Result := Math.Max(Result - 1, 0);
    IsEnable := ClientHeight < Result;
    If ClientHeight >= Result Then begin
      SetHMax(0);
      Result := 0;
    end;
  end;
  FScrollBar.Enabled := isEnable;
end;

{------------------------------------------------------------------------------}
procedure TSRVImagesScroll.HookOnScroll(Sender: TObject; ScrollCode: TScrollCode;
  var ScrollPos: Integer);
begin
  FScrollOffs := -ScrollPos;
  Repaint;
end;

{-----------------------------------------------------------------------}
function TSRVImagesScroll.GetClientWidth: Integer;
begin
  with GetImagesScrollRect do
    Result := Right - Left;
end;

{-----------------------------------------------------------------------}
function TSRVImagesScroll.GetClientHeight: Integer;
begin
  with GetImagesScrollRect do
    Result := Bottom - Top;
end;

{-----------------------------------------------------------------------}
function TSRVImagesScroll.GetClientRect: TRect;
begin
  Result := GetImagesScrollRect;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.BeginUpdate;
begin
  LockUpdate := LockUpdate + 1;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.EndUpdate;
begin
  LockUpdate := LockUpdate - 1;
  if LockUpdate = 0 then
    Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.WMRepaintControl(var Message: TMessage);
begin
  If ParentSRV then begin
    if Parent <> nil then
      PostMessage(Parent.Handle, WM_REPAINT_CONTROL, 0, 0);
  end else
    Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.Invalidate;
begin
  If ParentSRV and (Parent <> nil) then
    Paint
  else
    inherited;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetImageList(const Value : TCustomImageList);
begin
  If FImageList <> Value then begin
    FImageList := Value;
    Repaint;
  end;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetDoubleBuffered(Value: Boolean);
begin
  FDoubleBuffered := Value;
  FScrollBar.DoubleBuffered := Value;
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.WMEraseBkgnd(var Message: TWMPaint);
begin
  Message.Result := 1;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemColor(const Value: TColor);
begin
  FItemColor := Value;
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemDownColor(const Value: TColor);
begin
  FItemDownColor := Value;
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemSelectedColor(const Value: TColor);
begin
  FItemSelectedColor := Value;
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemHotColor(const Value: TColor);
begin
  FItemHotColor := Value;
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemBorderColor(const Value: TColor);
begin
  FItemBorderColor := Value;
  Repaint;
end;

{-----------------------------------------------------------------------}
procedure TSRVImagesScroll.SetItemBorderStyle(const Value: TPenStyle);
begin
  FItemBorderStyle := Value;
  Repaint;
end;

{-----------------------------------------------------------------------}

end.
