MMCtrl.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:30k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49(0)351-8037944               =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/index.html               =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 03.11.98 - 21:39:50 $                                        =}
  24. {========================================================================}
  25. unit MMCtrl;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.     Windows,
  31. {$ELSE}
  32.     WinTypes,
  33.     WinProcs,
  34. {$ENDIF}
  35.     Forms,
  36.     SysUtils,
  37.     Messages,
  38.     Classes,
  39.     Graphics,
  40.     Controls,
  41.     Dialogs,
  42.     ExtCtrls,
  43.     Menus,
  44.     Buttons,
  45.     MMObj,
  46.     MMUtils,
  47.     MMMath,
  48.     MMString,
  49.     MMBmpLst,
  50.     MMObsrv;
  51. type
  52.   TMMOrientation   = (orVertical,orHorizontal);
  53.   TMMZeroPosition  = (zpBottomLeft,zpTopRight);
  54.   TMMGetGylphIndex = procedure(Sender: TObject; IsDown: Boolean; var Index: integer) of object;
  55.   TMMGetBackGround = procedure(Sender: TObject; Bmp: TBitmap; R: TRect) of object;
  56.   {-- TMMBitmapSlider ---------------------------------------------------------}
  57.   TMMBitmapSlider = class(TMMCustomBitmapListControl)
  58.   private
  59.     FAutoSize                : Boolean;
  60.     FDragging                : Boolean;
  61.     FHandCursor              : Boolean;
  62.     FThumbCursor             : TCursor;
  63.     FThumbWidth, FThumbHeight: Byte;
  64.     FMax,FMin,FPosition      : Longint;
  65.     FLineSize                : Integer;
  66.     FPageSize                : Integer;
  67.     FZeroPosition            : TMMZeroPosition;
  68.     FOrientation             : TMMOrientation;
  69.     FSaveBitmap              : TBitmap;
  70.     FDragOffset              : integer;
  71.     FDragVal                 : Longint;
  72.     FThumbRect               : TRect;
  73.     FSensitivity             : integer;
  74.     FLogMode                 : Boolean;
  75.     FNeedTrackEnd            : Boolean;
  76.     FForceChange             : Boolean;
  77.     FMargin                  : integer;
  78.     FNumGlyphs               : integer;
  79.     FNumThumbGlyphs          : integer;
  80.     FBitmapOK                : Boolean;
  81.     FBitmapThumbIndex        : integer;
  82.     FThumbMargin             : integer;
  83.     FOnChange                : TNotifyEvent;
  84.     FOnTrack                 : TNotifyEvent;
  85.     FOnTrackEnd              : TNotifyEvent;
  86.     FOnGetGlyphIndex         : TMMGetGylphIndex;
  87.     FOnGetThumbGlyphIndex    : TMMGetGylphIndex;
  88.     FOnGetBackground         : TMMGetBackGround;
  89.     procedure SetBitmapThumbIndex(aValue: integer);
  90.     procedure SetMargin(aValue: integer);
  91.     procedure SetThumbMargin(aValue: integer);
  92.     procedure UpdateSlider;
  93.     procedure SetAutoSize(aValue: Boolean);
  94.     procedure SetNumThumbGlyphs(aValue: integer);
  95.     procedure SetNumGlyphs(aValue: integer);
  96.     procedure SetMax(aValue: Longint);
  97.     procedure SetMin(aValue: Longint);
  98.     procedure SetOrientation(aValue: TMMOrientation);
  99.     procedure SetZeroPosition(aValue: TMMZeroPosition);
  100.     procedure SetPosition(aValue: Longint);
  101.     function  GetPosition: Longint;
  102.     function  UpdatePosition(aValue: Longint): Boolean;
  103.     procedure SetSensitivity(aValue: integer);
  104.     procedure SetLogMode(aValue: Boolean);
  105.     function  NewPosition(WhereX,WhereY: Integer): Longint;
  106.     function  IsVert: Boolean;
  107.     function  IsInverted: Boolean;
  108.     function  GetSrcRect(index: integer): TRect;
  109.     function  GetThumbSrcRect(index: integer): TRect;
  110.     procedure DrawBitmapImage(Canvas: TCanvas; Bitmap: TBitmap; X,Y: integer; Src: TRect);
  111.     procedure WhereIsThumb(const ClientRect: TRect; var aRect: TRect);
  112.     procedure DrawThumb(Canvas: TCanvas; aRect: TRect);
  113.     procedure RedrawThumb;
  114.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  115.     function  GetThumbBitmap: TBitmap;
  116.   protected
  117.     procedure Change; dynamic;
  118.     procedure Track; dynamic;
  119.     procedure TrackEnd; dynamic;
  120.     procedure Paint; override;
  121.     procedure BitmapChanged; override;
  122.     function  FindTransparentColor: TColor; override;
  123.     procedure SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
  124.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  125.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  126.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  127.     procedure SetThumbCursor(AtThumb: Boolean);
  128.   public
  129.     constructor Create(AOwner: TComponent); override;
  130.     destructor Destroy; override;
  131.     procedure SetMinMax(aMin,aMax: Longint);
  132.     function ThumbBitmapValid: Boolean;
  133.     property ThumbBitmap: TBitmap read GetThumbBitmap;
  134.   published
  135.     property OnDragDrop;
  136.     property OnDragOver;
  137.     property OnEndDrag;
  138.     property OnStartDrag;
  139.     property OnMouseDown;
  140.     property OnMouseMove;
  141.     property OnMouseUp;
  142.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  143.     property OnTrack: TNotifyEvent read FOnTrack write FOnTrack;
  144.     property OnTrackEnd: TNotifyEvent read FOnTrackEnd write FOnTrackEnd;
  145.     property OnGetGlyphIndex: TMMGetGylphIndex read FOnGetGlyphIndex write FOnGetGlyphIndex;
  146.     property OnGetThumbGlyphIndex: TMMGetGylphIndex read FOnGetThumbGlyphIndex write FOnGetThumbGlyphIndex;
  147.     property OnGetBackground: TMMGetBackground read FOnGetBackground write FOnGetBackground;
  148.     property Width default 200;
  149.     property Height default 40;
  150.     property DragCursor;
  151.     property Visible;
  152.     property Enabled;
  153.     property ParentShowHint;
  154.     property PopupMenu;
  155.     property ShowHint;
  156.     property TransparentColor;
  157.     property TransparentMode;
  158.     property BitmapList;
  159.     property BitmapIndex;
  160.     property BitmapBackIndex;
  161.     property BitmapThumbIndex: Integer read FBitmapThumbIndex write SetBitmapThumbIndex default -1;
  162.     property Margin: integer read FMargin write SetMargin default 2;
  163.     property ThumbMargin: integer read FThumbMargin write SetThumbMargin default 0;
  164.     property NumGlyphs: integer read FNumGlyphs write SetNumGlyphs default 1;
  165.     property NumThumbGlyphs: integer read FNumThumbGlyphs write SetNumThumbGlyphs default 1;
  166.     property AutoSize: Boolean read FAutoSize write SetAutoSize default False;
  167.     property HandCursor: Boolean read FHandCursor write FHandCursor default False;
  168.     property ThumbCursor: TCursor read FThumbCursor write FThumbCursor default crDefault;
  169.     property MinValue: Longint read FMin write SetMin default 0;
  170.     property MaxValue: Longint read FMax write SetMax default 10;
  171.     property LineSize: Integer read FLineSize write FLineSize default 1;
  172.     property PageSize: Integer read FPageSize write FPageSize default 5;
  173.     property Orientation: TMMOrientation read FOrientation write SetOrientation default orHorizontal;
  174.     property ZeroPosition: TMMZeroPosition read FZeroPosition write SetZeroPosition default zpBottomLeft;
  175.     property Position: Longint read GetPosition write SetPosition default 0;
  176.     property Logarithmic: Boolean read FLogMode write SetLogMode default False;
  177.     property Sensitivity: Integer read FSensitivity write SetSensitivity default -24;
  178.     property Transparent;
  179.   end;
  180. implementation
  181. {== TMMBitmapSlider ===========================================================}
  182. constructor TMMBitmapSlider.Create(AOwner: TComponent);
  183. begin
  184.    FBitmapOK := False;
  185.    inherited Create(AOwner);
  186.    ControlStyle := ControlStyle - [csOpaque];
  187.    FAutoSize          := False;
  188.    FNumGlyphs         :=  1;
  189.    FNumThumbGlyphs    :=  1;
  190.    FBitmapThumbIndex  := -1;
  191.    FThumbCursor       := crDefault;
  192.    FForceChange       := False;
  193.    FSaveBitmap        := TBitmap.Create;
  194.    SetBounds(0,0,40,200);
  195.    FHandCursor        := False;
  196.    FMin               := 0;
  197.    FMax               := 10;
  198.    FLineSize          := 1;
  199.    FPageSize          := 5;
  200.    FOrientation       := orHorizontal;
  201.    FZeroPosition      := zpBottomLeft;
  202.    FPosition          := 0;
  203.    FDragging          := False;
  204.    FDragOffset        := 0;
  205.    FDragVal           := 0;
  206.    FSensitivity       := -24;
  207.    FLogMode           := False;
  208.    FNeedTrackEnd      := False;
  209.    FMargin            := 2;
  210.    FThumbMargin       := 0;
  211.    
  212.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  213.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  214. end;
  215. {-- TMMBitmapSlider -----------------------------------------------------}
  216. destructor TMMBitmapSlider.Destroy;
  217. begin
  218.    FSaveBitmap.Free;
  219.    FSaveBitmap := nil;
  220.    inherited Destroy;
  221. end;
  222. {-- TMMBitmapSlider -----------------------------------------------------}
  223. procedure TMMBitmapSlider.BitmapChanged;
  224. begin
  225.    UpdateSlider;
  226. end;
  227. {-- TMMBitmapSlider -----------------------------------------------------------}
  228. procedure TMMBitmapSlider.SetBitmapThumbIndex(aValue: integer);
  229. begin
  230.    if (FBitmapThumbIndex <> aValue) then
  231.    begin
  232.       FBitmapThumbIndex := Max(aValue,-1);
  233.       BitmapChanged;
  234.    end;
  235. end;
  236. {-- TMMBitmapSlider -----------------------------------------------------}
  237. function TMMBitmapSlider.ThumbBitmapValid: Boolean;
  238. begin
  239.    Result := assigned(BitmapList) and (FBitmapThumbIndex >= 0) and (FBitmapThumbIndex <  BitmapList.Count);
  240. end;
  241. {-- TMMBitmapSlider -----------------------------------------------------}
  242. function TMMBitmapSlider.GetThumbBitmap: TBitmap;
  243. begin
  244.    if ThumbBitmapValid then
  245.       Result := BitmapList[BitmapThumbIndex]
  246.    else
  247.       Result := nil;
  248. end;
  249. {-- TMMBitmapSlider -----------------------------------------------------}
  250. procedure TMMBitmapSlider.UpdateSlider;
  251. begin
  252.    if ThumbBitmapValid then
  253.    begin
  254.       FThumbWidth := ThumbBitmap.Width div FNumThumbGlyphs;
  255.       FThumbHeight:= ThumbBitmap.Height;
  256.    end;
  257.    if BitmapValid and AutoSize then
  258.    begin
  259.       { adjust sizes }
  260.       if (Orientation = orHorizontal) then
  261.           SetBounds(Left,Top,Width,Height div FNumGlyphs)
  262.       else
  263.           SetBounds(Left,Top,Width div FNumGlyphs,Height);
  264.    end;
  265.    FBitmapOK := False;
  266.    Invalidate;
  267. end;
  268. {-- TMMBitmapSlider -----------------------------------------------------}
  269. procedure TMMBitmapSlider.SetAutoSize(aValue: Boolean);
  270. begin
  271.    if (aValue <> FAutoSize) then
  272.    begin
  273.       FAutoSize := aValue;
  274.       UpdateSlider;
  275.    end;
  276. end;
  277. {-- TMMBitmapSlider -----------------------------------------------------}
  278. procedure TMMBitmapSlider.Change;
  279. begin
  280.    if (csLoading in ComponentState) or
  281.       (csReading in ComponentState) or
  282.       (csDestroying in ComponentState) then exit;
  283.    if assigned(FOnChange) then FOnChange(Self);
  284. end;
  285. {-- TMMBitmapSlider -----------------------------------------------------}
  286. function TMMBitmapSlider.GetSrcRect(index: integer): TRect;
  287. begin
  288.    index := Min(index,FNumGlyphs-1);
  289.    if (Orientation = orHorizontal) then
  290.    begin
  291.       Result.Left := 0;
  292.       Result.Top := index * (Bitmap.Height div FNumGlyphs);
  293.       Result.Right := Bitmap.Width;
  294.       Result.Bottom := (index+1) * (Bitmap.Height div FNumGlyphs);
  295.    end
  296.    else
  297.    begin
  298.       Result.Left := index * (Bitmap.Width div FNumGlyphs);
  299.       Result.Top := 0;
  300.       Result.Right := (index+1) * (Bitmap.Width div FNumGlyphs);
  301.       Result.Bottom := Bitmap.Height;
  302.    end;
  303. end;
  304. {-- TMMBitmapSlider -----------------------------------------------------}
  305. function TMMBitmapSlider.GetThumbSrcRect(index: integer): TRect;
  306. begin
  307.    index := Min(index,FNumThumbGlyphs-1);
  308.    Result.Left := index * (ThumbBitmap.Width div FNumThumbGlyphs);
  309.    Result.Top := 0;
  310.    Result.Right := (index+1) * (ThumbBitmap.Width div FNumThumbGlyphs);
  311.    Result.Bottom := ThumbBitmap.Height;
  312. end;
  313. {-- TMMBitmapSlider -----------------------------------------------------}
  314. procedure TMMBitmapSlider.SetNumGlyphs(aValue: integer);
  315. begin
  316.    if (FNumGlyphs <> aValue) then
  317.    begin
  318.       FNumGlyphs := Max(aValue,1);
  319.       UpdateSlider;
  320.       Refresh;
  321.    end;
  322. end;
  323. {-- TMMBitmapSlider -----------------------------------------------------}
  324. procedure TMMBitmapSlider.SetNumThumbGlyphs(aValue: integer);
  325. begin
  326.    if (FNumThumbGlyphs <> aValue) then
  327.    begin
  328.       FNumThumbGlyphs := Max(aValue,1);
  329.       UpdateSlider;
  330.       Refresh;
  331.    end;
  332. end;
  333. {-- TMMBitmapSlider -----------------------------------------------------}
  334. procedure TMMBitmapSlider.Track;
  335. begin
  336.    FNeedTrackEnd := True;
  337.    if assigned(FOnTrack) then FOnTrack(Self);
  338. end;
  339. {-- TMMBitmapSlider -----------------------------------------------------}
  340. procedure TMMBitmapSlider.TrackEnd;
  341. begin
  342.    if FNeedTrackEnd then
  343.    begin
  344.       if assigned(FOnTrackEnd) then FOnTrackEnd(Self);
  345.       FNeedTrackEnd := False;
  346.    end;
  347. end;
  348. {-- TMMBitmapSlider -----------------------------------------------------}
  349. procedure TMMBitmapSlider.CMEnabledChanged(var Message: TMessage);
  350. begin
  351.    if (csDesigning in ComponentState) or not FBitmapOK then
  352.       Invalidate
  353.    else
  354.       RedrawThumb;
  355. end;
  356. {-- TMMBitmapSlider -----------------------------------------------------}
  357. procedure TMMBitmapSlider.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
  358. begin
  359.    if BitmapValid and AutoSize then
  360.    begin
  361.       aWidth := Bitmap.Width;
  362.       aHeight:= Bitmap.Height;
  363.       if (Orientation = orHorizontal) then
  364.           aHeight := aHeight div FNumGlyphs
  365.       else
  366.           aWidth := aWidth div FNumGlyphs;
  367.    end;
  368.    if (Width <> aWidth) or (Height <> aHeight) and (FSaveBitmap <> nil) then
  369.    begin
  370.       FSaveBitmap.Width  := aWidth;
  371.       FSaveBitmap.Height := 2*aHeight;
  372.       FBitmapOK          := False;
  373.    end;
  374.    inherited SetBounds(aLeft, aTop, aWidth, aHeight);
  375. end;
  376. {-- TMMBitmapSlider -----------------------------------------------------}
  377. procedure TMMBitmapSlider.SetSensitivity(aValue: integer);
  378. var
  379.    oldVal: integer;
  380. begin
  381.    aValue:= MinMax(aValue, -96, -10);
  382.    if aValue <> FSensitivity then
  383.    begin
  384.       oldVal := Position;
  385.       FSensitivity:= aValue;
  386.       Position := oldVal;
  387.    end;
  388. end;
  389. {-- TMMBitmapSlider -----------------------------------------------------}
  390. procedure TMMBitmapSlider.SetLogMode;
  391. var
  392.    oldVal: integer;
  393. begin
  394.    if (aValue <> FlogMode) then
  395.    begin
  396.       oldVal := Position;
  397.       FLogMode := aValue;
  398.       if not (csLoading in ComponentState) then FMax := Max(FMax,FMin+Ord(FLogMode));
  399.       Position := oldVal;
  400.    end;
  401. end;
  402. {-- TMMBitmapSlider -----------------------------------------------------}
  403. procedure TMMBitmapSlider.SetMin(aValue: Longint);
  404. begin
  405.    SetMinMax(aValue,FMax);
  406. end;
  407. {-- TMMBitmapSlider -----------------------------------------------------}
  408. procedure TMMBitmapSlider.SetMax(aValue: Longint);
  409. begin
  410.    SetMinMax(FMin,aValue);
  411. end;
  412. {-- TMMBitmapSlider -----------------------------------------------------}
  413. procedure TMMBitmapSlider.SetMinMax(aMin,aMax: Longint);
  414. begin
  415.    if (FMin <> aMin) or (FMax <> aMax) then
  416.    begin
  417.       FMin := aMin;
  418.       FMax := aMax;
  419.       if not (csLoading in ComponentState) then
  420.          FMax := Max(FMax,FMin+Ord(FLogMode));
  421.       FForceChange := True;
  422.       Position := MinMax(Position,FMin,FMax);
  423.       FForceChange := False;
  424.       if (csDesigning in ComponentState) or not FBitmapOK then
  425.           Invalidate
  426.       else
  427.           RedrawThumb;
  428.    end;
  429. end;
  430. {-- TMMBitmapSlider -----------------------------------------------------}
  431. procedure TMMBitmapSlider.SetOrientation(aValue: TMMOrientation);
  432. begin
  433.    if (aValue <> FOrientation) then
  434.    begin
  435.       FOrientation := aValue;
  436.       UpdateSlider;
  437.    end;
  438.    {$IFDEF WIN32}
  439.    {$IFDEF TRIAL}
  440.    {$DEFINE _HACK2}
  441.    {$I MMHACK.INC}
  442.    {$ENDIF}
  443.    {$ENDIF}
  444. end;
  445. {-- TMMBitmapSlider -----------------------------------------------------}
  446. procedure TMMBitmapSlider.SetZeroPosition(aValue: TMMZeroPosition);
  447. begin
  448.    if (aValue <> FZeroPosition) then
  449.    begin
  450.       FZeroPosition := aValue;
  451.       Invalidate;
  452.    end;
  453. end;
  454. {-- TMMBitmapSlider -----------------------------------------------------}
  455. procedure TMMBitmapSlider.DrawBitmapImage(Canvas: TCanvas; Bitmap: TBItmap; X, Y: integer; Src: TRect);
  456. var
  457.    Done,H,W: integer;
  458. begin
  459.    if (Orientation = orVertical) and (Src.Bottom-Src.Top >= Height) or
  460.       (Orientation = orHorizontal) and (Src.Right-Src.Left >= Width) then
  461.    begin
  462.       DrawTransparentBitmapEx(Canvas.Handle, Bitmap.Handle, X, Y, Src, GetTransparentColor);
  463.    end
  464.    else if (Orientation = orVertical) then
  465.    begin
  466.       Done := 0;
  467.       Dec(Src.Bottom,2);
  468.       while (Done < Height) do
  469.       begin
  470.          DrawTransparentBitmapEx(Canvas.Handle, Bitmap.Handle, X, Y+Done, Src, GetTransparentColor);
  471.          H := Src.Bottom-Src.Top;
  472.          if (Done = 0) then Inc(Src.Top,2);
  473.          inc(Done,H);
  474.       end;
  475.    end
  476.    else
  477.    begin
  478.       Done := 0;
  479.       Dec(Src.Right,2);
  480.       while (Done < Width) do
  481.       begin
  482.          DrawTransparentBitmapEx(Canvas.Handle, Bitmap.Handle, X+Done, Y, Src, GetTransparentColor);
  483.          W := Src.Right-Src.Left;
  484.          if (Done = 0) then Inc(Src.Left,4);
  485.          inc(Done,W);
  486.       end;
  487.    end;
  488. end;
  489. {-- TMMBitmapSlider -----------------------------------------------------}
  490. procedure TMMBitmapSlider.RedrawThumb;
  491. var
  492.    index: integer;
  493.    SrcRect: TRect;
  494. begin
  495.    if Visible then
  496.    begin
  497.       { copy saved background to temp bitmap (top) }
  498.       FSaveBitmap.Canvas.CopyRect(Rect(0,0,Width,Height),
  499.                                   FSaveBitmap.Canvas,
  500.                                   Rect(0,Height,Width,2*Height));
  501.       if (NumGlyphs > 1) and BitmapValid then
  502.       begin
  503.          Index := 0;
  504.          if assigned(FOnGetGlyphIndex) then
  505.          begin
  506.             FOnGetGlyphIndex(Self, FDragging, Index);
  507.             Index := MinMax(Index,0,FNumGlyphs-1);
  508.          end;
  509.          SrcRect := GetSrcRect(Index);
  510.          { draw the image to the top bitmap }
  511.          DrawBitmapImage(FSaveBitmap.Canvas,Bitmap,0,0,SrcRect);
  512.       end;
  513.       { draw Thumb to Bitmap }
  514.       DrawThumb(FSaveBitmap.Canvas,FThumbRect);
  515.       { and copy to screen }
  516.       Canvas.Draw(0,0,FSaveBitmap);
  517.    end;
  518. end;
  519. {-- TMMBitmapSlider -----------------------------------------------------}
  520. function TMMBitmapSlider.UpdatePosition(aValue: Longint): Boolean;
  521. var
  522.    aRect: TRect;
  523. begin
  524.    if (aValue <> FPosition) or FForceChange then
  525.    begin
  526.       Result := True;
  527.       FPosition := MinMax(aValue,FMin,FMax);
  528.       if not (csDesigning in ComponentState) and
  529.          not (csLoading in ComponentState) then
  530.       begin
  531.          WhereIsThumb(ClientRect,aRect);
  532.          if (aRect.Left <> FThumbRect.Left) or (aRect.Top <> FThumbRect.Top) or
  533.             (aRect.Right <> FThumbRect.Right) or (aRect.Bottom <> FThumbRect.Bottom) then
  534.          begin
  535.             FThumbRect := aRect;
  536.             if FBitmapOK then
  537.                RedrawThumb
  538.             else
  539.                Refresh;
  540.          end;
  541.          Change;
  542.       end
  543.       else Refresh;
  544.    end
  545.    else Result := False;
  546. end;
  547. {-- TMMBitmapSlider -----------------------------------------------------}
  548. procedure TMMBitmapSlider.SetPosition(aValue: Longint);
  549. var
  550.    aPos: Float;
  551. begin
  552.    if FLogMode and (aValue <> 0) then
  553.    begin
  554.       aPos:= Log10(aValue/(FMax-FMin))*20 + -FSensitivity;
  555.       aPos:= MinMax(Round(aPos*(FMax-FMin)/-FSensitivity),FMin,FMax);
  556.       aValue := Round(aPos);
  557.    end;
  558.    UpdatePosition(aValue);
  559. end;
  560. {-- TMMBitmapSlider -----------------------------------------------------}
  561. function TMMBitmapSlider.GetPosition: Longint;
  562. var
  563.    aPos: Float;
  564. begin
  565.    aPos := MinMax(FPosition,FMin,FMax);
  566.    if FLogMode and (aPos <> 0) then
  567.    begin
  568.       aPos:= Pow(10,(aPos*(-FSensitivity)/(FMax-FMin)-(-FSensitivity))/20)*(FMax-FMin);
  569.    end;
  570.    Result := MinMax(Round(aPos),FMin,FMax);
  571. end;
  572. {-- TMMBitmapSlider -----------------------------------------------------}
  573. function TMMBitmapSlider.NewPosition(WhereX,WhereY: Integer): Longint;
  574. var
  575.   aHeight,aWidth: Integer;
  576. begin
  577.    { Calculate the nearest position to where the mouse is located }
  578.    with ClientRect do
  579.    begin
  580.       aHeight := (Bottom - Top) - FThumbHeight;
  581.       aWidth  := (Right - Left) - FThumbWidth;
  582.       WhereY  := WhereY - Top - (FThumbHeight div 2);
  583.       WhereX  := WhereX - Left - (FThumbWidth div 2);
  584.    end;
  585.    if IsVert then
  586.    begin
  587.       if IsInverted then
  588.          Result := Round((WhereY/aHeight)*(FMax-FMin)+FMin)
  589.       else
  590.          Result := Round(((aHeight-WhereY)/aHeight)*(FMax-FMin)+FMin);
  591.    end
  592.    else
  593.    begin
  594.       if IsInverted then
  595.          Result := Round(((aWidth-WhereX)/aWidth)*(FMax-FMin)+FMin)
  596.       else
  597.          Result := Round((WhereX/aWidth)*(FMax-FMin)+FMin);
  598.    end;
  599.    Result := Min(Max(Result,FMin),FMax);
  600. end;
  601. {-- TMMBitmapSlider -----------------------------------------------------}
  602. function TMMBitmapSlider.IsVert: Boolean;
  603. begin
  604.    Result := (Orientation = orVertical);
  605. end;
  606. {-- TMMBitmapSlider -----------------------------------------------------}
  607. function TMMBitmapSlider.IsInverted: Boolean;
  608. begin
  609.    Result := (ZeroPosition = zpTopRight);
  610. end;
  611. {-- TMMBitmapSlider -----------------------------------------------------}
  612. function TMMBitmapSlider.FindTransparentColor: TColor;
  613. var
  614.    HBM: HBITMAP;
  615. begin
  616.    Result := clDefault;
  617.    if assigned(BitmapList) then
  618.    begin
  619.       if ThumbBitmapValid then
  620.           HBM := ThumbBitmap.Handle
  621.       else if BitmapValid then
  622.           HBM := Bitmap.Handle
  623.       else exit;
  624.       Result := MMUtils.GetTransparentColor(HBM);
  625.    end;
  626.  end;
  627. {-- TMMBitmapSlider -----------------------------------------------------}
  628. procedure TMMBitmapSlider.SetMargin(aValue: integer);
  629. begin
  630.    if (aValue <> FMargin) then
  631.    begin
  632.       FMargin := MinMax(aValue,0,25);
  633.       Refresh;
  634.    end;
  635. end;
  636. {-- TMMBitmapSlider -----------------------------------------------------}
  637. procedure TMMBitmapSlider.SetThumbMargin(aValue: integer);
  638. begin
  639.    if (aValue <> FThumbMargin) then
  640.    begin
  641.       FThumbMargin := MinMax(aValue,-5,5);
  642.       Refresh;
  643.    end;
  644. end;
  645. {-- TMMBitmapSlider -----------------------------------------------------}
  646. procedure TMMBitmapSlider.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  647. begin
  648.    if PtInRect(FThumbRect,Point(X,Y)) then
  649.    begin
  650.       if (Button = mbLeft) then FDragging := True;
  651.       SetThumbCursor(True);
  652.    end;
  653.    if (Button = mbLeft) then
  654.    begin
  655.       if IsVert then
  656.          FDragOffset := Y
  657.       else
  658.          FDragOffset := X;
  659.       FDragVal := FPosition;
  660.       if not FDragging then
  661.          UpdatePosition(NewPosition(X,Y))
  662.       else if (FNumThumbGlyphs > 1) then
  663.          RedrawThumb;
  664.       Track;
  665.    end;
  666.    inherited MouseDown(Button, Shift, X, Y);
  667. end;
  668. {-- TMMBitmapSlider -----------------------------------------------------}
  669. procedure TMMBitmapSlider.MouseMove(Shift: TShiftState; X, Y: Integer);
  670. var
  671.    aPos,aWidth,aHeight: integer;
  672. begin
  673.    if not FDragging then
  674.    begin
  675.      {$IFDEF WIN32}
  676.      SetThumbCursor(ptInRect(FThumbRect,Point(X,Y)));
  677.      {$ELSE}
  678.      SetThumbCursor(ptInRect(FThumbRect,Point(X,Y)) or FDragging);
  679.      {$ENDIF}
  680.    end;
  681.    {Is the left mouse button down and dragging the thumb bar?}
  682.    if (ssLeft in Shift) and FDragging then
  683.    begin
  684.       with ClientRect do
  685.       begin
  686.          aHeight := (Bottom - Top) - FThumbHeight - 2*Margin;
  687.          aWidth  := (Right - Left) - FThumbWidth - 2*Margin;
  688.       end;
  689.       if IsVert then
  690.       begin
  691.          if IsInverted then
  692.             aPos := Round(((Y-FDragOffset)*(FMax-FMin))/aHeight)
  693.          else
  694.             aPos := Round(((FDragOffset-Y)*(FMax-FMin))/aHeight);
  695.       end
  696.       else
  697.       begin
  698.          if IsInverted then
  699.             aPos := Round(((FDragOffset-X)*(FMax-FMin))/aWidth)
  700.          else
  701.             aPos := Round(((X-FDragOffset)*(FMax-FMin))/aWidth);
  702.       end;
  703.       aPos := Min(Max(FDragVal+aPos,FMin),FMax);
  704.       if UpdatePosition(aPos) then Track;
  705.    end;
  706.    inherited MouseMove(Shift, X, Y);
  707. end;
  708. {-- TMMBitmapSlider -----------------------------------------------------}
  709. procedure TMMBitmapSlider.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  710. begin
  711.    if (Button = mbLeft) then
  712.    begin
  713.       FDragging := False;
  714.       if (FNumThumbGlyphs > 1) then RedrawThumb;
  715.       Update;
  716.       TrackEnd;
  717.    end;
  718.    inherited MouseUp(Button, Shift, X, Y);
  719. end;
  720. {-- TMMBitmapSlider -----------------------------------------------------}
  721. procedure TMMBitmapSlider.WhereIsThumb(const ClientRect: TRect; var aRect: Trect);
  722. var
  723.   Each           : Real;
  724.   ThumbX,ThumbY  : integer;
  725.   aWidth, aHeight: integer;
  726. begin
  727.    aWidth := ClientRect.Right - ClientRect.Left;
  728.    aHeight := ClientRect.Bottom - ClientRect.Top;
  729.    { Calculate where to paint the thumb bar - store in aRect }
  730.    if IsVert then
  731.    begin
  732.       if (FMax-FMin = 0) then
  733.           Each := (aHeight-FThumbHeight-2*Margin)/1
  734.       else
  735.           Each := (aHeight-FThumbHeight-2*Margin)/Max(FMax-FMin,Sign(FMin));
  736.       if IsInverted then
  737.          ThumbY := Round(Each*(FPosition-FMin))+Margin
  738.       else
  739.          ThumbY := (aHeight-Round(Each*(FPosition-FMin))-FThumbHeight)-Margin;
  740.       ThumbY := ClientRect.Top + Max(0,Min(aHeight-FThumbHeight-Margin,ThumbY));
  741.       ThumbX := ClientRect.Left + ((aWidth+1) div 2) - ((FThumbWidth+1) div 2) + FThumbMargin;
  742.    end
  743.    else
  744.    begin
  745.       if (FMax-FMin = 0) then
  746.           Each := (aWidth-FThumbWidth-2*Margin)/1
  747.       else
  748.           Each := (aWidth-FThumbWidth-2*Margin)/(FMax-FMin);
  749.       if IsInverted then
  750.          ThumbX := (aWidth-Round(Each*(FPosition-FMin))-FThumbWidth)-Margin
  751.       else
  752.          ThumbX := Round(Each*(FPosition-FMin))+Margin;
  753.       ThumbX := ClientRect.Left + Max(0,Min(aWidth-FThumbWidth-Margin,ThumbX))+FThumbMargin;
  754.       ThumbY := ClientRect.Top + ((aHeight+1) div 2) - ((FThumbHeight+1) div 2);
  755.    end;
  756.    aRect := Rect(ThumbX,ThumbY,ThumbX+FThumbWidth,ThumbY+FThumbHeight);
  757. end;
  758. {-- TMMBitmapSlider -----------------------------------------------------}
  759. procedure TMMBitmapSlider.SetThumbCursor(AtThumb: Boolean);
  760. begin
  761.    if AtThumb then
  762.       if FHandCursor then
  763.          SetCursor(Screen.Cursors[crsHand5])
  764.       else
  765.          SetCursor(Screen.Cursors[ThumbCursor])
  766.    else
  767.        SetCursor(Screen.Cursors[Cursor]);
  768. end;
  769. {-- TMMBitmapSlider -----------------------------------------------------}
  770. procedure TMMBitmapSlider.DrawThumb(Canvas: TCanvas; aRect: TRect);
  771. var
  772.    index: integer;
  773.    SrcRect: TRect;
  774. begin
  775.    with Canvas,aRect do
  776.    begin
  777.       if ThumbBitmapValid then
  778.       begin
  779.          index := 0;
  780.          if assigned(FOnGetThumbGlyphIndex) then
  781.          begin
  782.             FOnGetThumbGlyphIndex(Self, FDragging, Index);
  783.             Index := MinMax(Index,0,FNumThumbGlyphs-1);
  784.          end
  785.          else
  786.          begin
  787.             case FNumThumbGlyphs of   {normal,disabled,down,down }
  788.                2: if not Enabled then Index := 1;
  789.                3: if not Enabled then
  790.                      Index := 1
  791.                   else if Dragging then
  792.                      Index := 2;
  793.             end;
  794.          end;
  795.          SrcRect := GetThumbSrcRect(index);
  796.          DrawTransparentBitmapEx(Handle, ThumbBitmap.Handle,
  797.                                  aRect.Left, aRect.Top,
  798.                                  SrcRect,
  799.                                  GetTransparentColor);
  800.       end;
  801.    end;
  802. end;
  803. {-- TMMBitmapSlider -----------------------------------------------------}
  804. procedure TMMBitmapSlider.Paint;
  805. var
  806.    S: string;
  807.    SrcRect: TRect;
  808.    index,Done,H,W: integer;
  809. begin
  810.    if (FSaveBitmap = nil) then exit;
  811.    if not (csDesigning in ComponentState) and assigned(FOnGetBackground) then
  812.    begin
  813.       FOnGetBackground(Self,FSaveBitmap,Rect(0,Height,Width,2*Height));
  814.    end
  815.    else
  816.    begin
  817.       { save the actual background to the bottom of the bitmap }
  818.       FSaveBitmap.Canvas.CopyRect(Rect(0,Height,Width,2*Height),Canvas,ClientRect);
  819.    end;
  820.    FBitmapOK := True;
  821.    { draw the image to our bitmap }
  822.    with FSaveBitmap.Canvas,ClientRect do
  823.    begin
  824.       if not BitmapValid then
  825.       begin
  826.          if (csDesigning in ComponentState) then
  827.          begin
  828.             Font := Self.Font;
  829.             Brush.Style := bsClear;
  830.             S := 'Empty';
  831.             TextOut((Right-TextWidth(S)) div 2,Height+((Bottom-TextHeight(S))) div 2,S);
  832.             Pen.Style   := psDot;
  833.             Rectangle(Left,Height+Top,Right,Height+Bottom);
  834.             Pen.Mode := pmCopy;
  835.          end;
  836.       end
  837.       else
  838.       begin
  839.          Index := 0;
  840.          if assigned(FOnGetGlyphIndex) then
  841.          begin
  842.             FOnGetGlyphIndex(Self, FDragging, Index);
  843.             Index := MinMax(Index,0,FNumGlyphs-1);
  844.          end;
  845.          SrcRect := GetSrcRect(Index);
  846.          { draw the background to the top of the bitmap }
  847.          DrawBitmapImage(FSaveBitmap.Canvas,Bitmap,0,Height,SrcRect);
  848.       end;
  849.    end;
  850.    { copy the background to screen }
  851.    Canvas.CopyRect(ClientRect,FSaveBitmap.Canvas,Rect(0,Height,Width,2*Height));
  852.    { draw the Thumb }
  853.    WhereIsThumb(ClientRect,FThumbRect);
  854.    DrawThumb(Canvas,FThumbRect);
  855. end;
  856. end.