home *** CD-ROM | disk | FTP | other *** search
- unit RsRuler;
-
- // Delphi 2-6 Ruler component, version 1.1, 30 jun 2001
- //
- // (c) 2000, 2001 Hans Roos, Roos Software, The Netherlands
- // Website: www.RoosSoftware.nl
- // Email: mail@roossoftware.nl
- //
- // Features:
- // 4 layouts rdTop, rdLeft, rdRight and rdBottom with
- // automatic scale adjustments for each layout
- // Scale: from 1-1000
- // Units: Inches, Centimetres, Millimetres
- // Automatic calculation of scalenumbers (no overlapping)
- // Sideways text for vertical layouts
- // Flat or 3D appearance
- // TRsRulerCorner: extra component for joining up to 4
- // rulers, can show the unit ('cm', 'mm' or 'in')
- //
- // See demo project for usage
- // Licence: Freeware! Use in non-commercial or commercial apps
- // Feel free to modify the source for your own needs, but don't remove
- // my name from this file, please.
- // If you find this component useful, please let me know.
- // Don't send money, just be grateful ;)
- //
- // Known issues: None
- // Better scale divisions when Inches are used
- // (is it customary to divide inches in 4ths, 8ths, 16ths etc?)
- // Use custom colors/fonts
- // Anything YOU can think of; please let me know!! (mail@roossoftware.nl)
- //
- // Revision History
- // 30/06/2001
- // Added properties :
- // property HairLine, HairLinePosition: line on scale, moving with CursorPos
- // property HairLineStyle: hlsLine (just a hairline) or hlsRect (inverted rectangle)
- // 22/11/2000
- // First release.
-
-
-
-
- interface
-
- uses
- Windows, SysUtils, Messages, Classes, Graphics, Controls, Forms;
-
- const
- Centi: String = 'cm';
- Milli: String = 'mm';
- Inch: String = 'in';
- None: String = '';
-
- type
- TRulerDir = (rdTop, rdLeft, rdRight, rdBottom);
- TRulerUnit = (ruCenti, ruMilli, ruInch, ruNone);
- TCornerPos = (cpLeftTop, cpRightTop, cpLeftBottom, cpRightBottom);
- THairLineStyle = (hlsLine, hlsRect);
-
- TRsRuler = class(TGraphicControl)
- private
- fDirection: TRulerDir;
- fUnits: TRulerUnit;
- fScale: Integer;
- fScaleFactor: Double;
- fAdvance: Double;
- fFlat: Boolean;
- fHairLine: Boolean;
- fHairLinePos: Integer;
- fHairLineStyle: THairLineStyle;
- procedure SetDirection(const Value: TRulerDir);
- procedure SetScale(const Value: Integer);
- procedure SetUnit(const Value: TRulerUnit);
- procedure SetFlat(const Value: Boolean);
- procedure SetHairLine(const Value: Boolean);
- procedure SetHairLinePos(const Value: Integer);
- procedure SetHairLineStyle(const Value: THairLineStyle);
- protected
- LeftSideLF, RightSideLF, NormLF: TLogFont;
- NormFont, LeftSideFont, RightSideFont: HFont;
- FirstTime: Boolean;
- procedure DrawHairLine;
- procedure CalcAdvance;
- procedure PaintScaleTics;
- procedure PaintScaleLabels;
- procedure Paint; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- published
- property Align;
- property Direction: TRulerDir read fDirection write SetDirection;
- property Units: TRulerUnit read fUnits write SetUnit;
- property Scale: Integer read fScale write SetScale;
- property Flat: Boolean read fFlat write SetFlat;
- property HairLine: Boolean read fHairLine write SetHairLine;
- property HairLinePos: Integer read fHairLinePos write SetHairLinePos;
- property HairLineStyle: THairLineStyle read fHairLineStyle write SetHairLineStyle;
- property Height;
- property Width;
- property Visible;
- property Hint;
- property ShowHint;
- property Tag;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnClick;
- property OnDblClick;
- property OnResize;
- end;
-
- TRsRulerCorner = class(TGraphicControl)
- private
- fPosition: TCornerPos;
- fFlat: Boolean;
- fUnits: TRulerUnit;
- procedure SetPosition(const Value: TCornerPos);
- procedure SetFlat(const Value: Boolean);
- procedure SetUnits(const Value: TRulerUnit);
- protected
- fUStr: String;
- procedure Paint; override;
- public
- constructor Create(AOwner: TComponent); override;
- published
- property Align;
- property Position: TCornerPos read fPosition write SetPosition;
- property Flat: Boolean read fFlat write SetFlat;
- property Units: TRulerUnit read fUnits write SetUnits;
- property Height;
- property Width;
- property Visible;
- property Hint;
- property ShowHint;
- property Tag;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnClick;
- property OnDblClick;
- property OnResize;
- end;
-
- procedure Register;
-
- implementation
-
- {$R RSRULER.DCR}
-
- procedure Register;
- begin
- RegisterComponents('Xtra', [TRsRuler, TRsRulerCorner]);
- end;
-
- { TRsRuler }
- constructor TRsRuler.Create(AOwner: TComponent);
- begin
- inherited;
- fDirection := rdTop;
- fUnits := ruCenti;
- fScale := 100;
- Color := clBtnFace;
- Height := 33;
- Width := 200;
- fScaleFactor := 1;
- fAdvance := 1;
- with LeftSideLF do
- begin
- FillChar(LeftSideLF, SizeOf(LeftSideLF), 0);
- lfHeight := 11;
- lfEscapement := 900;
- lfOrientation := 900;
- StrPCopy(lfFaceName, 'Tahoma');
- end;
- with RightSideLF do
- begin
- FillChar(RightSideLF, SizeOf(RightSideLF), 0);
- lfHeight := 11;
- lfEscapement := 2700;
- lfOrientation := 2700;
- StrPCopy(lfFaceName, 'Tahoma');
- end;
- with NormLF do
- begin
- FillChar(NormLF, SizeOf(NormLF), 0);
- lfHeight := 11;
- StrPCopy(lfFaceName, 'Tahoma');
- end;
- FirstTime := True;
- fFlat := False;
- fHairLinePos := -1;
- fHairLine := False;
- fHairLineStyle := hlsLine;
- end;
-
- destructor TRsRuler.Destroy;
- begin
- DeleteObject(NormFont);
- DeleteObject(LeftSideFont);
- DeleteObject(RightSideFont);
- inherited;
- end;
-
- procedure TRsRuler.CalcAdvance;
- begin
- fAdvance := Screen.PixelsPerInch / 10 * Scale / 100;
- if fUnits <> ruInch then fAdvance := fAdvance / 2.54;
- case Scale of
- 1: fScaleFactor := 100;
- 2: fScaleFactor := 50;
- 3..5: fScaleFactor := 25;
- 6..8: fScaleFactor := 20;
- 9..12: fScaleFactor := 10;
- 13..25: fScaleFactor := 5;
- 26..35: fScaleFactor := 4;
- 36..50: fScaleFactor := 2;
- 51..125: fScaleFactor := 1;
- 126..300: fScaleFactor := 0.5;
- 301..400: fScaleFactor := 0.25;
- 401..500: fScaleFactor := 0.2;
- 501..1000: fScaleFactor := 0.1;
- end;
- fAdvance := fAdvance * fScaleFactor;
- end;
-
- procedure TRsRuler.PaintScaleTics;
- var
- Pos: Double;
- N, Last, LongTick: Integer;
- begin
- if (fDirection = rdTop) or (fDirection = rdBottom) then Last := Width else Last := Height;
- Pos := 0;
- N := 0;
- while Pos < Last do with Canvas do
- begin
- LongTick := 2 * (3 + Integer(N mod 5 = 0));
- if (fDirection = rdTop) or (fDirection = rdBottom) then
- begin
- if fDirection = rdTop then
- begin
- MoveTo(Trunc(Pos), Height - 1);
- LineTo(Trunc(Pos), Height - LongTick);
- end;
- if fDirection = rdBottom then
- begin
- MoveTo(Trunc(Pos), 1);
- LineTo(Trunc(Pos), LongTick);
- end;
- end else
- begin
- if fDirection = rdLeft then
- begin
- MoveTo(Width - 1, Trunc(Pos));
- LineTo(Width - LongTick, Trunc(Pos));
- end;
- if fDirection = rdRight then
- begin
- MoveTo(1, Trunc(Pos));
- LineTo(LongTick, Trunc(Pos));
- end;
- end;
- Inc(N);
- Pos := Pos + 2 * fAdvance; // always advance two units to next ticmark
- end;
- end;
-
- procedure TRsRuler.PaintScaleLabels;
- var
- Pos, Number: Double;
- N, Last, Wi, He: Integer;
- S: String;
- begin
- if (fDirection = rdTop) or (fDirection = rdBottom) then Last := Width else Last := Height;
- Pos := 0;
- N := 0;
- while Pos < Last do with Canvas do
- begin
- Number := fScaleFactor * N / 10;
- if Units = ruMilli then Number := 10 * Number;
- S := FloatToStr(Number);
- Wi := TextWidth(S);
- He := TextHeight(S);
- if (fDirection = rdTop) or (fDirection = rdBottom) then
- begin
- MoveTo(Trunc(Pos), 1); // only Pos is important
- if fDirection = rdTop then
- begin
- if (N > 0) and (N mod 10 = 0) then TextOut(PenPos.X - Wi div 2, Height - He - 8, S)
- else if (N > 0) and (N mod 5 = 0) then
- begin
- MoveTo(Trunc(Pos), Height - 12);
- LineTo(Trunc(Pos), Height - 16);
- end;
- end;
- if fDirection = rdBottom then
- begin
- if (N > 0) and (N mod 10 = 0) then TextOut(PenPos.X - Wi div 2, 8, S)
- else if (N > 0) and (N mod 5 = 0) then
- begin
- MoveTo(Trunc(Pos), 12);
- LineTo(Trunc(Pos), 16);
- end;
- end;
- end else
- begin
- MoveTo(1, Trunc(Pos));
- if fDirection = rdLeft then
- begin
- if (N > 0) and (N mod 10 = 0) then TextOut(Width - He - 8, PenPos.Y + Wi div 2, S)
- else if (N > 0) and (N mod 5 = 0) then
- begin
- MoveTo(Width - 12, Trunc(Pos));
- LineTo(Width - 16, Trunc(Pos));
- end;
- end;
- if fDirection = rdRight then
- begin
- if (N > 0) and (N mod 10 = 0) then TextOut(He + 8, PenPos.Y - Wi div 2, S)
- else if (N > 0) and (N mod 5 = 0) then
- begin
- MoveTo(12, Trunc(Pos));
- LineTo(16, Trunc(Pos));
- end;
- end;
- end;
- Inc(N);
- Pos := Pos + fAdvance;
- end;
- end;
-
- procedure TRsRuler.Paint;
- var
- Rect: TRect;
- He: Integer;
- begin
- inherited;
- fHairLinePos := -1;
- if FirstTime then
- begin
- FirstTime := False;
- LeftSideFont := CreateFontIndirect(LeftSideLF);
- RightSideFont := CreateFontIndirect(RightSideLF);
- NormFont := CreateFontIndirect(NormLF);
- end;
- Rect := ClientRect;
- if Not Flat then DrawEdge(Canvas.Handle, Rect, EDGE_RAISED, BF_RECT);
- He := Canvas.TextHeight('0') + 6;
- if (fDirection = rdTop) or (fDirection = rdBottom) then
- begin
- if fDirection = rdTop then SetRect(Rect, 2, Height - He, Width - 2, Height - 8);
- if (fDirection = rdBottom) then SetRect(Rect, 2, 8, Width - 2, He);
- SelectObject(Canvas.Handle, NormFont);
- end else
- begin
- if fDirection = rdLeft then
- begin
- SetRect(Rect, Width - He, 2, Width - 8, Height - 2);
- SelectObject(Canvas.Handle, LeftSideFont);
- end;
- if fDirection = rdRight then
- begin
- SetRect(Rect, He, 2, 8, Height - 2);
- SelectObject(Canvas.Handle, RightSideFont);
- end;
- end;
- Canvas.Brush.Color := clWindow;
- Canvas.FillRect(Rect);
- CalcAdvance;
- SetBKMode(Canvas.Handle, TRANSPARENT);
- PaintScaleTics;
- PaintScaleLabels;
- SetBKMode(Canvas.Handle, OPAQUE);
- end;
-
- procedure TRsRuler.SetDirection(const Value: TRulerDir);
- var
- Dim: TPoint;
- OldDir: TRulerDir;
- begin
- OldDir := fDirection;
- if Value <> fDirection then
- begin
- if ((OldDir = rdTop) or (OldDir = rdBottom)) and ((Value = rdLeft) or (Value = rdRight))
- or ((OldDir = rdLeft) or (OldDir = rdRight)) and ((Value = rdTop) or (Value = rdBottom)) then
- begin
- Dim := Point(Width, Height);
- Width := Dim.Y;
- Height := Dim.X;
- end;
- fDirection := Value;
- Invalidate;
- end;
- end;
-
- procedure TRsRuler.SetScale(const Value: Integer);
- begin
- if (Value <> fScale) and (Value > 0) then
- begin
- fScale := Value;
- Invalidate;
- end;
- end;
-
- procedure TRsRuler.SetUnit(const Value: TRulerUnit);
- begin
- if Value <> fUnits then
- begin
- fUnits := Value;
- Invalidate;
- end;
- end;
-
- procedure TRsRuler.SetFlat(const Value: Boolean);
- begin
- if Value <> fFlat then
- begin
- fFlat := Value;
- Invalidate;
- end;
- end;
-
- procedure TRsRuler.SetHairLine(const Value: Boolean);
- begin
- if Value <> fHairLine then
- begin
- fHairLine := Value;
- Invalidate;
- end;
- end;
-
- procedure TRsRuler.SetHairLinePos(const Value: Integer);
- begin
- if Value <> fHairLinePos then
- begin
- DrawHairLine; // erase old position
- fHairLinePos := Value;
- DrawHairLine; // draw new position
- end;
- end;
-
- procedure TRsRuler.DrawHairLine;
- var
- He: Integer;
- begin
- if fHairLine then if fHairLinePos <> -1 then with Canvas do
- begin
- Pen.Mode := pmNotXOr;
- He := TextHeight('0') + 6;
- if fDirection = rdTop then
- begin
- if fHairLineStyle = hlsLine then
- begin
- MoveTo(fHairLinePos, Height - He);
- LineTo(fHairLinePos, Height - 8);
- end else InvertRect(Canvas.Handle, Rect(2, Height - He, fHairLinePos, Height - 8));
- end;
- if fDirection = rdBottom then
- begin
- if fHairLineStyle = hlsLine then
- begin
- MoveTo(fHairLinePos, 8);
- LineTo(fHairLinePos, He);
- end else InvertRect(Canvas.Handle, Rect(2, 8, fHairLinePos, He));
- end;
- if fDirection = rdLeft then
- begin
- if fHairLineStyle = hlsLine then
- begin
- MoveTo(Width - He, fHairLinePos);
- LineTo(Width - 8, fHairLinePos);
- end else InvertRect(Canvas.Handle, Rect(Width - He, 2, Width - 8, fHairLinePos));
- end;
- if fDirection = rdRight then
- begin
- if fHairLineStyle = hlsLine then
- begin
- MoveTo(8, fHairLinePos);
- LineTo(He, fHairLinePos);
- end else InvertRect(Canvas.Handle, Rect(8, 2, He, fHairLinePos));
- end;
- end;
- end;
-
-
-
- procedure TRsRuler.SetHairLineStyle(const Value: THairLineStyle);
- begin
- if Value <> fHairLineStyle then
- begin
- fHairLineStyle := Value;
- Invalidate;
- end;
- end;
-
- { TRsRulerCorner }
-
- constructor TRsRulerCorner.Create(AOwner: TComponent);
- begin
- inherited;
- fPosition := cpLeftTop;
- fFlat := False;
- fUnits := ruCenti;
- fUStr := Centi;
- Width := 24;
- Height := 24;
- Hint := 'centimeter';
- end;
-
- procedure TRsRulerCorner.Paint;
- var
- OrgH, Wi, He: Integer;
- R: TRect;
- begin
- inherited;
- R := ClientRect;
- with Canvas do
- begin
- if Not Flat then DrawEdge(Handle, R, EDGE_RAISED, BF_RECT);
- Brush.Color := clWindow;
- He := TextHeight('0') + 6;
- Font.Name := 'Tahoma';
- OrgH := Font.Height;
- Font.Height := 11;
- SetBKMode(Handle, TRANSPARENT);
- Font.Color := clBtnShadow;
- Wi := TextWidth(fUStr);
- if fPosition = cpLeftTop then
- begin
- FillRect(Rect(Width - He, Height - He, Width - 2, Height - 8));
- FillRect(Rect(Width - He, Height - He, Width - 8, Height - 2));
- TextOut(Width - He + 1 + (He - 2 - Wi) div 2, Height - He, fUStr);
- end;
- if fPosition = cpRightTop then
- begin
- FillRect(Rect(2, Height - He, He, Height - 8));
- FillRect(Rect(8, Height - He, He, Height - 2));
- TextOut(2 + (He - Wi) div 2, Height - He, fUStr);
- end;
- if fPosition = cpLeftBottom then
- begin
- FillRect(Rect(Width - He, 8, Width - 2, He));
- FillRect(Rect(Width - He, 2, Width - 8, He));
- TextOut(Width - He + 1 + (He - 2 - Wi) div 2, 8, fUStr);
- end;
- if fPosition = cpRightBottom then
- begin
- FillRect(Rect(2, 8, He, He));
- FillRect(Rect(8, 2, He, He));
- TextOut(2 + (He - Wi) div 2, 8, fUStr);
- end;
- end;
- Canvas.Font.Height := OrgH;
- SetBKMode(Canvas.Handle, OPAQUE);
- end;
-
- procedure TRsRulerCorner.SetFlat(const Value: Boolean);
- begin
- if Value <> fFlat then
- begin
- fFlat := Value;
- Invalidate;
- end;
- end;
-
- procedure TRsRulerCorner.SetPosition(const Value: TCornerPos);
- begin
- if Value <> fPosition then
- begin
- fPosition := Value;
- Invalidate;
- end;
- end;
-
- procedure TRsRulerCorner.SetUnits(const Value: TRulerUnit);
- begin
- if Value <> fUnits then
- begin
- fUnits := Value;
- if fUnits = ruCenti then begin fUStr := Centi; Hint := 'centimeter'; end;
- if fUnits = ruMilli then begin fUStr := Milli; Hint := 'millimeter'; end;
- if fUnits = ruInch then begin fUStr := Inch; Hint := 'inch'; end;
- if fUnits = ruNone then begin fUStr := None; Hint := ''; end;
- Invalidate;
- end;
- end;
-
- end.
-