2013-10-22 7 views
5

Ich versuche, zur Laufzeit ein 32-Bit-Bitmap zu erstellen und zu malen und es dann zu einer ImageList hinzuzufügen. Die Bitmap hat Transparenz (Alpha-Kanal). Ich kann die Bitmap erstellen und ohne Probleme auf Canvas zeichnen, und sie zeichnet normalerweise mit Transparenz über jede andere Leinwand.Hinzufügen von 32-Bit-Bitmap zu ImageList

Das Problem ist, wenn ich es zu einer ImageList hinzufügen, scheint das Bild die Zeichnungen verlieren mit der Canvas-Eigenschaft der Bitmap gemacht.

Hier ist, wie ich die Bitmap starten:

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'); 

Wenn ich diese Bitmap auf jede Kontrolle Leinwand zeichnen, zieht normaly, mit dem Bild aus der Bildliste, das Rechteck mit abgerundeten Ecken und dem Text, mit transparentem Hintergrund (überall, wo nichts gemalt wurde, wird transparent; behält den Hintergrund, der schon da war). Das bedeutet, dass Form1.Canvas.Draw(0, 0, Bitmap); das Bitmap über das Form1 zeichnet und wenn dort ein anderes Bild vorhanden ist, wird es als Hintergrund beibehalten.

ABER, wenn ich diese Bitmap zu einer Bildliste hinzufügen, tritt ein seltsames Problem auf. Die Abbildungsliste hat es ColorDepth auf cd32bit gesetzt, und dann rufe ich:

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

Jetzt, Wenn ich versuche, das Bild von Imagelist zu ziehen mit:

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

Das einzige, was angezeigt wird, ist die Bild, das in Bitmap von der ImageList gezeichnet wurde, verschwindet das abgerundete Rechteck und der Text, der in dem Canvas gezeichnet wurde, verschwindet.

Was fehlt mir?

Antwort

5

Dies kann der Schaffung eines zusätzlichen Bitmap (Intrans), dessen alpha chanel auf 0 gesetzt
Intrans für ImageList.Add als Maske, um die Original-Bitmap als Bild verwendet, durchgeführt werden.
Das Beispiel sollte Ihre reflektieren.

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; 

Eine kürzere Version wäre

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; 
+1

Gut gemacht. Ich hatte die Maske vergessen. Ich füge immer Symbole zu Bildlisten hinzu, und ich erinnere mich jetzt, dass wenn ich die Symbole mache, es wichtig ist, eine Maske anzugeben. –

+0

Ehrfürchtig. Ich suchte nach einer Antwort für dieses Problem, Alter und konnte keine finden. Ihre Lösung funktioniert PERFEKT. Eine letzte Sache zu beachten ist, dass "BitmapImageList" in dem Beispiel ColorDepth auf Cd24Bit gesetzt sein muss. Vielen Dank. – Marcio