home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 1999 March / DPPCPRO0399.ISO / Editor / Code.txt next >
Encoding:
Text File  |  1998-12-18  |  11.6 KB  |  394 lines

  1. unit PCProgress;
  2.  
  3. interface
  4.  
  5. uses
  6.     Wintypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.     CommCtrl;
  8.  
  9. type
  10.     TPCProgressOrientation = ( pbHorizontal, pbVertical );
  11.  
  12.     TPCProgressBar = class(TCustomControl)
  13.     private
  14.         { Private declarations }
  15.     fLowRange: Integer;
  16.     fHighRange: Integer;
  17.     fPosition: Integer;
  18.     fStep: Integer;
  19.     fBarColor: TColor;
  20.         fWholeBars: Boolean;
  21.         fOrientation: TPCProgressOrientation;
  22.         fSmooth: Boolean;
  23.         fSpectrum: TBitmap;
  24.         function GetSpectrumBar: Boolean;
  25.         procedure SetSpectrumBar (Value: Boolean);
  26.         procedure SetRangePos (Index, Value: Integer);
  27.         procedure SetSmooth (Value: Boolean);
  28.         procedure SetBarColor (Value: TColor);
  29.         procedure SetWholeBars (Value: Boolean);
  30.         procedure InitBitmap;
  31.         procedure SetOrientation (Value: TPCProgressOrientation);
  32.     protected
  33.         { Protected declarations }
  34.         procedure CreateParams (var Params: TCreateParams); override;
  35.         procedure Loaded; override;
  36.         procedure Paint; override;
  37.     public
  38.         { Public declarations }
  39.         constructor Create (AOwner: TComponent); override;
  40.         destructor Destroy; override;
  41.     procedure StepIt;
  42.         procedure StepBy (Delta: Integer);
  43.     published
  44.         { Published declarations }
  45.         property OnDragDrop;
  46.         property OnDragOver;
  47.         property OnEndDrag;
  48.         property OnMouseDown;
  49.         property OnMouseMove;
  50.         property OnMouseUp;
  51.         {$IFDEF Ver120}
  52.         property BorderWidth;
  53.         {$ENDIF}
  54.         property Color;
  55.         property Align;
  56.         property Enabled;
  57.         property SpectrumBar: Boolean read GetSpectrumBar write SetSpectrumBar default False;
  58.         property Min: Integer index 0 read fLowRange write SetRangePos default 0;
  59.         property Max: Integer index 1 read fHighRange write SetRangePos default 100;
  60.         property Position: Integer index 2 read fPosition write SetRangePos default 0;
  61.         property Orientation: TPCProgressOrientation read fOrientation write SetOrientation default pbHorizontal;
  62.         property Smooth: Boolean read fSmooth write SetSmooth default False;
  63.         property Step: Integer read fStep write fStep default 10;
  64.         property BarColor: TColor read fBarColor write SetBarColor default clHighlight;
  65.         property WholeBars: Boolean read fWholeBars write SetWholeBars default True;
  66.     end;
  67.  
  68. procedure Register;
  69.  
  70. implementation
  71.  
  72. uses Math;
  73.  
  74. function NanoMetresToRGB (NanoMetres: Integer; Brightness: Double): ColorRef;
  75. var
  76.     Red, Green, Blue, Factor: Double;
  77.  
  78.    function Adjust (Color, Factor: Double): Integer;
  79.    const
  80.        Gamma = 0.80;
  81.    begin
  82.        if Color = 0.0 then Result := 0 else
  83.        Result := Round (255 * Power (Color * Factor * Brightness, Gamma));
  84.     end;
  85.  
  86. begin
  87.     Red := 0.0; Green := 0.0; Blue := 0.0;
  88.     if Brightness > 1.0 then Brightness := 1.0;
  89.     if Brightness < 0.0 then Brightness := 0.0;
  90.  
  91.     // Calculate relative RGB values
  92.     case Trunc (NanoMetres) of
  93.         380..439:   begin    // Ultra-violet to blue
  94.                 Red   := -(NanoMetres - 440) / (440 - 380);
  95.                     Blue  := 1.0;
  96.             end;
  97.  
  98.     440..489:   begin      // Blue to cyan
  99.             Green := (NanoMetres - 440) / (490 - 440);
  100.             Blue  := 1.0;
  101.             end;
  102.  
  103.     490..509:   begin    // Cyan to green
  104.             Green := 1.0;
  105.             Blue  := -(NanoMetres - 510) / (510 - 490);
  106.             end;
  107.  
  108.     510..579:   begin      // Green to yellow-orange
  109.                 Red   := (NanoMetres - 510) / (580 - 510);
  110.             Green := 1.0;
  111.             end;
  112.  
  113.     580..644:   begin      // Yellow-orange to full red
  114.                 Red   := 1.0;
  115.                 Green := -(NanoMetres - 645) / (645 - 580);
  116.             end;
  117.  
  118.     645..780:   begin     // Full red from hereon....
  119.                 Red   := 1.0;
  120.             Green := 0.0;
  121.             end;
  122.     end;
  123.  
  124.     // Condition RGB according to limits of vision
  125.     case Trunc (NanoMetres) of
  126.         380..419:  Factor := 0.3 + 0.7 * (NanoMetres - 380) / (420 - 380);
  127.         420..700:  Factor := 1.0;
  128.         701..780:  Factor := 0.3 + 0.7 * (780 - NanoMetres) / (780 - 700);
  129.         else       Factor := 0.0;
  130.     end;
  131.  
  132.     Result := RGB (Adjust (Red, Factor), Adjust (Green, Factor), Adjust (Blue, Factor));
  133. end;
  134.  
  135. procedure BlitRect (dc: hDC; const R: TRect; Color: LongInt);                    { $BFEB5B72 }
  136. begin
  137.     Color := SetBkColor (dc, Color);
  138.     ExtTextOut (dc, 0, 0, eto_Opaque, @R, Nil, 0, Nil);
  139.     SetBkColor (dc, Color);
  140. end;
  141.  
  142. { TPCProgressBar }
  143.  
  144. constructor TPCProgressBar.Create (AOwner: TComponent);
  145. begin
  146.     Inherited Create (AOwner);
  147.     fLowRange := 0; fHighRange := 100; fStep := 10;
  148.     fWholeBars := True; fBarColor := clHighlight; fOrientation := pbHorizontal;
  149.     Width := 150; Height := GetSystemMetrics (sm_cyVScroll);
  150. end;
  151.  
  152. destructor TPCProgressBar.Destroy;
  153. begin
  154.     fSpectrum.Free;
  155.     Inherited Destroy;
  156. end;
  157.  
  158. procedure TPCProgressBar.CreateParams (var Params: TCreateParams);
  159. begin
  160.     Inherited CreateParams (Params);
  161.     Params.ExStyle := (Params.ExStyle and (not ws_ex_ClientEdge)) or ws_ex_StaticEdge;
  162. end;
  163.  
  164. procedure TPCProgressBar.Loaded;
  165. var
  166.     x: Integer;
  167. begin
  168.     Inherited Loaded;
  169.     if fOrientation = pbVertical then begin
  170.         x := Width;
  171.         Width := Height;
  172.         Height := x;
  173.         InitBitmap;
  174.     end;
  175. end;
  176.  
  177. procedure TPCProgressBar.SetWholeBars (Value: Boolean);
  178. begin
  179.     if Value <> fWholeBars then begin
  180.         fWholeBars := Value;
  181.         Invalidate;
  182.     end;
  183. end;
  184.  
  185. procedure TPCProgressBar.SetSmooth (Value: Boolean);
  186. begin
  187.     if Value <> fSmooth then begin
  188.         fSmooth := Value;
  189.         Invalidate;
  190.     end;
  191. end;
  192.  
  193. procedure TPCProgressBar.SetBarColor (Value: TColor);
  194. begin
  195.     if Value <> fBarColor then begin
  196.         fBarColor := Value;
  197.         Invalidate;
  198.     end;
  199. end;
  200.  
  201. procedure TPCProgressBar.SetRangePos (Index, Value: Integer);
  202.  
  203.     procedure OutOfRange;
  204.     begin
  205.         raise EInvalidOperation.CreateFmt ('%s property out of range', [Self.Classname]);
  206.     end;
  207.  
  208. begin
  209.     case Index of
  210.         0:     begin
  211.                    if Value > fHighRange then OutOfRange;
  212.                    fLowRange := Value;
  213.                    Position := fPosition;  { Force repin of position }
  214.                end;
  215.  
  216.         1:     begin
  217.                    if Value < fLowRange then OutOfRange;
  218.                    fHighRange := Value;
  219.                    Position := fPosition;  { Force repin of position }
  220.                end;
  221.  
  222.         2:     begin
  223.                    if Value < fLowRange then Value := fLowRange;
  224.                    if Value > fHighRange then Value := fHighRange;
  225.                    fPosition := Value;
  226.                end;
  227.     end;
  228.  
  229.     if Index = 2 then Invalidate; { No point invalidating twice }
  230. end;
  231.  
  232. procedure TPCProgressBar.SetOrientation (Value: TPCProgressOrientation);
  233. var
  234.     x: Integer;
  235. begin
  236.     if Value <> fOrientation then begin
  237.         fOrientation := Value;
  238.         x := Width;
  239.         Width := Height;
  240.         Height := x;
  241.         Invalidate;
  242.     end;
  243. end;
  244.  
  245. procedure TPCProgressBar.Paint;
  246. var
  247.     SrcDC: hDC;
  248.     hbm: HBitmap;
  249.     cRect, boxRect: TRect;
  250.     BlockLen, Count, physWidth, physRange, physPos, InterBlockGap: Integer;
  251.  
  252.     function CalcBoxSize (var r: TRect): Boolean;
  253.     begin
  254.         if fOrientation = pbVertical then begin
  255.             r.Top := r.Bottom - BlockLen;
  256.         Result := r.Bottom <= cRect.Top;
  257.         if r.Top <= cRect.Top then r.Top := cRect.Top + 1;
  258.             if (not fWholeBars) and (cRect.Bottom - r.Top > physPos) then r.Top := cRect.Bottom - physPos;
  259.         end else begin
  260.             r.Right := r.Left + BlockLen;
  261.         Result := r.Left >= cRect.Right;
  262.         if r.Right >= cRect.Right then r.Right := cRect.Right - 1;
  263.             if (not fWholeBars) and (r.Right - cRect.Left > physPos) then r.Right := cRect.Left + physPos;
  264.         end;
  265.     end;
  266.  
  267. begin
  268.     { Reinitialise the bitmap if necessary }
  269.     if (fSpectrum <> Nil) and
  270.         ((fSpectrum.Width <> Width) or (fSpectrum.Height <> Height))
  271.             then InitBitmap;
  272.  
  273.     cRect := ClientRect;
  274.     InflateRect (cRect, -1, -1);
  275.     boxRect := cRect;
  276.  
  277.     if fOrientation = pbVertical then begin
  278.         physWidth := cRect.Right - cRect.Left;
  279.     physRange := cRect.Bottom - cRect.Top;
  280.     end else begin
  281.     physWidth := cRect.Bottom - cRect.Top;
  282.     physRange := cRect.Right - cRect.Left;
  283.     end;
  284.  
  285.     BlockLen := (physWidth * 2) div 3;
  286.     if BlockLen = 0 then BlockLen := 1;
  287.     physPos := MulDiv (physRange, fPosition - fLowRange, fHighRange - fLowRange);
  288.  
  289.     InterBlockGap := 2;
  290.     if fSmooth then begin
  291.     InterBlockGap := 0;
  292.     BlockLen := 1;
  293.     end;
  294.  
  295.     for Count := 0 to ((physPos + BlockLen + InterBlockGap - 1) div (BlockLen + InterBlockGap)) - 1 do begin
  296.     if CalcBoxSize (boxRect) then break;
  297.  
  298.         if fSpectrum <> Nil then begin
  299.             SrcDC := CreateCompatibleDC (0);
  300.             hbm := SelectObject (SrcDC, fSpectrum.Handle);
  301.             BitBlt (Canvas.Handle, boxRect.Left, boxRect.Top,
  302.                     boxRect.Right - boxRect.Left,
  303.                     boxRect.Bottom - boxRect.Top,
  304.                     SrcDC, boxRect.Left, boxRect.Top, SrcCopy);
  305.             SelectObject (SrcDC, hbm);
  306.             DeleteDC (SrcDC);
  307.         end else BlitRect (Canvas.Handle, boxRect, ColorToRGB (fBarColor));
  308.  
  309.     if fOrientation = pbVertical then
  310.             boxRect.Bottom := boxRect.Top - InterBlockGap else boxRect.Left := boxRect.Right + InterBlockGap;
  311.     end;
  312. end;
  313.  
  314. procedure TPCProgressBar.StepIt;
  315. begin
  316.     Perform (pbm_StepIt, 0, 0);
  317. end;
  318.  
  319. procedure TPCProgressBar.StepBy (Delta: Integer);
  320. begin
  321.     Perform (pbm_DeltaPos, Delta, 0);
  322. end;
  323.  
  324. procedure TPCProgressBar.InitBitmap;
  325. const
  326.     fWaveMin = 380;
  327.     fWaveMax = 780;
  328. type
  329.     pRGBArray = ^TRGBArray;
  330.     TRGBArray = array [0..32767] of TRGBTriple;
  331. var
  332.     Row: pRGBArray;
  333.     CurColor: TColor;
  334.     Wavelength: Double;
  335.     x, y: Integer;
  336. begin
  337.     if fSpectrum = Nil then fSpectrum := TBitmap.Create;
  338.     fSpectrum.PixelFormat := pf24bit;
  339.     fSpectrum.Width := Width;
  340.     fSpectrum.Height := Height;
  341.  
  342.     if fOrientation = pbHorizontal then
  343.         for x := 0 to Width - 1 do begin
  344.             Wavelength := fWaveMin + (fWaveMax - fWaveMin) * x / Width;
  345.             CurColor := NanoMetresToRGB (Trunc (Wavelength), 1.0);
  346.             for y := 0 To Height - 1 do begin
  347.                 row := fSpectrum.Scanline [y];
  348.                 with row [x] do begin
  349.                     rgbtRed   := GetRValue (CurColor);
  350.                     rgbtGreen := GetGValue (CurColor);
  351.                     rgbtBlue  := GetBValue (CurColor);
  352.                 end;
  353.             end;
  354.         end
  355.     else
  356.         for y := 0 to Height - 1 do begin
  357.             WaveLength := fWaveMin + (fWaveMax - fWaveMin) * y / Height;
  358.             CurColor := NanoMetresToRGB (Trunc (Wavelength), 1.0);
  359.             row := fSpectrum.Scanline [y];
  360.             for x := 0 to Width - 1 do
  361.                 with row [x] do begin
  362.                     rgbtRed   := GetRValue (CurColor);
  363.                     rgbtGreen := GetGValue (CurColor);
  364.                     rgbtBlue  := GetBValue (CurColor);
  365.                 end;
  366.         end;
  367. end;
  368.  
  369. function TPCProgressBar.GetSpectrumBar: Boolean;
  370. begin
  371.     Result := fSpectrum <> Nil;
  372. end;
  373.  
  374. procedure TPCProgressBar.SetSpectrumBar (Value: Boolean);
  375. begin
  376.     if Value <> GetSpectrumBar then begin
  377.         if Value then InitBitmap else begin
  378.             fSpectrum.Free;
  379.             fSpectrum := Nil;
  380.         end;
  381.         Invalidate;
  382.     end;
  383. end;
  384.  
  385. procedure Register;
  386. begin
  387.     RegisterComponents ('PC Pro', [TPCProgressBar]);
  388. end;
  389.  
  390. end.
  391.  
  392.  
  393.  
  394.