Delphi 如何在画布上同时绘制两个渐变?
请看我使用绘画程序制作的渐变图像示例: 它包含2个垂直渐变 从顶部到中间的第一个渐变是白色到浅色橙色的混合 从底部到中间的第二个渐变也是白色的混合色,但略暗的橙色 重点是使用了2种渐变,4种颜色,2种白色和2种橙色 我想在画布上做这个,但不知道怎么做。颜色可以是任何东西,以上只是一个例子Delphi 如何在画布上同时绘制两个渐变?,delphi,Delphi,请看我使用绘画程序制作的渐变图像示例: 它包含2个垂直渐变 从顶部到中间的第一个渐变是白色到浅色橙色的混合 从底部到中间的第二个渐变也是白色的混合色,但略暗的橙色 重点是使用了2种渐变,4种颜色,2种白色和2种橙色 我想在画布上做这个,但不知道怎么做。颜色可以是任何东西,以上只是一个例子 我该怎么做呢?我用普通的TCanvas编码 代码通过稳定增加颜色在画布上绘制渐变。例如,您可以通过向起始颜色或结束颜色添加权重(例如,增加白色部分)来调整 可以这样称呼: procedure TForm18.
我该怎么做呢?我用普通的TCanvas编码 代码通过稳定增加颜色在画布上绘制渐变。例如,您可以通过向起始颜色或结束颜色添加权重(例如,增加白色部分)来调整 可以这样称呼:
procedure TForm18.Button1Click(Sender: TObject);
const
white1: TColor = clWhite;
white2: TColor = $00CFCFCF;
color1: TColor = $000080FF;
color2: TColor = $00007AF4;
begin
// pb is a TPaintbox, but this works with any canvas
drawGradient(pb.Canvas, pb.Height, pb.Width, 0, white1, color1);
drawGradient(pb.Canvas, pb.Height, pb.Width, pb.Height div 2, color2, white2);
end;
结果如下所示:
procedure TForm18.Button1Click(Sender: TObject);
const
white1: TColor = clWhite;
white2: TColor = $00CFCFCF;
color1: TColor = $000080FF;
color2: TColor = $00007AF4;
begin
// pb is a TPaintbox, but this works with any canvas
drawGradient(pb.Canvas, pb.Height, pb.Width, 0, white1, color1);
drawGradient(pb.Canvas, pb.Height, pb.Width, pb.Height div 2, color2, white2);
end;
Delphi 2005及以上:
从抓斗装置中使用:
早期的Delphi版本: 从Msimg32.dll使用。将以下代码添加到全局实用程序单元:
type
PTriVertex = ^TTriVertex;
TTriVertex = record
X, Y: DWORD;
Red, Green, Blue, Alpha: WORD;
end;
function GradientFill(DC: HDC; Vertex: PTriVertex; NumVertex: ULONG;
Mesh: Pointer; NumMesh, Mode: ULONG): BOOL; stdcall; overload;
external msimg32 name 'GradientFill';
function GradientFill(DC: HDC; const ARect: TRect; StartColor,
EndColor: TColor; Vertical: Boolean): Boolean; overload;
const
Modes: array[Boolean] of ULONG = (GRADIENT_FILL_RECT_H, GRADIENT_FILL_RECT_V);
var
Vertices: array[0..1] of TTriVertex;
GRect: TGradientRect;
begin
Vertices[0].X := ARect.Left;
Vertices[0].Y := ARect.Top;
Vertices[0].Red := GetRValue(ColorToRGB(StartColor)) shl 8;
Vertices[0].Green := GetGValue(ColorToRGB(StartColor)) shl 8;
Vertices[0].Blue := GetBValue(ColorToRGB(StartColor)) shl 8;
Vertices[0].Alpha := 0;
Vertices[1].X := ARect.Right;
Vertices[1].Y := ARect.Bottom;
Vertices[1].Red := GetRValue(ColorToRGB(EndColor)) shl 8;
Vertices[1].Green := GetGValue(ColorToRGB(EndColor)) shl 8;
Vertices[1].Blue := GetBValue(ColorToRGB(EndColor)) shl 8;
Vertices[1].Alpha := 0;
GRect.UpperLeft := 0;
GRect.LowerRight := 1;
Result := GradientFill(DC, @Vertices, 2, @GRect, 1, Modes[Vertical]);
end;
现在,绘制代码变为:
procedure TForm1.FormPaint(Sender: TObject);
var
R: TRect;
begin
SetRect(R, 0, 0, ClientWidth, ClientHeight div 2);
GradientFill(Canvas.Handle, R, clWhite, $00056AFF, True);
SetRect(R, 0, ClientHeight div 2, ClientWidth, ClientHeight);
GradientFill(Canvas.Handle, R, $000055FF, clWhite, True);
end;
procedure TForm1.FormResize(Sender: TObject);
begin
Invalidate;
end;
我喜欢在TCanvas上使用类助手,因此我修改了另一个答案中的代码
type
TTriVertex = record
public
type
P = ^TTriVertex;
public
X, Y: DWORD;
Red, Green, Blue, Alpha: WORD;
constructor Create(APoint: TPoint; AColor: TColor; AAlpha: Word = 0);
end;
TTriVertexRect = record
public
TopLeft: TTriVertex;
LowerRight: TTriVertex;
constructor Create(ARect: TRect; Color1,Color2; AAlpha1: Word = 0; AAlpha2: Word = 0);
end;
{Enumerate the constants so they will show up on alt space in the IDE}
TGradientFillType = (
gftRectH = GRADIENT_FILL_RECT_H
,gftRectV = GRADIENT_FILL_RECT_V
,gftTriangle = GRADIENT_FILL_TRIANGLE);
TCavas_Helper = class helper for TCanvas
public
function GradientFill(const Vertexes: array of TTriVertexRect; FillType: TGradientFillType): Boolean; overload;
end;
{ TTriVertex }
constructor TTriVertex.Create(APoint: TPoint; AColor: TColor; AAlpha: Word = 0);
begin
X := APoint.X;
Y := APoint.Y;
Red := GetRValue(ColorToRGB(AColor)) SHL 8;
Green := GetGValue(ColorToRGB(AColor)) SHL 8;
Blue := GetBValue(ColorToRGB(AColor)) SHL 8;
Alpha := 0;
end;
{ TTriVertexRect }
constructor TTriVertexRect.Create(ARect: TRect; Color1, Color2: TColor; AAlpha1,
AAlpha2: Word);
begin
TopLeft.Create(ARect.TopLeft,Color1,AAlpha1);
LowerRight.Create(ARect.BottomRight,Color2,AAlpha2);
end;
{ TCavas_Helper }
function TCavas_Helper.GradientFill(const Vertexes: array of TTriVertexRect; FillType: TGradientFillType): Boolean;
var
GRect: array of TGradientRect;
Index: Integer;
begin
SetLength(GRect,Length(Vertexes));
for Index := 0 to Length(GRect) do begin
GRect[Index].UpperLeft := Index*2;
GRect[Index].LowerRight := Index*2 + 1;
end;
Result := WIndows.GradientFill(Handle,@Vertexes[0],Length(Vertexes)*2,@GRect[0],Length(GRect),Ord(FillType))
end;
所以实际的通话是这样的
procedure TForm56.FormPaint(Sender: TObject);
begin
Canvas.GradientFill([
TTriVertexRect.Create(Rect(0,0,ClientWidth,ClientHeight DIV 2),clWhite,$00056AFF)
,TTriVertexRect.Create(Rect(0,ClientHeight DIV 2,ClientWidth,ClientHeight),$00056AFF,clWhite)
],gftRectV);
end;
样本:
找到一个代码来制作双色渐变,并从顶部到橙色绘制一个,从橙色到白色绘制第二个?您使用哪种类型的画布?GDI+或Direct2D?@TLama这就是这种渐变双色的名称?@teran只是普通的TCanvas,如窗体或画框等,+1看起来非常好,谢谢Chris。我将尝试一下,可能还有一些关于代码等的问题要问。为了更好地理解,我添加了一些注释(并修复了一个错误,我在末尾使用了
pb.Width
,并用一个额外的参数替换)你能给我推荐一些关于图形的好文章吗。上面你贴的我仍然觉得很难理解,即使有评论。我需要先了解基本知识,然后才能理解您的解决方案是如何工作的:)老实说,我真的不知道有哪篇文章可以推荐。上面的代码基本上是一些相当简单的数学运算(它在每行的颜色值上添加一个固定的数字)。我相信你会发现一些使用谷歌的好文章(例如,看起来不错)已经有了GradientFill
的包装器。在GraphUtil.pas中
:。你可以用类似的方法,一个电话也只是一条线。但是,如果你可以自己编写代码,那么乐趣何在;-)@Chris这并不是因为我喜欢编写已经完成的代码,但是旧的Delphi版本没有这样的例程。如果WinAPI代码比手工编写的Delphi代码快一个数量级,我也不会感到惊讶。@TLama:我同意你的观点,修改后的答案会更好。如果他不想对梯度做任何修改,他应该使用这个答案。这看起来真的很平滑。我不想从你身上夺走荣誉,克里斯,因为你也做得很好,但如果这个方法更好,我会重新接受。谢谢你们两位提供的解决方案:)谢谢你们发布这个问题的答案!代码只回答堆栈溢出问题,因为没有上下文的代码转储无法解释解决方案的工作方式或原因,使原始海报(或任何未来读者)无法理解其背后的逻辑。请编辑您的问题,并对您的代码进行解释,以便其他人可以从您的答案中受益。此信息已在3年前的一篇帖子中发布(附有完整解释)。在完全没有解释和补充细节的情况下,简单地复制这些信息的目的是什么?
type
TTriVertex = record
public
type
P = ^TTriVertex;
public
X, Y: DWORD;
Red, Green, Blue, Alpha: WORD;
constructor Create(APoint: TPoint; AColor: TColor; AAlpha: Word = 0);
end;
TTriVertexRect = record
public
TopLeft: TTriVertex;
LowerRight: TTriVertex;
constructor Create(ARect: TRect; Color1,Color2; AAlpha1: Word = 0; AAlpha2: Word = 0);
end;
{Enumerate the constants so they will show up on alt space in the IDE}
TGradientFillType = (
gftRectH = GRADIENT_FILL_RECT_H
,gftRectV = GRADIENT_FILL_RECT_V
,gftTriangle = GRADIENT_FILL_TRIANGLE);
TCavas_Helper = class helper for TCanvas
public
function GradientFill(const Vertexes: array of TTriVertexRect; FillType: TGradientFillType): Boolean; overload;
end;
{ TTriVertex }
constructor TTriVertex.Create(APoint: TPoint; AColor: TColor; AAlpha: Word = 0);
begin
X := APoint.X;
Y := APoint.Y;
Red := GetRValue(ColorToRGB(AColor)) SHL 8;
Green := GetGValue(ColorToRGB(AColor)) SHL 8;
Blue := GetBValue(ColorToRGB(AColor)) SHL 8;
Alpha := 0;
end;
{ TTriVertexRect }
constructor TTriVertexRect.Create(ARect: TRect; Color1, Color2: TColor; AAlpha1,
AAlpha2: Word);
begin
TopLeft.Create(ARect.TopLeft,Color1,AAlpha1);
LowerRight.Create(ARect.BottomRight,Color2,AAlpha2);
end;
{ TCavas_Helper }
function TCavas_Helper.GradientFill(const Vertexes: array of TTriVertexRect; FillType: TGradientFillType): Boolean;
var
GRect: array of TGradientRect;
Index: Integer;
begin
SetLength(GRect,Length(Vertexes));
for Index := 0 to Length(GRect) do begin
GRect[Index].UpperLeft := Index*2;
GRect[Index].LowerRight := Index*2 + 1;
end;
Result := WIndows.GradientFill(Handle,@Vertexes[0],Length(Vertexes)*2,@GRect[0],Length(GRect),Ord(FillType))
end;
procedure TForm56.FormPaint(Sender: TObject);
begin
Canvas.GradientFill([
TTriVertexRect.Create(Rect(0,0,ClientWidth,ClientHeight DIV 2),clWhite,$00056AFF)
,TTriVertexRect.Create(Rect(0,ClientHeight DIV 2,ClientWidth,ClientHeight),$00056AFF,clWhite)
],gftRectV);
end;