zoukankan      html  css  js  c++  java
  • TAQSkinScrollBar 类美化滚动条再讨论

    再说:TAQSkinScrollBar 类美化滚动条,http://www.138soft.com/?p=156  里面有人提到不可以滚动

    滚动的改善方法:

    unit AQSkinScrollBar;
    (*
     说明:本单元提取自TdsaSkinAdapter控件,版权归原作者所有。
    
     提取:www.138soft.com
    
    *)
    {$R Scroll.RES}
    
    interface
    uses
      ComCtrls,
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms;
    
    const
      // Billenium Effects messages
      BE_ID = $41A2;
      BE_BASE = CM_BASE + $0C4A;
      CM_BENCPAINT = BE_BASE + 1;
      CM_SENCPAINT = CM_BASE + 457;
    
    type
      TStretchType = (stFull, stHorz, stVert);
      TAQSkinScrollBarControl = record
        SkinRect: TRect;
        //============================
        LTPoint, RTPoint, LBPoint, RBPoint: TPoint;
        ClRect: TRect;
        StretchEffect: Boolean;
        LeftStretch, TopStretch, RightStretch, BottomStretch: Boolean;
        StretchType: TStretchType;
        //============================
        TrackArea: TRect;
        UpButtonRect, ActiveUpButtonRect, DownUpButtonRect: TRect;
        DownButtonRect, ActiveDownButtonRect, DownDownButtonRect: TRect;
        ThumbRect, ActiveThumbRect, DownThumbRect: TRect;
        ThumbOffset1, ThumbOffset2: Integer;
        GlyphRect, ActiveGlyphRect, DownGlyphRect: TRect;
        GlyphTransparent: Boolean;
        GlyphTransparentColor: TColor;
        ThumbTransparent: Boolean;
        ThumbTransparentColor: TColor;
        ThumbStretchEffect: Boolean;
        ThumbMinSize: Integer;
        ThumbMinPageSize: Integer;
      end;
    
    type
      TScrollButtonDrawState = (
        bsasbNormal,
        bsasbPressed,
        bsasbHot,
        bsasbDisabled
        );
    
    type
      TAQSkinScrollBar = class(TObject)
      private
        FControl: TControl;
        FHandle: THandle;
        FHandled: Boolean;
        FOldWinProc: TWndMethod;
        SMouseInControl: Boolean;
        lbtndown: Boolean;
        procedure SetControl(Value: TControl);
        procedure NewWindowProc(var Message: TMessage);
      private
        FKind: TScrollBarKind;
        procedure DrawBorder(ADC: HDC; AUseExternalDC: Boolean);
        procedure DrawButton(Cnvs: TCanvas; i: Integer);
        function GetBoundsRect: TRect;
        function GetBorderTopLeft: TPoint;
        function HaveBorder: Boolean;
        function GetHeight: Integer;
        function GetWidth: Integer;
        function GetEnabled: Boolean;
      protected
        FOldPos: Integer;
        FCurPos, LVOldCurPos: single;
        VScrollWnd, HScrollWnd: TWinControl;
        VSliderState, VUpState, VDownState: TScrollButtonDrawState;
        HSliderState, HUpState, HDownState: TScrollButtonDrawState;
        function VScrollDisabled: Boolean;
        function HScrollDisabled: Boolean;
        function VDownButtonRect: TRect;
        function VScrollRect: TRect;
        function VSliderRect: TRect;
        function VTrackRect: TRect;
        function VUpButtonRect: TRect;
        function HDownButtonRect: TRect;
        function HScrollRect: TRect;
        function HSliderRect: TRect;
        function HTrackRect: TRect;
        function HUpButtonRect: TRect;
        procedure VDrawScroll(DC: HDC = 0);
        procedure HDrawScroll(DC: HDC = 0);
        // Billenium
        procedure CMBENCPaint(var Message: TMessage); //message CM_BENCPAINT;
        // SmartEffects
        procedure CMSENCPaint(var Message: TMessage); //message CM_SENCPAINT;
        //
        procedure WMLButtonDown(var Msg: TWMMouse); //message WM_LBUTTONDOWN;
        procedure WMLButtonUp(var Msg: TWMMouse); //message WM_LBUTTONUP;
        procedure WMNCLButtonDblClk(var Msg: TWMMouse); //message WM_NCLBUTTONDBLCLK;
        procedure WMNCLButtonDown(var Msg: TWMMouse); //message WM_NCLBUTTONDOWN;
        procedure WMNCMouseMove(var Msg: TWMNCHitMessage); //message WM_NCMOUSEMOVE;
        procedure WMNCLButtonUp(var Msg: TWMMouse); //message WM_NCLBUTTONUP;
        procedure WMMouseMove(var Msg: TWMMouse); //message WM_MOUSEMOVE;
        procedure WMNCPaint(var Msg: TWMNCPaint); //message WM_NCPAINT;
        procedure WMEraseBkgnd(var Msg: TMessage); //message WM_ERASEBKGND;
        procedure WMMouseWheel(var Msg: TMessage); //message WM_MOUSEWHEEL;
        procedure WMVScroll(var Msg: TMessage); //message WM_VSCROLL;
        procedure WMHScroll(var Msg: TMessage); //message WM_HSCROLL;
        procedure WMSize(var Msg: TMessage); //message WM_SIZE;
        procedure WMKeyDown(var Msg: TMessage); //message WM_KEYDOWN;
        procedure WMCAPTURECHANGED(var Msg: TMessage); //message WM_CAPTURECHANGED;
        procedure WMVTChangeState(var Msg: TMessage); message WM_APP + 32;
        procedure CMVisibleChanged(var Msg: TMessage); //message CM_VISIBLECHANGED;
        procedure CMMouseEnter(var Msg: TMessage); //message CM_MOUSEENTER;
        procedure CMMouseLeave(var Msg: TMessage); //message CM_MOUSELEAVE;
        procedure EMLINEINDEX(var Msg: TMessage); //message EM_LINEINDEX;
        procedure WMWindowPosChanging(var Msg: TWMWindowPosChanged); //message WM_WINDOWPOSCHANGING;
        procedure WMWindowPosChanged(var Msg: TWMWindowPosChanged); //message WM_WINDOWPOSCHANGED;
        procedure OnContextPopupAction(var Message: TMessage);
        procedure PaintBorder(Canvas: TCanvas; R: TRect); //override;
        function IsPopupWindow: Boolean;
        procedure PaintScroll;
        procedure UpdateScroll;
        procedure Paint(Canvas: TCanvas); //override;
        procedure SetHandle(const Value: HWnd); //override;
      private
        FBmp_Border: TBitmap;
    
        FBmp_skinrect_V: TBitmap;
        FBmp_activeupbuttonrect_V: TBitmap;
        FBmp_activedownbuttonrect_V: TBitmap;
        FBmp_thumbrect_V: TBitmap;
        FBmp_activethumbrect_V: TBitmap;
    
        FBmp_skinrect_H: TBitmap;
        FBmp_activeupbuttonrect_H: TBitmap;
        FBmp_activedownbuttonrect_H: TBitmap;
        FBmp_thumbrect_H: TBitmap;
        FBmp_activethumbrect_H: TBitmap;
    
    
        FVScrollCtrl, FHScrollCtrl: TAQSkinScrollBarControl;
        FBtnFace: TColor;
      public
        constructor Create;
        destructor Destroy; override;
      published
        property Control: TControl read FControl write SetControl;
        property Handle: THandle read FHandle;
        property Handled: Boolean read FHandled write FHandled;
        property Width: Integer read GetWidth;
        property Height: Integer read GetHeight;
        property Enabled: Boolean read GetEnabled;
      end;
    
      TWinScroll = class(TCustomControl)
      public
        FSubclass: TAQSkinScrollBar;
        FVertical: Boolean;
      private
      protected
        procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
        procedure WMEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND;
        procedure Paint; override;
        procedure CreateParams(var Params: TCreateParams); override;
      public
      end;
    
    
    implementation
    
    function RectWidth(R: TRect): Integer;
    begin
      Result := R.Right - R.Left;
    end;
    
    function RectHeight(R: TRect): Integer;
    begin
      Result := R.Bottom - R.Top;
    end;
    
    type
      //  TStretchType = (stFull, stHorz, stVert);
      TButtonLayout = (blGlyphLeft, blGlyphRight, blGlyphTop, blGlyphBottom);
    
    procedure CreateSkinImage(LtPt, RTPt, LBPt, RBPt: TPoint; ClRect: TRect;
      NewLTPt, NewRTPt, NewLBPt, NewRBPt: TPoint; NewClRect: TRect;
      B, SB: TBitMap; R: TRect; AW, AH: Integer; ADrawClient: Boolean;
      ALeftStretch, ATopStretch, ARightStretch, ABottomStretch,
      AClientStretch: Boolean; AStretchType: TStretchType);
    var
      w, h, rw, rh: Integer;
      X, Y, XCnt, YCnt: Integer;
      XO, YO: Integer;
      R1, R2, R3: TRect;
      Buffer, Buffer2: TBitMap;
      SaveIndex: Integer;
    begin
      B.Width := AW;
      B.Height := AH;
      if (RBPt.X - LTPt.X = 0) or
        (RBPt.Y - LTPt.Y = 0) or SB.Empty then Exit;
      with B.Canvas do
      begin
        // Draw lines
        // top
        if not ATopStretch
          then
        begin
          w := RTPt.X - LTPt.X;
          XCnt := (NewRTPt.X - NewLTPt.X) div (RTPt.X - LTPt.X);
          for X := 0 to XCnt do
          begin
            if NewLTPt.X + X * w + w > NewRTPt.X
              then XO := NewLTPt.X + X * w + w - NewRTPt.X else XO := 0;
            CopyRect(Rect(NewLTPt.X + X * w, 0, NewLTPt.X + X * w + w - XO, NewClRect.Top),
              SB.Canvas, Rect(R.Left + LTPt.X, R.Top,
              R.Left + RTPt.X - XO, R.Top + ClRect.Top));
          end;
        end
        else
        begin
          R1 := Rect(NewLTPt.X, 0, NewRTPt.X, NewClRect.Top);
          R2 := Rect(R.Left + LTPt.X, R.Top, R.Left + RTPt.X, R.Top + ClRect.Top);
          Buffer := TBitMap.Create;
          Buffer.Width := RectWidth(R2);
          Buffer.Height := RectHeight(R2);
          R3 := Rect(0, 0, Buffer.Width, Buffer.Height);
          Buffer.Canvas.CopyRect(R3, SB.Canvas, R2);
          StretchDraw(R1, Buffer);
          Buffer.Free;
        end;
        // bottom
        if not ABottomStretch
          then
        begin
          w := RBPt.X - LBPt.X;
          XCnt := (NewRBPt.X - NewLBPt.X) div (RBPt.X - LBPt.X);
          for X := 0 to XCnt do
          begin
            if NewLBPt.X + X * w + w > NewRBPt.X
              then XO := NewLBPt.X + X * w + w - NewRBPt.X else XO := 0;
            CopyRect(Rect(NewLBPt.X + X * w, NewClRect.Bottom, NewLBPt.X + X * w + w - XO, AH),
              SB.Canvas, Rect(R.Left + LBPt.X, R.Top + ClRect.Bottom,
              R.Left + RBPt.X - XO, R.Bottom));
          end;
        end
        else
        begin
          R1 := Rect(NewLBPt.X, NewClRect.Bottom, NewRBPt.X, AH);
          R2 := Rect(R.Left + LBPt.X, R.Top + ClRect.Bottom, R.Left + RBPt.X, R.Bottom);
          Buffer := TBitMap.Create;
          Buffer.Width := RectWidth(R2);
          Buffer.Height := RectHeight(R2);
          R3 := Rect(0, 0, Buffer.Width, Buffer.Height);
          Buffer.Canvas.CopyRect(R3, SB.Canvas, R2);
          StretchDraw(R1, Buffer);
          Buffer.Free;
        end;
        // left
        if not ALeftStretch
          then
        begin
          w := NewClRect.Left;
          h := LBPt.Y - LTPt.Y;
          YCnt := (NewLBPt.Y - NewLTPt.Y) div h;
          for Y := 0 to YCnt do
          begin
            if NewLTPt.Y + Y * h + h > NewLBPt.Y
              then YO := NewLTPt.Y + Y * h + h - NewLBPt.Y else YO := 0;
            CopyRect(Rect(0, NewLTPt.Y + Y * h, w, NewLTPt.Y + Y * h + h - YO),
              SB.Canvas,
              Rect(R.Left, R.Top + LTPt.Y, R.Left + w, R.Top + LBPt.Y - YO));
          end
        end
        else
        begin
          R1 := Rect(0, NewLTPt.Y, NewClRect.Left, NewLBPt.Y);
          R2 := Rect(R.Left, R.Top + LtPt.Y, R.Left + ClRect.Left, R.Top + LBPt.Y);
          Buffer := TBitMap.Create;
          Buffer.Width := RectWidth(R2);
          Buffer.Height := RectHeight(R2);
          R3 := Rect(0, 0, Buffer.Width, Buffer.Height);
          Buffer.Canvas.CopyRect(R3, SB.Canvas, R2);
          StretchDraw(R1, Buffer);
          Buffer.Free;
        end;
        // right
        if not ARightStretch
          then
        begin
          h := RBPt.Y - RTPt.Y;
          YCnt := (NewRBPt.Y - NewRTPt.Y) div h;
          for Y := 0 to YCnt do
          begin
            if NewRTPt.Y + Y * h + h > NewRBPt.Y
              then YO := NewRTPt.Y + Y * h + h - NewRBPt.Y else YO := 0;
            CopyRect(Rect(NewClRect.Right, NewRTPt.Y + Y * h,
              AW, NewRTPt.Y + Y * h + h - YO),
              SB.Canvas,
              Rect(R.Left + ClRect.Right, R.Top + RTPt.Y,
              R.Right, R.Top + RBPt.Y - YO));
          end
        end
        else
        begin
          R1 := Rect(NewClRect.Right, NewRTPt.Y, AW, NewRBPt.Y);
          R2 := Rect(R.Left + ClRect.Right, R.Top + RtPt.Y, R.Right, R.Top + RBPt.Y);
          Buffer := TBitMap.Create;
          Buffer.Width := RectWidth(R2);
          Buffer.Height := RectHeight(R2);
          R3 := Rect(0, 0, Buffer.Width, Buffer.Height);
          Buffer.Canvas.CopyRect(R3, SB.Canvas, R2);
          StretchDraw(R1, Buffer);
          Buffer.Free;
        end;
    
        // Draw corners
        // lefttop
    
        CopyRect(Rect(0, 0, NewLTPt.X, NewClRect.Top),
          SB.Canvas, Rect(R.Left, R.Top,
          R.Left + LTPt.X, R.Top + ClRect.Top));
    
        CopyRect(Rect(0, NewClRect.Top, NewClRect.Left, NewLTPt.Y),
          SB.Canvas, Rect(R.Left, R.Top + ClRect.Top,
          R.Left + ClRect.left, R.Top + LTPT.Y));
    
        //topright
    
        CopyRect(Rect(NewRTPt.X, 0, AW, NewClRect.Top), SB.Canvas,
          Rect(R.Left + RTPt.X, R.Top, R.Right, R.Top + ClRect.Top));
        CopyRect(Rect(NewClRect.Right, NewClRect.Top, AW, NewRTPt.Y), SB.Canvas,
          Rect(R.Left + ClRect.Right, R.Top + ClRect.Top,
          R.Right, R.Top + RTPt.Y));
    
        //leftbottom
    
        CopyRect(Rect(0, NewLBPt.Y, NewClRect.Left, AH), SB.Canvas,
          Rect(R.Left, R.Top + LBPt.Y, R.Left + ClRect.Left, R.Bottom));
    
        CopyRect(Rect(NewClRect.Left, NewClRect.Bottom, NewLBPt.X, AH), SB.Canvas,
          Rect(R.Left + ClRect.Left, R.Top + ClRect.Bottom, R.Left + LBPt.X, R.Bottom));
    
    
        //rightbottom
    
        CopyRect(Rect(NewRBPt.X, NewClRect.Bottom, AW, AH), SB.Canvas,
          Rect(R.Left + RBPt.X, R.Top + ClRect.Bottom, R.Right, R.Bottom));
    
        CopyRect(Rect(NewClRect.Right, NewRBPt.Y, AW, NewClRect.Bottom), SB.Canvas,
          Rect(R.Left + ClRect.Right, R.Top + RBPt.Y,
          R.Right, R.Top + ClRect.Bottom));
    
        //Draw client
        if ADrawClient
          then
          if AClientStretch
            then
          begin
            Buffer := TBitMap.Create;
            Buffer.Width := RectWidth(ClRect);
            Buffer.Height := RectHeight(ClRect);
            Buffer.Canvas.CopyRect(Rect(0, 0, Buffer.Width, Buffer.Height),
              SB.Canvas, Rect(R.Left + ClRect.Left, R.Top + ClRect.Top,
              R.Left + ClRect.Right, R.Top + ClRect.Bottom));
            if (RectWidth(NewClRect) > 0) and (RectHeight(NewClRect) > 0) then
              case AStretchType of
                stFull:
                  StretchDraw(NewClRect, Buffer);
                stHorz:
                  begin
                    SaveIndex := SaveDC(B.Canvas.Handle);
                    IntersectClipRect(B.Canvas.Handle,
                      NewCLRect.Left, NewCLRect.Top, NewCLRect.Right, NewClRect.Bottom);
                    //
                    Buffer2 := TBitMap.Create;
                    Buffer2.Width := Buffer.Width;
                    Buffer2.Height := RectHeight(NewClRect);
                    Buffer2.Canvas.StretchDraw(Rect(0, 0, Buffer2.Width, Buffer2.Height), Buffer);
                    XCnt := RectWidth(NewClRect) div Buffer2.Width;
                    for X := 0 to XCnt do
                      B.Canvas.Draw(NewClRect.Left + X * Buffer2.Width, NewClRect.Top, Buffer2);
                    Buffer2.Free;
                    //
                    RestoreDC(B.Canvas.Handle, SaveIndex);
                  end;
                stVert:
                  begin
                    SaveIndex := SaveDC(B.Canvas.Handle);
                    IntersectClipRect(B.Canvas.Handle,
                      NewCLRect.Left, NewCLRect.Top, NewCLRect.Right, NewClRect.Bottom);
                    //
                    Buffer2 := TBitMap.Create;
                    Buffer2.Width := RectWidth(NewClRect);
                    Buffer2.Height := Buffer.Height;
                    Buffer2.Canvas.StretchDraw(Rect(0, 0, Buffer2.Width, Buffer2.Height), Buffer);
                    YCnt := RectHeight(NewClRect) div Buffer2.Height;
                    for Y := 0 to YCnt do
                      B.Canvas.Draw(NewClRect.Left, NewClRect.Top + Y * Buffer2.Height, Buffer2);
                    Buffer2.Free;
                    //
                    RestoreDC(B.Canvas.Handle, SaveIndex);
                  end;
              end;
    
            Buffer.Free;
          end
          else
          begin
            w := RectWidth(ClRect);
            h := RectHeight(ClRect);
            rw := RectWidth(NewClRect);
            rh := RectHeight(NewClRect);
            // Draw client area
            XCnt := rw div w;
            YCnt := rh div h;
            for X := 0 to XCnt do
              for Y := 0 to YCnt do
              begin
                if X * w + w > rw then XO := X * W + W - rw else XO := 0;
                if Y * h + h > rh then YO := Y * h + h - rh else YO := 0;
                CopyRect(Rect(NewClRect.Left + X * w, NewClRect.Top + Y * h,
                  NewClRect.Left + X * w + w - XO,
                  NewClRect.Top + Y * h + h - YO),
                  SB.Canvas,
                  Rect(R.Left + ClRect.Left, R.Top + ClRect.Top,
                  R.Left + ClRect.Right - XO,
                  R.Top + ClRect.Bottom - YO));
              end;
          end;
      end;
    end;
    
    procedure CreateStretchImage(B: TBitMap; SB: TBitMap; R: TRect; ClRect: TRect;
      ADrawClient: Boolean);
    var
      LTPt, RTPt, LBPt, RBPt: TPoint;
      NewLTPt, NewRTPt, NewLBPt, NewRBPt: TPoint;
      NewClRect: TRect;
    begin
      LtPt := Point(ClRect.Left, ClRect.Top);
      RtPt := Point(ClRect.Right, ClRect.Top);
      LBPt := Point(ClRect.Left, ClRect.Bottom);
      RBPt := Point(ClRect.Right, ClRect.Bottom);
    
      NewClRect := ClRect;
      NewClRect.Right := B.Width - (RectWidth(R) - ClRect.Right);
      NewClRect.Bottom := B.Height - (RectHeight(R) - ClRect.Bottom);
    
      NewLtPt := Point(NewClRect.Left, NewClRect.Top);
      NewRtPt := Point(NewClRect.Right, NewClRect.Top);
      NewLBPt := Point(NewClRect.Left, NewClRect.Bottom);
      NewRBPt := Point(NewClRect.Right, NewClRect.Bottom);
    
      CreateSkinImage(LtPt, RTPt, LBPt, RBPt, ClRect,
        NewLTPt, NewRTPt, NewLBPt, NewRBPt, NewClRect,
        B, SB, R, B.Width, B.Height, ADrawClient,
        True, True, True, True, True, stFull);
    end;
    
    procedure CreateHSkinImage(LO, RO: Integer;
      B, SB: TBitMap; R: TRect; AW, AH: Integer; AStretch: Boolean);
    var
      X, XCnt, w, XO: Integer;
      R1: TRect;
      Buffer: TBitMap;
    begin
      B.Width := AW;
      B.Height := RectHeight(R);
      with B.Canvas do
      begin
        if LO <> 0 then
          CopyRect(Rect(0, 0, LO, B.Height), SB.Canvas,
            Rect(R.Left, R.Top, R.Left + LO, R.Bottom));
        if RO <> 0 then
          CopyRect(Rect(B.Width - RO, 0, B.Width, B.Height),
            SB.Canvas,
            Rect(R.Right - RO, R.Top, R.Right, R.Bottom));
        Inc(R.Left, LO);
        Dec(R.Right, RO);
        w := RectWidth(R);
        if w = 0 then w := 1;
        XCnt := (B.Width - LO - RO) div w;
        if AStretch
          then
        begin
          Buffer := TBitMap.Create;
          Buffer.Width := RectWidth(R);
          Buffer.Height := RectHeight(R);
          Buffer.Canvas.CopyRect(Rect(0, 0, Buffer.Width, Buffer.Height),
            SB.Canvas, R);
          R1 := Rect(LO, 0, B.Width - RO, B.Height);
          B.Canvas.StretchDraw(R1, Buffer);
          Buffer.Free;
        end
        else
          for X := 0 to XCnt do
          begin
            if LO + X * w + w > B.Width - RO
              then XO := LO + X * w + w - (B.Width - RO)
            else XO := 0;
            B.Canvas.CopyRect(Rect(LO + X * w, 0, LO + X * w + w - XO,
              B.Height),
              SB.Canvas,
              Rect(R.Left, R.Top, R.Right - XO, R.Bottom));
          end;
      end;
    end;
    
    procedure CreateVSkinImage(TpO, BO: Integer;
      B, SB: TBitMap; R: TRect; AW, AH: Integer; AStretch: Boolean);
    var
      Y, YCnt, h, YO: Integer;
      R1: TRect;
      Buffer: TBitMap;
    begin
      B.Width := RectWidth(R);
      B.Height := AH;
      with B.Canvas do
      begin
        if TpO <> 0 then
          CopyRect(Rect(0, 0, B.Width, TpO), SB.Canvas,
            Rect(R.Left, R.Top, R.Right, R.Top + TpO));
        if BO <> 0 then
          CopyRect(Rect(0, B.Height - BO, B.Width, B.Height),
            SB.Canvas,
            Rect(R.Left, R.Bottom - BO, R.Right, R.Bottom));
        Inc(R.Top, TpO);
        Dec(R.Bottom, BO);
        h := RectHeight(R);
        if H <> 0
          then
          YCnt := (B.Height - TpO - BO) div h
        else
          YCnt := 0;
        if AStretch
          then
        begin
          Buffer := TBitMap.Create;
          Buffer.Width := RectWidth(R);
          Buffer.Height := RectHeight(R);
          Buffer.Canvas.CopyRect(Rect(0, 0, Buffer.Width, Buffer.Height),
            SB.Canvas, R);
          R1 := Rect(0, TpO, B.Width, B.Height - BO);
          B.Canvas.StretchDraw(R1, Buffer);
          Buffer.Free;
        end
        else
          for Y := 0 to YCnt do
          begin
            if TpO + Y * h + h > B.Height - BO
              then YO := TpO + Y * h + h - (B.Height - BO)
            else YO := 0;
            B.Canvas.CopyRect(
              Rect(0, TpO + Y * h, B.Width, TpO + Y * h + h - YO),
              SB.Canvas,
              Rect(R.Left, R.Top, R.Right, R.Bottom - YO));
          end;
      end;
    end;
    
    
    procedure DrawGlyph(Cnvs: TCanvas; X, Y: Integer; FGlyph: TBitMap;
      FNumGlyphs, FGlyphNum: Integer);
    var
      B: TBitMap;
      gw, gh: Integer;
      GR: TRect;
    begin
      if FGlyph.Empty then Exit;
      gw := FGlyph.Width div FNumGlyphs;
      gh := FGlyph.Height;
      B := TBitMap.Create;
      B.Width := gw;
      B.Height := gh;
      GR := Rect(gw * (FGlyphNum - 1), 0, gw * FGlyphNum, gh);
      B.Canvas.CopyRect(Rect(0, 0, gw, gh), FGlyph.Canvas, GR);
      B.Transparent := True;
      Cnvs.Draw(X, Y, B);
      B.Free;
    end;
    
    procedure CreateSkinBorderImages(LtPt, RTPt, LBPt, RBPt: TPoint; ClRect: TRect;
      NewLTPt, NewRTPt, NewLBPt, NewRBPt: TPoint; NewClRect: TRect;
      LeftB, TopB, RightB, BottomB, SB: TBitMap; R: TRect; AW, AH: Integer;
      LS, TS, RS, BS: Boolean);
    var
      XCnt, YCnt, i, X, Y, XO, YO, w, h: Integer;
      TB: TBitMap;
      TR, TR1: TRect;
    begin
      // top
      w := AW;
      h := NewClRect.Top;
      if (w > 0) and (h > 0) and (RTPt.X - LTPt.X > 0) then
      begin
        TopB.Width := w;
        TopB.Height := h;
        w := RTPt.X - LTPt.X;
        XCnt := TopB.Width div w;
        if TS then
        begin
          TB := TBitMap.Create;
          TR := Rect(R.Left + LTPt.X, R.Top,
            R.Left + RTPt.X, R.Top + h);
          TR1 := Rect(NewLTPt.X, 0, NewRTPt.X, h);
          TB.Width := RectWidth(TR);
          TB.Height := RectHeight(TR);
          TB.Canvas.CopyRect(Rect(0, 0, TB.Width, TB.Height),
            SB.Canvas, TR);
          TopB.Canvas.StretchDraw(TR1, TB);
          TB.Free;
        end
        else
          for X := 0 to XCnt do
          begin
            if X * w + w > TopB.Width
              then XO := X * w + w - TopB.Width else XO := 0;
            with TopB.Canvas do
            begin
              CopyRect(Rect(X * w, 0, X * w + w - XO, h),
                SB.Canvas,
                Rect(R.Left + LTPt.X, R.Top,
                R.Left + RTPt.X - XO, R.Top + h));
            end;
          end;
        with TopB.Canvas do
        begin
          CopyRect(Rect(0, 0, NewLTPt.X, h), SB.Canvas,
            Rect(R.Left, R.Top, R.Left + LTPt.X, R.Top + h));
          CopyRect(Rect(NewRTPt.X, 0, TopB.Width, h), SB.Canvas,
            Rect(R.Left + RTPt.X, R.Top, R.Right, R.Top + h));
        end;
      end;
    
      // bottom
      w := AW;
      h := AH - NewClRect.Bottom;
      if (w > 0) and (h > 0) and (RBPt.X - LBPt.X > 0)
        then
      begin
        BottomB.Width := w;
        BottomB.Height := h;
        w := RBPt.X - LBPt.X;
        XCnt := BottomB.Width div w;
        if BS then
        begin
          TB := TBitMap.Create;
          TR := Rect(R.Left + LBPt.X, R.Bottom - h,
            R.Left + RBPt.X, R.Bottom);
          TR1 := Rect(NewLBPt.X, 0, NewRBPt.X, h);
          TB.Width := RectWidth(TR);
          TB.Height := RectHeight(TR);
          TB.Canvas.CopyRect(Rect(0, 0, TB.Width, TB.Height),
            SB.Canvas, TR);
          BottomB.Canvas.StretchDraw(TR1, TB);
          TB.Free;
        end
        else
          for X := 0 to XCnt do
          begin
            if X * w + w > BottomB.Width
              then XO := X * w + w - BottomB.Width else XO := 0;
            with BottomB.Canvas do
            begin
              CopyRect(Rect(X * w, 0, X * w + w - XO, h),
                SB.Canvas,
                Rect(R.Left + LBPt.X, R.Bottom - h,
                R.Left + RBPt.X - XO, R.Bottom));
            end;
          end;
        with BottomB.Canvas do
        begin
          CopyRect(Rect(0, 0, NewLBPt.X, h), SB.Canvas,
            Rect(R.Left, R.Bottom - h, R.Left + LBPt.X, R.Bottom));
          CopyRect(Rect(NewRBPt.X, 0, BottomB.Width, h), SB.Canvas,
            Rect(R.Left + RBPt.X, R.Bottom - h, R.Right, R.Bottom));
        end;
      end;
      // draw left
      h := AH - BottomB.Height - TopB.Height;
      w := NewClRect.Left;
      if (w > 0) and (h > 0) and (LBPt.Y - LTPt.Y > 0)
        then
      begin
        LeftB.Width := w;
        LeftB.Height := h;
        h := LBPt.Y - LTPt.Y;
        YCnt := LeftB.Height div h;
        if LS then
        begin
          TB := TBitMap.Create;
          TR := Rect(R.Left, R.Top + LTPt.Y,
            R.Left + w, R.Top + LBPt.Y);
          TR1 := Rect(0, LTPt.Y - ClRect.Top, w,
            LeftB.Height - (ClRect.Bottom - LBPt.Y));
          TB.Width := RectWidth(TR);
          TB.Height := RectHeight(TR);
          TB.Canvas.CopyRect(Rect(0, 0, TB.Width, TB.Height),
            SB.Canvas, TR);
          LeftB.Canvas.StretchDraw(TR1, TB);
          TB.Free;
        end
        else
          for Y := 0 to YCnt do
          begin
            if Y * h + h > LeftB.Height
              then YO := Y * h + h - LeftB.Height else YO := 0;
            with LeftB.Canvas do
              CopyRect(Rect(0, Y * h, w, Y * h + h - YO),
                SB.Canvas,
                Rect(R.Left, R.Top + LTPt.Y, R.Left + w, R.Top + LBPt.Y - YO));
          end;
        with LeftB.Canvas do
        begin
          YO := LTPt.Y - ClRect.Top;
          if YO > 0
            then
            CopyRect(Rect(0, 0, w, YO), SB.Canvas,
              Rect(R.Left, R.Top + ClRect.Top,
              R.Left + w, R.Top + LTPt.Y));
          YO := ClRect.Bottom - LBPt.Y;
          if YO > 0 then
            CopyRect(Rect(0, LeftB.Height - YO, w, LeftB.Height),
              SB.Canvas,
              Rect(R.Left, R.Top + LBPt.Y,
              R.Left + w, R.Top + ClRect.Bottom));
        end;
      end;
      // draw right
      h := AH - BottomB.Height - TopB.Height;
      w := AW - NewClRect.Right;
      if (w > 0) and (h > 0) and (RBPt.Y - RTPt.Y > 0) then
      begin
        RightB.Width := w;
        RightB.Height := h;
        h := RBPt.Y - RTPt.Y;
        YCnt := RightB.Height div h;
        if RS then
        begin
          TB := TBitMap.Create;
          TR := Rect(R.Left + ClRect.Right, R.Top + RTPt.Y,
            R.Right, R.Top + RBPt.Y);
          TR1 := Rect(0, RTPt.Y - ClRect.Top, w,
            RightB.Height - (ClRect.Bottom - RBPt.Y));
          TB.Width := RectWidth(TR);
          TB.Height := RectHeight(TR);
          TB.Canvas.CopyRect(Rect(0, 0, TB.Width, TB.Height),
            SB.Canvas, TR);
          RightB.Canvas.StretchDraw(TR1, TB);
          TB.Free;
        end
        else
          for Y := 0 to YCnt do
          begin
            if Y * h + h > RightB.Height
              then YO := Y * h + h - RightB.Height else YO := 0;
            with RightB.Canvas do
              CopyRect(Rect(0, Y * h, w, Y * h + h - YO),
                SB.Canvas,
                Rect(R.Left + ClRect.Right, R.Top + RTPt.Y,
                R.Right, R.Top + RBPt.Y - YO));
          end;
        with RightB.Canvas do
        begin
          YO := RTPt.Y - ClRect.Top;
          if YO > 0 then
            CopyRect(Rect(0, 0, w, YO), SB.Canvas,
              Rect(R.Left + ClRect.Right, R.Top + ClRect.Top,
              R.Right, R.Top + RTPt.Y));
    
          YO := ClRect.Bottom - RBPt.Y;
          if YO > 0 then
            CopyRect(Rect(0, RightB.Height - YO, w, RightB.Height),
              SB.Canvas,
              Rect(R.Left + ClRect.Right, R.Top + RBPt.Y,
              R.Right, R.Top + ClRect.Bottom));
        end;
      end;
    end;
    
    function NullRect: TRect;
    begin
      Result := Rect(0, 0, 0, 0);
    end;
    
    function IsNullRect(R: TRect): Boolean;
    begin
      Result := (R.Right - R.Left <= 0) or (R.Bottom - R.Top <= 0)
    end;
    
    procedure DrawArrowImage(Cnvs: TCanvas; R: TRect; Color: TColor; Code: Integer);
    var
      i: Integer;
      X, Y: Integer;
    begin
      with Cnvs do
      begin
        Pen.Color := Color;
        case Code of
          1:
            begin
              X := R.Left + RectWidth(R) div 2 - 2;
              Y := R.Top + RectHeight(R) div 2;
              for i := 0 to 3 do
              begin
                MoveTo(X + i, Y - i);
                LineTo(X + i, Y + i + 1);
              end;
            end;
          2:
            begin
              X := R.Left + RectWidth(R) div 2 + 2;
              Y := R.Top + RectHeight(R) div 2;
              for i := 3 downto 0 do
              begin
                MoveTo(X - i, Y + i);
                LineTo(X - i, Y - i - 1);
              end;
            end;
          3:
            begin
              X := R.Left + RectWidth(R) div 2;
              Y := R.Top + RectHeight(R) div 2 - 2;
              for i := 0 to 3 do
              begin
                MoveTo(X - i, Y + i);
                LineTo(X + i + 1, Y + i);
              end;
            end;
          4:
            begin
              X := R.Left + RectWidth(R) div 2;
              Y := R.Top + RectHeight(R) div 2 + 2;
              for i := 3 downto 0 do
              begin
                MoveTo(X - i, Y - i);
                LineTo(X + i + 1, Y - i);
              end;
            end;
          5: begin
              X := R.Left + RectWidth(R) div 2;
              Y := R.Top + RectHeight(R) div 2;
              MoveTo(X - 4, Y - 1);
              LineTo(X + 4, Y - 1);
              MoveTo(X - 4, Y);
              LineTo(X + 4, Y);
              //
              MoveTo(X - 1, Y - 4);
              LineTo(X - 1, Y + 4);
              MoveTo(X, Y - 4);
              LineTo(X, Y + 4);
            end;
        end;
      end;
    end;
    
    
    { TWinScroll }
    
    procedure TWinScroll.CreateParams(var Params: TCreateParams);
    begin
      inherited;
      Params.Style := Params.Style or WS_CHILDWINDOW or WS_CLIPCHILDREN or WS_CLIPSIBLINGS;
      Params.ExStyle := Params.ExStyle or WS_EX_NOPARENTNOTIFY;
      Params.WindowClass.style := Params.WindowClass.style;
    end;
    
    procedure TWinScroll.Paint;
    begin
      if Width * Height = 0 then Exit;
      if FSubclass <> nil then
      begin
        if FVertical then
        begin
          with FSubclass.VScrollRect do
            MoveWindowOrg(Canvas.Handle, -Left, -Top);
          FSubclass.VDrawScroll(Canvas.Handle);
          with FSubclass.VScrollRect do
            MoveWindowOrg(Canvas.Handle, Left, Top);
        end
        else
        begin
          with FSubclass.HScrollRect do
            MoveWindowOrg(Canvas.Handle, -Left, -Top);
          FSubclass.HDrawScroll(Canvas.Handle);
          with FSubclass.HScrollRect do
            MoveWindowOrg(Canvas.Handle, Left, Top);
        end;
      end;
    end;
    
    procedure TWinScroll.WMEraseBkgnd(var Msg: TMessage);
    begin
      Msg.Result := 1;
    end;
    
    procedure TWinScroll.WMNCHitTest(var Msg: TWMNCHitTest);
    begin
      Msg.Result := HTTRANSPARENT;
    end;
    
    { TAQSkinScrollBar }
    
    const
      BUTCOUNT = 3;
      THUMB = 0;
      UPBUTTON = 1;
      DOWNBUTTON = 2;
      TRACK = 3;
      CLIENT = 4;
      SBUTTONW = 16;
    
    procedure TAQSkinScrollBar.CMBENCPaint(var Message: TMessage);
    begin
      if (Message.LParam = BE_ID) then
      begin
        if (Message.wParam <> 0) then
          DrawBorder(Message.wParam, True);
        Message.Result := BE_ID;
        Handled := True;
      end
      else
      begin
        Handled := False;
        FOldWinProc(TMessage(Message));
      end;
    end;
    
    procedure TAQSkinScrollBar.CMMouseEnter(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      SMouseInControl := True;
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.CMMouseLeave(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      SMouseInControl := False;
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.CMSENCPaint(var Message: TMessage);
    begin
      FOldWinProc(TMessage(Message));
      if (Message.wParam <> 0) then
      begin
        DrawBorder(Message.wParam, True);
        if HScrollWnd <> nil then
          HScrollWnd.PaintTo(Message.wParam,
            HScrollWnd.Left - Control.Left, HScrollWnd.Top - Control.Top);
        if VScrollWnd <> nil then
          VScrollWnd.PaintTo(Message.wParam,
            VScrollWnd.Left - Control.Left, VScrollWnd.Top - Control.Top);
      end;
    end;
    
    procedure TAQSkinScrollBar.CMVisibleChanged(var Msg: TMessage);
    begin
      if (Control <> nil) and (Control.Visible) then
        ShowWindow(VScrollWnd.Handle, SW_SHOW);
      if (Control <> nil) and (not Control.Visible) then
        ShowWindow(VScrollWnd.Handle, SW_HIDE);
      if (Control <> nil) and (Control.Visible) then
        ShowWindow(HScrollWnd.Handle, SW_SHOW);
      if (Control <> nil) and (not Control.Visible) then
        ShowWindow(HScrollWnd.Handle, SW_HIDE);
    end;
    
    constructor TAQSkinScrollBar.Create;
    begin
      FControl := nil;
      FHandle := 0;
      FOldWinProc := nil;
    
      with FVScrollCtrl do
      begin
        skinrect := Rect(225, 25, 240, 89);
        LTPoint := point(7, 14);
        RTPoint := point(0, 0);
        LBPoint := point(8, 50);
        RBPoint := point(0, 0);
        ClRect := Rect(0, 15, 15, 49);
        LeftStretch := False;
        topstretch := False;
        rightstretch := False;
        bottomstretch := False;
        stretcheffect := False;
        stretchtype := stfull;
        trackarea := Rect(0, 13, 15, 51);
        upbuttonrect := Rect(0, 51, 15, 64);
        activeupbuttonrect := Rect(241, 36, 256, 49);
        downupbuttonrect := Rect(0, 0, 0, 0);
        downbuttonrect := Rect(0, 0, 15, 13);
        activedownbuttonrect := Rect(241, 25, 256, 38);
        downdownbuttonrect := Rect(0, 0, 0, 0);
        thumbrect := Rect(245, 2, 255, 16);
        activethumbrect := Rect(228, 2, 238, 16);
        downthumbrect := Rect(0, 0, 0, 0);
        thumboffset1 := 5;
        thumboffset2 := 5;
        thumbtransparent := False;
        thumbtransparentcolor := 0;
        thumbstretcheffect := False;
        thumbminsize := 10;
        thumbminpagesize := 14;
        glyphrect := Rect(0, 0, 0, 0);
        activeglyphrect := Rect(0, 0, 0, 0);
        downglyphrect := Rect(0, 0, 0, 0);
        glyphtransparent := False;
        glyphtransparentcolor := 0;
      end;
    
      with FHScrollCtrl do
      begin
        skinrect := Rect(153, 132, 217, 147);
        LTPoint := point(14, 5);
        RTPoint := point(49, 7);
        LBPoint := point(0, 0);
        RBPoint := point(0, 0);
        ClRect := Rect(16, 1, 48, 14);
        LeftStretch := False;
        topstretch := False;
        rightstretch := False;
        bottomstretch := False;
        stretcheffect := False;
        stretchtype := stfull;
        trackarea := Rect(14, 0, 50, 15);
        upbuttonrect := Rect(51, 0, 64, 15);
        activeupbuttonrect := Rect(164, 148, 177, 163);
        downupbuttonrect := Rect(0, 0, 0, 0);
        downbuttonrect := Rect(0, 0, 13, 15);
        activedownbuttonrect := Rect(153, 148, 166, 163);
        downdownbuttonrect := Rect(0, 0, 0, 0);
        thumbrect := Rect(133, 151, 147, 161);
        activethumbrect := Rect(133, 134, 147, 144);
        downthumbrect := Rect(0, 0, 0, 0);
        thumboffset1 := 4;
        thumboffset2 := 4;
        thumbtransparent := False;
        thumbtransparentcolor := 0;
        thumbstretcheffect := False;
        thumbminsize := 10;
        thumbminpagesize := 14;
        glyphrect := Rect(0, 0, 0, 0);
        activeglyphrect := Rect(0, 0, 0, 0);
        downglyphrect := Rect(0, 0, 0, 0);
        glyphtransparent := False;
        glyphtransparentcolor := 0;
      end;
    
    
      FBtnFace := 15852243;
    
    
    
      FBmp_Border := TBitmap.Create;
      FBmp_Border.LoadFromResourceName(HInstance, 'memo_skinrect');
    
      FBmp_skinrect_V := TBitmap.Create;
      FBmp_activeupbuttonrect_V := TBitmap.Create;
      FBmp_activedownbuttonrect_V := TBitmap.Create;
      FBmp_thumbrect_V := TBitmap.Create;
      FBmp_activethumbrect_V := TBitmap.Create;
    
      FBmp_skinrect_V.LoadFromResourceName(HInstance, 'v_skinrect');
      FBmp_activeupbuttonrect_V.LoadFromResourceName(HInstance, 'v_activeupbuttonrect');
      FBmp_activedownbuttonrect_V.LoadFromResourceName(HInstance, 'v_activedownbuttonrect');
      FBmp_thumbrect_V.LoadFromResourceName(HInstance, 'v_thumbrect');
      FBmp_activethumbrect_V.LoadFromResourceName(HInstance, 'v_activethumbrect');
    
    
      FBmp_skinrect_H := TBitmap.Create;
      FBmp_activeupbuttonrect_H := TBitmap.Create;
      FBmp_activedownbuttonrect_H := TBitmap.Create;
      FBmp_thumbrect_H := TBitmap.Create;
      FBmp_activethumbrect_H := TBitmap.Create;
      FBmp_skinrect_H.LoadFromResourceName(HInstance, 'h_skinrect');
      FBmp_activeupbuttonrect_H.LoadFromResourceName(HInstance, 'h_activeupbuttonrect');
      FBmp_activedownbuttonrect_H.LoadFromResourceName(HInstance, 'h_activedownbuttonrect');
      FBmp_thumbrect_H.LoadFromResourceName(HInstance, 'h_thumbrect');
      FBmp_activethumbrect_H.LoadFromResourceName(HInstance, 'h_activethumbrect');
    end;
    
    destructor TAQSkinScrollBar.Destroy;
    begin
      if (FControl <> nil) and (@FOldWinProc <> nil) then FControl.WindowProc := FOldWinProc;
    
      if VScrollWnd <> nil then
      begin
        TWinScroll(VScrollWnd).FSubclass := nil;
        FreeAndNil(VScrollWnd);
      end;
      if HScrollWnd <> nil then
      begin
        TWinScroll(HScrollWnd).FSubclass := nil;
        FreeAndNil(HScrollWnd);
      end;
    
      FBmp_skinrect_V.Free;
      FBmp_activeupbuttonrect_V.Free;
      FBmp_activedownbuttonrect_V.Free;
      FBmp_thumbrect_V.Free;
      FBmp_activethumbrect_V.Free;
    
      FBmp_skinrect_H.Free;
      FBmp_activeupbuttonrect_H.Free;
      FBmp_activedownbuttonrect_H.Free;
      FBmp_thumbrect_H.Free;
      FBmp_activethumbrect_H.Free;
    
      FBmp_Border.Free;
    
      inherited;
    end;
    
    procedure TAQSkinScrollBar.DrawBorder(ADC: HDC; AUseExternalDC: Boolean);
    var
      R: TRect;
      Canvas: TCanvas;
      P: TPoint;
    begin
      if Handle = 0 then Exit;
    
      Canvas := TCanvas.Create;
      if not AUseExternalDC
        then Canvas.Handle := GetWindowDC(Handle)
      else Canvas.Handle := ADC;
    
      P := Point(0, 0);
      Windows.ClientToScreen(Handle, P);
      Windows.GetWindowRect(Handle, R);
      P.X := P.X - R.Left;
      P.Y := P.Y - R.Top;
    
      Windows.GetClientRect(Handle, R);
      ExcludeClipRect(Canvas.Handle, P.X, P.Y, R.Right - R.Left + P.X, R.Bottom - R.Top + P.Y);
    
      Windows.GetWindowRect(Handle, R);
      OffsetRect(R, -R.Left, -R.Top);
    
      PaintBorder(Canvas, R);
    
      SelectClipRgn(Canvas.Handle, 0);
      if not AUseExternalDC then ReleaseDC(Handle, Canvas.Handle);
    
      Canvas.Handle := 0;
      Canvas.Free;
    end;
    
    procedure TAQSkinScrollBar.DrawButton(Cnvs: TCanvas; i: Integer);
    const
      SP_XP_BTNFRAMECOLOR = 8388608;
      SP_XP_BTNACTIVECOLOR = 13811126;
      SP_XP_BTNDOWNCOLOR = 11899781;
    var
      R1, R2: TRect;
      C: TColor;
      ThumbB: TBitMap;
      B1: TBitMap;
    
      kf: Double;
      FPageSize: Integer;
      SkinCtrl: TAQSkinScrollBarControl;
      TrackR, R: TRect;
      B: TBitmap;
      x, ResizeMode: Integer;
      NewLTPoint, NewRTPoint, NewLBPoint, NewRBPoint: TPoint;
      NewClRect: TRect;
      MinW, MinH: Integer;
      GlyphB: TBitMap;
      //==============================================
      Bmp_skinrect_V: TBitmap;
      Bmp_activeupbuttonrect_V: TBitmap;
      Bmp_activedownbuttonrect_V: TBitmap;
      Bmp_thumbrect_V: TBitmap;
      Bmp_activethumbrect_V: TBitmap;
      Bmp_r1: TBitmap;
    
      Bmp_skinrect_H: TBitmap;
      Bmp_activeupbuttonrect_H: TBitmap;
      Bmp_activedownbuttonrect_H: TBitmap;
      Bmp_thumbrect_H: TBitmap;
      Bmp_activethumbrect_H: TBitmap;
    begin
      Bmp_skinrect_V := FBmp_skinrect_V;
      Bmp_activeupbuttonrect_V := FBmp_activeupbuttonrect_V;
      Bmp_activedownbuttonrect_V := FBmp_activedownbuttonrect_V;
      Bmp_thumbrect_V := FBmp_thumbrect_V;
      Bmp_activethumbrect_V := FBmp_activethumbrect_V;
    
      Bmp_skinrect_H := FBmp_skinrect_H;
      Bmp_activeupbuttonrect_H := FBmp_activeupbuttonrect_H;
      Bmp_activedownbuttonrect_H := FBmp_activedownbuttonrect_H;
      Bmp_thumbrect_H := FBmp_thumbrect_H;
      Bmp_activethumbrect_H := FBmp_activethumbrect_H;
    
      if FKind = sbVertical then
      begin
        SkinCtrl := FVScrollCtrl;
        with SkinCtrl do
        begin
          SkinRect := Rect(0, 0, Bmp_skinrect_V.Width, Bmp_skinrect_V.Height);
          ActiveUpButtonRect := Rect(0, 0, Bmp_activeupbuttonrect_V.Width, Bmp_activeupbuttonrect_V.Height);
          ActiveDownButtonRect := Rect(0, 0, Bmp_activedownbuttonrect_V.Width, Bmp_activedownbuttonrect_V.Height);
          ThumbRect := Rect(0, 0, Bmp_thumbrect_V.Width, Bmp_thumbrect_V.Height);
          ActiveThumbRect := Rect(0, 0, Bmp_activethumbrect_V.Width, Bmp_activethumbrect_V.Height);
        end;
      end
      else
      begin
        SkinCtrl := FHScrollCtrl;
        with SkinCtrl do
        begin
          SkinRect := Rect(0, 0, Bmp_skinrect_H.Width, Bmp_skinrect_H.Height);
          ActiveUpButtonRect := Rect(0, 0, Bmp_activeupbuttonrect_H.Width, Bmp_activeupbuttonrect_H.Height);
          ActiveDownButtonRect := Rect(0, 0, Bmp_activedownbuttonrect_H.Width, Bmp_activedownbuttonrect_H.Height);
          ThumbRect := Rect(0, 0, Bmp_thumbrect_H.Width, Bmp_thumbrect_H.Height);
          ActiveThumbRect := Rect(0, 0, Bmp_activethumbrect_H.Width, Bmp_activethumbrect_H.Height);
        end;
      end;
    
      FPageSize := 20;
    
      { Offset }
      if FKind = sbVertical then
      begin
        R := VTrackRect;
        if RectWidth(SkinCtrl.SkinRect) < RectWidth(R) then
          MoveWindowOrg(Cnvs.Handle, RectWidth(R) - RectWidth(SkinCtrl.SkinRect), 0);
      end
      else
      begin
        R := HTrackRect;
        if RectHeight(SkinCtrl.SkinRect) < RectHeight(R) then
          MoveWindowOrg(Cnvs.Handle, 0, RectHeight(R) - RectHeight(SkinCtrl.SkinRect));
      end;
    
      if I = CLIENT then
      begin
        if FKind = sbVertical then
          R := VScrollRect
        else
          R := HScrollRect;
    
        with SkinCtrl do
        begin
          if IsNullRect(SkinRect) then
            ResizeMode := -1
          else if (RBPoint.X <> 0) and (RBPoint.Y <> 0) then
            ResizeMode := 1
          else if (RTPoint.X <> 0) or (RTPoint.Y <> 0) then
            ResizeMode := 2
          else if (LBPoint.X <> 0) or (LBPoint.Y <> 0) then
            ResizeMode := 3
          else
            ResizeMode := 0;
    
          if RectWidth(R) * RectHEight(R) > 0 then
          begin
            B := TBitmap.Create;
            B.Width := RectWidth(R);
            B.Height := RectHeight(R);
            R1 := SkinRect;
            if FKind = sbVertical then
              Bmp_r1 := Bmp_skinrect_V
            else
              Bmp_r1 := Bmp_skinrect_H;
    
            case ResizeMode of
              0:
                begin
                  B.Canvas.CopyRect(Rect(0, 0, B.Width, B.Height), Bmp_r1.Canvas, R1);
                end;
              1: CreateSkinImage(LTPoint, RTPoint, LBPoint, RBPoint, CLRect,
                  NewLtPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewCLRect,
                  B, Bmp_r1, R1, B.Width, B.Height, True,
                  LeftStretch, TopStretch, RightStretch, BottomStretch,
                  StretchEffect, StretchType);
    
              2: CreateHSkinImage(LTPoint.X, RectWidth(SkinRect) - RTPoint.X,
                  B, Bmp_r1, R1, B.Width, B.Height, StretchEffect);
              3: CreateVSkinImage(LTPoint.Y, RectHeight(SkinRect) - LBPoint.Y,
                  B, Bmp_r1, R1, B.Width, B.Height, StretchEffect);
            end;
            Cnvs.Draw(R.Left, R.Top, B);
            B.Free;
          end;
        end; //end for "with SkinCtrl do"
      end; //end for "if I = CLIENT then"
    
      if I = THUMB then
      begin
        if FKind = sbVertical then
        begin
          if RectHeight(VTrackRect) = 0 then Exit;
    
          R := VSliderRect;
          if (VSliderState = bsasbPressed) and (not IsNullRect(SkinCtrl.DownThumbRect)) then
          begin
            R1 := SkinCtrl.DownThumbRect;
            Bmp_r1 := Bmp_skinrect_V; //Add
          end
          else if (VSliderState = bsasbHot) and sMouseInControl and (not IsNullRect(SkinCtrl.ActiveThumbRect)) then
          begin
            R1 := SkinCtrl.ActiveThumbRect;
            Bmp_r1 := Bmp_activethumbrect_V; //Add
          end
          else
          begin
            R1 := SkinCtrl.ThumbRect;
            Bmp_r1 := Bmp_thumbrect_V; //Add
          end;
    
          TrackR := SkinCtrl.TrackArea;
          TrackR.Bottom := RectHeight(VScrollRect) - (RectHeight(SkinCtrl.SkinRect) - SkinCtrl.TrackArea.Bottom);
          OffsetRect(TrackR, VScrollRect.Left, VScrollRect.Top);
    
          R.Left := R.Left + SkinCtrl.TrackArea.Left + ((RectWidth(SkinCtrl.TrackArea) - RectWidth(SkinCtrl.ThumbRect)) div 2);
          R.Top := TrackR.Top + Round(((R.Top - VTrackRect.Top) / RectHeight(VTrackRect)) * RectHeight(TrackR)) + 1;
          R.Bottom := TrackR.Top + Round(((R.Bottom - VTrackRect.Top) / RectHeight(VTrackRect)) * RectHeight(TrackR)) + 1;
    
          MinH := RectHeight(SkinCtrl.ThumbRect);
          if SkinCtrl.ThumbMinSize > 0 then MinH := SkinCtrl.ThumbMinSize;
    
          if RectHeight(R) < MinH then
          begin
            X := ((R.Top + R.Bottom) div 2);
            R.Top := X - (MinH div 2);
            R.Bottom := X + (MinH div 2);
            if R.Bottom > VScrollRect.Bottom - (MinH - SkinCtrl.TrackArea.Bottom) then
            begin
              R.Bottom := VScrollRect.Bottom - (MinH - SkinCtrl.TrackArea.Bottom);
              R.Top := R.Bottom - MinH;
            end;
            if R.Top < VScrollRect.Top + SkinCtrl.TrackArea.Top then
            begin
              R.Top := VScrollRect.Top + SkinCtrl.TrackArea.Top;
              R.Bottom := R.Top + MinH;
            end;
          end;
        end //end for "if FKind = sbVertical then"
        else
        begin
          R := HSliderRect;
          if RectWidth(HTrackRect) = 0 then Exit;
          if (HSliderState = bsasbPressed) and (not IsNullRect(SkinCtrl.DownThumbRect)) then
          begin
            R1 := SkinCtrl.DownThumbRect;
            Bmp_r1 := Bmp_skinrect_H; //Add
          end
          else if (HSliderState = bsasbHot) and sMouseInControl and (not IsNullRect(SkinCtrl.ActiveThumbRect)) then
          begin
            R1 := SkinCtrl.ActiveThumbRect;
            Bmp_r1 := Bmp_activethumbrect_H; //Add
          end
          else
          begin
            R1 := SkinCtrl.ThumbRect;
            Bmp_r1 := Bmp_thumbrect_H; //Add
          end;
    
          TrackR := SkinCtrl.TrackArea;
          TrackR.Right := RectWidth(HScrollRect) - (RectWidth(SkinCtrl.SkinRect) - SkinCtrl.TrackArea.Right);
          OffsetRect(TrackR, HScrollRect.Left, HScrollRect.Top);
    
          R.Top := R.Top + SkinCtrl.TrackArea.Top + ((RectHeight(SkinCtrl.TrackArea) - RectHeight(SkinCtrl.ThumbRect)) div 2);
          R.Left := TrackR.Left + Round(((R.Left - HTrackRect.Left) / RectWidth(HTrackRect)) * RectWidth(TrackR)) + 1;
          R.Right := TrackR.Left + Round(((R.Right - HTrackRect.Left) / RectWidth(HTrackRect)) * RectWidth(TrackR)) + 1;
    
          MinW := RectWidth(SkinCtrl.ThumbRect);
          if SkinCtrl.ThumbMinSize > 0 then MinW := SkinCtrl.ThumbMinSize;
    
          if RectWidth(R) < MinW then
          begin
            X := ((R.Left + R.Right) div 2);
            R.Left := X - (MinW div 2);
            R.Right := X + (MinW div 2);
            if R.Right > HScrollRect.Right - (MinW - SkinCtrl.TrackArea.Right) then
            begin
              R.Right := HScrollRect.Right - (MinW - SkinCtrl.TrackArea.Right);
              R.Left := R.Right - MinW;
            end;
            if R.Left < HScrollRect.Left + SkinCtrl.TrackArea.Left then
            begin
              R.Left := HScrollRect.Left + SkinCtrl.TrackArea.Left;
              R.Right := R.Left + MinW;
            end;
          end;
        end;
    
        if RectHeight(R) * RectWidth(R) > 0 then
        begin
          ThumbB := TBitMap.Create;
          ThumbB.Width := RectWidth(R);
          ThumbB.Height := RectHeight(R);
          if FPageSize = 0 then
            ThumbB.Canvas.CopyRect(Rect(0, 0, ThumbB.Width, ThumbB.Height), Bmp_r1.Canvas, R1)
          else
            case FKind of
              sbHorizontal:
                CreateHSkinImage(SkinCtrl.ThumbOffset1, SkinCtrl.ThumbOffset2, ThumbB, Bmp_r1, R1,
                  ThumbB.Width, ThumbB.Height, SkinCtrl.ThumbStretchEffect);
              sbVertical:
                CreateVSkinImage(SkinCtrl.ThumbOffset1, SkinCtrl.ThumbOffset2, ThumbB, Bmp_r1, R1,
                  ThumbB.Width, ThumbB.Height, SkinCtrl.ThumbStretchEffect);
            end;
    
          // draw glyph
          if FKind = sbVertical then
          begin
            if (VSliderState = bsasbPressed) and sMouseInControl and (not IsNullRect(SkinCtrl.DownGlyphRect)) then
            begin
              R1 := SkinCtrl.DownGlyphRect;
              Bmp_r1 := Bmp_skinrect_V; //Add
            end
            else if (VSliderState = bsasbHot) and sMouseInControl and (not IsNullRect(SkinCtrl.ActiveGlyphRect)) then
            begin
              R1 := SkinCtrl.ActiveGlyphRect;
              Bmp_r1 := Bmp_skinrect_V; //Add
            end
            else
            begin
              R1 := SkinCtrl.GlyphRect;
              Bmp_r1 := Bmp_skinrect_V; //Add
            end;
          end
          else
          begin
            if (HSliderState = bsasbPressed) and sMouseInControl and (not IsNullRect(SkinCtrl.DownGlyphRect)) then
            begin
              R1 := SkinCtrl.DownGlyphRect;
              Bmp_r1 := Bmp_skinrect_H; //Add
            end
            else
              if (HSliderState = bsasbHot) and sMouseInControl and (not IsNullRect(SkinCtrl.ActiveGlyphRect)) then
              begin
                R1 := SkinCtrl.ActiveGlyphRect;
                Bmp_r1 := Bmp_skinrect_H; //Add
              end
              else
              begin
                R1 := SkinCtrl.GlyphRect;
                Bmp_r1 := Bmp_skinrect_H; //Add
              end;
          end;
    
          if not IsNullRect(R1) then
          begin
            R2 := Rect(ThumbB.Width div 2 - RectWidth(R1) div 2,
              ThumbB.Height div 2 - RectHeight(R1) div 2,
              ThumbB.Width div 2 - RectWidth(R1) div 2 + RectWidth(R1),
              ThumbB.Height div 2 - RectHeight(R1) div 2 + RectHeight(R1));
            if SkinCtrl.GlyphTransparent then
            begin
              GlyphB := TBitMap.Create;
              GlyphB.Width := RectWidth(R1);
              GlyphB.Height := RectHeight(R1);
              GlyphB.Canvas.CopyRect(Rect(0, 0, GlyphB.Width, GlyphB.Height),
                Bmp_r1.Canvas, R1);
              GlyphB.Transparent := True;
              GlyphB.TransparentMode := tmFixed;
              GlyphB.TransparentColor := SkinCtrl.GlyphTransparentColor;
              ThumbB.Canvas.Draw(R2.Left, R2.Top, GlyphB);
              GlyphB.Free;
            end
            else
              ThumbB.Canvas.CopyRect(R2, Bmp_r1.Canvas, R1);
          end;
          //
    
          if SkinCtrl.ThumbTransparent then
          begin
            ThumbB.Transparent := True;
            ThumbB.TransparentMode := tmFixed;
            ThumbB.TransparentColor := SkinCtrl.ThumbTransparentColor;
          end;
    
          Cnvs.Draw(R.Left, R.Top, ThumbB);
          ThumbB.Free;
        end;
      end
      else
      begin
        R1 := NullRect;
        if FKind = sbVertical then
          Bmp_r1 := Bmp_skinrect_V //Add
        else
          Bmp_r1 := Bmp_skinrect_H; //Add
    
        if FKind = sbVertical then
        begin
          case I of
            UPBUTTON:
              begin
                if (VUpState = bsasbPressed) and sMouseInControl then
                begin
                  R1 := SkinCtrl.DownUpButtonRect;
                  Bmp_r1 := Bmp_skinrect_V; //Add
                  if IsNullRect(R1) then
                  begin
                    R1 := SkinCtrl.ActiveUpButtonRect;
                    Bmp_r1 := Bmp_activeupbuttonrect_V; //Add
                  end;
                end
                else
                  if (VUpState = bsasbHot) and sMouseInControl and (not IsNullRect(SkinCtrl.ActiveUpButtonRect)) then
                  begin
                    R1 := SkinCtrl.ActiveUpButtonRect;
                    Bmp_r1 := Bmp_activeupbuttonrect_V; //Add
                  end
                  else
                  begin
                    R1 := SkinCtrl.UpButtonRect;
                    Bmp_r1 := Bmp_skinrect_V; //Add
                    OffsetRect(R1, SkinCtrl.SkinRect.Left, SkinCtrl.SkinRect.Top);
                  end;
    
                R := VDownButtonRect;
                OffsetRect(R, SkinCtrl.UpButtonRect.Left, RectHeight(R) - (RectHeight(SkinCtrl.SkinRect) - SkinCtrl.UpButtonRect.Top));
              end;
            DOWNBUTTON:
              begin
                if (VDownState = bsasbPressed) and sMouseInControl then
                begin
                  R1 := SkinCtrl.DownDownButtonRect;
                  Bmp_r1 := Bmp_skinrect_V; //Add
                  if IsNullRect(R1) then
                  begin
                    R1 := SkinCtrl.ActiveDownButtonRect;
                    Bmp_r1 := Bmp_activedownbuttonrect_V; //Add
                  end;
                end
                else if (VDownState = bsasbHot) and sMouseInControl and (not IsNullRect(SkinCtrl.ActiveUpButtonRect)) then
                begin
                  R1 := SkinCtrl.ActiveDownButtonRect;
                  Bmp_r1 := Bmp_activedownbuttonrect_V; //Add
                end
                else
                begin
                  R1 := SkinCtrl.DownButtonRect;
                  Bmp_r1 := Bmp_skinrect_V; //Add
                  OffsetRect(R1, SkinCtrl.SkinRect.Left, SkinCtrl.SkinRect.Top);
                end;
    
                R := VUpButtonRect;
                OffsetRect(R, SkinCtrl.DownButtonRect.Left, SkinCtrl.DownButtonRect.Top);
              end
          end;
        end
        else
        begin
          case I of
            UPBUTTON:
              begin
                if (HUpState = bsasbPressed) and sMouseInControl then
                begin
                  R1 := SkinCtrl.DownUpButtonRect;
                  Bmp_r1 := Bmp_skinrect_H; //Add
                  if IsNullRect(R1) then
                  begin
                    R1 := SkinCtrl.ActiveUpButtonRect;
                    Bmp_r1 := Bmp_activeupbuttonrect_H; //Add
                  end;
                end
                else
                  if (HUpState = bsasbHot) and sMouseInControl and (not IsNullRect(SkinCtrl.ActiveUpButtonRect)) then
                  begin
                    R1 := SkinCtrl.ActiveUpButtonRect;
                    Bmp_r1 := Bmp_activeupbuttonrect_H; //Add
                  end
                  else
                  begin
                    R1 := SkinCtrl.UpButtonRect;
                    Bmp_r1 := Bmp_skinrect_H; //Add
                    OffsetRect(R1, SkinCtrl.SkinRect.Left, SkinCtrl.SkinRect.Top);
                  end;
    
                R := HDownButtonRect;
                OffsetRect(R, RectWidth(R) - (RectWidth(SkinCtrl.SkinRect) - SkinCtrl.UpButtonRect.Left), SkinCtrl.UpButtonRect.Top);
              end;
            DOWNBUTTON:
              begin
                if (HDownState = bsasbPressed) and sMouseInControl then
                begin
                  R1 := SkinCtrl.DownDownButtonRect;
                  Bmp_r1 := Bmp_skinrect_H; //Add
                  if IsNullRect(R1) then
                  begin
                    R1 := SkinCtrl.ActiveDownButtonRect;
                    Bmp_r1 := Bmp_activedownbuttonrect_H; //Add
                  end;
                end
                else
                  if (HDownState = bsasbHot) and sMouseInControl and (not IsNullRect(SkinCtrl.ActiveUpButtonRect)) then
                  begin
                    R1 := SkinCtrl.ActiveDownButtonRect;
                    Bmp_r1 := Bmp_activedownbuttonrect_H; //Add
                  end
                  else
                  begin
                    R1 := SkinCtrl.DownButtonRect;
                    Bmp_r1 := Bmp_skinrect_H; //Add
                    OffsetRect(R1, SkinCtrl.SkinRect.Left, SkinCtrl.SkinRect.Top);
                  end;
    
                R := HUpButtonRect;
                OffsetRect(R, SkinCtrl.DownButtonRect.Left, SkinCtrl.DownButtonRect.Top);
              end
          end;
        end;
        if not IsNullRect(R1) then
          BitBlt(Cnvs.Handle, R.Left, R.Top, RectWidth(R1), RectHeight(R1), Bmp_r1.Canvas.Handle,
            R1.Left, R1.Top, SRCCOPY);
      end;
    
      { Restore Offset }
      if FKind = sbVertical then
      begin
        R := VTrackRect;
        if RectWidth(SkinCtrl.SkinRect) < RectWidth(R) then
          MoveWindowOrg(Cnvs.Handle, -(RectWidth(R) - RectWidth(SkinCtrl.SkinRect)), 0);
      end
      else
      begin
        R := HTrackRect;
        if RectHeight(SkinCtrl.SkinRect) < RectHeight(R) then
          MoveWindowOrg(Cnvs.Handle, 0, -(RectHeight(R) - RectHeight(SkinCtrl.SkinRect)));
      end;
    end;
    
    procedure TAQSkinScrollBar.EMLINEINDEX(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      PaintScroll;
    end;
    
    function TAQSkinScrollBar.GetBorderTopLeft: TPoint;
    var
      PWnd: HWnd;
      CP, PP: TPoint;
    begin
      Result := Point(0, 0);
    
      PWnd := GetParent(Handle);
      CP := Point(0, 0);
      ClientToScreen(Handle, CP);
    
      with GetBoundsRect do
        PP := Point(Left, Top);
      ClientToScreen(PWnd, PP);
    
      Result := Point(CP.X - PP.X, CP.Y - PP.Y);
    end;
    
    function TAQSkinScrollBar.GetBoundsRect: TRect;
    begin
      if (Control <> nil) and (Control is TGraphicControl) and
        (Control.Parent = nil) then
      begin
        Result := Rect(0, 0, 0, 0);
        Exit;
      end;
    
      if FControl <> nil then
        Result := Rect(FControl.Left, FControl.Top, FControl.Left + FControl.Width, FControl.Top + FControl.Height)
      else
        if FHandle <> 0 then
          Windows.GetWindowRect(Handle, Result)
        else
          Result := Rect(0, 0, 0, 0);
    end;
    
    function TAQSkinScrollBar.GetEnabled: Boolean;
    begin
      if FControl <> nil then
        Result := FControl.Enabled
      else
        Result := True;
    end;
    
    function TAQSkinScrollBar.GetHeight: Integer;
    var
      R: TRect;
    begin
      if (Control <> nil) and (Control is TGraphicControl) and
        (Control.Parent = nil) then
      begin
        Result := 0;
        Exit;
      end;
    
      if FControl <> nil then
        Result := FControl.Height
      else
        if FHandle <> 0 then
        begin
          Windows.GetClientRect(Handle, R);
          Result := R.Bottom;
        end
        else
          Result := 0;
    end;
    
    function TAQSkinScrollBar.GetWidth: Integer;
    var
      R: TRect;
    begin
      if (Control <> nil) and (Control is TGraphicControl) and
        (Control.Parent = nil) then
      begin
        Result := 0;
        Exit;
      end;
    
      if FControl <> nil then
        Result := FControl.Width
      else
        if FHandle <> 0 then
        begin
          Windows.GetClientRect(Handle, R);
          Result := R.Right;
        end
        else
          Result := 0;
    end;
    
    function TAQSkinScrollBar.HaveBorder: Boolean;
    var
      S, ExS: Cardinal;
    begin
      S := GetWindowLong(Handle, GWL_STYLE);
      ExS := GetWindowLong(Handle, GWL_EXSTYLE);
      if S and WS_BORDER = WS_BORDER then
        Result := True
      else
        Result := False;
      if ExS and WS_EX_CLIENTEDGE = WS_EX_CLIENTEDGE then
        Result := True
      else
        Result := False;
    end;
    
    function TAQSkinScrollBar.HDownButtonRect: TRect;
    begin
      Result := HScrollRect;
      if RectHeight(Result) > 0 then
      begin
        Result.Left := Result.Right - RectHeight(Result);
      end
      else
        Result := Rect(0, 0, 0, 0);
    end;
    
    procedure TAQSkinScrollBar.HDrawScroll(DC: HDC);
    var
      //  R: TRect;
      Canvas: TCanvas;
      //  P: TPoint;
      i: Integer;
      //  X, Y: Integer;
    begin
      if Handle = 0 then Exit;
      if DC = 0 then Exit;
    
      Canvas := TCanvas.Create;
      Canvas.Handle := DC;
    
    
      { Fill back }
    
      Canvas.Brush.Color := FBtnFace;
      Canvas.FillRect(Rect(0, 0, Width, Height));
    
      { Draw Hscroll }
      if RectHeight(HScrollRect) > 0 then
      begin
        FKind := sbHorizontal;
        DrawButton(Canvas, CLIENT);
        for i := 1 to BUTCOUNT - 1 do
          DrawButton(Canvas, i);
        if not HScrollDisabled then
          DrawButton(Canvas, THUMB);
      end;
    
    
      Canvas.Handle := 0;
      Canvas.Free;
    end;
    
    function TAQSkinScrollBar.HScrollDisabled: Boolean;
    var
      //  P: TPoint;
      BarInfo: TScrollBarInfo;
    begin
      BarInfo.cbSize := SizeOf(BarInfo);
      GetScrollBarInfo(Handle, integer(OBJID_HSCROLL), BarInfo);
      if STATE_SYSTEM_UNAVAILABLE and BarInfo.rgstate[0] = STATE_SYSTEM_UNAVAILABLE then
        Result := True
      else
        Result := False;
    end;
    
    function TAQSkinScrollBar.HScrollRect: TRect;
    var
      P: TPoint;
      BarInfo: TScrollBarInfo;
    begin
      BarInfo.cbSize := SizeOf(BarInfo);
      GetScrollBarInfo(Handle, integer(OBJID_HSCROLL), BarInfo);
      if STATE_SYSTEM_INVISIBLE and BarInfo.rgstate[0] <> 0 then
        Result := Rect(0, 0, 0, 0)
      else
      begin
        P := BarInfo.rcScrollBar.TopLeft;
        Windows.ScreenToClient(Handle, P);
        Result.TopLeft := P;
        P := BarInfo.rcScrollBar.BottomRight;
        Windows.ScreenToClient(Handle, P);
        Result.BottomRight := P;
        with GetBorderTopLeft do
          OffsetRect(Result, X, Y);
      end;
    end;
    
    function TAQSkinScrollBar.HSliderRect: TRect;
    var
      Offset: Integer;
      P: TPoint;
      BarInfo: TScrollBarInfo;
    begin
      BarInfo.cbSize := SizeOf(BarInfo);
      GetScrollBarInfo(Handle, integer(OBJID_HSCROLL), BarInfo);
      if STATE_SYSTEM_INVISIBLE and BarInfo.rgstate[0] <> 0 then
        Result := Rect(0, 0, 0, 0)
      else
      begin
        P := BarInfo.rcScrollBar.TopLeft;
        Windows.ScreenToClient(Handle, P);
        Result.TopLeft := P;
        P := BarInfo.rcScrollBar.BottomRight;
        Windows.ScreenToClient(Handle, P);
        Result.BottomRight := P;
    
        with GetBorderTopLeft do
          OffsetRect(Result, X, Y);
    
        Offset := Result.Left;
        Result.Left := Offset + BarInfo.xyThumbTop - 1;
        Result.Right := Offset + BarInfo.xyThumbBottom - 1;
      end;
    end;
    
    function TAQSkinScrollBar.HTrackRect: TRect;
    begin
      Result := HScrollRect;
      if RectWidth(Result) > 0 then
      begin
        Result.Left := Result.Left + RectHeight(Result);
        Result.Right := Result.Right - RectHeight(Result);
      end
      else
        Result := Rect(0, 0, 0, 0);
    end;
    
    function TAQSkinScrollBar.HUpButtonRect: TRect;
    begin
      Result := HScrollRect;
      if RectHeight(Result) > 0 then
      begin
        Result.Right := Result.Left + RectHeight(Result);
      end
      else
        Result := Rect(0, 0, 0, 0);
    end;
    
    function TAQSkinScrollBar.IsPopupWindow: Boolean;
    begin
      Result := (GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOOLWINDOW = WS_EX_TOOLWINDOW) or
        (GetWindowLong(Handle, GWL_STYLE) and WS_POPUP = WS_POPUP);
    end;
    
    procedure TAQSkinScrollBar.NewWindowProc(var Message: TMessage);
    const
      WM_VTChangeState = WM_APP + 32;
    begin
      case Message.Msg of
        CM_BENCPAINT: CMBENCPaint(Message);
        CM_SENCPAINT: CMSENCPaint(Message);
        WM_LBUTTONDOWN: WMLButtonDown(TWMMouse(Message));
        WM_LBUTTONUP: WMLButtonUp(TWMMouse(Message));
        WM_NCLBUTTONDBLCLK: WMNCLButtonDblClk(TWMMouse(Message));
        WM_NCLBUTTONDOWN: WMNCLButtonDown(TWMMouse(Message));
        WM_NCMOUSEMOVE: WMNCMouseMove(TWMNCHitMessage(Message));
        WM_NCLBUTTONUP: WMNCLButtonUp(TWMMouse(Message));
        WM_MOUSEMOVE: WMMouseMove(TWMMouse(Message));
        WM_NCPAINT: WMNCPaint(TWMNCPaint(Message));
        WM_ERASEBKGND: WMEraseBkgnd(message);
        WM_MOUSEWHEEL: WMMouseWheel(message);
        WM_VSCROLL: WMVScroll(message);
        WM_HSCROLL: WMHScroll(message);
        WM_SIZE: WMSize(message);
        WM_KEYDOWN: WMKeyDown(message);
        WM_CAPTURECHANGED: WMCAPTURECHANGED(message);
        WM_VTChangeState: WMVTChangeState(message);
        CM_VISIBLECHANGED: CMVisibleChanged(message);
        CM_MOUSEENTER: CMMouseEnter(message);
        CM_MOUSELEAVE: CMMouseLeave(message);
        EM_LINEINDEX: EMLINEINDEX(message);
        WM_WINDOWPOSCHANGING: WMWindowPosChanging(TWMWindowPosChanged(Message));
        WM_WINDOWPOSCHANGED: WMWindowPosChanged(TWMWindowPosChanged(Message));
        WM_UNDO, WM_CUT, WM_PASTE, WM_CLEAR, EM_REPLACESEL: OnContextPopupAction(Message);
      else
        FOldWinProc(Message);
      end;
    end;
    
    procedure TAQSkinScrollBar.OnContextPopupAction(var Message: TMessage);
    begin
      FOldWinProc(Message);
      PaintScroll;
    end;
    
    procedure TAQSkinScrollBar.Paint(Canvas: TCanvas);
    begin
    
    end;
    
    procedure TAQSkinScrollBar.PaintBorder(Canvas: TCanvas; R: TRect);
    var //这些是叼毛
      LTPoint, RTPoint, LBPoint, RBPoint: TPoint;
      SkinRect, ClRect: TRect;
      LeftStretch, TopStretch, RightStretch, BottomStretch: Boolean;
    var
      //  R1, R2: TRect;
      Picture: TBitmap;
      //  SkinCtrl: TDataSkinMemoControl;
    
      //  FIndex: Integer;
      NewClRect: TRect;
      NewLTPoint, NewRTPoint, NewLBPoint, NewRBPoint: TPoint;
      LeftB, TopB, RightB, BottomB: TBitMap;
      OffX, OffY: Integer;
      //  X, Y: Integer;
    var
      GripSize: Integer;
    begin
    
    
      LTPoint := Point(6, 5);
      RTPoint := Point(52, 6);
      LBPoint := Point(4, 46);
      RBPoint := Point(53, 45);
    
      SkinRect := rect(224, 347, 283, 399);
    
      ClRect := rect(1, 1, 57, 51);
      LeftStretch := False;
      TopStretch := False;
      RightStretch := False;
      BottomStretch := False;
      (*
        LTPoint:=
        RTPoint:=
        LBPoint:=leftbottompoint=4,46
      RBPoint:=rightbottompoint=53,45
    
        skinrect=
       clientrect=
    
       leftstretch=0
      topstretch=0
      rightstretch=0
      bottomstretch=0
      *)
    
      SkinRect := rect(0, 0, FBmp_Border.Width, FBmp_Border.Height);
      Picture := FBmp_Border;
    
    
      LeftB := TBitMap.Create;
      TopB := TBitMap.Create;
      RightB := TBitMap.Create;
      BottomB := TBitMap.Create;
    
      OffX := FControl.Width - RectWidth(SkinRect);
      OffY := FControl.Height - RectHeight(SkinRect);
    
      NewLTPoint := LTPoint;
      NewRTPoint := Point(RTPoint.X + OffX, RTPoint.Y);
      NewLBPoint := Point(LBPoint.X, LBPoint.Y + OffY);
      NewRBPoint := Point(RBPoint.X + OffX, RBPoint.Y + OffY);
      NewClRect := Rect(ClRect.Left, ClRect.Top,
        ClRect.Right + OffX, ClRect.Bottom + OffY);
    
      CreateSkinBorderImages(LTPoint, RTPoint, LBPoint, RBPoint, CLRect,
        NewLtPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewCLRect,
        LeftB, TopB, RightB, BottomB, Picture, SkinRect, Width, Height,
        LeftStretch, TopStretch, RightStretch, BottomStretch);
    
      Canvas.Draw(0, 0, TopB);
      Canvas.Draw(0, TopB.Height, LeftB);
      Canvas.Draw(FControl.Width - RightB.Width, TopB.Height, RightB);
      Canvas.Draw(0, FControl.Height - BottomB.Height, BottomB);
    
      TopB.Free;
      LeftB.Free;
      RightB.Free;
      BottomB.Free;
      //===============================
      Canvas.Brush.Color := FBtnFace;
      GripSize := GetSystemMetrics(SM_CXVSCROLL);
      if Self.HaveBorder then
        Canvas.FillRect(Rect(Width - GripSize - 2, Height - GripSize - 2, Width - 2, Height - 2))
      else
        Canvas.FillRect(Rect(Width - GripSize, Height - GripSize, Width, Height));
    end;
    
    procedure TAQSkinScrollBar.PaintScroll;
    begin
      { Paint scrollbars }
      if VScrollWnd <> nil then
      begin
        VScrollWnd.Invalidate;
      end;
      if HScrollWnd <> nil then
      begin
        HScrollWnd.Invalidate;
      end;
    end;
    
    procedure TAQSkinScrollBar.SetControl(Value: TControl);
    begin
      if FControl <> nil then
      begin
        if @FOldWinProc <> nil then FControl.WindowProc := FOldWinProc;
      end;
      FControl := Value;
      FOldWinProc := FControl.WindowProc;
      FControl.WindowProc := NewWindowProc;
    
      if (FControl is TWinControl) then
        FHandle := TWinControl(FControl).Handle
      else
        FHandle := 0;
    
      if VScrollWnd <> nil then FreeAndNil(VScrollWnd);
      VScrollWnd := TWinScroll.CreateParented(Control.Parent.Handle);
      VScrollWnd.DoubleBuffered := True;
      TWinScroll(VScrollWnd).FSubclass := Self;
      TWinScroll(VScrollWnd).FVertical := True;
      with VScrollRect do
        if IsPopupWindow
          then
          SetWindowPos(VScrollWnd.Handle, HWND_TOPMOST, Control.Left + Left, Control.Top + Top, Right - Left, Bottom - Top, SWP_NOREDRAW)
        else
          SetWindowPos(VScrollWnd.Handle, HWND_TOP, Control.Left + Left, Control.Top + Top, Right - Left, Bottom - Top, SWP_NOREDRAW);
    
      if IsRectEmpty(VScrollRect) then
        ShowWindow(VScrollWnd.Handle, SW_HIDE)
      else
        ShowWindow(VScrollWnd.Handle, SW_SHOW);
    
      if HScrollWnd <> nil then FreeAndNil(HScrollWnd);
      HScrollWnd := TWinScroll.CreateParented(Control.Parent.Handle);
      HScrollWnd.DoubleBuffered := True;
      TWinScroll(HScrollWnd).FSubclass := Self;
      TWinScroll(HScrollWnd).FVertical := False;
      with HScrollRect do
        if IsPopupWindow
          then
          SetWindowPos(HScrollWnd.Handle, HWND_TOPMOST, Control.Left + Left, Control.Top + Top, Right - Left, Bottom - Top, SWP_NOREDRAW)
        else
          SetWindowPos(HScrollWnd.Handle, HWND_TOP, Control.Left + Left, Control.Top + Top, Right - Left, Bottom - Top, SWP_NOREDRAW);
    
      if IsRectEmpty(HScrollRect) then
        ShowWindow(HScrollWnd.Handle, SW_HIDE)
      else
        ShowWindow(HScrollWnd.Handle, SW_SHOW);
    
    
    
    end;
    
    procedure TAQSkinScrollBar.SetHandle(const Value: HWnd);
    begin
    
    end;
    
    procedure TAQSkinScrollBar.UpdateScroll;
    begin
      { Paint scrollbars }
      if (VScrollWnd <> nil) and (VScrollWnd.HandleAllocated) then
      begin
        with VScrollRect do
          if IsPopupWindow then
            SetWindowPos(VScrollWnd.Handle, HWND_TOPMOST,
              Control.Left + Left, Control.Top + Top,
              Right - Left, Bottom - Top, SWP_SHOWWINDOW)
          else
            SetWindowPos(VScrollWnd.Handle, HWND_TOP,
              Control.Left + Left, Control.Top + Top,
              Right - Left, Bottom - Top, SWP_SHOWWINDOW);
      end;
      if (HScrollWnd <> nil) and (HScrollWnd.HandleAllocated) then
      begin
        with HScrollRect do
          if IsPopupWindow then
            SetWindowPos(HScrollWnd.Handle, HWND_TOPMOST,
              Control.Left + Left, Control.Top + Top,
              Right - Left, Bottom - Top, SWP_SHOWWINDOW)
          else
            SetWindowPos(HScrollWnd.Handle, HWND_TOP,
              Control.Left + Left, Control.Top + Top,
              Right - Left, Bottom - Top, SWP_SHOWWINDOW);
      end;
      PaintScroll;
    end;
    
    function TAQSkinScrollBar.VDownButtonRect: TRect;
    begin
      Result := VScrollRect;
      if RectWidth(Result) > 0 then
      begin
        Result.Top := Result.Bottom - RectWidth(Result);
      end
      else
        Result := Rect(0, 0, 0, 0);
    end;
    
    procedure TAQSkinScrollBar.VDrawScroll(DC: HDC);
    var
      //  R: TRect;
      Canvas: TCanvas;
      //  P: TPoint;
      i: Integer;
      //  X, Y: Integer;
    begin
      if Handle = 0 then Exit;
      if DC = 0 then Exit;
    
      Canvas := TCanvas.Create;
      if DC <> 0 then
        Canvas.Handle := DC;
      begin
        { Fill back }
        Canvas.Brush.Color := FBtnFace;
        Canvas.FillRect(Rect(0, 0, Width, Height));
    
        { Draw Vscroll }
        if RectWidth(VScrollRect) > 0 then
        begin
          FKind := sbVertical;
          DrawButton(Canvas, CLIENT);
          for i := 1 to BUTCOUNT - 1 do
            DrawButton(Canvas, i);
          if not VScrollDisabled then
            DrawButton(Canvas, THUMB);
        end;
      end;
    
      Canvas.Handle := 0;
      Canvas.Free;
    end;
    
    function TAQSkinScrollBar.VScrollDisabled: Boolean;
    var
      BarInfo: TScrollBarInfo;
    begin
      BarInfo.cbSize := SizeOf(BarInfo);
      GetScrollBarInfo(Handle, integer(OBJID_VSCROLL), BarInfo);
      if STATE_SYSTEM_UNAVAILABLE and BarInfo.rgstate[0] = STATE_SYSTEM_UNAVAILABLE then
        Result := True
      else
        Result := False;
    end;
    
    function TAQSkinScrollBar.VScrollRect: TRect;
    var
      P: TPoint;
      BarInfo: TScrollBarInfo;
    begin
      BarInfo.cbSize := SizeOf(BarInfo);
      GetScrollBarInfo(Handle, integer(OBJID_VSCROLL), BarInfo);
      if STATE_SYSTEM_INVISIBLE and BarInfo.rgstate[0] <> 0 then
        Result := Rect(0, 0, 0, 0)
      else
      begin
        P := BarInfo.rcScrollBar.TopLeft;
        Windows.ScreenToClient(Handle, P);
        Result.TopLeft := P;
        P := BarInfo.rcScrollBar.BottomRight;
        Windows.ScreenToClient(Handle, P);
        Result.BottomRight := P;
        with GetBorderTopLeft do
          OffsetRect(Result, X, Y);
      end;
    end;
    
    function TAQSkinScrollBar.VSliderRect: TRect;
    var
      Offset: Integer;
      P: TPoint;
      BarInfo: TScrollBarInfo;
    begin
      BarInfo.cbSize := SizeOf(BarInfo);
      GetScrollBarInfo(Handle, integer(OBJID_VSCROLL), BarInfo);
      if STATE_SYSTEM_INVISIBLE and BarInfo.rgstate[0] <> 0 then
        Result := Rect(0, 0, 0, 0)
      else
      begin
        P := BarInfo.rcScrollBar.TopLeft;
        Windows.ScreenToClient(Handle, P);
        Result.TopLeft := P;
        P := BarInfo.rcScrollBar.BottomRight;
        Windows.ScreenToClient(Handle, P);
        Result.BottomRight := P;
    
        with GetBorderTopLeft do
          OffsetRect(Result, X, Y);
    
        Offset := Result.Top;
        Result.Top := Offset + BarInfo.xyThumbTop - 1;
        Result.Bottom := Offset + BarInfo.xyThumbBottom - 1;
      end;
    end;
    
    function TAQSkinScrollBar.VTrackRect: TRect;
    begin
      Result := VScrollRect;
      if RectWidth(Result) > 0 then
      begin
        Result.Top := Result.Top + RectWidth(Result);
        Result.Bottom := Result.Bottom - RectWidth(Result);
      end
      else
        Result := Rect(0, 0, 0, 0)
    end;
    
    function TAQSkinScrollBar.VUpButtonRect: TRect;
    begin
      Result := VScrollRect;
      if RectWidth(Result) > 0 then
      begin
        Result.Bottom := Result.Top + RectWidth(Result);
      end
      else
        Result := Rect(0, 0, 0, 0);
    end;
    
    procedure TAQSkinScrollBar.WMCAPTURECHANGED(var Msg: TMessage);
    begin
      if VUpState = bsasbPressed then
      begin
        VUpState := bsasbNormal;
        PaintScroll;
      end;
      if VDownState = bsasbPressed then
      begin
        VDownState := bsasbNormal;
        PaintScroll;
      end;
      if HUpState = bsasbPressed then
      begin
        HUpState := bsasbNormal;
        PaintScroll;
      end;
      if HDownState = bsasbPressed then
      begin
        HDownState := bsasbNormal;
        PaintScroll;
      end;
    
      FOldWinProc(TMessage(Msg));
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMEraseBkgnd(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      if (Self.Control.ClassName = 'TRichView') or
        (Self.Control.ClassName = 'TRichViewEdit')
        then
        PaintScroll;
    end;
    
    procedure TAQSkinScrollBar.WMHScroll(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMKeyDown(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      PaintScroll;
    end;
    
    procedure TAQSkinScrollBar.WMLButtonDown(var Msg: TWMMouse);
    begin
      FOldWinProc(TMessage(Msg));
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMLButtonUp(var Msg: TWMMouse);
    begin
    
      if VSliderState = bsasbPressed then
      begin
        ReleaseCapture;
        lbtndown := False;
        VSliderState := bsasbNormal;
        PaintScroll;
        Handled := True;
        SendMessage(Handle, WM_VSCROLL, SB_ENDSCROLL, 0);
        Exit;
      end;
    
    
      if HSliderState = bsasbPressed then
      begin
        ReleaseCapture;
        lbtndown := False;
        HSliderState := bsasbNormal;
        PaintScroll;
        Handled := True;
        SendMessage(Handle, WM_HSCROLL, SB_ENDSCROLL, 0);
        Exit;
      end;
    
    
      if VUpState = bsasbPressed then
      begin
        VUpState := bsasbNormal;
      end;
      if VDownState = bsasbPressed then
      begin
        VDownState := bsasbNormal;
      end;
      if HUpState = bsasbPressed then
      begin
        HUpState := bsasbNormal;
      end;
      if HDownState = bsasbPressed then
      begin
        HDownState := bsasbNormal;
      end;
    
      FOldWinProc(TMessage(Msg));
      lbtndown := False;
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMMouseMove(var Msg: TWMMouse);
    var
      SF: TScrollInfo;
      OldCurPos: single;
    begin
      if VSliderState = bsasbPressed then
      begin
        SF.fMask := SIF_ALL;
        SF.cbSize := SizeOf(SF);
        GetScrollInfo(Handle, SB_VERT, SF);
    
    
        OldCurPos := FCurPos;
        FCurPos := FCurPos + (SF.nMax - SF.nMin) * ((Mouse.CursorPos.Y - FOldPos) / RectHeight(VTrackRect));
        if FCurPos < SF.nMin then FCurPos := SF.nMin;
        if FCurPos > SF.nMax then FCurPos := SF.nMax;
        FOldPos := Mouse.CursorPos.Y;
    
        SetScrollPos(Handle, SB_VERT, Round(FCurPos), False);
        PostMessage(Handle, WM_VSCROLL, Integer(SmallPoint(SB_THUMBPOSITION, Round(FCurPos))), 0);
    
        PaintScroll;
        Handled := True;
        Exit;
      end;
      if HSliderState = bsasbPressed then
      begin
        SF.fMask := SIF_ALL;
        SF.cbSize := SizeOf(SF);
        GetScrollInfo(Handle, SB_HORZ, SF);
        OldCurPos := FCurPos;
        FCurPos := FCurPos + (SF.nMax - SF.nMin) * ((Mouse.CursorPos.X - FOldPos) / RectWidth(HTrackRect));
        if FCurPos < SF.nMin then FCurPos := SF.nMin;
        if FCurPos > SF.nMax then FCurPos := SF.nMax;
    
        FOldPos := Mouse.CursorPos.X;
    
        if Control is TCustomListView then
        begin
          TCustomListView(FControl).Scroll(Round(FCurPos - OldCurPos), 0);
        end
        else
        begin
          SetScrollPos(Handle, SB_HORZ, Round(FCurPos), False);
          PostMessage(Handle, WM_HSCROLL, Integer(SmallPoint(SB_THUMBPOSITION, Round(FCurPos))), 0);
        end;
        PaintScroll;
        Handled := True;
        Exit;
      end;
    
      if (HSliderState <> bsasbPressed) and (HSliderState = bsasbHot) then
      begin
        HSliderState := bsasbNormal;
        PaintScroll;
      end;
      if (VSliderState <> bsasbPressed) and (VSliderState = bsasbHot) then
      begin
        VSliderState := bsasbNormal;
        PaintScroll;
      end;
      if (HUpState <> bsasbPressed) and (HUpState = bsasbHot) then
      begin
        HUpState := bsasbNormal;
        PaintScroll;
      end;
      if (HDownState <> bsasbPressed) and (HDownState = bsasbHot) then
      begin
        HDownState := bsasbNormal;
        PaintScroll;
      end;
      if (VUpState <> bsasbPressed) and (VUpState = bsasbHot) then
      begin
        VUpState := bsasbNormal;
        PaintScroll;
      end;
      if (VDownState <> bsasbPressed) and (VDownState = bsasbHot) then
      begin
        VDownState := bsasbNormal;
        PaintScroll;
      end;
    
      FOldWinProc(TMessage(Msg));
      if lbtndown then
        PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMMouseWheel(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMNCLButtonDblClk(var Msg: TWMMouse);
    begin
      WMNCLButtonDown(Msg);
    end;
    
    procedure TAQSkinScrollBar.WMNCLButtonDown(var Msg: TWMMouse);
    var
      P: TPoint;
      SF: TScrollInfo;
      VEnabled, HEnabled: Boolean;
    begin
      P := Point(Msg.XPos, Msg.YPos);
      ScreenToClient(Handle, P);
      with GetBorderTopLeft do
      begin
        P.X := P.X + X;
        P.Y := P.Y + Y;
      end;
    
      VEnabled := not VScrollDisabled;
      HEnabled := not HScrollDisabled;
    
      if PtInRect(VSliderRect, P) then
      begin
        lbtndown := True;
        SF.fMask := SIF_ALL;
        SF.cbSize := SizeOf(SF);
        GetScrollInfo(Handle, SB_VERT, SF);
        FCurPos := SF.nPos;
        FOldPos := Mouse.CursorPos.Y;
        VSliderState := bsasbPressed;
        Handled := True;
        PaintScroll;
        SetCapture(Handle);
        Exit;
      end;
    
      if PtInRect(HSliderRect, P) then
      begin
        lbtndown := True;
        SF.fMask := SIF_ALL;
        SF.cbSize := SizeOf(SF);
        GetScrollInfo(Handle, SB_HORZ, SF);
        FCurPos := SF.nPos;
        FOldPos := Mouse.CursorPos.X;
        HSliderState := bsasbPressed;
        PaintScroll;
        SetCapture(Handle);
        Handled := True;
        Exit;
      end;
    
      if PtInRect(VDownButtonRect, P) and VEnabled then
      begin
        VUpState := bsasbPressed;
      end;
    
      if PtInRect(VUpButtonRect, P) and VEnabled then
      begin
        VDownState := bsasbPressed;
      end;
    
      if PtInRect(HDownButtonRect, P) and HEnabled then
      begin
        HUpState := bsasbPressed;
      end;
    
      if PtInRect(HUpButtonRect, P) and HEnabled then
      begin
        HDownState := bsasbPressed;
      end;
    
      FOldWinProc(TMessage(Msg));
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMNCLButtonUp(var Msg: TWMMouse);
    begin
      if VSliderState = bsasbPressed then
      begin
        lbtndown := False;
        VSliderState := bsasbNormal;
        PaintScroll;
        Handled := True;
        Exit;
      end;
      if HSliderState = bsasbPressed then
      begin
        lbtndown := False;
        HSliderState := bsasbNormal;
        PaintScroll;
        Handled := True;
        Exit;
      end;
    
      if VUpState = bsasbPressed then
      begin
        VUpState := bsasbNormal;
      end;
      if VDownState = bsasbPressed then
      begin
        VDownState := bsasbNormal;
      end;
      if HUpState = bsasbPressed then
      begin
        HUpState := bsasbNormal;
      end;
      if HDownState = bsasbPressed then
      begin
        HDownState := bsasbNormal;
      end;
    
      FOldWinProc(TMessage(Msg));
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMNCMouseMove(var Msg: TWMNCHitMessage);
    var
      SF: TScrollInfo;
      OldCurPos: single;
      P: TPoint;
      VEnabled, HEnabled: Boolean;
    begin
      P := Point(Msg.XCursor, Msg.YCursor);
      ScreenToClient(Handle, P);
      with GetBorderTopLeft do
      begin
        P.X := P.X + X;
        P.Y := P.Y + Y;
      end;
    
      VEnabled := not VScrollDisabled;
      HEnabled := not HScrollDisabled;
    
      if VSliderState <> bsasbPressed then
      begin
        if PtInRect(VSliderRect, P) then
          VSliderState := bsasbHot
        else
          VSliderState := bsasbNormal;
      end;
      if HSliderState <> bsasbPressed then
      begin
        if PtInRect(HSliderRect, P) then
          HSliderState := bsasbHot
        else
          HSliderState := bsasbNormal;
      end;
    
      if (VUpState <> bsasbPressed) and VEnabled then
      begin
        if PtInRect(VDownButtonRect, P) then
          VUpState := bsasbHot
        else
          VUpState := bsasbNormal;
      end;
    
      if (HUpState <> bsasbPressed) and HEnabled then
      begin
        if PtInRect(HDownButtonRect, P) then
          HUpState := bsasbHot
        else
          HUpState := bsasbNormal;
      end;
    
      if (VDownState <> bsasbPressed) and VEnabled then
      begin
        if PtInRect(VUpButtonRect, P) then
          VDownState := bsasbHot
        else
          VDownState := bsasbNormal;
      end;
    
      if (HDownState <> bsasbPressed) and HEnabled then
      begin
        if PtInRect(HUpButtonRect, P) then
          HDownState := bsasbHot
        else
          HDownState := bsasbNormal;
      end;
    
      if VSliderState = bsasbPressed then
      begin
        SF.fMask := SIF_ALL;
        SF.cbSize := SizeOf(SF);
        GetScrollInfo(Handle, SB_VERT, SF);
        OldCurPos := FCurPos;
        FCurPos := FCurPos + (SF.nMax - SF.nMin) * ((Mouse.CursorPos.Y - FOldPos) / RectHeight(VTrackRect));
        if FCurPos < SF.nMin then FCurPos := SF.nMin;
        if FCurPos > SF.nMax then FCurPos := SF.nMax;
    
        FOldPos := Mouse.CursorPos.Y;
    
        if Control is TCustomListView then
        begin
          TCustomListView(FControl).Scroll(0, Round((FCurPos - OldCurPos)));
        end
        else
        begin
          PostMessage(Handle, WM_VSCROLL, Integer(SmallPoint(SB_THUMBPOSITION, Round(FCurPos))), 0);
        end;
        PaintScroll;
        Handled := True;
        Exit;
      end;
      if HSliderState = bsasbPressed then
      begin
        SF.fMask := SIF_ALL;
        SF.cbSize := SizeOf(SF);
        GetScrollInfo(Handle, SB_HORZ, SF);
        OldCurPos := FCurPos;
        FCurPos := FCurPos + (SF.nMax - SF.nMin) * ((Mouse.CursorPos.X - FOldPos) / RectWidth(HTrackRect));
        if FCurPos < SF.nMin then FCurPos := SF.nMin;
        if FCurPos > SF.nMax then FCurPos := SF.nMax;
    
        FOldPos := Mouse.CursorPos.X;
    
        if Control is TCustomListView then
        begin
          TCustomListView(FControl).Scroll(Round(FCurPos - OldCurPos), 0);
        end
        else
          PostMessage(Handle, WM_HSCROLL, Integer(SmallPoint(SB_THUMBPOSITION, Round(FCurPos))), 0);
        PaintScroll;
        Handled := True;
        Exit;
      end;
    
      FOldWinProc(TMessage(Msg));
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMNCPaint(var Msg: TWMNCPaint);
    begin
      FOldWinProc(TMessage(Msg));
      DrawBorder(0, False);
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMSize(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      UpdateScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMVScroll(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMVTChangeState(var Msg: TMessage);
    begin
      FOldWinProc(TMessage(Msg));
      PaintScroll;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMWindowPosChanged(var Msg: TWMWindowPosChanged);
    begin
      FOldWinProc(TMessage(Msg));
      if Msg.WindowPos.Flags and SWP_HIDEWINDOW = SWP_HIDEWINDOW then
      begin
        if VScrollWnd <> nil then
          ShowWindow(VScrollWnd.Handle, SW_HIDE);
        if HScrollWnd <> nil then
          ShowWindow(HScrollWnd.Handle, SW_HIDE);
      end
      else
        if IsWindowVisible(Handle) then
        begin
          UpdateScroll;
          DrawBorder(0, False);
        end;
      Handled := True;
    end;
    
    procedure TAQSkinScrollBar.WMWindowPosChanging(var Msg: TWMWindowPosChanged);
    begin
      if (Control is TScrollBox) and IsWindowVisible(Handle) then
      begin
        UpdateScroll;
      end;
      FOldWinProc(TMessage(Msg));
    end;
    
    end.
    unit AQSkinScrollBar;
  • 相关阅读:
    数据绑定表达式语法(Eval,Bind区别)
    使用博客园的第一件事 自定义主题
    sql2000 跨服务器复制表数据
    使用UpdatePanel 局部刷新出现中文乱码的解决方法!!
    MMC不能打开文件MSC文件
    sql 日期 、时间相关
    loaded AS2 swf call function in AS3 holder
    Rewrite the master page form action attribute in asp.net 2.0
    100万个不重复的8位的随机数
    flash 中实现斜切变型
  • 原文地址:https://www.cnblogs.com/rogge7/p/6178740.html
Copyright © 2011-2022 走看看