📄 rxslider.pas
字号:
procedure TRxCustomSlider.SetIncrement(Value: Longint);
begin
if not (csReading in ComponentState) and ((Value > MaxValue - MinValue) or
(Value < 1)) then
raise Exception.CreateFmt(ResStr(SOutOfRange), [1, MaxValue - MinValue]);
if (Value > 0) and (FIncrement <> Value) then begin
FIncrement := Value;
Self.Value := FValue;
Invalidate;
end;
end;
function TRxCustomSlider.GetValueByOffset(Offset: Integer): Longint;
var
Range: Double;
R: TRect;
begin
R := SliderRect;
if Orientation = soVertical then
Offset := ClientHeight - Offset - FImages[siVThumb].Height;
Range := MaxValue - MinValue;
Result := Round((Offset - R.Left - Indent) * Range / GetRulerLength);
if not (soSmooth in Options) then
Result := Round(Result / Increment) * Increment;
Result := Min(MinValue + Max(Result, 0), MaxValue);
end;
function TRxCustomSlider.GetOffsetByValue(Value: Longint): Integer;
var
Range: Double;
R: TRect;
MinIndent: Integer;
begin
R := SliderRect;
Range := MaxValue - MinValue;
if Orientation = soHorizontal then
MinIndent := R.Left + Indent
else
MinIndent := R.Top + Indent;
Result := Round((Value - MinValue) / Range * GetRulerLength) + MinIndent;
if Orientation = soVertical then
Result := R.Top + R.Bottom - Result - FImages[siVThumb].Height;
Result := Max(Result, MinIndent);
end;
function TRxCustomSlider.GetThumbPosition(var Offset: Integer): TPoint;
var
R: TRect;
MinIndent: Integer;
begin
R := SliderRect;
if Orientation = soHorizontal then
MinIndent := R.Left + Indent
else
MinIndent := R.Top + Indent;
Offset := Min(GetOffsetByValue(GetValueByOffset(Min(Max(Offset, MinIndent),
MinIndent + GetRulerLength))), MinIndent + GetRulerLength);
if Orientation = soHorizontal then begin
Result.X := Offset;
Result.Y := FThumbRect.Top;
end
else begin
Result.Y := Offset;
Result.X := FThumbRect.Left;
end;
end;
function TRxCustomSlider.GetThumbOffset: Integer;
begin
if Orientation = soHorizontal then Result := FThumbRect.Left
else Result := FThumbRect.Top;
end;
procedure TRxCustomSlider.InvalidateThumb;
begin
if HandleAllocated then
InvalidateRect(Handle, @FThumbRect, not (csOpaque in ControlStyle));
end;
procedure TRxCustomSlider.SetThumbOffset(Value: Integer);
var
ValueBefore: Longint;
P: TPoint;
begin
ValueBefore := FValue;
P := GetThumbPosition(Value);
InvalidateThumb;
FThumbRect := Bounds(P.X, P.Y, WidthOf(FThumbRect), HeightOf(FThumbRect));
InvalidateThumb;
if FSliding then begin
FValue := GetValueByOffset(Value);
if ValueBefore <> FValue then Change;
end;
end;
function TRxCustomSlider.GetRulerLength: Integer;
begin
if Orientation = soHorizontal then begin
Result := FRuler.Width;
Dec(Result, FImages[siHThumb].Width div NumThumbStates);
end
else begin
Result := FRuler.Height;
Dec(Result, FImages[siVThumb].Height);
end;
end;
procedure TRxCustomSlider.SetValue(Value: Longint);
var
ValueChanged: Boolean;
begin
if Value > MaxValue then Value := MaxValue;
if Value < MinValue then Value := MinValue;
ValueChanged := FValue <> Value;
FValue := Value;
ThumbOffset := GetOffsetByValue(Value);
if ValueChanged then Change;
end;
procedure TRxCustomSlider.SetReadOnly(Value: Boolean);
begin
if FReadOnly <> Value then begin
if Value then begin
StopTracking;
if FSliding then ThumbMouseUp(mbLeft, [], 0, 0);
end;
FReadOnly := Value;
end;
end;
procedure TRxCustomSlider.ThumbJump(Jump: TJumpMode);
var
NewValue: Longint;
begin
if Jump <> jmNone then begin
case Jump of
jmHome: NewValue := MinValue;
jmPrior:
NewValue := (Round(Value / Increment) * Increment) - Increment;
jmNext:
NewValue := (Round(Value / Increment) * Increment) + Increment;
jmEnd: NewValue := MaxValue;
else Exit;
end;
if NewValue >= MaxValue then NewValue := MaxValue
else if NewValue <= MinValue then NewValue := MinValue;
if (NewValue <> Value) then Value := NewValue;
end;
end;
function TRxCustomSlider.JumpTo(X, Y: Integer): TJumpMode;
begin
Result := jmNone;
if Orientation = soHorizontal then begin
if FThumbRect.Left > X then Result := jmPrior
else if FThumbRect.Right < X then Result := jmNext;
end
else if Orientation = soVertical then begin
if FThumbRect.Top > Y then Result := jmNext
else if FThumbRect.Bottom < Y then Result := jmPrior;
end;
end;
procedure TRxCustomSlider.WMTimer(var Message: TMessage);
begin
TimerTrack;
end;
procedure TRxCustomSlider.CMEnabledChanged(var Message: TMessage);
begin
inherited;
InvalidateThumb;
end;
procedure TRxCustomSlider.CMFocusChanged(var Message: TCMFocusChanged);
var
Active: Boolean;
begin
with Message do Active := (Sender = Self);
if Active <> FFocused then begin
FFocused := Active;
if (soShowFocus in Options) then Invalidate;
end;
inherited;
end;
procedure TRxCustomSlider.WMGetDlgCode(var Msg: TWMGetDlgCode);
begin
Msg.Result := DLGC_WANTARROWS;
end;
procedure TRxCustomSlider.WMSize(var Message: TWMSize);
begin
inherited;
if not (csReading in ComponentState) then Sized;
end;
procedure TRxCustomSlider.WMSetCursor(var Message: TWMSetCursor);
var
P: TPoint;
begin
GetCursorPos(P);
if not (csDesigning in ComponentState) and PtInRect(FThumbRect,
ScreenToClient(P)) then
begin
{$IFDEF WIN32}
Windows.SetCursor(Screen.Cursors[crHand]);
{$ELSE}
WinProcs.SetCursor(Screen.Cursors[crHand]);
{$ENDIF}
end
else inherited;
end;
procedure TRxCustomSlider.StopTracking;
begin
if FTracking then begin
if FTimerActive then begin
KillTimer(Handle, 1);
FTimerActive := False;
end;
FTracking := False;
MouseCapture := False;
Changed;
end;
end;
procedure TRxCustomSlider.TimerTrack;
var
Jump: TJumpMode;
begin
Jump := JumpTo(FMousePos.X, FMousePos.Y);
if Jump = FStartJump then begin
ThumbJump(Jump);
if not FTimerActive then begin
SetTimer(Handle, 1, JumpInterval, nil);
FTimerActive := True;
end;
end;
end;
procedure TRxCustomSlider.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
Rect: TRect;
P: TPoint;
begin
inherited MouseDown(Button, Shift, X, Y);
if (Button = mbLeft) and not (ssDouble in Shift) then begin
if CanFocus then SetFocus;
P := Point(X, Y);
if PointInRect(P, FThumbRect) then
ThumbMouseDown(Button, Shift, X, Y)
else begin
with FRulerOrg, FRuler do
Rect := Bounds(X, Y, Width, Height);
InflateRect(Rect, Ord(Orientation = soVertical) * 3,
Ord(Orientation = soHorizontal) * 3);
if PointInRect(P, Rect) and CanModify and not ReadOnly then begin
MouseCapture := True;
FTracking := True;
FMousePos := P;
FStartJump := JumpTo(X, Y);
TimerTrack;
end;
end;
end;
end;
procedure TRxCustomSlider.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
if (csLButtonDown in ControlState) and FSliding then
ThumbMouseMove(Shift, X, Y)
else if FTracking then FMousePos := Point(X, Y);
inherited MouseMove(Shift, X, Y);
end;
procedure TRxCustomSlider.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
StopTracking;
if FSliding then ThumbMouseUp(Button, Shift, X, Y);
inherited MouseUp(Button, Shift, X, Y);
end;
procedure TRxCustomSlider.KeyDown(var Key: Word; Shift: TShiftState);
var
Jump: TJumpMode;
begin
Jump := jmNone;
if Shift = [] then begin
if Key = VK_HOME then Jump := jmHome
else if Key = VK_END then Jump := jmEnd;
if Orientation = soHorizontal then begin
if Key = VK_LEFT then Jump := jmPrior
else if Key = VK_RIGHT then Jump := jmNext;
end
else begin
if Key = VK_UP then Jump := jmNext
else if Key = VK_DOWN then Jump := jmPrior;
end;
end;
if (Jump <> jmNone) and CanModify and not ReadOnly then begin
Key := 0;
ThumbJump(Jump);
Changed;
end;
inherited KeyDown(Key, Shift);
end;
procedure TRxCustomSlider.ThumbMouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if CanFocus then SetFocus;
if (Button = mbLeft) and CanModify and not ReadOnly then begin
FSliding := True;
FThumbDown := True;
if Orientation = soHorizontal then FHit := X - FThumbRect.Left
else FHit := Y - FThumbRect.Top;
InvalidateThumb;
Update;
end;
end;
procedure TRxCustomSlider.ThumbMouseMove(Shift: TShiftState; X, Y: Integer);
begin
if (csLButtonDown in ControlState) and CanModify and not ReadOnly then
begin
if Orientation = soHorizontal then ThumbOffset := X - FHit
else ThumbOffset := Y - FHit;
end;
end;
procedure TRxCustomSlider.ThumbMouseUp(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if (Button = mbLeft) then begin
FSliding := False;
FThumbDown := False;
InvalidateThumb;
Update;
if CanModify and not ReadOnly then Changed;
end;
end;
{ TRxCustomTrackBar }
constructor TRxCustomTrackBar.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FImages := TRxSliderImages.Create;
FImages.FSlider := Self;
end;
destructor TRxCustomTrackBar.Destroy;
begin
FImages.Free;
inherited Destroy;
end;
{ TRxSliderImages }
function TRxSliderImages.GetImage(Index: Integer): TBitmap;
begin
Result := FSlider.GetImage(Index);
end;
procedure TRxSliderImages.SetImage(Index: Integer; Value: TBitmap);
begin
FSlider.SetImage(Index, Value);
end;
function TRxSliderImages.StoreImage(Index: Integer): Boolean;
begin
Result := FSlider.StoreImage(Index);
end;
function TRxSliderImages.GetNumThumbStates: TNumThumbStates;
begin
Result := FSlider.NumThumbStates;
end;
procedure TRxSliderImages.SetNumThumbStates(Value: TNumThumbStates);
begin
FSlider.NumThumbStates := Value;
end;
function TRxSliderImages.GetEdgeSize: Integer;
begin
Result := FSlider.EdgeSize;
end;
procedure TRxSliderImages.SetEdgeSize(Value: Integer);
begin
FSlider.EdgeSize := Value;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -