[gelöst] Eine Grafik in eine andere einfügen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

[gelöst] Eine Grafik in eine andere einfügen

Beitrag von fliegermichl »

In meinem Programm gibt es verschiedene Speedbuttons.
Manchen dieser Speedbuttons sind bestimmte Eigenschaften zugeordnet.

Um das sichtbar zu machen, wollte ich oben rechts ein kleines Symbol auf dem Buttonglyph zeichnen.
In Delphi geht das auch.
In Lazarus nicht.
Angenommen, es sind zwei Speedbuttons ein größerer sb1 und ein kleinerer sb2 in dem Formular.
Wenn SetGlyph aufgerufen wird, soll das Glyph von sb2 oben rechts in der Ecke von sb1 eingezeichnet werden

Code: Alles auswählen

procedure SetGlyph;
var bmp1, bmp2 : TBitmap;
begin
  bmp1 := TBitmap.Create;
  bmp1.Assign(sb1.Glyph);
  bmp2 := TBitmap.Create;
  bmp2.Assign(sb2.Glyph);
  bmp1.Canvas.Draw(bmp1.Width - bmp2.Width, 0, bmp2);
  sb1.Glyph.Assign(bmp1);
  bmp1.Free;
  bmp2.Free;
 end;
Obiger Code wird ausgeführt aber ohne das etwas gezeichnet wird.
Wenn ich statt sb1.Glyph.Assign(bmp1), sb1.Glyph.Assign(bmp2) schreibe, dann hat der große Speedbutton die gleiche Grafik wie sb2.
Also scheint das bmp1.Canvas.Draw nicht zu funktionieren.
Wie gesagt, es erscheint keine Fehlermeldung, funktioniert aber nicht.

Jemand eine Idee?
Dateianhänge
sbgrafik.zip
(254.33 KiB) 48-mal heruntergeladen
Zuletzt geändert von fliegermichl am Do 6. Feb 2025, 13:26, insgesamt 3-mal geändert.

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Eine Grafik in eine andere einfügen

Beitrag von Jorg3000 »

Hallo!
Ich habe mich beim Umstieg von Delphi auf Lazarus mehrfach mit Bitmaps ohne Inhalt rumgeärgert.

Versuche es mal damit, nach den Assigns das Pixelformat zu setzen (nicht getestet)

Code: Alles auswählen

bmp1 := TBitmap.Create;
bmp1.Assign(sb1.Glyph);
bmp1.PixelFormat:=pf24bit;
bmp2 := TBitmap.Create;
bmp2.Assign(sb2.Glyph);
bmp2.PixelFormat:=pf24bit;
...
Falls das nichts bringt, evtl. folgendes ... (ebenfalls nicht getestet)

Code: Alles auswählen

bmp1 := TBitmap.Create;
bmp1.PixelFormat:=pf24bit;
bmp1.SetSize(sb1.Glyph.Width, sb1.Glyph.Height);
bmp1.Canvas.FillRect(0,0,sb1.Glyph.Width, sb1.Glyph.Height);    
bmp1.Assign(sb1.Glyph);

... und genauso für bmp2
Es liegt wohl daran, dass ein TBitmap in Lazarus kein DIB (Device Independent Bitmap) ist, sondern ein GDI-abhängiges Bitmap. Deshalb muss man das Canvas wohl erst "aktivieren" bevor es empfangsbereit ist. Aber nichts genaues weiß ich nicht.
Grüße, Jörg

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eine Grafik in eine andere einfügen

Beitrag von fliegermichl »

Jorg3000 hat geschrieben: Mi 5. Feb 2025, 15:42 ...
Versuche es mal damit, nach den Assigns das Pixelformat zu setzen (nicht getestet)
...
Hallo Jörg,

Version 1 macht das Glyph von sb1 schwarz, Version zwei macht gar nichts.
Ich hab jetzt auch mal statt TBitmap TPortableNetworkGraphic bzw. TJPegImage versucht. Immer das gleiche.

Das sollte doch eigentlich ein simples Problem sein. Ich finde aber keine Lösung dafür.

Gruß
Michael

Benutzeravatar
Ally
Beiträge: 283
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Eine Grafik in eine andere einfügen

Beitrag von Ally »

Hallo fliegermichl,

ich hätte da noch einen anderen Vorschlag und zwar die Verwendung einer ImageList.
Das macht das Ganze zum Einen ziemlich einfach und ermöglicht zum Anderen eine High-DPI-Anwendung.
Mit Glyph müsste man da, glaube ich, noch Einiges drumherum Programmieren.

Gruß Roland
Dateianhänge
BitBtnOvl.zip
(22.4 KiB) 69-mal heruntergeladen

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Eine Grafik in eine andere einfügen

Beitrag von Jorg3000 »

In einem Programm verwende ich folgende Procedure, die mit Canvas.CopyRect() arbeitet.
Vielleicht kannst du sie irgendwo einbauen. Ich habe gerade keine Zeit es selber in deinem Source zu testen.

Code: Alles auswählen

procedure copyToBitmap(SrcBmp, DstBmp: TBitmap; DestX,DestY: Integer);
var SrcRect, DstRect: TRect;
begin
  SrcRect.Left:=0;
  SrcRect.Top :=0;
  SrcRect.Right :=SrcBmp.Width;
  SrcRect.Bottom:=SrcBmp.Height;

  DstRect.Left:=DestX;
  DstRect.Top :=DestY;
  DstRect.Right :=DestX+SrcBmp.Width;
  DstRect.Bottom:=DestY+SrcBmp.Height;

  DstBmp.Canvas.CopyRect(DstRect,SrcBmp.Canvas,SrcRect);
end; 

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eine Grafik in eine andere einfügen

Beitrag von fliegermichl »

Ally hat geschrieben: Mi 5. Feb 2025, 16:29 Hallo fliegermichl,

ich hätte da noch einen anderen Vorschlag und zwar die Verwendung einer ImageList.
Das macht das Ganze zum Einen ziemlich einfach und ermöglicht zum Anderen eine High-DPI-Anwendung.
Mit Glyph müsste man da, glaube ich, noch Einiges drumherum Programmieren.

Gruß Roland
Hallo Roland,

ja das funktioniert zwar, aber ich müsste dann von jedem Button mehrere Versionen vorhalten.
Mir ist das schleierhaft.

Wenn ich statt bmp1.Canvas.Draw irgendwelche Canvas Zeichenoperationen (LineTo, Rectangle, FillRect etc.) durchführe, dann funktionieren die alle. Nur eben das Draw nicht.

Gruß
Michael

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eine Grafik in eine andere einfügen

Beitrag von fliegermichl »

Jorg3000 hat geschrieben: Mi 5. Feb 2025, 16:36 In einem Programm verwende ich folgende Procedure, die mit Canvas.CopyRect() arbeitet.
Vielleicht kannst du sie irgendwo einbauen. Ich habe gerade keine Zeit es selber in deinem Source zu testen.
Das bringt das gleiche Ergebnis wie Draw.

Ich hab jetzt mal folgendes probiert:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var bmp1, bmp2, bmp3 : TBitmap;
begin
  bmp1 := TBitmap.Create;
  bmp2 := TBitmap.Create;
  bmp3 := TBitmap.Create;
  bmp1.Assign(sb1.Glyph);
  bmp2.Assign(sb2.Glyph);
  bmp3.Width := bmp1.Width;
  bmp3.Height := bmp1.Height;
  bmp3.Canvas.Draw(0, 0, bmp1);
  bmp3.Canvas.Draw(bmp1.width-bmp2.width, 0, bmp2);
  sb1.Glyph.Assign(bmp3);
  bmp1.Free;
  bmp2.Free;
  bmp3.Free;
end;
Das erzeugt im Prinzip das gewünschte Ergebnis, nur ist da jetzt der Hintergrund schwarz.
Sehr mysteriös diese Grafikdinger.

Benutzeravatar
Ally
Beiträge: 283
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Eine Grafik in eine andere einfügen

Beitrag von Ally »

Hallo Michael,
aber ich müsste dann von jedem Button mehrere Versionen vorhalten
Also genau genommen zwei, Eine mit und Eine ohne Overlay. (Bei High-DPI naturgemäß natürlich mehr.)
Wenn es sich nicht gerade um hunderte von Buttons handelt, sollte das vom Ressourcenverbrauch nicht ins Gewicht fallen.
Und wenn es eine High-DPI-Anwendung werden soll, müsste man dafür sorgen das dann auch Glyph mit dem passenden Icon und Overlay gefüllt wird.

Gruß Roland

wennerer
Beiträge: 609
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Eine Grafik in eine andere einfügen

Beitrag von wennerer »

Hallo Michael,
ich denke das Problem kommt daher das der Speedbutton und das Glyph verschiedene Größen besitzen. Mein untenstehender Code funktioniert bei mir jedenfalls. Ob die Transparenz bei manchen Bitmaps doch nötig wird kann ich nicht einschätzen.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var bmp1, bmp2 : TBitmap;
begin
 try
  bmp1 := TBitmap.Create;
  bmp1.SetSize(sb1.Width,sb1.Height);
  //bmp1.Canvas.Brush.Color:= clWhite;
  //bmp1.Transparent:= true;
  //bmp1.TransparentColor:= clWhite;
  bmp1.Canvas.FillRect(0,0,sb1.Width,sb1.Height);
  bmp1.Canvas.Draw((sb1.width div 2)-(sb1.Glyph.Width div 2),(sb1.height div 2)-(sb1.Glyph.height div 2),sb1.Glyph);
  //bmp1.Assign(sb1.Glyph);


  bmp2 := TBitmap.Create;
  bmp2.SetSize(sb2.Width,sb2.Height);
  //bmp2.Canvas.Brush.Color:= clWhite;
  //bmp2.Transparent:= true;
  //bmp2.TransparentColor:= clWhite;
  bmp2.Canvas.FillRect(0,0,sb2.Width,sb2.Height);
  bmp2.Canvas.Draw((sb2.width div 2)-(sb2.Glyph.Width div 2),(sb2.height div 2)-(sb2.Glyph.height div 2),sb2.Glyph);
  //bmp2.Assign(sb2.Glyph);

  bmp1.Canvas.Draw(bmp1.Width - bmp2.Width, 0, bmp2);

  sb1.Glyph.Assign(bmp1);
 finally
  bmp1.Free;
  bmp2.Free;
  end;
