📄 rm_ctrls.pas
字号:
FDownBitmap.Handle := LoadBitmap(HInstance, sSpinDownBtn);
FUpBitmap.OnChange := GlyphChanged;
FDownBitmap.OnChange := GlyphChanged;
Height := 20;
Width := 20;
FTopDownBtn := TBitmap.Create;
FBottomDownBtn := TBitmap.Create;
FNotDownBtn := TBitmap.Create;
DrawAllBitmap;
FLastDown := rmsbNotDown;
end;
destructor TRMSpinButton.Destroy;
begin
FTopDownBtn.Free;
FBottomDownBtn.Free;
FNotDownBtn.Free;
FUpBitmap.Free;
FDownBitmap.Free;
FRepeatTimer.Free;
inherited Destroy;
end;
procedure TRMSpinButton.GlyphChanged(Sender: TObject);
begin
FInvalidate := True;
Invalidate;
end;
procedure TRMSpinButton.SetDown(Value: TRMSpinButtonState);
var
OldState: TRMSpinButtonState;
begin
OldState := FDown;
FDown := Value;
if OldState <> FDown then
Repaint;
end;
procedure TRMSpinButton.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent = FFocusControl) then
FFocusControl := nil;
end;
procedure TRMSpinButton.Paint;
begin
if not Enabled and not (csDesigning in ComponentState) then
FDragging := False;
if (FNotDownBtn.Height <> Height) or (FNotDownBtn.Width <> Width) or FInvalidate then
DrawAllBitmap;
FInvalidate := False;
with Canvas do
case FDown of
rmsbNotDown: Draw(0, 0, FNotDownBtn);
rmsbTopDown: Draw(0, 0, FTopDownBtn);
rmsbBottomDown: Draw(0, 0, FBottomDownBtn);
end;
end;
procedure TRMSpinButton.DrawAllBitmap;
begin
DrawBitmap(FTopDownBtn, rmsbTopDown);
DrawBitmap(FBottomDownBtn, rmsbBottomDown);
DrawBitmap(FNotDownBtn, rmsbNotDown);
end;
procedure TRMSpinButton.DrawBitmap(ABitmap: TBitmap; ADownState: TRMSpinButtonState);
var
R, RSrc: TRect;
dRect: Integer;
begin
ABitmap.Height := Height;
ABitmap.Width := Width;
with ABitmap.Canvas do
begin
R := Bounds(0, 0, Width, Height);
Pen.Width := 1;
Brush.Color := clBtnFace;
Brush.Style := bsSolid;
FillRect(R);
{ buttons frame }
Pen.Color := clWindowFrame;
Rectangle(0, 0, Width, Height);
MoveTo(-1, Height);
LineTo(Width, -1);
{ top button }
if ADownState = rmsbTopDown then
Pen.Color := clBtnShadow
else
Pen.Color := clBtnHighlight;
MoveTo(1, Height - 4);
LineTo(1, 1);
LineTo(Width - 3, 1);
if ADownState = rmsbTopDown then
Pen.Color := clBtnHighlight
else
Pen.Color := clBtnShadow;
if ADownState <> rmsbTopDown then
begin
MoveTo(1, Height - 3);
LineTo(Width - 2, 0);
end;
{ bottom button }
if ADownState = rmsbBottomDown then
Pen.Color := clBtnHighlight
else
Pen.Color := clBtnShadow;
MoveTo(2, Height - 2);
LineTo(Width - 2, Height - 2);
LineTo(Width - 2, 1);
if ADownState = rmsbBottomDown then
Pen.Color := clBtnShadow
else
Pen.Color := clBtnHighlight;
MoveTo(2, Height - 2);
LineTo(Width - 1, 1);
{ top glyph }
dRect := 1;
if ADownState = rmsbTopDown then
Inc(dRect);
R := Bounds(Round((Width / 4) - (FUpBitmap.Width / 2)) + dRect,
Round((Height / 4) - (FUpBitmap.Height / 2)) + dRect, FUpBitmap.Width,
FUpBitmap.Height);
RSrc := Bounds(0, 0, FUpBitmap.Width, FUpBitmap.Height);
BrushCopy(R, FUpBitmap, RSrc, FUpBitmap.TransparentColor);
{ bottom glyph }
R := Bounds(Round((3 * Width / 4) - (FDownBitmap.Width / 2)) - 1,
Round((3 * Height / 4) - (FDownBitmap.Height / 2)) - 1,
FDownBitmap.Width, FDownBitmap.Height);
RSrc := Bounds(0, 0, FDownBitmap.Width, FDownBitmap.Height);
BrushCopy(R, FDownBitmap, RSrc, FDownBitmap.TransparentColor);
if ADownState = rmsbBottomDown then
begin
Pen.Color := clBtnShadow;
MoveTo(3, Height - 2);
LineTo(Width - 1, 2);
end;
end;
end;
procedure TRMSpinButton.CMEnabledChanged(var Message: TMessage);
begin
inherited;
FInvalidate := True;
Invalidate;
end;
procedure TRMSpinButton.TopClick;
begin
if Assigned(FOnTopClick) then
begin
FOnTopClick(Self);
if not (csLButtonDown in ControlState) then
FDown := rmsbNotDown;
end;
end;
procedure TRMSpinButton.BottomClick;
begin
if Assigned(FOnBottomClick) then
begin
FOnBottomClick(Self);
if not (csLButtonDown in ControlState) then
FDown := rmsbNotDown;
end;
end;
procedure TRMSpinButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited MouseDown(Button, Shift, X, Y);
if (Button = mbLeft) and Enabled then
begin
if (FFocusControl <> nil) and FFocusControl.TabStop and
FFocusControl.CanFocus and (GetFocus <> FFocusControl.Handle) then
FFocusControl.SetFocus;
if FDown = rmsbNotDown then
begin
FLastDown := FDown;
if Y > (-(Height / Width) * X + Height) then
begin
FDown := rmsbBottomDown;
BottomClick;
end
else
begin
FDown := rmsbTopDown;
TopClick;
end;
if FLastDown <> FDown then
begin
FLastDown := FDown;
Repaint;
end;
if FRepeatTimer = nil then
FRepeatTimer := TTimer.Create(Self);
FRepeatTimer.OnTimer := TimerExpired;
FRepeatTimer.Interval := InitRepeatPause;
FRepeatTimer.Enabled := True;
end;
FDragging := True;
end;
end;
procedure TRMSpinButton.MouseMove(Shift: TShiftState; X, Y: Integer);
var
NewState: TRMSpinButtonState;
begin
inherited MouseMove(Shift, X, Y);
if FDragging then
begin
if (X >= 0) and (X <= Width) and (Y >= 0) and (Y <= Height) then
begin
NewState := FDown;
if Y > (-(Width / Height) * X + Height) then
begin
if (FDown <> rmsbBottomDown) then
begin
if FLastDown = rmsbBottomDown then
FDown := rmsbBottomDown
else
FDown := rmsbNotDown;
if NewState <> FDown then
Repaint;
end;
end
else
begin
if (FDown <> rmsbTopDown) then
begin
if (FLastDown = rmsbTopDown) then
FDown := rmsbTopDown
else
FDown := rmsbNotDown;
if NewState <> FDown then
Repaint;
end;
end;
end
else if FDown <> rmsbNotDown then
begin
FDown := rmsbNotDown;
Repaint;
end;
end;
end;
procedure TRMSpinButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited MouseUp(Button, Shift, X, Y);
if FDragging then
begin
FDragging := False;
if (X >= 0) and (X <= Width) and (Y >= 0) and (Y <= Height) then
begin
FDown := rmsbNotDown;
FLastDown := rmsbNotDown;
Repaint;
end;
end;
end;
procedure TRMSpinButton.TimerExpired(Sender: TObject);
begin
FRepeatTimer.Interval := RepeatPause;
if (FDown <> rmsbNotDown) and MouseCapture then
begin
try
if FDown = rmsbBottomDown then
BottomClick
else
TopClick;
except
FRepeatTimer.Enabled := False;
raise;
end;
end;
end;
function DefBtnWidth: Integer;
begin
Result := GetSystemMetrics(SM_CXVSCROLL);
if Result > 15 then
Result := 15;
end;
type
TRxUpDown = class(TCustomUpDown)
private
FChanging: Boolean;
procedure ScrollMessage(var Message: TWMVScroll);
procedure WMHScroll(var Message: TWMHScroll); message CN_HSCROLL;
procedure WMVScroll(var Message: TWMVScroll); message CN_VSCROLL;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnClick;
end;
constructor TRxUpDown.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Orientation := udVertical;
Min := -1;
Max := 1;
Position := 0;
end;
destructor TRxUpDown.Destroy;
begin
OnClick := nil;
inherited Destroy;
end;
procedure TRxUpDown.ScrollMessage(var Message: TWMVScroll);
begin
if Message.ScrollCode = SB_THUMBPOSITION then
begin
if not FChanging then
begin
FChanging := True;
try
if Message.Pos > 0 then
Click(btNext)
else if Message.Pos < 0 then
Click(btPrev);
if HandleAllocated then
SendMessage(Handle, UDM_SETPOS, 0, 0);
finally
FChanging := False;
end;
end;
end;
end;
procedure TRxUpDown.WMHScroll(var Message: TWMHScroll);
begin
ScrollMessage(TWMVScroll(Message));
end;
procedure TRxUpDown.WMVScroll(var Message: TWMVScroll);
begin
ScrollMessage(Message);
end;
procedure TRxUpDown.WMSize(var Message: TWMSize);
begin
inherited;
if Width <> DefBtnWidth then
Width := DefBtnWidth;
end;
{ TRMSpinEdit }
constructor TRMSpinEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Text := '0';
ControlStyle := ControlStyle - [csSetCaption];
FIncrement := 1.0;
FDecimal := 2;
FMinValue := 0;
FMaxValue := MaxInt;
FEditorEnabled := True;
FArrowKeys := True;
RecreateButton;
end;
destructor TRMSpinEdit.Destroy;
begin
Destroying;
FChanging := True;
if FButton <> nil then
begin
FButton.Free;
FButton := nil;
FBtnWindow.Free;
FBtnWindow := nil;
end;
if FUpDown <> nil then
begin
FUpDown.Free;
FUpDown := nil;
end;
inherited Destroy;
end;
procedure TRMSpinEdit.RecreateButton;
begin
if (csDestroying in ComponentState) then
Exit;
FButton.Free;
FButton := nil;
FBtnWindow.Free;
FBtnWindow := nil;
FUpDown.Free;
FUpDown := nil;
FUpDown := TRxUpDown.Create(Self);
with TRxUpDown(FUpDown) do
begin
Visible := True;
SetBounds(0, 0, DefBtnWidth, Self.Height);
{$IFDEF COMPILER4_UP}
if (BiDiMode = bdRightToLeft) then
Align := alLeft
else
{$ENDIF}
Align := alRight;
Parent := Self;
OnClick := UpDownClick;
end;
end;
procedure TRMSpinEdit.SetArrowKeys(Value: Boolean);
begin
FArrowKeys := Value;
ResizeButton;
end;
procedure TRMSpinEdit.UpDownClick(Sender: TObject; Button: TUDBtnType);
begin
if TabStop and CanFocus then
SetFocus;
case Button of
btNext: UpClick(Sender);
btPrev: DownClick(Sender);
end;
end;
function TRMSpinEdit.GetButtonWidth: Integer;
begin
if FUpDown <> nil then
Result := FUpDown.Width
else if FButton <> nil then
Result := FButton.Width
else
Result := DefBtnWidth;
end;
procedure TRMSpinEdit.ResizeButton;
var
R: TRect;
begin
if FUpDown <> nil then
begin
FUpDown.Width := DefBtnWidth;
{$IFDEF COMPILER4_UP}
if (BiDiMode = bdRightToLeft) then
FUpDown.Align := alLeft
else
{$ENDIF}
FUpDown.Align := alRight;
end
else if FButton <> nil then
begin { bkDiagonal }
if NewStyleControls and Ctl3D and (BorderStyle = bsSingle) then
R := Bounds(Width - Height - 1, -1, Height - 3, Height - 3)
else
R := Bounds(Width - Height, 0, Height, Height);
{$IFDEF COMPILER4_UP}
if (BiDiMode = bdRightToLeft) then
begin
if NewStyleControls and Ctl3D and (BorderStyle = bsSingle) then
begin
R.Left := -1;
R.Right := Height - 4;
end
else
begin
R.Left := 0;
R.Right := Height;
end;
end;
{$ENDIF}
with R do
FBtnWindow.SetBounds(Left, Top, Right - Left, Bottom - Top);
FButton.SetBounds(0, 0, FBtnWindow.Width, FBtnWindow.Height);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -