给你个单元,绝对可以用,我目前编的程序就是用这个unit drawGradient;interface
    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Math;
   function SSDrawGradient(ACanvas: TCanvas; AClipRect: TRect;
   FromPoint, ToPoint: TPoint; FromColor, ToColor: TColor): Boolean;
implementationfunction SSDrawGradient(ACanvas: TCanvas; AClipRect: TRect;
  FromPoint, ToPoint: TPoint; FromColor, ToColor: TColor): Boolean;
type
  TSSGradientDirection=(gdEast, gdWest, gdNorth, gdSouth, gdOther);
var
  buf:TBitmap;
  w,h,y,x,XOffset,ir,ig,ib,pw,ph:Integer;
  c1, c2: TColor;
  r1,g1,b1,r2,g2,b2,br,bg,bb,rmax,rmin,gmax,gmin,bmax,bmin: Byte;
  kx,ky,kx0,ky0,rx0,gx0,bx0,r0,g0,b0,drx,dry,dgx,dgy,dbx,dby,dr,dg,db: Double;
  P : PByteArray;  function GetStep(V1, V2, V3:Integer): Double;
  begin
    if V2=V1 then Result:=0
    else Result:=V3/(V2-V1);
  end;begin
  Result:=False;
  if (FromPoint.Y=ToPoint.Y)and(FromPoint.X=ToPoint.X) then Exit;
  buf:=TBitmap.Create;
  try
    //初始化缓冲区
    buf.PixelFormat:=pf24bit;
    w:=AClipRect.Right -AClipRect.Left;
    buf.Width:=w;
    h:=AClipRect.Bottom -AClipRect.Top ;
    buf.Height:=h;
    //为了防止运算溢出而设的检查
    if (w>Screen.Width)or(h>Screen.Height) then Exit;    //读取渐变起点和终点的RGB值
    c1:=ColorToRGB(FromColor);
    c2:=ColorToRGB(ToColor);
    r1:=GetRValue(c1);
    g1:=GetGValue(c1);
    b1:=GetBValue(c1);
    r2:=GetRValue(c2);
    g2:=GetGValue(c2);
    b2:=GetBValue(c2);
    if r1>r2 then begin rmin:=r2; rmax:=r1 end
    else begin rmin:=r1; rmax:=r2 end;
    if g1>g2 then begin gmin:=g2; gmax:=g1 end
    else begin gmin:=g1; gmax:=g2 end;
    if b1>b2 then begin bmin:=b2; bmax:=b1 end
    else begin bmin:=b1; bmax:=b2 end;
    pw:=Abs(ToPoint.X-FromPoint.X);
    ph:=Abs(ToPoint.Y-FromPoint.Y);
    kx:=pw/Sqrt(ph*ph+pw*pw);
    ky:=ph/Sqrt(ph*ph+pw*pw);
    
    //计算出RGB值相对于XY轴的线性变化系数
    drx:=GetStep(AClipRect.Left, AClipRect.Right, Round((r2-r1)*kx));
    dry:=GetStep(AClipRect.Top, AClipRect.Bottom, Round((r2-r1)*ky));
    dgx:=GetStep(AClipRect.Left, AClipRect.Right, Round((g2-g1)*kx));
    dgy:=GetStep(AClipRect.Top, AClipRect.Bottom, Round((g2-g1)*ky));
    dbx:=GetStep(AClipRect.Left, AClipRect.Right, Round((b2-b1)*kx));
    dby:=GetStep(AClipRect.Top, AClipRect.Bottom, Round((b2-b1)*ky));    //计算出矩形左上角的RGB值,备用
    kx0:=GetStep(FromPoint.X, ToPoint.X, FromPoint.X);
    ky0:=GetStep(FromPoint.Y, ToPoint.Y, FromPoint.Y);
    r0:=r1+(kx0+ky0)*r2;
    g0:=g1+(kx0+ky0)*g2;
    b0:=b1+(kx0+ky0)*b2;    //这三个变量是每个扫描线的第一个点的RGB值
    rx0:=r0;
    gx0:=g0;
    bx0:=b0;
    for y:=0 to h-1 do
    begin
      XOffset:=0;
      //dr意思是Double类型的红色值,其他类推
      dr:=rx0;
      dg:=gx0;
      db:=bx0;
      P := buf.ScanLine[y];
      for x:=0 to w-1 do
      begin
        //ir的意思是整型的红色值,其他类推
        //之所以要先转成整型,是因为我觉得整型的比较也许会比浮点快一点
        //反正都要三次Round的,不如早做……
        ir:=Round(dr);
        ig:=Round(dg);
        ib:=Round(db);
        //br的意思是字节型的红色值
        br:=Max(Min(rmax,ir),rmin);
        bg:=Max(Min(gmax,ig),gmin);
        bb:=Max(Min(bmax,ib),bmin);
        //按照偏移量设置RGB值
        P[XOffset]:=bb;
        P[XOffset+1]:=bg;
        P[XOffset+2]:=br;        if FromPoint.X<>ToPoint.X then
        begin
          //下一个像素的RGB值分别按照一定的系数递增
          dr:=dr+drx;
          dg:=dg+dgx;
          db:=db+dbx;
        end;
        //因为我定义的P是字节型的数组,所以这里递增“3”,避免使用乘法
        Inc(XOffset, 3);
      end;
      if FromPoint.Y<>ToPoint.Y then
      begin
        //按照RGB在Y轴方向上的变化规律计算下一行的第一个像素RGB值
        rx0:=rx0+dry;
        gx0:=gx0+dgy;
        bx0:=bx0+dby;
      end;
    end;
    //将缓冲区复制到目标上
    BitBlt(ACanvas.Handle, AClipRect.Left, AClipRect.Top, w, h,
      buf.Canvas.Handle, 0, 0, SRCCOPY);
    Result:=True;
  finally
    buf.Free;
  end;
