{**************************************************** This file is part of the Eye Candy Controls (EC-C) Copyright (C) 2013 Vojtěch Čihák, Czech Republic This library is free software. See the file COPYING.LGPL.txt, included in this distribution, for details about the license. ****************************************************} unit ECRuler; {$mode objfpc}{$H+} //{$DEFINE DBGRULER} {don't remove, just comment} interface uses Classes, SysUtils, Controls, Graphics, ExtCtrls, ECScale, ECTypes, Math, LCLIntf, LMessages, {$IFDEF DBGRULER} LCLProc, {$ENDIF} LCLType, LResources, Themes, Types; type {$PACKENUM 2} TPointerMode = (epmNone, epmFixed, epmMovable); TPointerStyle = (epsSimple, epsDashed, epsDotted); { Event } TOnChangePosition = procedure(Sender: TObject; APosition: Double) of object; { TECRulerScale } TECRulerScale = class(TCustomECScale) protected const cDefTickAlign = etaInner; cDefValueVisible = evvValues; public constructor Create(AParent: TControl); published property DateTimeFormat; property Digits; { property FontOrientation; } property LogarithmBase; property Max; property Min; property ScaleType; property Text; property TickAlign default cDefTickAlign; property TickColor; property TickDesign; property TickIndent default 0; property TickLength; property TickLongValue; property TickMiddleValue; property TickShortValue; property TickVisible; property ValueDisplay; property ValueFormat; property ValueIndent; property ValueShift; property ValueVisible default cDefValueVisible; property OnPrepareValue; end; { TCustomECRuler } TCustomECRuler = class(TECBaseControl) private FCaptionAlign: SmallInt; FCaptionPos: TBasicPos; FIndentBottomRight: Integer; FIndentTopLeft: Integer; FMouseCoord: Integer; FOnChangePosition: TOnChangePosition; FPointerColor: TColor; FPointerMode: TPointerMode; FPointerStyle: TPointerStyle; FPointerWidth: SmallInt; FPositionToHint: Boolean; FReversed: Boolean; FScale: TECRulerScale; FScaleFontOptions: TFontOptions; FScalePos: TBasicPos; FTransparent: Boolean; function GetMax: Double; function GetMin: Double; function GetPosition: Double; procedure SetCaptionAlign(AValue: SmallInt); procedure SetCaptionPos(AValue: TBasicPos); procedure SetIndentBottomRight(AValue: Integer); procedure SetIndentTopLeft(AValue: Integer); procedure SetMax(AValue: Double); procedure SetMin(AValue: Double); procedure SetPointerColor(AValue: TColor); procedure SetPointerMode(AValue: TPointerMode); procedure SetPointerStyle(AValue: TPointerStyle); procedure SetPointerWidth(AValue: SmallInt); procedure SetPosition(AValue: Double); procedure SetPositionToHint(AValue: Boolean); procedure SetReversed(AValue: Boolean); procedure SetScalePos(AValue: TBasicPos); procedure SetTransparent(AValue: Boolean); protected const cDefPointerMode = epmMovable; cDefPointerWidth = 1; protected Background: TBitmap; CurrInvRect: TRect; FullBorderWidth: SmallInt; PointerOverlay: Integer; RedrawPointer: procedure(ACoord: Integer) of object; ScaleLength: Double; ScalePxLength, ScalePxStart: Integer; TimeFormat: TFormatSettings; WasEnabled: Boolean; { state of IsEnabled from previous Paint } procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; {%H-}WithThemeSpace: Boolean); override; procedure Calculate; procedure CMColorChanged(var {%H-}Message: TLMessage); message CM_COLORCHANGED; procedure CMParentColorChanged(var Message: TLMessage); message CM_PARENTCOLORCHANGED; procedure DrawBackground; procedure DrawScaleAndCaption(ACanvas: TCanvas); procedure FontChanged(Sender: TObject); override; procedure InvalidateCustomRect({%H-}AMove: Boolean); override; function MouseCoordToPosition(AMouseCoord: Integer): Double; inline; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure OrientationChanged(AValue: TObjectOrientation); override; procedure Paint; override; procedure RecalcRedraw; override; procedure Redraw3DColorAreas; override; procedure RedrawHorizontal(X: Integer); procedure RedrawVertical(Y: Integer); procedure SetPointerPenStyle; procedure TextChanged; override; procedure WMSize(var Message: TLMSize); message LM_SIZE; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure BeginUpdate; override; procedure EndUpdate(Recalculate: Boolean=True); override; procedure Redraw; override; procedure SetMouseCoord(AValue: Integer); property CaptionAlign: SmallInt read FCaptionAlign write SetCaptionAlign default 0; property CaptionPos: TBasicPos read FCaptionPos write SetCaptionPos default ebpBottomRight; property IndentBottomRight: Integer read FIndentBottomRight write SetIndentBottomRight default 0; property IndentTopLeft: Integer read FIndentTopLeft write SetIndentTopLeft default 0; property Max: Double read GetMax write SetMax stored False; property Min: Double read GetMin write SetMin stored False; property MouseCoord: Integer read FMouseCoord write SetMouseCoord; property PointerColor: TColor read FPointerColor write SetPointerColor default clDefault; property PointerMode: TPointerMode read FPointerMode write SetPointerMode default cDefPointerMode; property PointerStyle: TPointerStyle read FPointerStyle write SetPointerStyle default epsSimple; property PointerWidth: SmallInt read FPointerWidth write SetPointerWidth default cDefPointerWidth; property Position: Double read GetPosition write SetPosition stored False; property PositionToHint: Boolean read FPositionToHint write SetPositionToHint default False; property Reversed: Boolean read FReversed write SetReversed default False; property Scale: TECRulerScale read FScale write FScale; property ScaleFontOptions: TFontOptions read FScaleFontOptions write FScaleFontOptions; property ScalePos: TBasicPos read FScalePos write SetScalePos default ebpTopLeft; property Transparent: Boolean read FTransparent write SetTransparent default False; property OnChangePosition: TOnChangePosition read FOnChangePosition write FOnChangePosition; end; TECRuler = class(TCustomECRuler) published property Align; property Anchors; property AutoSize default True; property BevelInner; property BevelOuter; property BevelSpace; property BevelWidth; property BorderSpacing; property Caption; property CaptionAlign; property CaptionPos; property Color; property Color3DDark; property Color3DLight; property Constraints; property Enabled; property Font; property IndentBottomRight; property IndentTopLeft; property Max; property Min; property Orientation default eooHorizontal; property ParentColor; property ParentFont; property ParentShowHint; property PointerColor; property PointerMode; property PointerStyle; property PointerWidth; property PopupMenu; property Position; property PositionToHint; property Reversed; property Scale; property ScaleFontOptions; property ScalePos; property ShowHint; property Style default eosPanel; property Transparent; property Visible; property OnChangeBounds; property OnChangePosition; property OnClick; property OnContextPopup; property OnDblClick; property OnMouseDown; property OnMouseEnter; property OnMouseLeave; property OnMouseMove; property OnMouseUp; property OnResize; end; procedure Register; implementation { TECRulerScale } constructor TECRulerScale.Create(AParent: TControl); begin inherited Create(AParent); FTickAlign := cDefTickAlign; FTickIndent := 0; FValueVisible := cDefValueVisible; end; { TCustomECRuler } constructor TCustomECRuler.Create(AOwner: TComponent); begin inherited Create(AOwner); ControlStyle := ControlStyle + [csNoFocus] - [csSetCaption]; FCaptionPos := ebpBottomRight; FMouseCoord := low(Integer); FOrientation := eooHorizontal; RedrawPointer := @RedrawHorizontal; FPointerColor := clDefault; FPointerMode := cDefPointerMode; PointerWidth := cDefPointerWidth; {Set PointerOverlay} FStyle := eosPanel; AutoSize := True; TabStop := False; FScaleFontOptions := TFontOptions.Create(self); with FScaleFontOptions do begin FontSize := 7; OnRecalcRedraw := @self.RecalcRedraw; OnRedraw := @self.Redraw; end; FScale := TECRulerScale.Create(self); with FScale do begin OnRecalcRedraw := @self.RecalcRedraw; OnRedraw := @self.Redraw; end; Background := TBitmap.Create; with Background do begin Transparent := True; TransparentMode := tmFixed; end; SetInitialBounds(0, 0, 320, 50); RedrawMode := ermRecalcRedraw; end; destructor TCustomECRuler.Destroy; begin FreeAndNil(Background); FreeAndNil(FScale); FreeAndNil(FScaleFontOptions); inherited Destroy; end; procedure TCustomECRuler.CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; WithThemeSpace: Boolean); var aSize: Integer; begin Canvas.Font.Size := FScaleFontOptions.FontSize; Canvas.Font.Style := FScaleFontOptions.FontStyles; aSize := 2*GetBorderWidth + FScale.GetPreferredSize(Canvas, Orientation=eooHorizontal, True, True); if Orientation = eooHorizontal then begin PreferredHeight := aSize; PreferredWidth := 0; end else begin PreferredHeight := 0; PreferredWidth := aSize; end; end; procedure TCustomECRuler.BeginUpdate; begin inherited BeginUpdate; FScale.BeginUpdate; end; procedure TCustomECRuler.Calculate; var aBorderWidth, aLength: Integer; begin aBorderWidth := GetBorderWidth; FullBorderWidth := aBorderWidth; if Orientation = eooHorizontal then aLength := Width else aLength := Height; aLength := aLength - IndentTopLeft - IndentBottomRight - 2*aBorderWidth; ScaleLength := Max - Min; ScalePxLength := aLength; ScalePxStart := IndentTopLeft + aBorderWidth; FScale.CalcTickPosAndValues(aLength, Reversed); end; procedure TCustomECRuler.CMColorChanged(var Message: TLMessage); begin Redraw; end; procedure TCustomECRuler.CMParentColorChanged(var Message: TLMessage); begin inherited CMParentColorChanged(Message); if (Style = eosPanel) and (Color = clDefault) then Redraw; end; procedure TCustomECRuler.DrawBackground; var aColor: TColor; begin {$IFDEF DBGRULER} DebugLn('ECRuler DrawBackground'); {$ENDIF} Background.SetSize(Width, Height); aColor := ColorToRGB(GetColorResolvingDefault(Color, Parent.Brush.Color)); if (aColor and $FF) > 0 then dec(aColor) else inc(aColor); Background.TransparentColor := aColor; Background.TransparentClear; case Style of eosButton: Background.Canvas.DrawButtonBackground(ClientRect, True); eosPanel: Background.Canvas.DrawPanelBackGround(ClientRect, BevelInner, BevelOuter, BevelSpace, BevelWidth, Color3DDark, Color3DLight, GetColorResolvingDefault(Color, Parent.Brush.Color)); end; DrawScaleAndCaption(Background.Canvas); SetPointerPenStyle; end; procedure TCustomECRuler.DrawScaleAndCaption(ACanvas: TCanvas); const cIndent = 3; var aFlags, aHelpFlag: Cardinal; i, j, aAbsCaptionIndent, aBorderWidth, aBottom, aRight: Integer; aRect: TRect; aSize: TSize; begin aBorderWidth := GetBorderWidth; ACanvas.Font.Assign(Font); if Caption <> '' then begin ACanvas.Font.Color := GetColorResolvingDefault(ACanvas.Font.Color, clBtnText); aFlags := DT_NOPREFIX or DT_MODIFYSTRING or DT_END_ELLIPSIS or DT_SINGLELINE; if IsRightToLeft then aFlags := aFlags or DT_RTLREADING; aHelpFlag := DT_TOP; aBottom := Height; aRight := Width; aSize := ACanvas.TextExtent(Caption); aAbsCaptionIndent := abs(CaptionAlign); if Orientation = eooHorizontal then begin { Horizontal } if FScale.TickVisible > etvNone then begin if ScalePos = ebpTopLeft then j := Math.max(aBorderWidth + FScale.TickIndent, cIndent) else j := aBottom - Math.max(FScale.TickIndent + aBorderWidth, cIndent) - aSize.cy; end else begin if FScalePos = ebpTopLeft then j := Math.max(aBorderWidth + FScale.ValueIndent, cIndent) else j := aBottom - Math.max(aBorderWidth + FScale.ValueIndent, cIndent) - aSize.cy; end; if CaptionPos = ebpTopLeft then begin i := aBorderWidth; aRight := ScalePxStart; case CaptionAlign of low(CaptionAlign)..-1: inc(i, aAbsCaptionIndent); 0: aHelpFlag := DT_CENTER; 1..high(CaptionAlign): begin aHelpFlag := DT_RIGHT; dec(aRight, aAbsCaptionIndent); end; end; end else begin i := ScalePxStart + ScalePxLength; dec(aRight, aBorderWidth); case CaptionAlign of low(SmallInt)..-1: begin aHelpFlag := DT_RIGHT; dec(aRight, aAbsCaptionIndent); end; 0: aHelpFlag := DT_CENTER; 1..high(CaptionAlign): inc(i, aAbsCaptionIndent); end; end; dec(aBottom, aBorderWidth); end else begin { Vertical } if FScale.TickVisible > etvNone then begin if ScalePos = ebpTopLeft then i := Math.max(aBorderWidth + FScale.TickIndent, cIndent) else i := aRight - Math.max(FScale.TickIndent + aBorderWidth, cIndent) - aSize.cx; end else begin if ScalePos = ebpTopLeft then i := Math.max(aBorderWidth + FScale.ValueIndent, cIndent) else i := aRight - Math.max(aBorderWidth + FScale.ValueIndent, cIndent) - aSize.cx; end; if CaptionPos = ebpTopLeft then begin j := aBorderWidth; aBottom := ScalePxStart; case CaptionAlign of low(CaptionAlign)..-1: inc(j, aAbsCaptionIndent); 0: aHelpFlag := DT_VCENTER; 1..high(CaptionAlign): begin aHelpFlag := DT_BOTTOM; dec(aBottom, aAbsCaptionIndent); end; end; end else begin j := ScalePxStart + ScalePxLength; dec(aBottom, aBorderWidth); case CaptionAlign of low(SmallInt)..-1: begin aHelpFlag := DT_BOTTOM; dec(aBottom, aAbsCaptionIndent); end; 0: aHelpFlag := DT_VCENTER; 1..high(CaptionAlign): inc(j, aAbsCaptionIndent); end; end; dec(aRight, aBorderWidth); end; aRect := Rect(i, j, aRight, aBottom); aFlags := aFlags or aHelpFlag; with ThemeServices do DrawText(ACanvas, GetElementDetails(caThemedContent[caItemState[IsEnabled]]), Caption, aRect, aFlags, 0); end; ACanvas.Font.Color := GetColorResolvingDefault(FScaleFontOptions.FontColor, clBtnText); ACanvas.Font.Orientation := FScale.FontOrientation; ACanvas.Font.Size := FScaleFontOptions.FontSize; ACanvas.Font.Style := FScaleFontOptions.FontStyles; if Orientation = eooHorizontal then begin if ScalePos = ebpTopLeft then FScale.Draw(ACanvas, True, True, eopBottom, Color3DDark, Color3DLight, Point(ScalePxStart, aBorderWidth - 1), []) else FScale.Draw(ACanvas, True, True, eopTop, Color3DDark, Color3DLight, Point(ScalePxStart, Height - aBorderWidth), []); end else begin if ScalePos = ebpTopLeft then FScale.Draw(ACanvas, True, True, eopRight, Color3DDark, Color3DLight, Point(aBorderWidth - 1, ScalePxStart), []) else FScale.Draw(ACanvas, True, True, eopLeft, Color3DDark, Color3DLight, Point(Width - aBorderWidth, ScalePxStart), []); end; end; procedure TCustomECRuler.EndUpdate(Recalculate: Boolean); begin FScale.EndUpdate; inherited EndUpdate(Recalculate); end; procedure TCustomECRuler.FontChanged(Sender: TObject); begin inherited FontChanged(Sender); RecalcRedraw; end; procedure TCustomECRuler.InvalidateCustomRect(AMove: Boolean); begin end; function TCustomECRuler.MouseCoordToPosition(AMouseCoord: Integer): Double; begin Result := (AMouseCoord - ScalePxStart)*ScaleLength/(ScalePxLength - 1); if Reversed then Result := Max - Result; end; procedure TCustomECRuler.MouseMove(Shift: TShiftState; X, Y: Integer); begin inherited MouseMove(Shift, X, Y); if (PointerMode = epmMovable) and WasEnabled then begin if Orientation = eooHorizontal then RedrawPointer(X) else RedrawPointer(Y); if PositionToHint then Hint := FScale.GetStringPosition(Position); end; end; procedure TCustomECRuler.OrientationChanged(AValue: TObjectOrientation); begin if AValue = eooHorizontal then RedrawPointer := @RedrawHorizontal else RedrawPointer := @RedrawVertical; FMouseCoord := low(Integer); if not(csLoading in ComponentState) then SetBounds(Left, Top, Height, Width); inherited OrientationChanged(AValue); end; procedure TCustomECRuler.Paint; var bEnabled: Boolean; procedure DrawPointer; var aBorderWidth: SmallInt; begin aBorderWidth := FullBorderWidth + PointerOverlay; if Orientation = eooHorizontal then Canvas.Line(MouseCoord, aBorderWidth + 1, MouseCoord, self.Height - aBorderWidth) else Canvas.Line(aBorderWidth + 1, MouseCoord, self.Width - aBorderWidth, MouseCoord); end; begin {$IFDEF DBGRULER} DebugLn('Ruler Paint'); {$ENDIF} inherited Paint; if RedrawMode = ermRecalcRedraw then Calculate; bEnabled := IsEnabled; if bEnabled <> WasEnabled then begin RedrawMode := ermRedrawBkgnd; CurrInvRect := ClientRect; { the case that Position was changed when Disabled } end; if not Transparent then begin if RedrawMode >= ermRedrawBkgnd then DrawBackground; if RedrawMode >= ermFreeRedraw then Canvas.Draw(0, 0, Background); if bEnabled and (PointerMode > epmNone) then begin if RedrawMode < ermFreeRedraw then Canvas.CopyRect(FInvalidRect, Background.Canvas, FInvalidRect); DrawPointer; end; FInvalidRect := CurrInvRect; end else begin Canvas.Pen.Width:=1; DrawScaleAndCaption(Canvas); if bEnabled and (PointerMode > epmNone) then begin SetPointerPenStyle; DrawPointer; end; end; WasEnabled := bEnabled; RedrawMode := ermFreeRedraw; end; procedure TCustomECRuler.RecalcRedraw; begin RedrawMode := ermRecalcRedraw; if UpdateCount = 0 then begin if AutoSize then begin InvalidatePreferredSize; AdjustSize; end; Invalidate; end; end; procedure TCustomECRuler.Redraw; begin if RedrawMode < ermRedrawBkgnd then RedrawMode := ermRedrawBkgnd; if UpdateCount = 0 then Invalidate; end; procedure TCustomECRuler.Redraw3DColorAreas; begin Redraw; end; procedure TCustomECRuler.RedrawHorizontal(X: Integer); var aRect: TRect; aBorderWidth, i: Integer; begin if MouseCoord <> X then begin if RedrawMode <= ermFreeRedraw then RedrawMode := ermMoveKnob; i := PointerOverlay; aBorderWidth := FullBorderWidth; if (X >= aBorderWidth) and (X <= (Width - aBorderWidth)) then begin FMouseCoord := X; if assigned(FOnChangePosition) then FOnChangePosition(self, MouseCoordToPosition(X)); end; if not Transparent then begin aRect := Rect(X - i, aBorderWidth, X + i, Height - aBorderWidth); CurrInvRect := aRect; FInvalidRect.Left := Math.min(FInvalidRect.Left, aRect.Left); FInvalidRect.Right := Math.max(FInvalidRect.Right, aRect.Right); InvalidateRect(Handle, @FInvalidRect, False); end else Invalidate; end; end; procedure TCustomECRuler.RedrawVertical(Y: Integer); var aRect: TRect; aBorderWidth, j: Integer; begin if MouseCoord <> Y then begin if RedrawMode <= ermFreeRedraw then RedrawMode := ermMoveKnob; j := PointerOverlay; aBorderWidth := FullBorderWidth; if (Y >= aBorderWidth) and (Y <= (Height - aBorderWidth)) then begin FMouseCoord := Y; if assigned(FOnChangePosition) then FOnChangePosition(self, MouseCoordToPosition(Y)); end; if not Transparent then begin aRect := Rect(aBorderWidth, Y - j, Width - aBorderWidth, Y + j); CurrInvRect := aRect; FInvalidRect.Top := Math.min(FInvalidRect.Top, aRect.Top); FInvalidRect.Bottom := Math.max(FInvalidRect.Bottom, aRect.Bottom); InvalidateRect(Handle, @FInvalidRect, False); end else Invalidate; end; end; procedure TCustomECRuler.SetPointerPenStyle; begin with Canvas do begin case FPointerStyle of epsSimple: Pen.Style := psSolid; epsDashed: Pen.Style := psDash; epsDotted: Pen.Style := psDot; end; Brush.Style := bsClear; { necessary } Pen.Color := GetColorResolvingDefault(PointerColor, clBtnText); Pen.Width := PointerWidth; end; end; procedure TCustomECRuler.TextChanged; begin inherited TextChanged; Redraw; end; procedure TCustomECRuler.WMSize(var Message: TLMSize); begin inherited WMSize(Message); RedrawMode := ermRecalcRedraw; if UpdateCount = 0 then Invalidate; end; { TCustomECRuler.Setters } function TCustomECRuler.GetMax: Double; begin Result := Scale.Max; end; function TCustomECRuler.GetMin: Double; begin Result := Scale.Min; end; function TCustomECRuler.GetPosition: Double; begin Result := MouseCoordToPosition(MouseCoord) end; procedure TCustomECRuler.SetCaptionAlign(AValue: SmallInt); begin if FCaptionAlign = AValue then exit; FCaptionAlign := AValue; if Caption <> '' then Redraw; end; procedure TCustomECRuler.SetCaptionPos(AValue: TBasicPos); begin if FCaptionPos = AValue then exit; FCaptionPos := AValue; if Caption <> '' then Redraw; end; procedure TCustomECRuler.SetIndentBottomRight(AValue: Integer); begin if FIndentBottomRight = AValue then exit; FIndentBottomRight := AValue; RecalcRedraw; end; procedure TCustomECRuler.SetIndentTopLeft(AValue: Integer); begin if FIndentTopLeft = AValue then exit; FIndentTopLeft := AValue; RecalcRedraw; end; procedure TCustomECRuler.SetMax(AValue: Double); begin Scale.Max := AValue; end; procedure TCustomECRuler.SetMin(AValue: Double); begin Scale.Min := AValue; end; procedure TCustomECRuler.SetMouseCoord(AValue: Integer); begin if (PointerMode > epmNone) and WasEnabled then RedrawPointer(AValue); FMouseCoord := AValue; if PositionToHint then Hint := FScale.GetStringPosition(Position); end; procedure TCustomECRuler.SetPointerColor(AValue: TColor); begin if FPointerColor = AValue then exit; FPointerColor := AValue; SetPointerPenStyle; if PointerMode > epmNone then InvalidateNonUpdated; end; procedure TCustomECRuler.SetPointerMode(AValue: TPointerMode); begin if FPointerMode = AValue then exit; FPointerMode := AValue; if AValue > epmNone then CurrInvRect := ClientRect; InvalidateNonUpdated; end; procedure TCustomECRuler.SetPointerStyle(AValue: TPointerStyle); begin if FPointerStyle = AValue then exit; FPointerStyle := AValue; SetPointerPenStyle; if PointerMode > epmNone then InvalidateNonUpdated; end; procedure TCustomECRuler.SetPointerWidth(AValue: SmallInt); begin if FPointerWidth = AValue then exit; FPointerWidth := AValue; PointerOverlay := 1 + AValue div 2; SetPointerPenStyle; if PointerMode > epmNone then InvalidateNonUpdated; end; procedure TCustomECRuler.SetPosition(AValue: Double); var aCoord: Integer; begin if Reversed then AValue := Max - AValue; aCoord := round(AValue*(ScalePxLength - 1) /ScaleLength) + ScalePxStart; if PositionToHint then Hint := FScale.GetStringPosition(AValue); if (PointerMode > epmNone) and WasEnabled then RedrawPointer(aCoord); end; procedure TCustomECRuler.SetPositionToHint(AValue: Boolean); begin if FPositionToHint = AValue then exit; FPositionToHint := AValue; if AValue then Hint := FScale.GetStringPosition(Position); end; procedure TCustomECRuler.SetReversed(AValue: Boolean); begin if FReversed = AValue then exit; FReversed := AValue; RecalcRedraw; end; procedure TCustomECRuler.SetScalePos(AValue: TBasicPos); begin if FScalePos = AValue then exit; FScalePos := AValue; if (FScale.TickVisible > etvNone) or (FScale.ValueVisible > evvNone) then RecalcRedraw; end; procedure TCustomECRuler.SetTransparent(AValue: Boolean); begin if FTransparent = AValue then exit; FTransparent := AValue; if not AValue then RedrawMode := ermRedrawBkgnd; InvalidateNonUpdated; end; procedure Register; begin {$I ecruler.lrs} RegisterComponents('EC-C', [TECRuler]); end; end.