end;
Viele Grüße
Bernd
Dateianhänge
sbgrafik.zip
(254.49 KiB) 66-mal heruntergeladen

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eine Grafik in eine andere einfügen

Beitrag von fliegermichl »

Hallo Bernd,

das hat mich auf eine Idee gebracht.
Ich lass jetzt beide Glyphs in einen MemoryStream schreiben und die Bitmaps daraus laden. Funktioniert "fast".

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var bmp1, bmp2, bmp3 : TBitmap;
    ms1, ms2 : TMemoryStream;
begin
  ms1 := TMemoryStream.Create;
  ms2 := TMemoryStream.Create;
  sb1.Glyph.SaveToStream(ms1);
  sb2.Glyph.SaveToStream(ms2);
  ms1.Position := 0;
  ms2.Position := 0;
  bmp1 := TBitmap.Create;
  bmp1.LoadFromStream(ms1);
  bmp2 := TBitmap.Create;
  bmp2.LoadFromStream(ms2);
  bmp3 := TBitmap.Create;
  bmp3.Width := bmp1.Width;
  bmp3.Height := bmp1.Height;
  bmp3.Canvas.Draw(0, 0, bmp1);
  bmp3.Canvas.Draw(bmp1.width-bmp2.width, 0, bmp2);
  sb1.Glyph.Assign(bmp3);
  bmp1.Free;
  bmp2.Free;
  bmp3.Free;
  ms1.Free;
  ms2.Free;
end;
Vorher:
vorher.png
vorher.png (89.72 KiB) 2706 mal betrachtet
Nachher:
nachher.png
nachher.png (74.06 KiB) 2706 mal betrachtet

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Eine Grafik in eine andere einfügen

Beitrag von Jorg3000 »

Moin!
Den schwarzen Hintergrund kriegst du weg, wenn du vorher aufrufst ...

Code: Alles auswählen

Bitmap.Canvas.Brush.Color:=clWhite;
Bitmap.Canvas.FillRect(0,0,Bitmap.Width,Bitmap.Height);

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eine Grafik in eine andere einfügen

Beitrag von fliegermichl »

Jorg3000 hat geschrieben: Do 6. Feb 2025, 08:36 Moin!
Den schwarzen Hintergrund kriegst du weg, wenn du vorher aufrufst ...

Code: Alles auswählen

Bitmap.Canvas.Brush.Color:=clWhite;
Bitmap.Canvas.FillRect(0,0,Bitmap.Width,Bitmap.Height);
Ja schon, aber was mache ich, wenn der Hintergrund des Glyphs nicht weiß ist. Sowas wie bmp1.Pixels[0,0] gibt es wohl nicht mehr. Und Scanline ist ein Pointer (auf was?).

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Eine Grafik in eine andere einfügen

Beitrag von Jorg3000 »

Ich glaube man kann beim Source-Bitmap .Transparent=false setzen, oder?
Die transparente Farbe wird aus der Farbe des linken unteren Pixels oder über TransparentColor festgelegt.
Habe gerade keine Zeit mehr, um es auszuprobieren.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eine Grafik in eine andere einfügen

Beitrag von fliegermichl »

Jorg3000 hat geschrieben: Do 6. Feb 2025, 08:53 Ich glaube man kann beim Source-Bitmap .Transparent=false setzen, oder?
Die transparente Farbe wird aus der Farbe des linken unteren Pixels oder über TransparentColor festgelegt.
Habe gerade keine Zeit mehr, um es auszuprobieren.
Transparent true oder false ändert nichts am Ergebnis.
Wie kann ich denn die Farbe des linken unteren Pixels ermitteln?

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Eine Grafik in eine andere einfügen

Beitrag von fliegermichl »

Hab grad rausgefunden, dass es Canvas.Pixels gibt.
Wenn ich vor dem Draw:

Code: Alles auswählen

  bmp3.TransparentColor := bmp1.Canvas.Pixels[0, bmp1.Height-1];
einfüge, dann schaut es aber so aus. Auch nicht der Brüller.
nachher_transparentcolor.png
nachher_transparentcolor.png (73.92 KiB) 2680 mal betrachtet

Antworten