home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kompon / d23456 / RSRULER.ZIP / RsRuler.pas < prev    next >
Pascal/Delphi Source File  |  2001-07-01  |  16KB  |  590 lines

  1. unit RsRuler;
  2.  
  3. //  Delphi 2-6 Ruler component, version 1.1, 30 jun 2001
  4. //  
  5. //  (c) 2000, 2001 Hans Roos, Roos Software, The Netherlands
  6. //  Website: www.RoosSoftware.nl
  7. //  Email: mail@roossoftware.nl
  8. //
  9. //  Features:
  10. //  4 layouts rdTop, rdLeft, rdRight and rdBottom with
  11. //    automatic scale adjustments for each layout
  12. //  Scale: from 1-1000
  13. //  Units: Inches, Centimetres, Millimetres
  14. //  Automatic calculation of scalenumbers (no overlapping)
  15. //  Sideways text for vertical layouts
  16. //  Flat or 3D appearance
  17. //  TRsRulerCorner: extra component for joining up to 4
  18. //    rulers, can show the unit ('cm', 'mm' or 'in')
  19. //
  20. //  See demo project for usage
  21. //  Licence: Freeware! Use in non-commercial or commercial apps
  22. //  Feel free to modify the source for your own needs, but don't remove
  23. //  my name from this file, please.
  24. //  If you find this component useful, please let me know.
  25. //  Don't send money, just be grateful ;)
  26. //
  27. //  Known issues: None
  28. //  Better scale divisions when Inches are used
  29. //  (is it customary to divide inches in 4ths, 8ths, 16ths etc?)
  30. //  Use custom colors/fonts
  31. //  Anything YOU can think of; please let me know!! (mail@roossoftware.nl)
  32. //
  33. //  Revision History
  34. //  30/06/2001
  35. //    Added properties :
  36. //    property HairLine, HairLinePosition: line on scale, moving with CursorPos
  37. //    property HairLineStyle: hlsLine (just a hairline) or hlsRect (inverted rectangle)
  38. //  22/11/2000
  39. //    First release. 
  40.  
  41.  
  42.  
  43.  
  44. interface
  45.  
  46. uses
  47.   Windows, SysUtils, Messages, Classes, Graphics, Controls, Forms;
  48.  
  49. const
  50.   Centi: String = 'cm';
  51.   Milli: String = 'mm';
  52.   Inch: String = 'in';
  53.   None: String = '';
  54.  
  55. type
  56.   TRulerDir = (rdTop, rdLeft, rdRight, rdBottom);
  57.   TRulerUnit = (ruCenti, ruMilli, ruInch, ruNone);
  58.   TCornerPos = (cpLeftTop, cpRightTop, cpLeftBottom, cpRightBottom);
  59.   THairLineStyle = (hlsLine, hlsRect);
  60.  
  61.   TRsRuler = class(TGraphicControl)
  62.   private
  63.     fDirection: TRulerDir;
  64.     fUnits: TRulerUnit;
  65.     fScale: Integer;
  66.     fScaleFactor: Double;
  67.     fAdvance: Double;
  68.     fFlat: Boolean;
  69.     fHairLine: Boolean;
  70.     fHairLinePos: Integer;
  71.     fHairLineStyle: THairLineStyle;
  72.     procedure SetDirection(const Value: TRulerDir);
  73.     procedure SetScale(const Value: Integer);
  74.     procedure SetUnit(const Value: TRulerUnit);
  75.     procedure SetFlat(const Value: Boolean);
  76.     procedure SetHairLine(const Value: Boolean);
  77.     procedure SetHairLinePos(const Value: Integer);
  78.     procedure SetHairLineStyle(const Value: THairLineStyle);
  79.   protected
  80.     LeftSideLF, RightSideLF, NormLF: TLogFont;
  81.     NormFont, LeftSideFont, RightSideFont: HFont;
  82.     FirstTime: Boolean;
  83.     procedure DrawHairLine;
  84.     procedure CalcAdvance;
  85.     procedure PaintScaleTics;
  86.     procedure PaintScaleLabels;
  87.     procedure Paint; override;
  88.   public
  89.     constructor Create(AOwner: TComponent); override;
  90.     destructor Destroy; override;
  91.   published
  92.     property Align;
  93.     property Direction: TRulerDir read fDirection write SetDirection;
  94.     property Units: TRulerUnit read fUnits write SetUnit;
  95.     property Scale: Integer read fScale write SetScale;
  96.     property Flat: Boolean read fFlat write SetFlat;
  97.     property HairLine: Boolean read fHairLine write SetHairLine;
  98.     property HairLinePos: Integer read fHairLinePos write SetHairLinePos;
  99.     property HairLineStyle: THairLineStyle read fHairLineStyle write SetHairLineStyle;
  100.     property Height;
  101.     property Width;
  102.     property Visible;
  103.     property Hint;
  104.     property ShowHint;
  105.     property Tag;
  106.     property OnMouseDown;
  107.     property OnMouseMove;
  108.     property OnMouseUp;
  109.     property OnClick;
  110.     property OnDblClick;
  111.     property OnResize;
  112.   end;
  113.  
  114.   TRsRulerCorner = class(TGraphicControl)
  115.   private
  116.     fPosition: TCornerPos;
  117.     fFlat: Boolean;
  118.     fUnits: TRulerUnit;
  119.     procedure SetPosition(const Value: TCornerPos);
  120.     procedure SetFlat(const Value: Boolean);
  121.     procedure SetUnits(const Value: TRulerUnit);
  122.   protected
  123.     fUStr: String;
  124.     procedure Paint; override;
  125.   public
  126.     constructor Create(AOwner: TComponent); override;
  127.   published
  128.     property Align;
  129.     property Position: TCornerPos read fPosition write SetPosition;
  130.     property Flat: Boolean read fFlat write SetFlat;
  131.     property Units: TRulerUnit read fUnits write SetUnits;
  132.     property Height;
  133.     property Width;
  134.     property Visible;
  135.     property Hint;
  136.     property ShowHint;
  137.     property Tag;
  138.     property OnMouseDown;
  139.     property OnMouseMove;
  140.     property OnMouseUp;
  141.     property OnClick;
  142.     property OnDblClick;
  143.     property OnResize;
  144.   end;
  145.  
  146. procedure Register;
  147.  
  148. implementation
  149.  
  150. {$R RSRULER.DCR}
  151.  
  152. procedure Register;
  153. begin
  154.   RegisterComponents('Xtra', [TRsRuler, TRsRulerCorner]);
  155. end;
  156.  
  157. { TRsRuler }
  158. constructor TRsRuler.Create(AOwner: TComponent);
  159. begin
  160.   inherited;
  161.   fDirection := rdTop;
  162.   fUnits := ruCenti;
  163.   fScale := 100;
  164.   Color := clBtnFace;
  165.   Height := 33;
  166.   Width := 200;
  167.   fScaleFactor := 1;
  168.   fAdvance := 1;
  169.   with LeftSideLF do
  170.   begin
  171.     FillChar(LeftSideLF, SizeOf(LeftSideLF), 0);
  172.     lfHeight := 11;
  173.     lfEscapement := 900;
  174.     lfOrientation := 900;
  175.     StrPCopy(lfFaceName, 'Tahoma');
  176.   end;
  177.   with RightSideLF do
  178.   begin
  179.     FillChar(RightSideLF, SizeOf(RightSideLF), 0);
  180.     lfHeight := 11;
  181.     lfEscapement := 2700;
  182.     lfOrientation := 2700;
  183.     StrPCopy(lfFaceName, 'Tahoma');
  184.   end;
  185.   with NormLF do
  186.   begin
  187.     FillChar(NormLF, SizeOf(NormLF), 0);
  188.     lfHeight := 11;
  189.     StrPCopy(lfFaceName, 'Tahoma');
  190.   end;
  191.   FirstTime := True;
  192.   fFlat := False;
  193.   fHairLinePos := -1;
  194.   fHairLine := False;
  195.   fHairLineStyle := hlsLine;
  196. end;
  197.  
  198. destructor TRsRuler.Destroy;
  199. begin
  200.   DeleteObject(NormFont);
  201.   DeleteObject(LeftSideFont);
  202.   DeleteObject(RightSideFont);
  203.   inherited;
  204. end;
  205.  
  206. procedure TRsRuler.CalcAdvance;
  207. begin
  208.   fAdvance := Screen.PixelsPerInch / 10 * Scale / 100;
  209.   if fUnits <> ruInch then fAdvance := fAdvance / 2.54;
  210.   case Scale of
  211.     1: fScaleFactor := 100;
  212.     2: fScaleFactor := 50;
  213.     3..5: fScaleFactor := 25;
  214.     6..8: fScaleFactor := 20;
  215.     9..12: fScaleFactor := 10;
  216.     13..25: fScaleFactor := 5;
  217.     26..35: fScaleFactor := 4;
  218.     36..50: fScaleFactor := 2;
  219.     51..125: fScaleFactor := 1;
  220.     126..300: fScaleFactor :=  0.5;
  221.     301..400: fScaleFactor := 0.25;
  222.     401..500: fScaleFactor := 0.2;
  223.     501..1000: fScaleFactor := 0.1;
  224.   end;
  225.   fAdvance := fAdvance * fScaleFactor;
  226. end;
  227.  
  228. procedure TRsRuler.PaintScaleTics;
  229. var
  230.   Pos: Double;
  231.   N, Last, LongTick: Integer;
  232. begin
  233.   if (fDirection = rdTop) or (fDirection = rdBottom) then Last := Width else Last := Height;
  234.   Pos := 0;
  235.   N := 0;
  236.   while Pos < Last do with Canvas do
  237.   begin
  238.     LongTick := 2 * (3 + Integer(N mod 5 = 0));
  239.     if (fDirection = rdTop) or (fDirection = rdBottom) then
  240.     begin
  241.       if fDirection = rdTop then
  242.       begin
  243.         MoveTo(Trunc(Pos), Height - 1);
  244.         LineTo(Trunc(Pos), Height - LongTick);
  245.       end;
  246.       if fDirection = rdBottom then
  247.       begin
  248.         MoveTo(Trunc(Pos), 1);
  249.         LineTo(Trunc(Pos), LongTick);
  250.       end;
  251.     end else
  252.     begin
  253.       if fDirection = rdLeft then
  254.       begin
  255.         MoveTo(Width - 1, Trunc(Pos));
  256.         LineTo(Width - LongTick, Trunc(Pos));
  257.       end;
  258.       if fDirection = rdRight then
  259.       begin
  260.         MoveTo(1, Trunc(Pos));
  261.         LineTo(LongTick, Trunc(Pos));
  262.       end;
  263.     end;
  264.     Inc(N);
  265.     Pos := Pos + 2 * fAdvance; // always advance two units to next ticmark
  266.   end;
  267. end;
  268.  
  269. procedure TRsRuler.PaintScaleLabels;
  270. var
  271.   Pos, Number: Double;
  272.   N, Last, Wi, He: Integer;
  273.   S: String;
  274. begin
  275.   if (fDirection = rdTop) or (fDirection = rdBottom) then Last := Width else Last := Height;
  276.   Pos := 0;
  277.   N := 0;
  278.   while Pos < Last do with Canvas do
  279.   begin
  280.     Number := fScaleFactor * N / 10;
  281.     if Units = ruMilli then Number := 10 * Number;
  282.     S := FloatToStr(Number);
  283.     Wi := TextWidth(S);
  284.     He := TextHeight(S);
  285.     if (fDirection = rdTop) or (fDirection = rdBottom) then
  286.     begin
  287.       MoveTo(Trunc(Pos), 1);  // only Pos is important
  288.       if fDirection = rdTop then
  289.       begin
  290.         if (N > 0) and (N mod 10 = 0) then TextOut(PenPos.X - Wi div 2, Height - He - 8, S)
  291.         else if (N > 0) and (N mod 5 = 0) then
  292.         begin
  293.           MoveTo(Trunc(Pos), Height - 12);
  294.           LineTo(Trunc(Pos), Height - 16);
  295.         end;
  296.       end;
  297.       if fDirection = rdBottom then
  298.       begin
  299.         if (N > 0) and (N mod 10 = 0) then TextOut(PenPos.X - Wi div 2, 8, S)
  300.         else if (N > 0) and (N mod 5 = 0) then
  301.         begin
  302.           MoveTo(Trunc(Pos), 12);
  303.           LineTo(Trunc(Pos), 16);
  304.         end;
  305.       end;
  306.     end else
  307.     begin
  308.       MoveTo(1, Trunc(Pos));
  309.       if fDirection = rdLeft then
  310.       begin
  311.         if (N > 0) and (N mod 10 = 0) then TextOut(Width - He - 8, PenPos.Y + Wi div 2, S)
  312.         else if (N > 0) and (N mod 5 = 0) then
  313.         begin
  314.           MoveTo(Width - 12, Trunc(Pos));
  315.           LineTo(Width - 16, Trunc(Pos));
  316.         end;
  317.       end;
  318.       if fDirection = rdRight then
  319.       begin
  320.         if (N > 0) and (N mod 10 = 0) then TextOut(He + 8, PenPos.Y - Wi div 2, S)
  321.         else if (N > 0) and (N mod 5 = 0) then
  322.         begin
  323.           MoveTo(12, Trunc(Pos));
  324.           LineTo(16, Trunc(Pos));
  325.         end;
  326.       end;
  327.     end;
  328.     Inc(N);
  329.     Pos := Pos + fAdvance;
  330.   end;
  331. end;
  332.  
  333. procedure TRsRuler.Paint;
  334. var
  335.   Rect: TRect;
  336.   He: Integer;
  337. begin
  338.   inherited;
  339.   fHairLinePos := -1;
  340.   if FirstTime then
  341.   begin
  342.     FirstTime := False;
  343.     LeftSideFont := CreateFontIndirect(LeftSideLF);
  344.     RightSideFont := CreateFontIndirect(RightSideLF);
  345.     NormFont := CreateFontIndirect(NormLF);
  346.   end;
  347.   Rect := ClientRect;
  348.   if Not Flat then DrawEdge(Canvas.Handle, Rect, EDGE_RAISED, BF_RECT);
  349.   He := Canvas.TextHeight('0') + 6;
  350.   if (fDirection = rdTop) or (fDirection = rdBottom) then 
  351.   begin
  352.     if fDirection = rdTop then SetRect(Rect, 2, Height - He, Width - 2, Height - 8);
  353.     if (fDirection = rdBottom) then SetRect(Rect, 2, 8, Width - 2, He);
  354.     SelectObject(Canvas.Handle, NormFont);
  355.   end else
  356.   begin
  357.     if fDirection = rdLeft then
  358.     begin
  359.       SetRect(Rect, Width - He, 2, Width - 8, Height - 2);
  360.       SelectObject(Canvas.Handle, LeftSideFont);
  361.     end;
  362.     if fDirection = rdRight then
  363.     begin
  364.       SetRect(Rect, He, 2, 8, Height - 2);
  365.       SelectObject(Canvas.Handle, RightSideFont);
  366.     end;
  367.   end;
  368.   Canvas.Brush.Color := clWindow;
  369.   Canvas.FillRect(Rect);
  370.   CalcAdvance;
  371.   SetBKMode(Canvas.Handle, TRANSPARENT);
  372.   PaintScaleTics;
  373.   PaintScaleLabels;
  374.   SetBKMode(Canvas.Handle, OPAQUE);
  375. end;
  376.  
  377. procedure TRsRuler.SetDirection(const Value: TRulerDir);
  378. var
  379.   Dim: TPoint;
  380.   OldDir: TRulerDir;
  381. begin
  382.   OldDir := fDirection;
  383.   if Value <> fDirection then
  384.   begin
  385.     if ((OldDir = rdTop) or (OldDir = rdBottom)) and ((Value = rdLeft) or (Value = rdRight))
  386.     or ((OldDir = rdLeft) or (OldDir = rdRight)) and ((Value = rdTop) or (Value = rdBottom)) then
  387.     begin
  388.       Dim := Point(Width, Height);
  389.       Width := Dim.Y;
  390.       Height := Dim.X;
  391.     end;
  392.     fDirection := Value;
  393.     Invalidate;
  394.   end;
  395. end;
  396.  
  397. procedure TRsRuler.SetScale(const Value: Integer);
  398. begin
  399.   if (Value <> fScale) and (Value > 0) then
  400.   begin
  401.     fScale := Value;
  402.     Invalidate;
  403.   end;
  404. end;
  405.  
  406. procedure TRsRuler.SetUnit(const Value: TRulerUnit);
  407. begin
  408.   if Value <> fUnits then
  409.   begin
  410.     fUnits := Value;
  411.     Invalidate;
  412.   end;
  413. end;
  414.  
  415. procedure TRsRuler.SetFlat(const Value: Boolean);
  416. begin
  417.   if Value <> fFlat then
  418.   begin
  419.     fFlat := Value;
  420.     Invalidate;
  421.   end;
  422. end;
  423.  
  424. procedure TRsRuler.SetHairLine(const Value: Boolean);
  425. begin
  426.   if Value <> fHairLine then
  427.   begin
  428.     fHairLine := Value;
  429.     Invalidate;
  430.   end;
  431. end;
  432.  
  433. procedure TRsRuler.SetHairLinePos(const Value: Integer);
  434. begin
  435.   if Value <> fHairLinePos then
  436.   begin
  437.     DrawHairLine; // erase old position
  438.     fHairLinePos := Value;
  439.     DrawHairLine; // draw new position
  440.   end;
  441. end;
  442.  
  443. procedure TRsRuler.DrawHairLine;
  444. var
  445.   He: Integer;
  446. begin
  447.   if fHairLine then if fHairLinePos <> -1 then with Canvas do
  448.   begin
  449.     Pen.Mode := pmNotXOr;
  450.     He := TextHeight('0') + 6;
  451.     if fDirection = rdTop then
  452.     begin
  453.       if fHairLineStyle = hlsLine then
  454.       begin
  455.         MoveTo(fHairLinePos, Height - He);
  456.         LineTo(fHairLinePos, Height - 8);
  457.       end else InvertRect(Canvas.Handle, Rect(2, Height - He, fHairLinePos, Height - 8));
  458.     end;
  459.     if fDirection = rdBottom then
  460.     begin
  461.       if fHairLineStyle = hlsLine then
  462.       begin
  463.         MoveTo(fHairLinePos, 8);
  464.         LineTo(fHairLinePos, He);
  465.       end else InvertRect(Canvas.Handle, Rect(2, 8, fHairLinePos, He));
  466.     end;
  467.     if fDirection = rdLeft then
  468.     begin
  469.       if fHairLineStyle = hlsLine then
  470.       begin
  471.         MoveTo(Width - He, fHairLinePos);
  472.         LineTo(Width - 8, fHairLinePos);
  473.       end else InvertRect(Canvas.Handle, Rect(Width - He, 2, Width - 8, fHairLinePos));
  474.     end;
  475.     if fDirection = rdRight then
  476.     begin
  477.       if fHairLineStyle = hlsLine then
  478.       begin
  479.         MoveTo(8, fHairLinePos);
  480.         LineTo(He, fHairLinePos);
  481.       end else InvertRect(Canvas.Handle, Rect(8, 2, He, fHairLinePos));
  482.     end;
  483.   end;
  484. end;
  485.  
  486.  
  487.  
  488. procedure TRsRuler.SetHairLineStyle(const Value: THairLineStyle);
  489. begin
  490.   if Value <> fHairLineStyle then
  491.   begin
  492.     fHairLineStyle := Value;
  493.     Invalidate;
  494.   end;
  495. end;
  496.  
  497. { TRsRulerCorner }
  498.  
  499. constructor TRsRulerCorner.Create(AOwner: TComponent);
  500. begin
  501.   inherited;
  502.   fPosition := cpLeftTop;
  503.   fFlat := False;
  504.   fUnits := ruCenti;
  505.   fUStr := Centi;
  506.   Width := 24;
  507.   Height := 24;
  508.   Hint := 'centimeter';
  509. end;
  510.  
  511. procedure TRsRulerCorner.Paint;
  512. var
  513.   OrgH, Wi, He: Integer;
  514.   R: TRect;
  515. begin
  516.   inherited;
  517.   R := ClientRect;
  518.   with Canvas do
  519.   begin
  520.     if Not Flat then DrawEdge(Handle, R, EDGE_RAISED, BF_RECT);
  521.     Brush.Color := clWindow;
  522.     He := TextHeight('0') + 6;
  523.     Font.Name := 'Tahoma';
  524.     OrgH := Font.Height;
  525.     Font.Height := 11;
  526.     SetBKMode(Handle, TRANSPARENT);
  527.     Font.Color := clBtnShadow;
  528.     Wi := TextWidth(fUStr);
  529.     if fPosition = cpLeftTop then
  530.     begin
  531.       FillRect(Rect(Width - He, Height - He, Width - 2, Height - 8));
  532.       FillRect(Rect(Width - He, Height - He, Width - 8, Height - 2));
  533.       TextOut(Width - He + 1 + (He - 2 - Wi) div 2, Height - He, fUStr);
  534.     end;
  535.     if fPosition = cpRightTop then
  536.     begin
  537.       FillRect(Rect(2, Height - He, He, Height - 8));
  538.       FillRect(Rect(8, Height - He, He, Height - 2));
  539.       TextOut(2 + (He - Wi) div 2, Height - He, fUStr);
  540.     end;
  541.     if fPosition = cpLeftBottom then
  542.     begin
  543.       FillRect(Rect(Width - He, 8, Width - 2, He));
  544.       FillRect(Rect(Width - He, 2, Width - 8, He));
  545.       TextOut(Width - He + 1 + (He - 2 - Wi) div 2, 8, fUStr);
  546.     end;
  547.     if fPosition = cpRightBottom then
  548.     begin
  549.       FillRect(Rect(2, 8, He, He));
  550.       FillRect(Rect(8, 2, He, He));
  551.       TextOut(2 + (He - Wi) div 2, 8, fUStr);
  552.     end;
  553.   end;
  554.   Canvas.Font.Height := OrgH;
  555.   SetBKMode(Canvas.Handle, OPAQUE);
  556. end;
  557.  
  558. procedure TRsRulerCorner.SetFlat(const Value: Boolean);
  559. begin
  560.   if Value <> fFlat then
  561.   begin
  562.     fFlat := Value;
  563.     Invalidate;
  564.   end;
  565. end;
  566.  
  567. procedure TRsRulerCorner.SetPosition(const Value: TCornerPos);
  568. begin
  569.   if Value <> fPosition then
  570.   begin
  571.     fPosition := Value;
  572.     Invalidate;
  573.   end;
  574. end;
  575.  
  576. procedure TRsRulerCorner.SetUnits(const Value: TRulerUnit);
  577. begin
  578.   if Value <> fUnits then
  579.   begin
  580.     fUnits := Value;
  581.     if fUnits = ruCenti then begin fUStr := Centi; Hint := 'centimeter'; end;
  582.     if fUnits = ruMilli then begin fUStr := Milli; Hint := 'millimeter'; end;
  583.     if fUnits = ruInch then begin fUStr := Inch; Hint := 'inch'; end;
  584.     if fUnits = ruNone then begin fUStr := None; Hint := ''; end;
  585.     Invalidate;
  586.   end;
  587. end;
  588.  
  589. end.
  590.