home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / DELPHI5.iso / AddOns / Components / Essentials / SETUP.EXE / %MAINDIR% / EsGrad.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-11-28  |  10.7 KB  |  421 lines

  1. {*********************************************************}
  2. {*                   ESGRAD.PAS 1.05                     *}
  3. {*      Copyright (c) 1997-98 TurboPower Software Co     *}
  4. {*                 All rights reserved.                  *}
  5. {*********************************************************}
  6.  
  7. {$I ES.INC}
  8.  
  9. {$B-} {Complete Boolean Evaluation}
  10. {$I+} {Input/Output-Checking}
  11. {$P+} {Open Parameters}
  12. {$T-} {Typed @ Operator}
  13. {$W-} {Windows Stack Frame}
  14. {$X+} {Extended Syntax}
  15.  
  16. {$IFNDEF Win32}
  17.   {$G+} {286 Instructions}
  18.   {$N+} {Numeric Coprocessor}
  19.   {$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
  20. {$ENDIF}
  21.  
  22. unit EsGrad;
  23.   {-gadient component}
  24.  
  25. interface
  26.  
  27. uses
  28.   {$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  29.   Classes, Controls, Graphics, Messages,
  30.   EsConst, EsData;
  31.  
  32. const
  33.   MinColorBands = 2;   {two bands isn't much of a gradient}
  34.   MaxColorBands = 256; {more than 256 colors is not noticeable, and slows painting}
  35.  
  36. type
  37.   TGradDirection = (dHorizontal, dVertical);
  38.   TEsColorBand = MinColorBands..MaxColorBands;
  39.  
  40.   TEsCustomGradient = class(TGraphicControl)
  41.   protected {private}
  42.     {.Z+}
  43.     {property variables}
  44.     FFromColor  : TColor;
  45.     FToColor    : TColor;
  46.     FDirection  : TGradDirection;
  47.     FColorBands : TEsColorBand;
  48.  
  49.     {internal variables}
  50.     gGradColors : array[0..MaxColorBands-1] of TColorRef;
  51.     gPalette    : HPalette;
  52.  
  53.     {property methods}
  54.     function GetVersion : string;
  55.     procedure SetColorBands(Value : TEsColorBand);
  56.     procedure SetDirection(Value : TGradDirection);
  57.     procedure SetFromColor(Value : TColor);
  58.     procedure SetToColor(Value : TColor);
  59.     procedure SetVersion(const Value : string);
  60.  
  61.     {internal methods}
  62.     procedure gCalculateColors;
  63.     procedure gFillRectGradient(DC : hDC; const R : TRect);
  64.  
  65.     {windows message methods}
  66.     procedure WMEraseBkgnd(var Msg : TWMEraseBkgnd);
  67.       message WM_ERASEBKGND;
  68.     {.Z-}
  69.  
  70.   protected
  71.     {.Z+}
  72.     function PaletteChanged(Foreground : Boolean) : Boolean;
  73.       override;
  74.     procedure Paint;
  75.       override;
  76.     {.Z-}
  77.  
  78.     {protected properties}
  79.     property ColorBands : TEsColorBand
  80.       read FColorBands
  81.       write SetColorBands
  82.       default 128;
  83.  
  84.     property Direction : TGradDirection
  85.       read FDirection
  86.       write SetDirection
  87.       default dHorizontal;
  88.  
  89.     property FromColor : TColor
  90.       read FFromColor
  91.       write SetFromColor
  92.       default clRed;
  93.  
  94.     property ToColor : TColor
  95.       read FToColor
  96.       write SetToColor
  97.       default clYellow;
  98.  
  99.     property Version : string
  100.       read GetVersion
  101.       write SetVersion
  102.       stored False;
  103.  
  104.   public
  105.     {.Z+}
  106.     constructor Create(AComponent : TComponent);
  107.       override;
  108.     destructor Destroy;
  109.       override;
  110.     procedure PaintTo(DC : TEshDC; R : TRect);
  111.     {.Z-}
  112.   end;
  113.  
  114.   TEsGradient = class(TEsCustomGradient)
  115.   published
  116.     {properties}
  117.     property Align;
  118.     property ColorBands;
  119.     property Direction;
  120.     property FromColor;
  121.     property ToColor;
  122.     property Version;
  123.  
  124.     {events}
  125.     property OnClick;
  126.     property OnDblClick;
  127.     property OnDragDrop;
  128.     property OnDragOver;
  129.     property OnMouseDown;
  130.     property OnMouseMove;
  131.     property OnMouseUp;
  132.     {$IFDEF WIN32}
  133.     property OnStartDrag;
  134.     {$ENDIF WIN32}
  135.   end;
  136.  
  137.  
  138. implementation
  139.  
  140.  
  141. {$IFDEF TRIALRUN}
  142. uses
  143.   EsTrial;
  144. {$I ESTRIALF.INC}
  145. {$ENDIF}
  146.  
  147.  
  148. constructor TEsCustomGradient.Create(AComponent : TComponent);
  149. {$IFDEF TRIALRUN}
  150. var
  151.   X : Integer;
  152. {$ENDIF}
  153. begin
  154.   inherited Create(AComponent);
  155.  
  156.   ControlStyle := ControlStyle + [csOpaque];
  157.  
  158.   FColorBands := 128;
  159.   FDirection  := dHorizontal;
  160.   FFromColor  := clRed;
  161.   FToColor    := clYellow;
  162.  
  163.   Width       := 100;
  164.   Height      := 100;
  165.  
  166.   gCalculateColors;
  167.  
  168. {$IFDEF TRIALRUN}
  169.   X := _CC_;
  170.   if (X < ccRangeLow) or (X > ccRangeHigh) then Halt;
  171.   X := _VC_;
  172.   if (X < ccRangeLow) or (X > ccRangeHigh) then Halt;
  173. {$ENDIF}
  174. end;
  175.  
  176. destructor TEsCustomGradient.Destroy;
  177. begin
  178.   if gPalette <> 0 then begin
  179.     DeleteObject(gPalette);
  180.     gPalette := 0;
  181.   end;
  182.  
  183.   inherited Destroy;
  184. end;
  185.  
  186. procedure TEsCustomGradient.gCalculateColors;
  187. var
  188.   ToColor   : TRGBMap;
  189.   FromColor : TRGBMap;
  190.   RedPct    : Double;
  191.   GreenPct  : Double;
  192.   BluePct   : Double;
  193.   Band      : Byte;
  194.   LogPal    : PLogPalette;
  195.   LogSize   : Word;
  196. begin
  197.   ToColor.RGBValue := ColorToRGB(FToColor);
  198.   FromColor.RGBValue := ColorToRGB(FFromColor);
  199.   {figure out the percentage of each RGB value needed for banding}
  200.   with ToColor do begin
  201.     RedPct   := (ToColor.Red - FromColor.Red) / (FColorBands-1);
  202.     GreenPct := (ToColor.Green - FromColor.Green) / (FColorBands-1);
  203.     BluePct  := (ToColor.Blue - FromColor.Blue)/ (FColorBands-1);
  204.   end;
  205.  
  206.   {release any existing palette}
  207.   if gPalette <> 0 then begin
  208.     DeleteObject(gPalette);
  209.     gPalette := 0;
  210.   end;
  211.  
  212.   {create our palette}
  213.   LogSize := SizeOf(TLogPalette) + (FColorBands-1)*SizeOf(TPaletteEntry);
  214.   GetMem(LogPal, LogSize);
  215.   try
  216.     LogPal^.palVersion := $300;
  217.     LogPal^.palNumEntries := FColorBands;
  218.  
  219.     {use the percentage of each color to create each band color}
  220.     for Band := 0 to Pred(FColorBands) do begin
  221.       gGradColors[Band] := RGB(FromColor.Red + Round(RedPct*Band),
  222.                                FromColor.Green + Round(GreenPct*Band),
  223.                                FromColor.Blue + Round(BluePct*Band));
  224.       LogPal^.palPalEntry[Band].peRed := FromColor.Red + Round(RedPct*Band);
  225.       LogPal^.palPalEntry[Band].peGreen := FromColor.Green + Round(GreenPct*Band);
  226.       LogPal^.palPalEntry[Band].peBlue := FromColor.Blue + Round(BluePct*Band);
  227.       LogPal^.palPalEntry[Band].peFlags := 0;
  228.     end;
  229.  
  230.     gPalette := CreatePalette(LogPal^);
  231.   finally
  232.     FreeMem(LogPal, LogSize);
  233.   end;
  234. end;
  235.  
  236. procedure TEsCustomGradient.gFillRectGradient(DC : hDC; const R : TRect);
  237.   {-paint the given rectangle with the gradient pattern}
  238. var
  239.   OldBrush : hBrush;
  240.   Brush    : hBrush;
  241.   Step     : Double;
  242.   Band     : Integer;
  243.   H, W     : Integer;
  244.   X, Y     : Integer;
  245. begin
  246.   {determine how large each band should be in order to cover the}
  247.   {rectangle (one band for every color intensity level)}
  248.   case FDirection of
  249.     dHorizontal :
  250.       begin
  251.         Step := (R.Right - R.Left) / FColorBands;
  252.         H := R.Bottom - R.Top;
  253.         W := Round(1.5*Step);
  254.         if W < 1 then W := 1;
  255.         {start filling bands}
  256.         for Band := 0 to Pred(FColorBands) do begin
  257.           {create a brush with the appropriate color for this band}
  258.           Brush := CreateSolidBrush(gGradColors[Band]);
  259.           try
  260.             {select that brush into the temporary DC}
  261.             OldBrush := SelectObject(DC, Brush);
  262.             try
  263.               X := Round(Band*Step);
  264.               {fill the rectangle using the selected brush}
  265.               PatBlt(DC, X, 0, W, H, PATCOPY);
  266.             finally
  267.               {clean up the brush}
  268.               SelectObject(DC, OldBrush);
  269.             end;
  270.           finally
  271.             DeleteObject(Brush);
  272.           end;
  273.         end;
  274.       end;
  275.     dVertical :
  276.       begin
  277.         Step := (R.Bottom - R.Top) / FColorBands;
  278.         W := R.Right - R.Left;
  279.         H := Round(1.5*Step);
  280.         if H < 1 then H := 1;
  281.         {start filling bands}
  282.         for Band := 0 to Pred(FColorBands) do begin
  283.           {create a brush with the appropriate color for this band}
  284.           Brush := CreateSolidBrush(gGradColors[Band]);
  285.           try
  286.             {select that brush into the temporary DC}
  287.             OldBrush := SelectObject(DC, Brush);
  288.             try
  289.               Y := Round(Band*Step);
  290.               {fill the rectangle using the selected brush}
  291.               PatBlt(DC, 0, Y, W, H, PATCOPY);
  292.             finally
  293.               {clean up the brush}
  294.               SelectObject(DC, OldBrush);
  295.             end;
  296.           finally
  297.             DeleteObject(Brush);
  298.           end;
  299.         end;
  300.       end;
  301.   end;
  302. end;
  303.  
  304. function TEsCustomGradient.GetVersion : string;
  305. begin
  306.   Result := EsVersionStr;
  307. end;
  308.  
  309. procedure TEsCustomGradient.Paint;
  310. begin
  311.   PaintTo(Canvas.Handle, ClientRect);
  312. end;
  313.  
  314. procedure TEsCustomGradient.PaintTo(DC : TEshDC; R : TRect);
  315. var
  316.   TmpDC   : hDC;
  317.   Bmp     : hBitmap;
  318.   OldBmp  : hBitmap;
  319.   OldPal  : hPalette;
  320.   OldPal2 : hPalette;
  321.   CW, CH  : Integer;
  322. begin
  323.   {get the width and height}
  324.   CW := R.Right-R.Left;
  325.   CH := R.Bottom-R.Top;
  326.  
  327.   {select our palette into the canvas}
  328.   OldPal := SelectPalette(DC, gPalette, True);
  329.   RealizePalette(DC);
  330.   try
  331.     {create a temporary device context}
  332.     TmpDC := CreateCompatibleDC(DC);
  333.     try
  334.       {create a bitmap to draw on}
  335.       Bmp := CreateCompatibleBitmap(DC, CW, CH);
  336.       try
  337.         {select the bitmap into the temporary DC}
  338.         OldBmp := SelectObject(TmpDC, Bmp);
  339.         try
  340.           {select our palette into the temp DC}
  341.           OldPal2 := SelectPalette(TmpDC, gPalette, True);
  342.           RealizePalette(TmpDC);
  343.           try
  344.             {draw the gradient on the temporary device context}
  345.             gFillRectGradient(TmpDC, R);
  346.             {copy temporary device context to ours}
  347.             BitBlt(DC, 0, 0, CW, CH, TmpDC, 0, 0, SRCCOPY);
  348.           finally
  349.             if OldPal2 > 0 then
  350.               SelectPalette(TmpDC, OldPal2, True);
  351.           end;
  352.         finally
  353.           SelectObject(TmpDC, OldBmp);
  354.         end;
  355.       finally
  356.         DeleteObject(Bmp);
  357.       end;
  358.     finally
  359.       DeleteDC(TmpDC);
  360.     end;
  361.   finally
  362.     if OldPal <> 0 then
  363.       SelectPalette(Canvas.Handle, OldPal, True);
  364.   end;
  365. end;
  366.  
  367. function TEsCustomGradient.PaletteChanged(Foreground : Boolean) : Boolean;
  368. begin
  369.   gCalculateColors;
  370.   Refresh;
  371.   Result := True;
  372. end;
  373.  
  374. procedure TEsCustomGradient.SetColorBands(Value : TEsColorBand);
  375. begin
  376.   if (Value <> FColorBands) and (Value >= MinColorBands) and
  377.      (Value <= MaxColorBands) then begin
  378.     FColorBands := Value;
  379.     gCalculateColors;
  380.     Invalidate;
  381.   end;
  382. end;
  383.  
  384. procedure TEsCustomGradient.SetDirection(Value : TGradDirection);
  385. begin
  386.   if Value <> FDirection then begin
  387.     FDirection := Value;
  388.     gCalculateColors;
  389.     Invalidate;
  390.   end;
  391. end;
  392.  
  393. procedure TEsCustomGradient.SetFromColor(Value : TColor);
  394. begin
  395.   if Value <> FFromColor then begin
  396.     FFromColor := Value;
  397.     gCalculateColors;
  398.     Invalidate;
  399.   end;
  400. end;
  401.  
  402. procedure TEsCustomGradient.SetToColor(Value : TColor);
  403. begin
  404.   if Value <> FToColor then begin
  405.     FToColor := Value;
  406.     gCalculateColors;
  407.     Invalidate;
  408.   end;
  409. end;
  410.  
  411. procedure TEsCustomGradient.SetVersion(const Value : string);
  412. begin
  413. end;
  414.  
  415. procedure TEsCustomGradient.WMEraseBkgnd(var Msg : TWMEraseBkgnd);
  416. begin
  417.   Msg.Result := 1;   {don't erase background, just say we did}
  418. end;
  419.  
  420. end.
  421.