Difference between revisions of "Double Gradient"

From Lazarus wiki
Jump to navigationJump to search
m (Fixed syntax highlighting; deleted category included in page template)
 
(23 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
{{Double Gradient}}
 
{{Double Gradient}}
  
== Unit ==
+
Now 'DoubleGradientAlphaFill' & 'nGradientAlphaFill' are included in [[BGRABitmap]] in the unit 'BGRAGradients'.
 +
 
 +
== Double Gradient ==
  
 
[[Image:sampledoublegd.png]]
 
[[Image:sampledoublegd.png]]
  
With this unit 'ngradient' you can easily make gradients for toolbars, buttons, etc. Save the below code in a text file 'ngradient.pas' and add 'ngradient' in the 'uses' section of your project.
+
=== Unit ===
 +
 
 +
==== DoubleGradient ====
  
<delphi>unit ngradient;
+
<syntaxhighlight lang=pascal>
 +
unit doublegradient;
  
 
{$mode objfpc}{$H+}
 
{$mode objfpc}{$H+}
Line 15: Line 20:
 
uses
 
uses
 
   Classes, Graphics;
 
   Classes, Graphics;
 
type
 
  TnGradientInfo = record
 
    StartColor,StopColor:TColor;
 
    Direction: TGradientDirection;
 
    endPercent:single; // This is not the percent of the width, this is the percent of the end ob the rect- which means, if this value is 1 - the rect could be from 0.99 to 1 and need not be from 0 to 1
 
  end;
 
  
 
function DoubleGradientFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TColor;
 
function DoubleGradientFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TColor;
 
   ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBitmap;
 
   ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBitmap;
function nGradientFill(ARect: TRect;APos: TGradientDirection; AGrandient: array of TnGradientInfo): TBitmap;
 
  
 
implementation
 
implementation
 
function nGradientFill(ARect: TRect;APos: TGradientDirection; AGrandient: array of TnGradientInfo): TBitmap;
 
var
 
  i:integer;
 
  AnRect,OldRect: TRect;
 
begin
 
  Result := TBitmap.Create;
 
  Result.Width:=ARect.Right-ARect.Left;
 
  Result.Height:=ARect.Bottom-ARect.Top;
 
  OldRect := ARect;
 
  if APos = gdVertical then OldRect.Bottom := ARect.Top
 
    else OldRect.Right := ARect.Left ;  // upside down...  in case of i = 0...
 
 
  for i := 0 to high(AGrandient) do
 
      begin
 
      AnRect:=OldRect;
 
      if APos = gdVertical then
 
        begin
 
        AnRect.Bottom:=Round((ARect.Bottom-ARect.Top) * AGrandient[i].endPercent + ARect.Top);
 
        AnRect.Top:=OldRect.Bottom;
 
        end
 
        else
 
        begin
 
        AnRect.Right:=Round((ARect.Right-ARect.Left) * AGrandient[i].endPercent + ARect.Left);
 
        AnRect.Left:=OldRect.Right;
 
        end;
 
 
      Result.Canvas.GradientFill(AnRect,AGrandient[i].StartColor,AGrandient[i].StopColor,AGrandient[i].Direction);
 
      OldRect := AnRect;
 
      end;
 
end;
 
 
  
 
function DoubleGradientFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TColor;
 
function DoubleGradientFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TColor;
Line 69: Line 34:
 
   ABitmap.Width:=ARect.Right;
 
   ABitmap.Width:=ARect.Right;
 
   ABitmap.Height:=ARect.Bottom;
 
   ABitmap.Height:=ARect.Bottom;
   if AValue <> 0 then begin
+
   if AValue <> 0 then ARect1:=ARect;
     ARect1:=ARect;
+
  if AValue <> 1 then ARect2:=ARect;
   end;
+
  if APos = gdVertical then begin
   if AValue <> 1 then begin
+
     ARect1.Bottom:=Round(ARect1.Bottom * AValue);
     ARect2:=ARect;
+
    ARect2.Top:=ARect1.Bottom;
 +
   end
 +
   else if APos = gdHorizontal then begin
 +
    ARect1.Right:=Round(ARect1.Right * AValue);
 +
     ARect2.Left:=ARect1.Right;
 
   end;
 
   end;
 +
  if AValue <> 0 then ABitmap.Canvas.GradientFill(ARect1,AStart1,AStop1,ADirection1);
 +
  if AValue <> 1 then ABitmap.Canvas.GradientFill(ARect2,AStart2,AStop2,ADirection2);
 +
  Result:=ABitmap;
 +
end;
 +
 +
end.</syntaxhighlight>
 +
 +
==== DoubleGradientAlpha ====
 +
This requires [[BGRABitmap]].
 +
 +
<syntaxhighlight lang=pascal>
 +
unit doublegradientalpha;
 +
 +
{$mode objfpc}{$H+}
 +
 +
interface
 +
 +
uses
 +
  Classes, Graphics,
 +
  BGRABitmap, BGRABitmapTypes;
 +
 +
function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
 +
  ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBGRABitmap;
 +
 +
implementation
 +
 +
function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
 +
  ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBGRABitmap;
 +
var
 +
  ABitmap: TBGRABitmap; ARect1,ARect2: TRect; APoint1,APoint2,APoint3,APoint4: TPointF;
 +
begin
 +
  ABitmap := TBGRABitmap.Create(ARect.Right,ARect.Bottom);
 +
  if AValue <> 0 then ARect1:=ARect;
 +
  if AValue <> 1 then ARect2:=ARect;
 
   if APos = gdVertical then begin
 
   if APos = gdVertical then begin
 
     ARect1.Bottom:=Round(ARect1.Bottom * AValue);
 
     ARect1.Bottom:=Round(ARect1.Bottom * AValue);
Line 83: Line 86:
 
     ARect2.Left:=ARect1.Right;
 
     ARect2.Left:=ARect1.Right;
 
   end;
 
   end;
   if AValue <> 0 then begin
+
   if ADirection1 = gdVertical then begin
     ABitmap.Canvas.GradientFill(ARect1,AStart1,AStop1,ADirection1);
+
     APoint1:=PointF(ARect1.Left,ARect1.Top);
 +
    APoint2:=PointF(ARect1.Left,ARect1.Bottom);
 +
  end
 +
  else if ADirection1 = gdHorizontal then begin
 +
    APoint1:=PointF(ARect1.Left,ARect1.Top);
 +
    APoint2:=PointF(ARect1.Right,ARect1.Top);
 
   end;
 
   end;
   if AValue <> 1 then begin
+
   if ADirection2 = gdVertical then begin
     ABitmap.Canvas.GradientFill(ARect2,AStart2,AStop2,ADirection2);
+
     APoint3:=PointF(ARect2.Left,ARect2.Top);
 +
    APoint4:=PointF(ARect2.Left,ARect2.Bottom);
 +
  end
 +
  else if ADirection2 = gdHorizontal then begin
 +
    APoint3:=PointF(ARect2.Left,ARect2.Top);
 +
    APoint4:=PointF(ARect2.Right,ARect2.Top);
 
   end;
 
   end;
 +
  if AValue <> 0 then
 +
  ABitmap.GradientFill(ARect1.Left,ARect1.Top,ARect1.Right,ARect1.Bottom,
 +
  AStart1,AStop1,gtLinear,APoint1,APoint2,dmDrawWithTransparency,True,False);
 +
  if AValue <> 1 then
 +
  ABitmap.GradientFill( ARect2.Left,ARect2.Top,ARect2.Right,ARect2.Bottom,
 +
  AStart2,AStop2,gtLinear,APoint3,APoint4,dmDrawWithTransparency,True,False);
 
   Result:=ABitmap;
 
   Result:=ABitmap;
 
end;
 
end;
  
end.</delphi>
+
end.</syntaxhighlight>
  
== Usage ==
+
=== Usage ===
  
 
First you must have a 'TBitmap' to store the gradient, then you can draw the image, for example, in all the 'Form1' visible area:
 
First you must have a 'TBitmap' to store the gradient, then you can draw the image, for example, in all the 'Form1' visible area:
Line 102: Line 121:
 
''This is the result (using DoubleGradientFill).''
 
''This is the result (using DoubleGradientFill).''
  
<delphi>procedure TForm1.FormPaint(Sender: TObject);
+
<syntaxhighlight lang=pascal>
 +
procedure TForm1.FormPaint(Sender: TObject);
 
var
 
var
 
   ABitmap: TBitmap;
 
   ABitmap: TBitmap;
Line 109: Line 129:
 
   Self.Canvas.Draw(0,0,ABitmap);
 
   Self.Canvas.Draw(0,0,ABitmap);
 
   ABitmap.Free
 
   ABitmap.Free
end;</delphi>
+
end;</syntaxhighlight>
  
== Editor ==
+
If you use DoubleGradientAlphaFill first add BGRABitmap and BGRABitmapTypes in the Uses section, then use the function:
  
nGradient Editor is an updated version of Double Gradient Editor with a lot of changes and improvements, like the ability to create gradients with 'n' number of gradients.
+
<syntaxhighlight lang=pascal>
 
+
var
=== nGradient Editor ===
+
  myBitmap: TBGRABitmap;
With nGradient Editor you can use 'n' (number) of gradients.
+
begin
 
+
  myBitmap:= DoubleGradientAlphaFill(
[[Image:ngedit.png]]
+
  Self.ClientRect,
 
+
  BGRA(0,0,0,10),BGRA(255,255,255,100),
Version 1.1
+
  BGRA(100,100,100,255),BGRA(150,150,150,10),
* Name to n Gradient Edit, just because it is not any more double...
+
  gdVertical,gdVertical,gdVertical,0.5);
* I doesn't realy understand how to save configs - please corret it. Thanks
+
  Self.Canvas.Draw(0,0,myBitmap.Bitmap);
* I comment the Copy-to-clipboard thing - to lazy to corret it...
+
   myBitmap.Free;
* i stopped the dpi thing because the editor doesn't look ok on my pc, remove "//" in Form.Create if you want to use it.
+
end;</syntaxhighlight>
* I changed the editor for arrays, i use a stringlist.  Double Click on StartColor /StopColor or Gradient for an Combobox / ColorDialog.
 
* I paint on an Image.
 
* The Image is not longer in the middle - i Had some problems, if you could fix it : great.
 
* You can scale the Form.
 
* I tried to seperate render and the rest...
 
 
 
Bugfixes:
 
<delphi>(Rect.Bottom) *37
 
//and i corrected them to
 
(Rect.Bottom - Rect.Top) * 37 + Rect.Top.
 
//If Top and left was 0 there was no problem ...</delphi>
 
 
 
<delphi>//Also i just changed the line
 
GradientPB.Canvas.Draw(0,0,ABitmap);   
 
//to
 
Panel1.Canvas.Draw(0,0,ABitmap);</delphi>
 
  
=== Double Gradient Editor ===
+
=== Editor ===
  
Also you can use the 'Double Gradient Editor' that is a GUI to instantly see the result (only for double gradients), save to a bitmap file, save to '*.doublegradient' session file or just copy code to clipboard to use in lazarus.
+
You can use the 'Double Gradient Editor' that is a GUI to instantly see the result (only for double gradients), save to a bitmap file, save to '*.doublegradient' session file or just copy code to clipboard to use in lazarus.
  
 
[[Image:dbgedit.png]]
 
[[Image:dbgedit.png]]
Line 155: Line 159:
  
 
* default.doublegradient: this file has the last settings in the editor, is loaded at startup, saved when you close the application.
 
* default.doublegradient: this file has the last settings in the editor, is loaded at startup, saved when you close the application.
 
== Downloads ==
 
[http://www.multiupload.com/SJDCG5P21Z nGradient Editor 1.1 Source Code] ngdedit1.1.zip (26.14 KB)
 
  
 
[http://www.multiupload.com/5WJ6N8E0N0 Double Gradient Editor 1.0 Source Code] dbgdedit1.0.zip (5.64 KB)
 
[http://www.multiupload.com/5WJ6N8E0N0 Double Gradient Editor 1.0 Source Code] dbgdedit1.0.zip (5.64 KB)
  
 
You are free to edit and improve this editor, this is free of charge.
 
You are free to edit and improve this editor, this is free of charge.
 +
 +
== nGradient ==
 +
 +
With this unit 'ngradient' you can easily make gradients for toolbars, buttons, etc. Save the below code in a text file 'ngradient.pas' and add 'ngradient' in the 'uses' section of your project.
 +
 +
=== Unit ===
 +
 +
==== nGradientFill ====
 +
 +
Copy the code and save to a text file 'ngradient.pas':
 +
 +
<syntaxhighlight lang=pascal>
 +
unit ngradient;
 +
 +
{$mode objfpc}{$H+}
 +
 +
interface
 +
 +
uses
 +
  Classes, Graphics;
 +
 +
type
 +
  TnGradientInfo = record
 +
    StartColor,StopColor:TColor;
 +
    Direction: TGradientDirection;
 +
    endPercent:single; // This is not the percent of the width, this is the percent of the end of the rect- which means, if this value is 1 - the rect could be from 0.99 to 1 and needs not be from 0 to 1
 +
  end;
 +
 +
function nGradientFill(ARect: TRect;APos: TGradientDirection; AGradient: array of TnGradientInfo): TBitmap;
 +
 +
implementation
 +
 +
function nGradientFill(ARect: TRect;APos: TGradientDirection; AGradient: array of TnGradientInfo): TBitmap;
 +
var
 +
  i:integer;
 +
  AnRect,OldRect: TRect;
 +
begin
 +
  Result := TBitmap.Create;
 +
  Result.Width:=ARect.Right-ARect.Left;
 +
  Result.Height:=ARect.Bottom-ARect.Top;
 +
  OldRect := ARect;
 +
  if APos = gdVertical then OldRect.Bottom := ARect.Top
 +
    else OldRect.Right := ARect.Left ;  // upside down...  in case of i = 0...
 +
 +
  for i := 0 to high(AGradient) do
 +
      begin
 +
      AnRect:=OldRect;
 +
      if APos = gdVertical then
 +
        begin
 +
        AnRect.Bottom:=Round((ARect.Bottom-ARect.Top) * AGradient[i].endPercent + ARect.Top);
 +
        AnRect.Top:=OldRect.Bottom;
 +
        end
 +
        else
 +
        begin
 +
        AnRect.Right:=Round((ARect.Right-ARect.Left) * AGradient[i].endPercent + ARect.Left);
 +
        AnRect.Left:=OldRect.Right;
 +
        end;
 +
 +
      Result.Canvas.GradientFill(AnRect,AGradient[i].StartColor,AGradient[i].StopColor,AGradient[i].Direction);
 +
      OldRect := AnRect;
 +
      end;
 +
end;</syntaxhighlight>
 +
 +
==== nGradientAlphaFill ====
 +
 +
This requires [[BGRABitmap]].
 +
 +
Copy the code and save to a text file 'ngradientalpha.pas':
 +
 +
<syntaxhighlight lang=pascal>
 +
unit ngradientalpha;
 +
 +
{$mode objfpc}{$H+}
 +
 +
interface
 +
 +
uses
 +
  Classes, Graphics, BGRABitmap, BGRABitmapTypes;
 +
 +
type
 +
  TnGradientInfo = record
 +
    StartColor, StopColor : TBGRAPixel;
 +
    Direction            : TGradientDirection;
 +
    endPercent            : single;
 +
  end;
 +
 +
function nGradientAlphaFill(ARect: TRect;APos: TGradientDirection;
 +
  AGradient: array of TnGradientInfo): TBGRABitmap;
 +
 +
implementation
 +
 +
function nGradientAlphaFill(ARect: TRect;APos: TGradientDirection;
 +
  AGradient: array of TnGradientInfo): TBGRABitmap;
 +
var
 +
  i:integer; AnRect, OldRect: TRect; Point1, Point2: TPointF;
 +
begin
 +
  Result := TBGRABitmap.Create(ARect.Right-ARect.Left,ARect.Bottom-ARect.Top);
 +
  OldRect := ARect;
 +
  if APos = gdVertical then OldRect.Bottom := ARect.Top else OldRect.Right := ARect.Left;
 +
  for i := 0 to high(AGradient) do
 +
  begin
 +
    AnRect:=OldRect;
 +
    if APos = gdVertical then begin
 +
      AnRect.Bottom:=Round((ARect.Bottom-ARect.Top) * AGradient[i].endPercent + ARect.Top);
 +
      AnRect.Top:=OldRect.Bottom;
 +
      Point1:=PointF(AnRect.Left,AnRect.Top);
 +
      Point2:=PointF(AnRect.Left,AnRect.Bottom);
 +
    end
 +
    else begin
 +
    AnRect.Right:=Round((ARect.Right-ARect.Left) * AGradient[i].endPercent + ARect.Left);
 +
    AnRect.Left:=OldRect.Right;
 +
    Point1:=PointF(AnRect.Left,AnRect.Top);
 +
    Point2:=PointF(AnRect.Right,AnRect.Top);
 +
    end;
 +
  Result.GradientFill(AnRect.Left,AnRect.Top,AnRect.Right,AnRect.Bottom,
 +
  AGradient[i].StartColor,AGradient[i].StopColor,gtLinear,Point1,Point2,dmDrawWithTransparency,True,False);
 +
  OldRect := AnRect;
 +
  end;
 +
end;
 +
 +
end.</syntaxhighlight>
 +
 +
=== Usage ===
 +
 +
If you use nGradientAlphaFill first add BGRABitmap and BGRABitmapTypes in the Uses section, then use the function:
 +
 +
<syntaxhighlight lang=pascal>
 +
var
 +
  myBitmap: TBGRABitmap;
 +
  AGradInfo: array [0..1] of TnGradientInfo;
 +
begin
 +
  AGradInfo[0].Direction:=gdVertical;
 +
  AGradInfo[0].endPercent:=0.50;
 +
  AGradInfo[0].StartColor:=BGRA(0,0,0,200);
 +
  AGradInfo[0].StopColor:=BGRA(255,255,255,100);
 +
 +
  AGradInfo[1].Direction:=gdVertical;
 +
  AGradInfo[1].endPercent:=1.00;
 +
  AGradInfo[1].StartColor:=BGRA(0,0,0,100);
 +
  AGradInfo[1].StopColor:=BGRA(255,255,255,50);
 +
 +
  myBitmap:= nGradientAlphaFill(Self.ClientRect,gdVertical,Agradinfo);
 +
  Self.Canvas.Draw(0,0,myBitmap.Bitmap);
 +
  myBitmap.Free;
 +
end;</syntaxhighlight>
 +
 +
=== Editor ===
 +
 +
nGradient Editor is an updated version of Double Gradient Editor with a lot of changes and improvements, like the ability to create gradients with 'n' number of gradients.
 +
 +
With nGradient Editor you can use 'n' (number) of gradients.
 +
 +
[[Image:ngedit.png]]
 +
 +
[http://www.multiupload.com/Z5CEFYE5CO nGradient Editor 1.1 (With alpha support) Source Code] ngdedit1.1alpha.zip (22.58 KB) / [http://lazarus.freepascal.org/index.php?action=dlattach;topic=12145.0;attach=1641 forum attach]
 +
 +
'''Note:''' This editor doesn't use BGRABitmap, this uses their own Alpha procedures.
 +
 +
[http://www.multiupload.com/SJDCG5P21Z nGradient Editor 1.1 Source Code] ngdedit1.1.zip (26.14 KB) / [http://lazarus.freepascal.org/index.php?action=dlattach;topic=12145.0;attach=1636 forum attach]

Latest revision as of 07:50, 14 February 2020

Deutsch (de) English (en)

Now 'DoubleGradientAlphaFill' & 'nGradientAlphaFill' are included in BGRABitmap in the unit 'BGRAGradients'.

Double Gradient

sampledoublegd.png

Unit

DoubleGradient

unit doublegradient;

{$mode objfpc}{$H+}

interface

uses
  Classes, Graphics;

function DoubleGradientFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TColor;
  ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBitmap;

implementation

function DoubleGradientFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TColor;
  ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBitmap;
var
  ABitmap: TBitmap; ARect1,ARect2: TRect;
begin
  ABitmap := TBitmap.Create;
  ABitmap.Width:=ARect.Right;
  ABitmap.Height:=ARect.Bottom;
  if AValue <> 0 then ARect1:=ARect;
  if AValue <> 1 then ARect2:=ARect;
  if APos = gdVertical then begin
    ARect1.Bottom:=Round(ARect1.Bottom * AValue);
    ARect2.Top:=ARect1.Bottom;
  end
  else if APos = gdHorizontal then begin
    ARect1.Right:=Round(ARect1.Right * AValue);
    ARect2.Left:=ARect1.Right;
  end;
  if AValue <> 0 then ABitmap.Canvas.GradientFill(ARect1,AStart1,AStop1,ADirection1);
  if AValue <> 1 then ABitmap.Canvas.GradientFill(ARect2,AStart2,AStop2,ADirection2);
  Result:=ABitmap;
end;

end.

DoubleGradientAlpha

This requires BGRABitmap.

unit doublegradientalpha;

{$mode objfpc}{$H+}

interface

uses
  Classes, Graphics,
  BGRABitmap, BGRABitmapTypes;

function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
  ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBGRABitmap;

implementation

function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
  ADirection1,ADirection2,APos: TGradientDirection; AValue: Single): TBGRABitmap;
var
  ABitmap: TBGRABitmap; ARect1,ARect2: TRect; APoint1,APoint2,APoint3,APoint4: TPointF;
begin
  ABitmap := TBGRABitmap.Create(ARect.Right,ARect.Bottom);
  if AValue <> 0 then ARect1:=ARect;
  if AValue <> 1 then ARect2:=ARect;
  if APos = gdVertical then begin
    ARect1.Bottom:=Round(ARect1.Bottom * AValue);
    ARect2.Top:=ARect1.Bottom;
  end
  else if APos = gdHorizontal then begin
    ARect1.Right:=Round(ARect1.Right * AValue);
    ARect2.Left:=ARect1.Right;
  end;
  if ADirection1 = gdVertical then begin
    APoint1:=PointF(ARect1.Left,ARect1.Top);
    APoint2:=PointF(ARect1.Left,ARect1.Bottom);
  end
  else if ADirection1 = gdHorizontal then begin
    APoint1:=PointF(ARect1.Left,ARect1.Top);
    APoint2:=PointF(ARect1.Right,ARect1.Top);
  end;
  if ADirection2 = gdVertical then begin
    APoint3:=PointF(ARect2.Left,ARect2.Top);
    APoint4:=PointF(ARect2.Left,ARect2.Bottom);
  end
  else if ADirection2 = gdHorizontal then begin
    APoint3:=PointF(ARect2.Left,ARect2.Top);
    APoint4:=PointF(ARect2.Right,ARect2.Top);
  end;
  if AValue <> 0 then
  ABitmap.GradientFill(ARect1.Left,ARect1.Top,ARect1.Right,ARect1.Bottom,
  AStart1,AStop1,gtLinear,APoint1,APoint2,dmDrawWithTransparency,True,False);
  if AValue <> 1 then
  ABitmap.GradientFill( ARect2.Left,ARect2.Top,ARect2.Right,ARect2.Bottom,
  AStart2,AStop2,gtLinear,APoint3,APoint4,dmDrawWithTransparency,True,False);
  Result:=ABitmap;
end;

end.

Usage

First you must have a 'TBitmap' to store the gradient, then you can draw the image, for example, in all the 'Form1' visible area:

defaultdbgd.png

This is the result (using DoubleGradientFill).

procedure TForm1.FormPaint(Sender: TObject);
var
  ABitmap: TBitmap;
begin
  ABitmap:=DoubleGradientFill(Self.ClientRect,clMedGray,clWhite,clSilver,clGray,gdVertical,gdVertical,gdVertical,0.50);
  Self.Canvas.Draw(0,0,ABitmap);
  ABitmap.Free
end;

If you use DoubleGradientAlphaFill first add BGRABitmap and BGRABitmapTypes in the Uses section, then use the function:

var
  myBitmap: TBGRABitmap;
begin
  myBitmap:= DoubleGradientAlphaFill(
  Self.ClientRect,
  BGRA(0,0,0,10),BGRA(255,255,255,100),
  BGRA(100,100,100,255),BGRA(150,150,150,10),
  gdVertical,gdVertical,gdVertical,0.5);
  Self.Canvas.Draw(0,0,myBitmap.Bitmap);
  myBitmap.Free;
end;

Editor

You can use the 'Double Gradient Editor' that is a GUI to instantly see the result (only for double gradients), save to a bitmap file, save to '*.doublegradient' session file or just copy code to clipboard to use in lazarus.

dbgedit.png

  • To access the menu right click the ScrollBox (gradient area):
    • Save bitmap.. Show a dialog to save as a *.bmp file.
    • Load gradient.. Show a dialog to load a *.doublegradient session file.
    • Save gradient.. Show a dialog to save the current session settings to a file.
    • Copy code to clipboard.. Just copy the settings as text in the clipboard, then you can use it to paste in lazarus source editor to call the doublegradientfill procedure.
  • default.doublegradient: this file has the last settings in the editor, is loaded at startup, saved when you close the application.

Double Gradient Editor 1.0 Source Code dbgdedit1.0.zip (5.64 KB)

You are free to edit and improve this editor, this is free of charge.

nGradient

With this unit 'ngradient' you can easily make gradients for toolbars, buttons, etc. Save the below code in a text file 'ngradient.pas' and add 'ngradient' in the 'uses' section of your project.

Unit

nGradientFill

Copy the code and save to a text file 'ngradient.pas':

unit ngradient;

{$mode objfpc}{$H+}

interface

uses
  Classes, Graphics;

type
  TnGradientInfo = record
    StartColor,StopColor:TColor;
    Direction: TGradientDirection;
    endPercent:single; // This is not the percent of the width, this is the percent of the end of the rect- which means, if this value is 1 - the rect could be from 0.99 to 1 and needs not be from 0 to 1
  end;

function nGradientFill(ARect: TRect;APos: TGradientDirection; AGradient: array of TnGradientInfo): TBitmap;

implementation

function nGradientFill(ARect: TRect;APos: TGradientDirection; AGradient: array of TnGradientInfo): TBitmap;
var
  i:integer;
  AnRect,OldRect: TRect;
begin
  Result := TBitmap.Create;
  Result.Width:=ARect.Right-ARect.Left;
  Result.Height:=ARect.Bottom-ARect.Top;
  OldRect := ARect;
  if APos = gdVertical then OldRect.Bottom := ARect.Top
     else OldRect.Right := ARect.Left ;   // upside down...  in case of i = 0...

  for i := 0 to high(AGradient) do
      begin
      AnRect:=OldRect;
      if APos = gdVertical then
         begin
         AnRect.Bottom:=Round((ARect.Bottom-ARect.Top) * AGradient[i].endPercent + ARect.Top);
         AnRect.Top:=OldRect.Bottom;
         end
        else
         begin
         AnRect.Right:=Round((ARect.Right-ARect.Left) * AGradient[i].endPercent + ARect.Left);
         AnRect.Left:=OldRect.Right;
         end;

      Result.Canvas.GradientFill(AnRect,AGradient[i].StartColor,AGradient[i].StopColor,AGradient[i].Direction);
      OldRect := AnRect;
      end;
end;

nGradientAlphaFill

This requires BGRABitmap.

Copy the code and save to a text file 'ngradientalpha.pas':

unit ngradientalpha;

{$mode objfpc}{$H+}

interface

uses
  Classes, Graphics, BGRABitmap, BGRABitmapTypes;

type
  TnGradientInfo = record
    StartColor, StopColor : TBGRAPixel;
    Direction             : TGradientDirection;
    endPercent            : single;
  end;

function nGradientAlphaFill(ARect: TRect;APos: TGradientDirection;
  AGradient: array of TnGradientInfo): TBGRABitmap;

implementation

function nGradientAlphaFill(ARect: TRect;APos: TGradientDirection;
  AGradient: array of TnGradientInfo): TBGRABitmap;
var
  i:integer; AnRect, OldRect: TRect; Point1, Point2: TPointF;
begin
  Result := TBGRABitmap.Create(ARect.Right-ARect.Left,ARect.Bottom-ARect.Top);
  OldRect := ARect;
  if APos = gdVertical then OldRect.Bottom := ARect.Top else OldRect.Right := ARect.Left;
  for i := 0 to high(AGradient) do
  begin
    AnRect:=OldRect;
    if APos = gdVertical then begin
      AnRect.Bottom:=Round((ARect.Bottom-ARect.Top) * AGradient[i].endPercent + ARect.Top);
      AnRect.Top:=OldRect.Bottom;
      Point1:=PointF(AnRect.Left,AnRect.Top);
      Point2:=PointF(AnRect.Left,AnRect.Bottom);
    end
    else begin
     AnRect.Right:=Round((ARect.Right-ARect.Left) * AGradient[i].endPercent + ARect.Left);
     AnRect.Left:=OldRect.Right;
     Point1:=PointF(AnRect.Left,AnRect.Top);
     Point2:=PointF(AnRect.Right,AnRect.Top);
    end;
  Result.GradientFill(AnRect.Left,AnRect.Top,AnRect.Right,AnRect.Bottom,
  AGradient[i].StartColor,AGradient[i].StopColor,gtLinear,Point1,Point2,dmDrawWithTransparency,True,False);
  OldRect := AnRect;
  end;
end;

end.

Usage

If you use nGradientAlphaFill first add BGRABitmap and BGRABitmapTypes in the Uses section, then use the function:

var
   myBitmap: TBGRABitmap;
   AGradInfo: array [0..1] of TnGradientInfo;
begin
  AGradInfo[0].Direction:=gdVertical;
  AGradInfo[0].endPercent:=0.50;
  AGradInfo[0].StartColor:=BGRA(0,0,0,200);
  AGradInfo[0].StopColor:=BGRA(255,255,255,100);

  AGradInfo[1].Direction:=gdVertical;
  AGradInfo[1].endPercent:=1.00;
  AGradInfo[1].StartColor:=BGRA(0,0,0,100);
  AGradInfo[1].StopColor:=BGRA(255,255,255,50);

  myBitmap:= nGradientAlphaFill(Self.ClientRect,gdVertical,Agradinfo);
  Self.Canvas.Draw(0,0,myBitmap.Bitmap);
  myBitmap.Free;
end;

Editor

nGradient Editor is an updated version of Double Gradient Editor with a lot of changes and improvements, like the ability to create gradients with 'n' number of gradients.

With nGradient Editor you can use 'n' (number) of gradients.

ngedit.png

nGradient Editor 1.1 (With alpha support) Source Code ngdedit1.1alpha.zip (22.58 KB) / forum attach

Note: This editor doesn't use BGRABitmap, this uses their own Alpha procedures.

nGradient Editor 1.1 Source Code ngdedit1.1.zip (26.14 KB) / forum attach