| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- {******************************************************************************}
- { CnPack For Delphi/C++Builder }
- { 中国人自己的开放源码第三方开发包 }
- { (C)Copyright 2001-2018 CnPack 开发组 }
- { ------------------------------------ }
- { }
- { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
- { 改和重新发布这一程序。 }
- { }
- { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
- { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
- { }
- { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
- { 还没有,可访问我们的网站: }
- { }
- { 网站地址:http://www.cnpack.org }
- { 电子邮件:master@cnpack.org }
- { }
- {******************************************************************************}
- unit CnSpin;
- {* |<PRE>
- ================================================================================
- * 软件名称:界面控件包
- * 单元名称:CnSpin 控件单元
- * 单元作者:CnPack开发组
- * 开发平台:PWin98SE + Delphi 5.0
- * 兼容测试:PWin9X/2000/XP + Delphi 5/6
- * 本 地 化:该单元中的字符串均符合本地化处理方式
- * 备 注:由 周劲羽 从 Delphi 5 中移植而来,以实现 BCB 的兼容
- * 修改记录:2002.12.07 V1.0
- * 移植自 Delphi 5
- ================================================================================
- |</PRE>}
- interface
- {$I CnPack.inc}
- uses
- Windows, Classes, StdCtrls, ExtCtrls, Controls, Messages, SysUtils,
- Forms, Graphics, Menus, Buttons, CnConsts;
- const
- InitRepeatPause = 400; { pause before repeat timer (ms) }
- RepeatPause = 100; { pause before hint window displays (ms)}
- type
- TNumGlyphs = Buttons.TNumGlyphs;
- TCnTimerSpeedButton = class;
- { TCnSpinButton }
- TCnSpinButton = class(TWinControl)
- private
- FUpButton: TCnTimerSpeedButton;
- FDownButton: TCnTimerSpeedButton;
- FFocusedButton: TCnTimerSpeedButton;
- FFocusControl: TWinControl;
- FOnUpClick: TNotifyEvent;
- FOnDownClick: TNotifyEvent;
- function CreateButton: TCnTimerSpeedButton;
- function GetUpGlyph: TBitmap;
- function GetDownGlyph: TBitmap;
- procedure SetUpGlyph(Value: TBitmap);
- procedure SetDownGlyph(Value: TBitmap);
- function GetUpNumGlyphs: TNumGlyphs;
- function GetDownNumGlyphs: TNumGlyphs;
- procedure SetUpNumGlyphs(Value: TNumGlyphs);
- procedure SetDownNumGlyphs(Value: TNumGlyphs);
- procedure BtnClick(Sender: TObject);
- procedure BtnMouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure SetFocusBtn(Btn: TCnTimerSpeedButton);
- procedure AdjustSize(var W, H: Integer); reintroduce;
- procedure WMSize(var Message: TWMSize); message WM_SIZE;
- procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
- procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
- procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
- protected
- procedure Loaded; override;
- procedure KeyDown(var Key: Word; Shift: TShiftState); override;
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); override;
- public
- constructor Create(AOwner: TComponent); override;
- procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
- published
- property Align;
- property Anchors;
- property Constraints;
- property Ctl3D;
- property DownGlyph: TBitmap read GetDownGlyph write SetDownGlyph;
- property DownNumGlyphs: TNumGlyphs read GetDownNumGlyphs write SetDownNumGlyphs default 1;
- property DragCursor;
- property DragKind;
- property DragMode;
- property Enabled;
- property FocusControl: TWinControl read FFocusControl write FFocusControl;
- property ParentCtl3D;
- property ParentShowHint;
- property PopupMenu;
- property ShowHint;
- property TabOrder;
- property TabStop;
- property UpGlyph: TBitmap read GetUpGlyph write SetUpGlyph;
- property UpNumGlyphs: TNumGlyphs read GetUpNumGlyphs write SetUpNumGlyphs default 1;
- property Visible;
- property OnDownClick: TNotifyEvent read FOnDownClick write FOnDownClick;
- property OnDragDrop;
- property OnDragOver;
- property OnEndDock;
- property OnEndDrag;
- property OnEnter;
- property OnExit;
- property OnStartDock;
- property OnStartDrag;
- property OnUpClick: TNotifyEvent read FOnUpClick write FOnUpClick;
- end;
- { TCnSpinEdit }
- TCnSpinEdit = class(TCustomEdit)
- private
- FMinValue: LongInt;
- FMaxValue: LongInt;
- FIncrement: LongInt;
- FButton: TCnSpinButton;
- FEditorEnabled: Boolean;
- function GetMinHeight: Integer;
- function GetValue: LongInt;
- function CheckValue (NewValue: LongInt): LongInt;
- procedure SetValue (NewValue: LongInt);
- procedure SetEditRect;
- procedure WMSize(var Message: TWMSize); message WM_SIZE;
- procedure CMEnter(var Message: TCMGotFocus); message CM_ENTER;
- procedure CMExit(var Message: TCMExit); message CM_EXIT;
- procedure WMPaste(var Message: TWMPaste); message WM_PASTE;
- procedure WMCut(var Message: TWMCut); message WM_CUT;
- protected
- function IsValidChar(Key: Char): Boolean; virtual;
- procedure UpClick (Sender: TObject); virtual;
- procedure DownClick (Sender: TObject); virtual;
- procedure KeyDown(var Key: Word; Shift: TShiftState); override;
- procedure KeyPress(var Key: Char); override;
- procedure CreateParams(var Params: TCreateParams); override;
- procedure CreateWnd; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
- property Button: TCnSpinButton read FButton;
- published
- property Anchors;
- property AutoSelect;
- property AutoSize;
- property Color;
- property Constraints;
- property Ctl3D;
- property DragCursor;
- property DragMode;
- property EditorEnabled: Boolean read FEditorEnabled write FEditorEnabled default True;
- property Enabled;
- property Font;
- property Increment: LongInt read FIncrement write FIncrement default 1;
- property MaxLength;
- property MaxValue: LongInt read FMaxValue write FMaxValue;
- property MinValue: LongInt read FMinValue write FMinValue;
- property ParentColor;
- property ParentCtl3D;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property ReadOnly;
- property ShowHint;
- property TabOrder;
- property TabStop;
- property Value: LongInt read GetValue write SetValue;
- property Visible;
- property OnChange;
- property OnClick;
- property OnDblClick;
- property OnDragDrop;
- property OnDragOver;
- property OnEndDrag;
- property OnEnter;
- property OnExit;
- property OnKeyDown;
- property OnKeyPress;
- property OnKeyUp;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnStartDrag;
- end;
- { TTimerSpeedButton }
- TTimeBtnState = set of (tbFocusRect, tbAllowTimer);
- TCnTimerSpeedButton = class(TSpeedButton)
- private
- FRepeatTimer: TTimer;
- FTimeBtnState: TTimeBtnState;
- procedure TimerExpired(Sender: TObject);
- protected
- procedure Paint; override;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer); override;
- public
- destructor Destroy; override;
- property TimeBtnState: TTimeBtnState read FTimeBtnState write FTimeBtnState;
- end;
- implementation
- {$R CNSPIN}
- { TCnSpinButton }
- constructor TCnSpinButton.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] +
- [csFramed, csOpaque];
- FUpButton := CreateButton;
- FDownButton := CreateButton;
- UpGlyph := nil;
- DownGlyph := nil;
- Width := 20;
- Height := 25;
- FFocusedButton := FUpButton;
- end;
- function TCnSpinButton.CreateButton: TCnTimerSpeedButton;
- begin
- Result := TCnTimerSpeedButton.Create (Self);
- Result.OnClick := BtnClick;
- Result.OnMouseDown := BtnMouseDown;
- Result.Visible := True;
- Result.Enabled := True;
- Result.TimeBtnState := [tbAllowTimer];
- Result.Parent := Self;
- end;
- procedure TCnSpinButton.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- inherited Notification(AComponent, Operation);
- if (Operation = opRemove) and (AComponent = FFocusControl) then
- FFocusControl := nil;
- end;
- procedure TCnSpinButton.AdjustSize (var W, H: Integer);
- begin
- if (FUpButton = nil) or (csLoading in ComponentState) then Exit;
- if W < 15 then W := 15;
- FUpButton.SetBounds (0, 0, W, H div 2);
- FDownButton.SetBounds (0, FUpButton.Height - 1, W, H - FUpButton.Height + 1);
- end;
- procedure TCnSpinButton.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
- var
- W, H: Integer;
- begin
- W := AWidth;
- H := AHeight;
- AdjustSize(W, H);
- inherited SetBounds(ALeft, ATop, W, H);
- end;
- procedure TCnSpinButton.WMSize(var Message: TWMSize);
- var
- W, H: Integer;
- begin
- inherited;
- W := Width;
- H := Height;
- AdjustSize(W, H);
- if (W <> Width) or (H <> Height) then
- inherited SetBounds(Left, Top, W, H);
- Message.Result := 0;
- end;
- procedure TCnSpinButton.WMSetFocus(var Message: TWMSetFocus);
- begin
- FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState + [tbFocusRect];
- FFocusedButton.Invalidate;
- end;
- procedure TCnSpinButton.WMKillFocus(var Message: TWMKillFocus);
- begin
- FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState - [tbFocusRect];
- FFocusedButton.Invalidate;
- end;
- procedure TCnSpinButton.KeyDown(var Key: Word; Shift: TShiftState);
- begin
- case Key of
- VK_UP:
- begin
- SetFocusBtn(FUpButton);
- FUpButton.Click;
- end;
- VK_DOWN:
- begin
- SetFocusBtn(FDownButton);
- FDownButton.Click;
- end;
- VK_SPACE:
- FFocusedButton.Click;
- end;
- end;
- procedure TCnSpinButton.BtnMouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- begin
- if Button = mbLeft then
- begin
- SetFocusBtn(TCnTimerSpeedButton(Sender));
- if (FFocusControl <> nil) and FFocusControl.TabStop and
- FFocusControl.CanFocus and (GetFocus <> FFocusControl.Handle) then
- FFocusControl.SetFocus
- else if TabStop and (GetFocus <> Handle) and CanFocus then
- SetFocus;
- end;
- end;
- procedure TCnSpinButton.BtnClick(Sender: TObject);
- begin
- if Sender = FUpButton then
- begin
- if Assigned(FOnUpClick) then FOnUpClick(Self);
- end
- else
- if Assigned(FOnDownClick) then FOnDownClick(Self);
- end;
- procedure TCnSpinButton.SetFocusBtn(Btn: TCnTimerSpeedButton);
- begin
- if TabStop and CanFocus and (Btn <> FFocusedButton) then
- begin
- FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState - [tbFocusRect];
- FFocusedButton := Btn;
- if (GetFocus = Handle) then
- begin
- FFocusedButton.TimeBtnState := FFocusedButton.TimeBtnState + [tbFocusRect];
- Invalidate;
- end;
- end;
- end;
- procedure TCnSpinButton.WMGetDlgCode(var Message: TWMGetDlgCode);
- begin
- Message.Result := DLGC_WANTARROWS;
- end;
- procedure TCnSpinButton.Loaded;
- var
- W, H: Integer;
- begin
- inherited Loaded;
- W := Width;
- H := Height;
- AdjustSize(W, H);
- if (W <> Width) or (H <> Height) then
- inherited SetBounds(Left, Top, W, H);
- end;
- function TCnSpinButton.GetUpGlyph: TBitmap;
- begin
- Result := FUpButton.Glyph;
- end;
- procedure TCnSpinButton.SetUpGlyph(Value: TBitmap);
- begin
- if Value <> nil then
- FUpButton.Glyph := Value
- else
- begin
- FUpButton.Glyph.Handle := LoadBitmap(HInstance, 'CNSPINEDITUP');
- FUpButton.NumGlyphs := 1;
- FUpButton.Invalidate;
- end;
- end;
- function TCnSpinButton.GetUpNumGlyphs: TNumGlyphs;
- begin
- Result := FUpButton.NumGlyphs;
- end;
- procedure TCnSpinButton.SetUpNumGlyphs(Value: TNumGlyphs);
- begin
- FUpButton.NumGlyphs := Value;
- end;
- function TCnSpinButton.GetDownGlyph: TBitmap;
- begin
- Result := FDownButton.Glyph;
- end;
- procedure TCnSpinButton.SetDownGlyph(Value: TBitmap);
- begin
- if Value <> nil then
- FDownButton.Glyph := Value
- else
- begin
- FDownButton.Glyph.Handle := LoadBitmap(HInstance, 'CNSPINEDITDOWN');
- FUpButton.NumGlyphs := 1;
- FDownButton.Invalidate;
- end;
- end;
- function TCnSpinButton.GetDownNumGlyphs: TNumGlyphs;
- begin
- Result := FDownButton.NumGlyphs;
- end;
- procedure TCnSpinButton.SetDownNumGlyphs(Value: TNumGlyphs);
- begin
- FDownButton.NumGlyphs := Value;
- end;
- { TCnSpinEdit }
- constructor TCnSpinEdit.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FButton := TCnSpinButton.Create(Self);
- FButton.Width := 15;
- FButton.Height := 17;
- FButton.Visible := True;
- FButton.Parent := Self;
- FButton.FocusControl := Self;
- FButton.OnUpClick := UpClick;
- FButton.OnDownClick := DownClick;
- Text := '0';
- ControlStyle := ControlStyle - [csSetCaption];
- FIncrement := 1;
- FEditorEnabled := True;
- end;
- destructor TCnSpinEdit.Destroy;
- begin
- FButton := nil;
- inherited Destroy;
- end;
- procedure TCnSpinEdit.GetChildren(Proc: TGetChildProc; Root: TComponent);
- begin
- end;
- procedure TCnSpinEdit.KeyDown(var Key: Word; Shift: TShiftState);
- begin
- if Key = VK_UP then UpClick(Self)
- else if Key = VK_DOWN then DownClick(Self);
- inherited KeyDown(Key, Shift);
- end;
- procedure TCnSpinEdit.KeyPress(var Key: Char);
- begin
- if not IsValidChar(Key) then
- begin
- Key := #0;
- MessageBeep(0)
- end;
- if Key <> #0 then inherited KeyPress(Key);
- end;
- function TCnSpinEdit.IsValidChar(Key: Char): Boolean;
- begin
- Result := (AnsiChar(Key) in [{$IFDEF DELPHIXE3_UP}FormatSettings.{$ENDIF}DecimalSeparator, '+', '-', '0'..'9']) or
- ((Key < #32) and (Key <> Chr(VK_RETURN)));
- if not FEditorEnabled and Result and ((Key >= #32) or
- (Key = Char(VK_BACK)) or (Key = Char(VK_DELETE))) then
- Result := False;
- end;
- procedure TCnSpinEdit.CreateParams(var Params: TCreateParams);
- begin
- inherited CreateParams(Params);
- { Params.Style := Params.Style and not WS_BORDER; }
- Params.Style := Params.Style or ES_MULTILINE or WS_CLIPCHILDREN;
- end;
- procedure TCnSpinEdit.CreateWnd;
- begin
- inherited CreateWnd;
- SetEditRect;
- end;
- procedure TCnSpinEdit.SetEditRect;
- var
- Loc: TRect;
- begin
- SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc));
- Loc.Bottom := ClientHeight + 1; {+1 is workaround for windows paint bug}
- Loc.Right := ClientWidth - FButton.Width - 2;
- Loc.Top := 0;
- Loc.Left := 0;
- SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@Loc));
- SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc)); {debug}
- end;
- procedure TCnSpinEdit.WMSize(var Message: TWMSize);
- var
- MinHeight: Integer;
- begin
- inherited;
- MinHeight := GetMinHeight;
- { text edit bug: if size to less than minheight, then edit ctrl does
- not display the text }
- if Height < MinHeight then
- Height := MinHeight
- else if FButton <> nil then
- begin
- if NewStyleControls and Ctl3D then
- FButton.SetBounds(Width - FButton.Width - 5, 0, FButton.Width, Height - 5)
- else FButton.SetBounds(Width - FButton.Width, 1, FButton.Width, Height - 3);
- SetEditRect;
- end;
- end;
- function TCnSpinEdit.GetMinHeight: Integer;
- var
- DC: HDC;
- SaveFont: HFont;
- I: Integer;
- SysMetrics, Metrics: TTextMetric;
- begin
- DC := GetDC(0);
- GetTextMetrics(DC, SysMetrics);
- SaveFont := SelectObject(DC, Font.Handle);
- GetTextMetrics(DC, Metrics);
- SelectObject(DC, SaveFont);
- ReleaseDC(0, DC);
- I := SysMetrics.tmHeight;
- if I > Metrics.tmHeight then I := Metrics.tmHeight;
- Result := Metrics.tmHeight + I div 4 + GetSystemMetrics(SM_CYBORDER) * 4 + 2;
- end;
- procedure TCnSpinEdit.UpClick(Sender: TObject);
- begin
- if ReadOnly then MessageBeep(0)
- else Value := Value + FIncrement;
- end;
- procedure TCnSpinEdit.DownClick(Sender: TObject);
- begin
- if ReadOnly then MessageBeep(0)
- else Value := Value - FIncrement;
- end;
- procedure TCnSpinEdit.WMPaste(var Message: TWMPaste);
- begin
- if not FEditorEnabled or ReadOnly then Exit;
- inherited;
- end;
- procedure TCnSpinEdit.WMCut(var Message: TWMPaste);
- begin
- if not FEditorEnabled or ReadOnly then Exit;
- inherited;
- end;
- procedure TCnSpinEdit.CMExit(var Message: TCMExit);
- begin
- inherited;
- if CheckValue(Value) <> Value then
- SetValue(Value);
- end;
- function TCnSpinEdit.GetValue: LongInt;
- begin
- Result := StrToIntDef (Text, FMinValue);
- end;
- procedure TCnSpinEdit.SetValue(NewValue: LongInt);
- begin
- Text := IntToStr(CheckValue(NewValue));
- end;
- function TCnSpinEdit.CheckValue(NewValue: LongInt): LongInt;
- begin
- Result := NewValue;
- if (FMaxValue <> FMinValue) then
- begin
- if NewValue < FMinValue then
- Result := FMinValue
- else if NewValue > FMaxValue then
- Result := FMaxValue;
- end;
- end;
- procedure TCnSpinEdit.CMEnter(var Message: TCMGotFocus);
- begin
- if AutoSelect and not (csLButtonDown in ControlState) then
- SelectAll;
- inherited;
- end;
- {TTimerSpeedButton}
- destructor TCnTimerSpeedButton.Destroy;
- begin
- if FRepeatTimer <> nil then
- FRepeatTimer.Free;
- inherited Destroy;
- end;
- procedure TCnTimerSpeedButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer);
- begin
- inherited MouseDown(Button, Shift, X, Y);
- if tbAllowTimer in FTimeBtnState then
- begin
- if FRepeatTimer = nil then
- FRepeatTimer := TTimer.Create(Self);
- FRepeatTimer.OnTimer := TimerExpired;
- FRepeatTimer.Interval := InitRepeatPause;
- FRepeatTimer.Enabled := True;
- end;
- end;
- procedure TCnTimerSpeedButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer);
- begin
- inherited MouseUp(Button, Shift, X, Y);
- if FRepeatTimer <> nil then
- FRepeatTimer.Enabled := False;
- end;
- procedure TCnTimerSpeedButton.TimerExpired(Sender: TObject);
- begin
- FRepeatTimer.Interval := RepeatPause;
- if (FState = bsDown) and MouseCapture then
- begin
- try
- Click;
- except
- FRepeatTimer.Enabled := False;
- raise;
- end;
- end;
- end;
- procedure TCnTimerSpeedButton.Paint;
- var
- R: TRect;
- begin
- inherited Paint;
- if tbFocusRect in FTimeBtnState then
- begin
- R := Bounds(0, 0, Width, Height);
- InflateRect(R, -3, -3);
- if FState = bsDown then
- OffsetRect(R, 1, 1);
- DrawFocusRect(Canvas.Handle, R);
- end;
- end;
- end.
|