end;
end.

解决方案 »

  1.   

    不觉得楼上的太复杂了吗?我给你讲个道理,你自己就可以做了:
    1 取得起点颜色RGB1(就是TColor),和终点颜色RGB2;
    2 将起点颜色分解成R,G,B:
      GetRValue(RGB1),GetGValue(RGB1),GetBValue(RGB1); RGB2也一样
    3 计算每像素三种单色增加的幅度: deltaR:=(R2-R1)/Width
    4 讲递进后的单色合成RGB(R,G,B)然后画图
      for i:=0 to Width
        Line(0,0,i,Height,RGB(R,G,B))  //伪码
    其中 R=R1+i*deltaR
      简单吧?
      

  2.   

    先谢谢各位帮忙!特别是 yinmingke(黄豆汤) ,谢谢!
    我想各位应该见过Windows2000安装程序,瞧安装背景色,多平滑啊!
    我自己也曾做了画渐变色,但效果不理想,颜色有些突变..我的简要代码如下:=========================
    说明:
    在指定画布上指定区域内以startColor为开始色,endColor为结束色
    画过渡色。bFlag标志为横向或者纵向(尚未处理)
    procedure tform1.DrawRange(ACanvas: TCanvas; r:TRect;startColor, endColor: TColor;
      bFlag: boolean);
    var i,sR,sG,sB,eR,eG,eB:integer;
    const WIDTH=100;
    begin
        sR:=GetRValue(startColor);
        sG:=GetGValue(startColor);
        sB:=GetBValue(startColor);
        eR:=GetRValue(endColor);
        eG:=GetGValue(endColor);
        eB:=GetBValue(endColor);    for i:=0 to WIDTH do
        begin
            ACanvas.pen.color:=rgb(sR+(i*(eR-sR) div WIDTH),
                                   sG+(i*(eG-sG) div WIDTH),
                                   sB+(i*(eB-sB) div WIDTH));
            ACanvas.MoveTo(i,0);
            ACanvas.LineTo(i,30);
        end;
        
    end;
      

  3.   

    就是我说的现象!
    比如start=1;
    end=2;
    width=100;
    那就只有两种颜色所以肯定在中间的地方会出现突变,改变的方法是在你的30长的线上面加一些不同的颜色,比如在i=25的地方增加15个点2的颜色。你可以这样理解,你的方法每个颜色只在属于他的地方起作用,一旦超出了他起作用的范围她就突然不起作用了,这样造成了 突变。而好的方法是每个颜色在他应该起作用的点傍边一定范围内也渐变形的起一些作用,比如说颜色100应该在10到20的地方起作用,那么改进后在10到20的范围内100占的比重是100在9和21的地方占的比重是80在8和22的地方占比重60以此类推。
    最后可以得到在9的地方颜色100占比重80,颜色99占比重100,那么在9这个位置你应该每180个点中由100个99颜色的80个100颜色的,当然最好事均匀的随机分布的。这样一来你会发现他变成渐变得了。
    不知道我说明白了没有!