6

実行時に 32 ビット ビットマップを作成してペイントし、それを ImageList に追加しようとしています。ビットマップには透明度 (アルファ チャネル) があります。ビットマップを作成してそのキャンバスに問題なく描画できます。また、他のキャンバスの上に透明で正常に描画されます。

問題は、ImageList に追加すると、ビットマップの Canvas プロパティで作成された描画が失われるように見えることです。

ビットマップを開始する方法は次のとおりです。

Bitmap := TBitmap.Create;
Bitmap.PixelFormat := pf32bit;
Bitmap.Transparent := True;
Bitmap.AlphaFormat := afDefined;
SetBkMode(Bitmap.Canvas.Handle, TRANSPARENT);
Bitmap.SetSize(100, 42);

// now I can draw, let's say, an icon from an imagelist
ImageList.Draw(Bitmap.Canvas, 5, 5, 0, dsTransparent, itImage);

// and some other stuff
Bitmap.Canvas.RoundRect(0, 0, 99, 41, 5, 5);
Bitmap.Canvas.TextOut(50, 5, 'Test string');

このビットマップを任意のコントロール キャンバスに描画すると、イメージリストからのイメージ、角丸四角形、およびテキストが透明な背景で通常どおりに描画されます (何もペイントされていない場所はすべて透明になります。既に存在していた背景が保持されます)。 . これはForm1.Canvas.Draw(0, 0, Bitmap);、Form1 の上にビットマップを描画し、そこに他の画像があった場合は背景として保持されることを意味します。

しかし、このビットマップをイメージリストに追加すると、奇妙な問題が発生します。ImageList の ColorDepth が cd32bit に設定されているので、次のように呼び出します。

BitmapImageList.Width := Bitmap.Width;
BitmapImageList.Hieght := Bitmap.Height;
BitmapImageList.Add(Bitmap, nil);

今、私がイメージリストからそのイメージを描画しようとすると:

BitmapImageList.Draw(Form1.Canvas, 0, 0, 0);

表示される唯一のものは、ImageList から Bitmap で描画された画像、丸みを帯びた四角形、および Canvas で描画されたテキストが消えることです。

私は何が欠けていますか?

4

1 に答える 1

5

これは、アルファ チャネルが 0 に設定された追加のビットマップ (Intrans) を作成することで実行できます
。Intrans は ImageList に使用されます。マスクとして元のビットマップをイメージとして追加します。
例はあなたのものを反映する必要があります。

type
  pRGBQuadArray = ^TRGBQuadArray;
  TRGBQuadArray = ARRAY [0 .. 0] OF TRGBQuad;

Procedure GenIntransparentBitmap(bmp, Intrans: TBitmap);
var
  pscanLine32: pRGBQuadArray;
  i, j: Integer;
begin
  Intrans.Assign(bmp);
  for i := 0 to Intrans.Height - 1 do
  begin
    pscanLine32 := Intrans.Scanline[i];
    for j := 0 to Intrans.Width - 1 do
    begin
      pscanLine32[j].rgbReserved := 0;
    end;
  end;
end;

procedure TForm3.Button1Click(Sender: TObject);
var
  Bitmap, Intransp: TBitmap;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.PixelFormat := pf32bit;
    Bitmap.Transparent := true;
    Bitmap.AlphaFormat := afIgnored;
    SetBkMode(Bitmap.Canvas.Handle, BKMODE_LAST);
    Bitmap.SetSize(100, 42);

    ImageList1.Draw(Bitmap.Canvas, 5, 5, 0, dsTransparent, itImage);

    Bitmap.Canvas.Brush.Style := bsClear;
    Bitmap.Canvas.RoundRect(0, 0, 99, 41, 5, 5);
    Bitmap.Canvas.TextOut(50, 5, 'Test string');

    BitmapImageList.Width := Bitmap.Width;
    BitmapImageList.Height := Bitmap.Height;

    // Create intransparent bitmap from transparent bitmap
    Intransp := TBitmap.Create;
    try
      GenIntransparentBitmap(Bitmap, Intransp);
      // add intransparent bitmap as image and transparent bitmap as mask
      BitmapImageList.Add(Intransp, Bitmap);
    finally
      Intransp.Free;
    end;

    BitmapImageList.Draw(Canvas, 100, 100, 0);
  finally
    Bitmap.Free;
  end;
end;

短いバージョンは

Procedure GenIntransparentBitmap(bmp, Intrans: TBitmap);
begin
  Intrans.Assign(bmp);
  Intrans.PixelFormat := pf24bit;
end;

procedure TForm3.Button1Click(Sender: TObject);
var
  Bitmap, Intransp: TBitmap;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.PixelFormat := pf32bit;

    SetBkMode(Bitmap.Canvas.Handle, TRANSPARENT);
    Bitmap.SetSize(100, 42);

    ImageList1.Draw(Bitmap.Canvas, 5, 5, 0, dsTransparent, itImage);

    Bitmap.Canvas.Brush.Style := bsClear;
    Bitmap.Canvas.RoundRect(0, 0, 99, 41, 5, 5);
    Bitmap.Canvas.TextOut(50, 5, 'Test string');

    BitmapImageList.Width := Bitmap.Width;
    BitmapImageList.Height := Bitmap.Height;

    // Create intransparent bitmap from transparent bitmap
    Intransp := TBitmap.Create;
    try
      GenIntransparentBitmap(Bitmap, Intransp);
      // add intransparent bitmap as image and transparent bitmap as mask
      BitmapImageList.Add(Intransp, Bitmap);
    finally
      Intransp.Free;
    end;

    BitmapImageList.Draw(Canvas, 100, 100, 0);
  finally
    Bitmap.Free;
  end;
end;
于 2013-10-22T14:53:41.233 に答える