Autor Beitrag
Logikmensch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 390

Win XP
Delphi 2007 Prof., XE2, XE5
BeitragVerfasst: Di 11.01.11 19:22 
Hallo liebe Forum-Leser!

Ich habe eine Routine geschrieben, die die Größe meiner Icon-Leisten anpasst. Die Icons werden als transparente Bitmaps mit 16x16 Pixeln in ImageListen gespeichert. Meine Routine dient dazu, eine ImageList-Komponente auf eine andere Größe zu skalieren, z.B. 32x32. Dazu kopiere ich die einzelnen Images in eine Bitmap (bmps) und skaliere diese dann in eine Ziel-Bitmap (bmpd) mit der gewünschten Ziel-Größe. Die Ziel-Bitmap wird dann in eine neue ImageListe über AddMasked hinzugefügt, wobei ich auch die Transparenz-Farbe des unteren linken Pixels mit übergebe. Soweit so gut. Funktioniert eigentlich ganz prima. Eigentlich....

Ich habe ein enormes Verständnisproblem der Funktionsweise von TImageList.GetBitmap. Offenbar geht mir beim Einlesen eines Images meiner Imagelist über GetBitmap dessen Transparenz verloren. Das Problem verschwindet, wenn ich vor GetBitmap(i,bmps) die Bitmap bmps über FillRect mit einer wohldefinierten Farbe fülle. Diese Farbe darf in keinem der Icons verwendet werden.
Ich habe im nachfolgenden Beispiel mal die Füllfarbe clYellow verwendet. Das ist aber für Icons ungeeignet, die gelb als Farbe enthalten. clNone und clBackground sind ebenfalls ungeeignet. Ich verstehe einfach nicht, warum GetBitmap nicht überdeckend malt. Warum ich überhaupt die Bitmap vorher mit einer Farbe füllen muss, ist mit schleierhaft...

Meine Frage ist: Wie kann ich mit GetBitmap ein beliebiges transparentes Image aus meiner Imageliste rausholen, ohne diese Bitmap vorher mit einer Farbe füllen zu müssen? Wie kriege ich GetBitmap dazu, dies überdeckend zu malen?

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
procedure ScaleImageList(il:TImageList; destwidth,destheight:integer); overload;
var
  newil:TImageList;
  i:integer;
  bmps,bmpd:TBitmap;
begin
  newil:=TImageList.Create(nil);
  try
    bmps:=TBitmap.Create;
    try
      bmps.SetSize(il.Width,il.Height);
      bmpd:=TBitmap.Create;
      try
        bmpd.SetSize(destwidth,destheight);
        newil.Width:=destwidth;
        newil.Height:=destheight;
        for i:=0 to il.Count-1 do begin
          //Übermalen des ganzen Bitmaps bmps mit einer Farbe:
          bmps.Canvas.Brush.Style:=bsSolid;
          bmps.Canvas.Brush.Color:=clYellow;
          bmps.Canvas.FillRect(rect(0,0,il.Width+1,il.Height+1));
          il.GetBitmap(i,bmps); //deckt nicht ab!!
          StretchBlt(bmpd.Canvas.Handle,0,0,destwidth,destheight,bmps.Canvas.Handle,
            0,0,il.Width,il.Height,SRCCOPY);
          newil.AddMasked(bmpd,bmpd.Canvas.Pixels[0,bmpd.height-1]);
        end{for}
        //Skalierte Icons in die Ausgangsbitmap umkopieren:
        il.Clear;
        il.Width:=destwidth;
        il.Height:=destheight;
        il.AddImages(newil);
      finally
        bmpd.Free;
      end{try}
    finally
      bmps.Free;
    end{try}
  finally
    newil.Free;
  end{try}
end;


Für Tipps, die ich auch gerne sofort ausprobiere, bin ich sehr dankbar!


Moderiert von user profile iconMartok: Topic aus VCL (Visual Component Library) verschoben am Di 11.01.2011 um 18:48

_________________
Es gibt keine Probleme - nur Lösungen!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 11.01.11 20:05 
Moin!

Das Grundproblem bei Bitmaps ist einfach, dass sie keine (echte) Transparenz beherrschen. :nixweiss: Deshalb wird ja in der ImageList ein Bitmap und ein MaskBitmap rumgeschleppt.

Ich habe da auch mal mit gekämpft (beim MyJongg glaub ich :gruebel:), da hab ich das irgendwie mit .GetIcon() gelöst. Müsste ich aber mal nachsehen gehen... :?

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Logikmensch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 390

Win XP
Delphi 2007 Prof., XE2, XE5
BeitragVerfasst: Di 11.01.11 21:20 
Hi Narses! Vielen Dank für Deinen Tipp. Das hat's gebracht.
Der tolle Nebeneffekt, wenn ich über ein TIcon-Object umkopiere: Ich brauche nicht einmal StretchBlt, weil das Icon offenbar automatisch skaliert wird. Und das Transparenzproblem ist auch gelöst. Ich werde natürlich nochmal kritisch testen, aber es sieht seeeehr gut aus. Vielen lieben Dank! :D

Der Quelltext ist folgendermaßen geändert:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
procedure ScaleImageList(il:TImageList; destwidth,destheight:integer); overload;
var
  newil:TImageList;
  i:integer;
  bmpd:TBitmap;
  icon:TIcon;
begin
  newil:=TImageList.Create(nil);
  try
    try
      bmpd:=TBitmap.Create;
      try
        bmpd.SetSize(destwidth,destheight);
        newil.Width:=destwidth;
        newil.Height:=destheight;
        for i:=0 to il.Count-1 do begin
          icon:=TIcon.Create;
          try
            il.GetIcon(i,icon);
            newil.addicon(icon);
          finally
            icon.Free;
          end;

        end{for}
        il.Clear;
        il.Width:=destwidth;
        il.Height:=destheight;
        il.AddImages(newil);
      finally
        bmpd.Free;
      end{try}
    finally
      bmps.Free;
    end{try}
  finally
    newil.Free;
  end{try}
end;

_________________
Es gibt keine Probleme - nur Lösungen!