RT,做一个控件,可以背景透明和文字透明,背景透明已经搞好了,文字透明我是 建一张 32位的BITMAP,用GDI+调节ALPHA值来实现,但是把这张BITMAP画到画布上时,无法做透明处理,我已经设了透明色和透明为真,用 DrawImage画到画布上还是透明不了,不知道为什么。?
是不是要把它保存为BMP文件让后再画到画布上?如果是这样,那GDI+( TGpBitmap)如何保存为BMP文件?还有就是怎么将一张BMP图片以透明的方式画到画布上?

解决方案 »

  1.   

    如果实在做不出来的话,你可以动态创建LABEL控件,让它透明悬在图片上即可。
      

  2.   

    Label不是可以设置背景透明吗,用Label就没问题了
      

  3.   

    LABEL 不是有個: TransParent   嗎??
      

  4.   

    可以试试把文字做成窗体,用region
    窗体不是可以调透明度嘛。
      

  5.   

    文字可调透明度,调font的颜色  具体怎么算不清楚了
      

  6.   

    晕了,先看看题目吧.调FONT的颜色你觉得能达到透明的效果吗?最后也就是白色,跟透明是两回事
    另,哪位知道GDI+中的,SetColorKey 到底要怎么用?
    我把图片设置了透明度后,取它一个像素点的颜色,然后用
    lowcolor := RGB(p[3],p[3+1],p[3+2]);
    att.Setcolorkey(lowcolor,bkcolor);
    bkcolor 是开始时的颜色,lowcolor 是调整图片的透明度后的颜色,可是有些颜色值还是透明不了
    gd.drawimage(gpbmp,mygprect,0,0,gpbmp.widht,gpbmp.height,utpliex,attr);
      

  7.   

    不用bmp的图片,用png格式试试吧
      

  8.   

    var 
      BMP: TBitmap; procedure TForm1.Button1Click(Sender: TObject); 
    begin 
      if BMP=nil then BMP := TBitmap.Create; 
      BMP.LoadFromFile('c:\test.bmp'); 
      Image1.Picture.Bitmap := BMP; 
      Image1.Canvas.Brush.Style := bsClear; 
      Image1.Canvas.TextOut(50, 50, '楼主,你好'); 
    end; procedure TForm1.FormDestroy(Sender: TObject); 
    begin 
      if BMP <> nil then BMP.Free; 
    end;
    或:var
      BMP: TBitmap;procedure TForm1.Button1Click(Sender: TObject);
    var
      DC: HDC;
    begin
      if BMP=nil then BMP := TBitmap.Create;
      BMP.LoadFromFile('c:\test.bmp');
      Image1.Picture.Bitmap := BMP;
      DC := Image1.Canvas.Handle;
      SetBkMode(DC, TransParent);
      SetTextColor(DC, clRed);
      TextOut(DC, 50, 50, '你好,楼主,如果不行,你就用1楼所说的方法', 26);
      ReleaseDC(0, DC);
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
      if BMP<>nil then BMP.Free;
    end;
      

  9.   

    首先,你这个BITMAP是TBitmap还是TGPBitmap,如果是前者,是不行的,只能用TGPBitmap来处理
      

  10.   

    to mwy654321 :
    兄弟的做法只是在画布上输入背景透明的文字。和文字本身透明是两回事
    就是有没有什么方法,可以把一张32位的bmp 以某种颜色透明的方式画到画布上!!!!
     to Corn1 :
    现在 是用一个frame来写的呢,改起来工作量有点大,还有一个就是,文字做成窗体?不是很了解。能否说具体点?
      

  11.   

    GDI+处理这些事情是小儿科,肯定是楼主的代码有问题。
      

  12.   

    把一张32位的bmp 以某种颜色透明的方式画到画布上!!!! 32位的Bmp在GDI中是无法正确的画到画布上的。
    而且,32位的图本身就有了透明度,为什么还要用“以某种颜色透明“的方式呢。
      

  13.   

    楼主 既然你用了GDI+你还这么麻烦干嘛
    GDI+支持透明色 你先建一个透明刷子 再用这个刷子DrawString就行了呀
    GDI+颜色一般这样表示$ABGR,A表示Alpha值,RGB分别表示RGB值,例如$880000FF半透明红色$000000FF完全透明。
      

  14.   

    更正:GDI+颜色一般这样表示$ARGB,上面我搞反了
      

  15.   


    就是文字形状的窗体。窗体可以是任意形状的,包括方形、圆形、不规则形状,等等
    用region
      

  16.   

    好吧,我把代码写出来
    procedure DrawMoveText(AlphaValue,AlphaMode : integer;Color : TColor) ;
    //透明度,需要透明的模式 :0.背景,1.文字,颜色
    procedre pbmovepaint; //paintbox 的重画事件
    begin 
      DrawMoveText(50,0,BkColor);
      DrawMoveText(50,1,FontColor);
    end;procedure DrawMoveText(AlphaValue,AlphaMode : integer;Color : TColor) ;
      var Gd : TGpGraphics;
          GpBmp : TGpBitmap;
          Bmp : TBitmap;
          attr : TGpImageAttributes ;
    begin
      BMp := TBitmap.create;
      BMp.pixelFormat := fp32;
      with bmp do 
      begin
        width := pbMove.Width;
        height := pbmove.height;
        if AlphaMode = 0 then
        beign
          CanVas.Brush.Color := Color;
          canvas.FillRect(canvas.clientrect);
        end
        else begin
          CanVas.Brush.Color := Color;
          canvas.FillRect(canvas.clientrect);
          setbkmode(canvas.handle,1);
          settextcolor(Fontcolor);
          textout();//
        end;
        savetofile('tet.bmp');
      end;
      gpbmp := TGpbitmap.create('tet.bmp');
      //这里,我用 gpbmp := TGpbitmap.FormBitmap(bmp.handle,0); 无法正常调 alpha值,跟踪时发现和创建的指针值是一样的, 不知为什么
      gd := TGpgraphics.create(pbmove.canvas.handle);
      bd := Gpbmp.lockbits(); //可读可写,32位模式
      For i := 0 to bd.height -1 do 
      begin
        img := pbyte(bd.scan0);
        hd := pbyte(img) + i * bd.stride;
        for j := 0 to bd.width -1 do
        beign
         hd[j * 3 + 4] := char(AlphaValue);
        end;
      end;
      //调节透明度
      if AlphaMode  = 0 then
      beign
       gd.drawimage(gpbmp,r,0,0,gpbmp.width,gpbmp.height,utpixel);
      end
      else if AlphaMode  = 1 then //文字
      begin
       TEmpbmp := TBitmap.create;
       TEmpbmp.width := gpbmp.width;
       TEmpbmp.heigth := gpbmp.height;
       gd := TGpgraphics.create(TEmpbmp.canvas.handle);
       gd.drawimage(gpbmp,r,0,0,gpbmp.width,gpbmp.height,utpixel);
       
       attr := TGpImageAttributes.create;
       attr.setcolorkey(fbkcolor,TEmpbmp.canvas.pixels[0,0]);
       gd := TGpgraphics.create(pbmove.canvas.handle);
       gd.drawimage(gpbmp,r,0,0,gpbmp.width,gpbmp.height,utpixel,attr);
    .//如果颜色淡一些,可以透明地画到pbmove上,但是如果颜色深一些,就无法透明了
    .//释放操作
    .
    ..
      end;
    end;由于工作机不能上网,这些代码可能有些地方写错的....
      

  17.   

    to xzhifei 
    我的意思是这样的。建的位图是用背景色填充。再对这张图片调节透明度,但是无法把填充的颜色去掉,只留输出的文字,
      

  18.   

    function IntToByte(i: Integer): Byte;
    begin
      if i > 255 then
        Result := 255
      else if i < 0 then
        Result := 0
      else
        Result := i;
    end;procedure BmpAlphaBlend(var dBmp: TBitMap; sBmp: TBitmap; Pos: TPoint; Alpha: integer; TranColor: TColor = -1);
    type
      tagRGBTRIPLE = packed record
        rgbtBlue: Byte;
        rgbtGreen: Byte;
        rgbtRed: Byte;
      end;
      TRGBTriple = tagRGBTRIPLE;
      PRGBTripleArray = ^TRGBTripleArray;
      TRGBTripleArray = array[0..32767] of TRGBTriple;
      function GetSLColor(pRGB: TRGBTriple): TColor;
      begin
        Result := RGB(pRGB.rgbtRed, pRGB.rgbtGreen, pRGB.rgbtBlue);
      end;
    var
      p0, p1: PRGBTripleArray;
      r, g, b, p, x, y: Integer;
    begin
      sBmp.PixelFormat := pf24bit;
      dBmp.PixelFormat := pf24bit;
      if TranColor = -1 then
        TranColor := sBmp.Canvas.Pixels[0, 0];
      for y := 0 to sBmp.Height - 1 do
        if (y + Pos.y >= 0) and (y + Pos.Y < dBmp.Height) then
        begin
          p0 := dBmp.ScanLine[y + Pos.y];
          p1 := sBmp.ScanLine[y];
          for x := 0 to sBmp.Width - 1 do
            if (x + pos.X >= 0) and (x + Pos.X < dBmp.Width) then
              if GetSLCOlor(p1[x]) <> TranColor then
              begin
                p0[x + pos.X].rgbtRed := IntToByte((p0[x + pos.X].rgbtRed * (100 - Alpha) +
                  p1[x].rgbtRed * Alpha) div 100);            p0[x + pos.X].rgbtGreen := IntToByte((p0[x + pos.X].rgbtGreen * (100 - Alpha) +
                  p1[x].rgbtGreen * Alpha) div 100);            p0[x + pos.X].rgbtBlue := IntToByte((p0[x + pos.X].rgbtBlue * (100 - Alpha) +
                  p1[x].rgbtBlue * Alpha) div 100);
              end;
        end;end;procedure TForm1.Button1Click(Sender: TObject);
    var
      brBmp, srcBmp: TBitmap;
    begin
    //
      brBmp := TBitmap.Create;
      brBmp.LoadFromFile('c:\a.bmp');
      brBmp.PixelFormat := pf24bit;  srcBmp := TBitmap.Create;
      srcBmp.LoadFromFile('c:\b.bmp');
      srcBmp.PixelFormat := pf24bit;  BmpAlphaBlend(
        brBmp, //背景图(大图,也是结果图)
        srcBmp, //需要合成的小图
        Point(60, 60), //画小图的坐标
        100, //半透明度
        -1//需要透明的颜色(用于不规则图形,-1就表示以0,0位置的颜色为透明色)
        );  canvas.Draw(0, 0, brBmp);
      brBmp.Free;
      srcBmp.Free;
    end;以上代码是GDI方式的,半透明度0--100,自由设定
    你可以把字画到一个普通的Tbitmap上,然后再合成就搞定了,GDI+方式更简单一些
      

  19.   

    谢谢 xzhifei  兄弟,
    像素点逐点换算方法确实可行,不过有些点还是会粘有背景色,再琢磨一下
      

  20.   

    呆会结贴,谢谢所有热心人
    不过还是想知道为何gdi+ 里用 setcolorkey 无法达到透明,我的写法问题到底出在哪里???