VrSpinner.pas
上传用户:hbszzs
上传日期:2008-08-20
资源大小:628k
文件大小:16k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {*****************************************************}
  2. {                                                     }
  3. {     Varian Component Workshop                       }
  4. {                                                     }
  5. {     Varian Software NL (c) 1996-2000                }
  6. {     All Rights Reserved                             }
  7. {                                                     }
  8. {*****************************************************}
  9. unit VrSpinner;
  10. {$I VRLIB.INC}
  11. interface
  12. uses
  13.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  14.   CommCtrl, {$IFDEF VER110} ImgList,{$ENDIF} VrClasses, VrControls,
  15.   VrTypes, VrSysUtils, VrThreads;
  16. const
  17.   InitRepeatPause = 400;
  18.   RepeatPause     = 100;
  19. type
  20.   TVrSpinButton = class;
  21.   TVrTimerSpinButton = class;
  22.   TVrSpinButtonType = (stUp, stDown, stLeft, stRight);
  23.   TVrSpinner = class (TWinControl)
  24.   private
  25.     FUpButton: TVrTimerSpinButton;
  26.     FDownButton: TVrTimerSpinButton;
  27.     FFocusedButton: TVrTimerSpinButton;
  28.     FFocusControl: TWinControl;
  29.     FOrientation: TVrOrientation;
  30.     FPalette: TVrPalette;
  31.     FOnUpClick: TNotifyEvent;
  32.     FOnDownClick: TNotifyEvent;
  33.     function CreateButton(BtnType: TVrSpinButtonType): TVrTimerSpinButton;
  34.     procedure BtnClick(Sender: TObject);
  35.     procedure BtnMouseDown (Sender: TObject; Button: TMouseButton;
  36.       Shift: TShiftState; X, Y: Integer);
  37.     procedure SetFocusBtn (Btn: TVrTimerSpinButton);
  38.     procedure ChangeSize (var W: Integer; var H: Integer);
  39.     procedure SetOrientation(Value: TVrOrientation);
  40.     procedure SetPalette(Value: TVrPalette);
  41.     procedure PaletteModified(Sender: TObject);
  42.     procedure WMSize(var Message: TWMSize);  message WM_SIZE;
  43.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  44.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  45.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  46.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  47.   protected
  48.     procedure Loaded; override;
  49.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  50.     procedure Notification(AComponent: TComponent;
  51.       Operation: TOperation); override;
  52.   public
  53.     constructor Create(AOwner: TComponent); override;
  54.     destructor Destroy; override;
  55.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  56.   published
  57.     property FocusControl: TWinControl read FFocusControl write FFocusControl;
  58.     property Orientation: TVrOrientation read FOrientation write SetOrientation default voVertical;
  59.     property Palette: TVrPalette read FPalette write SetPalette;
  60.     property OnDownClick: TNotifyEvent read FOnDownClick write FOnDownClick;
  61.     property OnUpClick: TNotifyEvent read FOnUpClick write FOnUpClick;
  62.     property Align;
  63. {$IFDEF VER110}
  64.     property Anchors;
  65.     property Constraints;
  66. {$ENDIF}
  67.     property Color default clBtnFace;
  68.     property DragCursor;
  69. {$IFDEF VER110}
  70.     property DragKind;
  71. {$ENDIF}
  72.     property DragMode;
  73.     property Enabled;
  74.     property ParentColor;
  75.     property ParentShowHint;
  76.     property PopupMenu;
  77.     property ShowHint;
  78.     property TabOrder;
  79.     property TabStop;
  80.     property Visible;
  81.     property OnDragDrop;
  82.     property OnDragOver;
  83. {$IFDEF VER110}
  84.     property OnEndDock;
  85. {$ENDIF}
  86.     property OnEndDrag;
  87.     property OnEnter;
  88.     property OnExit;
  89. {$IFDEF VER110}
  90.     property OnStartDock;
  91. {$ENDIF}
  92.     property OnStartDrag;
  93.   end;
  94.   TVrSpinButton = class(TVrGraphicControl)
  95.   private
  96.     FBtnType: TVrSpinButtonType;
  97.     FPalette: TVrPalette;
  98.     ImageList: TImageList;
  99.     Bitmap: TBitmap; //Mask
  100.     MouseBtnDown: Boolean;
  101.     procedure SetBtnType(Value: TVrSpinButtonType);
  102.     procedure SetPalette(Value: TVrPalette);
  103.     procedure PaletteModified(Sender: TObject);
  104.     function InControl(X, Y: Integer): Boolean;
  105.   protected
  106.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  107.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  108.     procedure LoadBitmaps; virtual;
  109.     function ImageRect: TRect;
  110.     procedure Paint; override;
  111.     procedure Click; override;
  112.     procedure DoClick;
  113.     property BtnType: TVrSpinButtonType read FBtnType write SetBtnType default stUp;
  114.     property Palette: TVrPalette read FPalette write SetPalette;
  115.     property Color default clBtnFace;
  116.     property ParentColor default true;
  117.     property Enabled;
  118.   public
  119.     constructor Create(AOwner: TComponent); override;
  120.     destructor Destroy; override;
  121.   end;
  122.   { TTimerSpeedButton }
  123.   TTimeBtnState = set of (tbFocusRect, tbAllowTimer);
  124.   TVrTimerSpinButton = class(TVrSpinButton)
  125.   private
  126.     FRepeatTimer: TVrTimer;
  127.     FTimeBtnState: TTimeBtnState;
  128.     procedure TimerExpired(Sender: TObject);
  129.   protected
  130.     procedure Paint; override;
  131.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  132.       X, Y: Integer); override;
  133.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  134.       X, Y: Integer); override;
  135.   public
  136.     destructor Destroy; override;
  137.     property TimeBtnState: TTimeBtnState read FTimeBtnState write FTimeBtnState;
  138.   end;
  139. implementation
  140. {$R VRSPINNER.D32}
  141. const
  142.   ResId: array[TVrSpinButtonType] of PChar =
  143.     ('ARROWS_UP', 'ARROWS_DOWN', 'ARROWS_LEFT', 'ARROWS_RIGHT');
  144. { TVrSpinner }
  145. constructor TVrSpinner.Create(AOwner: TComponent);
  146. begin
  147.   inherited Create(AOwner);
  148.   ControlStyle := ControlStyle -
  149.     [csAcceptsControls, csSetCaption, csFramed] + [csOpaque];
  150.   Width := 35;
  151.   Height := 40;
  152.   Color := clBtnFace;
  153.   ParentColor := true;
  154.   FOrientation := voVertical;
  155.   FPalette := TVrPalette.Create;
  156.   FPalette.OnChange := PaletteModified;
  157.   FUpButton := CreateButton(stUp);
  158.   FDownButton := CreateButton(stDown);
  159.   FFocusedButton := FUpButton;
  160. end;
  161. destructor TVrSpinner.Destroy;
  162. begin
  163.   FPalette.Free;
  164.   inherited Destroy;
  165. end;
  166. function TVrSpinner.CreateButton(BtnType: TVrSpinButtonType): TVrTimerSpinButton;
  167. begin
  168.   Result := TVrTimerSpinButton.Create (Self);
  169.   Result.OnClick := BtnClick;
  170.   Result.OnMouseDown := BtnMouseDown;
  171.   Result.Visible := True;
  172.   Result.Enabled := True;
  173.   Result.TimeBtnState := [tbAllowTimer];
  174.   Result.BtnType := BtnType;
  175.   Result.Palette.Assign(Palette);
  176.   Result.Parent := Self;
  177. end;
  178. procedure TVrSpinner.Notification(AComponent: TComponent;
  179.   Operation: TOperation);
  180. begin
  181.   inherited Notification(AComponent, Operation);
  182.   if (Operation = opRemove) and (AComponent = FFocusControl) then
  183.     FFocusControl := nil;
  184. end;
  185. procedure TVrSpinner.ChangeSize(var W: Integer; var H: Integer);
  186. begin
  187.   if (FUpButton = nil) or (csLoading in ComponentState) then Exit;
  188.   if W < 15 then W := 15;
  189.   if FOrientation = voVertical then
  190.   begin
  191.     FUpButton.SetBounds (0, 0, W, H div 2);
  192.     FDownButton.SetBounds (0, FUpButton.Height - 1, W, H - FUpButton.Height + 1);
  193.   end
  194.   else
  195.   begin
  196.     FUpButton.SetBounds (0, 0, W div 2, H);
  197.     FDownButton.SetBounds(W div 2, 0, W div 2, H);
  198.   end;
  199. end;
  200. procedure TVrSpinner.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  201. var
  202.   W, H: Integer;
  203. begin
  204.   W := AWidth;
  205.   H := AHeight;
  206.   ChangeSize (W, H);
  207.   inherited SetBounds (ALeft, ATop, W, H);
  208. end;
  209. procedure TVrSpinner.WMSize(var Message: TWMSize);
  210. var
  211.   W, H: Integer;
  212. begin
  213.   inherited;
  214.   { check for minimum size }
  215.   W := Width;
  216.   H := Height;
  217.   ChangeSize (W, H);
  218.   if (W <> Width) or (H <> Height) then
  219.     inherited SetBounds(Left, Top, W, H);
  220.   Message.Result := 0;
  221. end;
  222. procedure TVrSpinner.WMSetFocus(var Message: TWMSetFocus);
  223. begin
  224.   FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState + [tbFocusRect];
  225.   FFocusedButton.UpdateControlCanvas;
  226. end;
  227. procedure TVrSpinner.WMKillFocus(var Message: TWMKillFocus);
  228. begin
  229.   FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState - [tbFocusRect];
  230.   FFocusedButton.UpdateControlCanvas;
  231. end;
  232. procedure TVrSpinner.KeyDown(var Key: Word; Shift: TShiftState);
  233. begin
  234.   case Key of
  235.     VK_UP:
  236.       if FOrientation = voVertical then
  237.       begin
  238.         SetFocusBtn (FUpButton);
  239.         FUpButton.DoClick;
  240.       end;
  241.     VK_DOWN:
  242.       if FOrientation = voVertical then
  243.       begin
  244.         SetFocusBtn (FDownButton);
  245.         FDownButton.DoClick;
  246.       end;
  247.     VK_LEFT:
  248.       if FOrientation = voHorizontal then
  249.       begin
  250.         SetFocusBtn (FUpButton);
  251.         FUpButton.DoClick;
  252.       end;
  253.     VK_RIGHT:
  254.       if FOrientation = voHorizontal then
  255.       begin
  256.         SetFocusBtn (FDownButton);
  257.         FDownButton.DoClick;
  258.       end;
  259.     VK_SPACE:
  260.       FFocusedButton.DoClick;
  261.   end;
  262. end;
  263. procedure TVrSpinner.BtnMouseDown (Sender: TObject; Button: TMouseButton;
  264.   Shift: TShiftState; X, Y: Integer);
  265. begin
  266.   if Button = mbLeft then
  267.   begin
  268.     SetFocusBtn (TVrTimerSpinButton(Sender));
  269.     if (FFocusControl <> nil) and FFocusControl.TabStop and
  270.         FFocusControl.CanFocus and (GetFocus <> FFocusControl.Handle) then
  271.       FFocusControl.SetFocus
  272.     else if TabStop and (GetFocus <> Handle) and CanFocus then
  273.       SetFocus;
  274.   end;
  275. end;
  276. procedure TVrSpinner.BtnClick(Sender: TObject);
  277. begin
  278.   if Sender = FUpButton then
  279.   begin
  280.     if Assigned(FOnUpClick) then FOnUpClick(Self);
  281.   end
  282.   else
  283.     if Assigned(FOnDownClick) then FOnDownClick(Self);
  284. end;
  285. procedure TVrSpinner.SetFocusBtn (Btn: TVrTimerSpinButton);
  286. begin
  287.   if TabStop and CanFocus and  (Btn <> FFocusedButton) then
  288.   begin
  289.     FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState - [tbFocusRect];
  290.     FFocusedButton := Btn;
  291.     if (GetFocus = Handle) then
  292.     begin
  293.        FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState + [tbFocusRect];
  294.        Repaint;
  295.     end;
  296.   end;
  297. end;
  298. procedure TVrSpinner.WMGetDlgCode(var Message: TWMGetDlgCode);
  299. begin
  300.   Message.Result := DLGC_WANTARROWS;
  301. end;
  302. procedure TVrSpinner.CMEnabledChanged(var Message: TMessage);
  303. begin
  304.   inherited;
  305.   FUpButton.Enabled := Enabled;
  306.   FDownButton.Enabled := Enabled;
  307. end;
  308. procedure TVrSpinner.Loaded;
  309. var
  310.   W, H: Integer;
  311. begin
  312.   inherited Loaded;
  313.   W := Width;
  314.   H := Height;
  315.   ChangeSize(W, H);
  316.   if (W <> Width) or (H <> Height) then
  317.     inherited SetBounds (Left, Top, W, H);
  318. end;
  319. procedure TVrSpinner.SetOrientation(Value: TVrOrientation);
  320. begin
  321.   if FOrientation <> Value then
  322.   begin
  323.     FOrientation := Value;
  324.     if FUpButton <> nil then FUpButton.Free;
  325.     if FDownButton <> nil then FDownButton.Free;
  326.     if Value = voVertical then
  327.     begin
  328.       FUpButton := CreateButton(stUp);
  329.       FDownButton := CreateButton(stDown);
  330.     end
  331.     else
  332.     begin
  333.       FUpButton := CreateButton(stLeft);
  334.       FDownButton := CreateButton(stRight);
  335.     end;
  336.     if csDesigning in ComponentState then
  337.     begin
  338.       if Align = alNone then
  339.         BoundsRect := Bounds(Left, Top, Height, Width)
  340.       else RecreateWnd;
  341.     end;
  342.   end;
  343. end;
  344. procedure TVrSpinner.PaletteModified(Sender: TObject);
  345. begin
  346.   FUpButton.Palette.Assign(FPalette);
  347.   FDownButton.Palette.Assign(FPalette);
  348. end;
  349. procedure TVrSpinner.SetPalette(Value: TVrPalette);
  350. begin
  351.   FPalette.Assign(Value);
  352. end;
  353. { VrSpinButton }
  354. constructor TVrSpinButton.Create(AOwner: TComponent);
  355. begin
  356.   inherited Create(AOwner);
  357.   ControlStyle := ControlStyle + [csOpaque, csClickEvents] - [csDoubleClicks];
  358.   Height := 25;
  359.   Width := 25;
  360.   Color := clBtnFace;
  361.   ParentColor := true;
  362.   FBtnType := stUp;
  363.   FPalette := TVrPalette.Create;
  364.   FPalette.OnChange := PaletteModified;
  365.   ImageList := TImageList.Create(nil);
  366.   ImageList.DrawingStyle := dsTransparent;
  367.   Bitmap := TBitmap.Create;
  368.   LoadBitmaps;
  369. end;
  370. destructor TVrSpinButton.Destroy;
  371. begin
  372.   FPalette.Free;
  373.   Bitmap.Free;
  374.   ImageList.Free;
  375.   inherited Destroy;
  376. end;
  377. procedure TVrSpinButton.LoadBitmaps;
  378. begin
  379.   ImageList.Width := 21;
  380.   ImageList.Height := 16;
  381.   if FBtnType in [stLeft, stRight] then
  382.   begin
  383.     ImageList.Width := 17;
  384.     ImageList.Height := 21;
  385.   end;
  386.   Bitmap.Handle := LoadBitmap(hInstance, ResId[FBtnType]);
  387.   FPalette.ToBMP(Bitmap, clGreen, clLime);
  388.   ImageList.Clear;
  389.   ImageList.AddMasked(Bitmap, Bitmap.TransparentColor);
  390.   ImageList.GetBitmap(0, Bitmap);
  391.   Bitmap.Mask(Bitmap.TransparentColor);
  392. end;
  393. procedure TVrSpinButton.SetBtnType(Value: TVrSpinButtonType);
  394. begin
  395.   if FBtnType <> Value then
  396.   begin
  397.     FBtnType := Value;
  398.     LoadBitmaps;
  399.     UpdateControlCanvas;
  400.   end;
  401. end;
  402. procedure TVrSpinButton.SetPalette(Value: TVrPalette);
  403. begin
  404.   FPalette.Assign(Value);
  405. end;
  406. procedure TVrSpinButton.PaletteModified(Sender: TObject);
  407. begin
  408.   LoadBitmaps;
  409.   UpdateControlCanvas;
  410. end;
  411. function TVrSpinButton.ImageRect: TRect;
  412. var
  413.   X, Y: Integer;
  414. begin
  415.   X := (Width - ImageList.Width) div 2;
  416.   Y := (Height - ImageList.Height) div 2;
  417.   Result := Bounds(X, Y, ImageList.Width, ImageList.Height);
  418. end;
  419. procedure TVrSpinButton.Paint;
  420. var
  421.   Index: Integer;
  422. begin
  423.   ClearClientCanvas;
  424.   Index := 1;
  425.   if Enabled then
  426.   begin
  427.     if (MouseBtnDown) then Index := 2;
  428.   end else Index := 0;
  429.   {$IFDEF VER110}
  430.     ImageList.Draw(Canvas,
  431.       ImageRect.Left, ImageRect.Top, Index, True);
  432.   {$ELSE}
  433.     ImageList.Draw(Canvas,
  434.       ImageRect.Left, ImageRect.Top, Index);
  435.   {$ENDIF}
  436. end;
  437. function TVrSpinButton.InControl(X, Y: Integer): Boolean;
  438. var
  439.   Px, Py: Integer;
  440. begin
  441.   Px := ImageRect.Right - X - 1;
  442.   Py := ImageRect.Bottom - Y - 1;
  443.   Result := (Bitmap.Canvas.Pixels[Px, Py] = clBlack) and
  444.             (Canvas.Pixels[X, Y] <> clBlack);
  445. end;
  446. procedure TVrSpinButton.Click;
  447. begin
  448. end;
  449. procedure TVrSpinButton.DoClick;
  450. begin
  451.   inherited Click;
  452. end;
  453. procedure TVrSpinButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  454.   X, Y: Integer);
  455. begin
  456.   inherited;
  457.   if (Button = mbLeft) and Enabled then
  458.     if InControl(X, Y) then
  459.     begin
  460.       MouseBtnDown := true;
  461.       MouseCapture := true;
  462.       UpdateControlCanvas;
  463.     end;
  464. end;
  465. procedure TVrSpinButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
  466.   X, Y: Integer);
  467. begin
  468.   inherited;
  469.   MouseBtnDown := false;
  470.   MouseCapture := false;
  471.   UpdateControlCanvas;
  472.   if InControl(X, Y) then DoClick;
  473. end;
  474. {TVrTimerSpinButton}
  475. destructor TVrTimerSpinButton.Destroy;
  476. begin
  477.   if FRepeatTimer <> nil then
  478.     FRepeatTimer.Free;
  479.   inherited Destroy;
  480. end;
  481. procedure TVrTimerSpinButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  482.   X, Y: Integer);
  483. begin
  484.   inherited MouseDown (Button, Shift, X, Y);
  485.   if tbAllowTimer in FTimeBtnState then
  486.   begin
  487.     if FRepeatTimer = nil then
  488.       FRepeatTimer := TVrTimer.Create(Self);
  489.     FRepeatTimer.Enabled := false;
  490.     FRepeatTimer.OnTimer := TimerExpired;
  491.     FRepeatTimer.Interval := InitRepeatPause;
  492.     FRepeatTimer.TimerType := ttSystem;
  493.     FRepeatTimer.Enabled := True;
  494.   end;
  495. end;
  496. procedure TVrTimerSpinButton.MouseUp(Button: TMouseButton;
  497.   Shift: TShiftState; X, Y: Integer);
  498. begin
  499.   inherited MouseUp(Button, Shift, X, Y);
  500.   if FRepeatTimer <> nil then
  501.     FRepeatTimer.Enabled  := False;
  502. end;
  503. procedure TVrTimerSpinButton.TimerExpired(Sender: TObject);
  504. begin
  505.   FRepeatTimer.Interval := RepeatPause;
  506.   if (MouseBtnDown) and MouseCapture then
  507.   begin
  508.     try
  509.       DoClick;
  510.     except
  511.       FRepeatTimer.Enabled := False;
  512.       raise;
  513.     end;
  514.   end;
  515. end;
  516. procedure TVrTimerSpinButton.Paint;
  517. var
  518.   R: TRect;
  519. begin
  520.   inherited Paint;
  521.   if tbFocusRect in FTimeBtnState then
  522.   begin
  523.     R := Bounds(0, 0, Width, Height);
  524.     InflateRect(R, -3, -3);
  525.     Canvas.Brush.Style := bsSolid;
  526.     Canvas.Brush.Color := clBlack;
  527.     Canvas.FrameRect(R);
  528.   end;
  529. end;
  530. end.