Autor Beitrag
DiBagger
Hält's aus hier
Beiträge: 9

Win XP prof. SP3

BeitragVerfasst: Fr 19.11.04 23:03 
Hallo,

in diesem Forum habe schon einige Tips zum Laden von Icons und Nutzung gefunden, aber zu folgendem Problem noch nichts:

Ich habe eine IconDatei mit einigen Symbolen (erstellt mit MicroAngelo). Diese haben Brutto 16x16 Pixel, Netto 14 Px breit, 12 Px hoch. Der nicht genutzte Bereich ist transparent gestellt.
Die Icons lade ich zur Laufzeit (ExtractIconEx()) und weise sie Bitmaps zu (über Bitmap.Canvas.Draw (0,0,Icon)), Bitmap.Transparent ist True.
Die geladenen Bitmaps werden in ListBoxen verwendet.

Mein Problem: alle Icons, die weiße Bereiche haben, werden mit anklicken der ListBox-Zeile (blauer Balken) auch blau. Aber nur die weißen Bereiche.
Warum ?
Ist weiß = transparent ?

Danke und Gruß
DiBagger

_________________
das Ganze ist nur halb so doppelt
.Chef
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Sa 20.11.04 11:42 
Meinst du ListBox oder ListView? Aber eigentlich egal, denn:
DiBagger hat folgendes geschrieben:
Ist weiß = transparent?
Ja. Bei Icons wird immer ein Eckpixel - links unten glaub ich - als Transparenzwert verwendet. Du solltest also deine überflüssigen Bereiche in einer ungenutzten Farbe darstellen.

Gruß,
Jörg

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
DiBagger Threadstarter
Hält's aus hier
Beiträge: 9

Win XP prof. SP3

BeitragVerfasst: So 21.11.04 13:43 
Hallo,

der Vorschlag, freie Bereiche mit einer ungenutzten Farbe zu belegen, wäre mir zu aufwändig. Außerdem nutze ich die Icons auch schon in anderen Progs.
Ich habe es nach einigen Versuchen geschafft, den Markierungsbalken zu Kürzen.
Dann störte mich, dass der Focusrahmen immer noch die volle Breite einnimmt. Nach weiteren Versuchen habe ich auch den auf die Breite des gekürzten Markierungsbalken gebracht.
Das Zeichnen des FocusRect ist eine XOR-Zeichnung. Ein 2. DrawFocusRect löscht den Rahmen wieder.
Ich zeichne am Schluss den Focusrahmen, der frei bleiben soll. Wird anschließend vom System der volle Rahmen gezeichnet, bleibt wegen XOR nur der kleine Rahmen übrig.
Jetzt bleibt das Icon frei und nur der Text wird markiert.
Die wichtigen Stellen habe ich mal als Source aufgelistet (Ich hoffe, ich werde jetzt nicht gesteinigt: da ich beruflich in C, C++ programmiere, mache ich das auch privat mit Borland C++. Ich habe versucht, den SourceCode in Pascal zu übersetzen, Fehler bitte ich zu entschuldigen):
ausblenden 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:
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin

  with (Control as TListBox) do
  begin
    if odSelected in State then
    begin
      Canvas.FillRect(Bounds(Rect.Left +<OffsetBisAnfangHighLight>,    // Offset setzt sich zusammen aus:
                             Rect.Top,                                 // Offset bis Icon + Breite Icon +
                             Rect.Width -<OffsetBisAnfangHighLight>,   // halber Abstand zwischen Icon und Text
                             Rect.Height()));
    end
    else
    begin
      Canvas.FillRect(Rect);
    end;
    Canvas.Draw(<OffsetBisIcon>, Rect.Top, Bitmap);
    Canvas.TextOut (<OffsetBisIcon> +<Iconbreite> +<Abstand bis Text>, Rect.Top +2,
                    ListBox.Items.Strings[Index]);
    if odFocused in State then
    begin
      Canvas.DrawFocusRect(Bounds(Rect.Left, Rect.Top, <OffsetBisAnfangHighLight>, Rect.Height()));
    end;
  end;

end;


Edit:
code optimiert, Erklärung zum Verkleinern des FocusRahmens ergänzt


Gruß DiBagger

_________________
das Ganze ist nur halb so doppelt
DiBagger Threadstarter
Hält's aus hier
Beiträge: 9

Win XP prof. SP3

BeitragVerfasst: Sa 27.11.04 12:05 
Hallo nochmal,

mit der oben beschriebenen Lösung war ich ganz zufrieden, bis ich mein Programm auf einem Rechner laufen lies, der keinen weißen Hintergrund hatte. Da waren sie wieder, diese weißen Quadrate um das Icon, das eigentlich transparent sein sollte.
Wieder Stunden gesucht, gelesen, probiert.

Jetzt funktionierts - weiße Flächen bleiben weiß, transparent bleibt transparent und wird nicht weiß dargestellt.

Im folgenden nochmal die wichtigen Zeilen, um beim Kopieren von Icon nach Bitmap transparente Flächen transparent zu lassen und nicht weiß zu färben (code wieder von C++ nach Delphi umgesetzt):

ausblenden 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:
var
  pSmall : PHICON;
  pLarge : PHICON;
  Icon   : TIcon;

begin
  Bitmap := TBitmap.Create(); 

  Icon := TIcon.Create;
  pSmall := AllocMem (2 *SizeOf (PHICON));
  pLarge := AllocMem (2 *SizeOf (PHICON));
  ExtractIconEx (<path/file>, 0, pLarge, pSmall, 2);  // ab [0] 2 Icon-Handle laden
  Icon.Handle := pSmall^;
  Bitmap.Width := 16;
  Bitmap.Height := 16;
  Bitmap.Canvas.Brush.Color := clWindow;        // diese Zeile brachte mit...
  Bitmap.Canvas.FillRect (Bounds(0,0,16,16));   // ...FillRect() den Erfolg
  Bitmap.Canvas.Draw (0,0,Icon);
  :
  :
  FreeMem (pSmall, 2 *SizeOf (PHICON));
  FreeMem (pLarge, 2 *SizeOf (PHICON));
  FreeAndNil (Icon);
end;


Gruß
DiBagger