![]() |
SpeedButton - kein Bild?
Mit folgender Prozedur möchte ich auf einem SpeedButton ein Bild,
aus einer Anwendung, Verknüpfung etc. (Icon) anzeigen lassen (ohne eine Icon/Bitmap-Datei speichern zu müssen).
Delphi-Quellcode:
Der SpeedButton bleibt aber bildlos.
procedure TForm1.Button1Click(Sender: TObject);
var IconIndex: Word; ImageHandle: HIcon; TmpBMP: TBitmap; TmpIcon : TIcon; begin if Edit1.Text <> '' then begin IconIndex := 0; ImageHandle := ExtractAssociatedIcon(hInstance, PChar(Edit1.Text), IconIndex); if LongInt(ImageHandle) <> 0 then begin TmpBMP := TBitmap.Create; TmpIcon := Icon.Create; TmpBMP.Width := Icon.Width; TmpBMP.Height := Icon.Height; try TmpIcon.Handle := ImageHandle; TmpBMP.Canvas.Draw(0, 0, TmpIcon); SpeedButton1.Glyph.Handle := LoadBitmap(hInstance, PChar(TmpBMP)); finally TmpBMP.Free; TmpIcon.Free; end; Memo1.Lines.Add('Icon gefunden'); end else Memo1.Lines.Add('kein Icon gefunden'); end; end; Zu dem Thema hab ich schon einiges im Forum gelesen, mittlerweile hab ich schon so viel rumprobiert dass ich den Wald vor lauter Bäume nicht mehr sehe ;-))). vllt. hat auch jemand eine bessere (resourenschonende) Variante im Petto Gruss MarLe |
Re: SpeedButton - kein Bild?
Du setzt die Größe des Bitmaps auf die Größe des Icons, obwohl das Icon noch leer ist.
Versuche mal:
Delphi-Quellcode:
Bin mir nicht sicher, ob es dann klappt - aber evtl. könnte das die Lösung sein :roll:
TmpBMP := TBitmap.Create;
TmpIcon := Icon.Create; try TmpIcon.Handle := ImageHandle; //erst zuweisen TmpBMP.Width := Icon.Width; //dann die Größe anpassen TmpBMP.Height := Icon.Height; TmpBMP.Canvas.Draw(0, 0, TmpIcon); //usw. |
Re: SpeedButton - kein Bild?
Hab's so probiert, hat aber am Problem nicht's geändert, trotzdem Danke.
|
Re: SpeedButton - kein Bild?
So, hab mal fix was gebastelt :coder:
Ist es das, was Du suchst?
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var ICO: TIcon; Large, Small: HIcon; begin ExtractIconEx(PChar(Edit1.Text), 0, Large, Small, 1); ICO := TIcon.Create; try ICO.Handle := Small; //oder Large, wenn du das große Symbol willst SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); finally ICO.Free; end; end |
Re: SpeedButton - kein Bild?
War bisher immer der Meinung ich müsste ein Bitmap zuweisen?!?.
Da ich mich nicht nur auf EXE/DLL beschränken will verwende ich ExtractAssociatedIcon. Sinnvoll ist auch noch jeweils das Bild zurückzusetzen ansonsten überlappen sich die Bilder bei mehrmaliger Zuweisung. Super funktioniert Danke - anbei leicht geänderte Code für andere "Unwissende"
Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
var ICO: TIcon; Large, Small: HIcon; IconIndex: Word; begin ICO := TIcon.Create; try IconIndex := 0; ICO.Handle := ExtractAssociatedIcon(hInstance, PChar(Edit1.Text), IconIndex); SpeedButton1.Glyph := nil; SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); finally ICO.Free; end; end; |
Re: SpeedButton - kein Bild?
Der Glyph eines SpeedButtons ist auch ein Bitmap.
Durch die Funktion Canvas.Draw kann allerdings jede beliebige Graphik auf den Glyph, also das Bitmap, gemalt werden - dies kann ein Icon, Bitmap, JPEG-Bild oder was auch immer sein. Dadurch wird auch die Zuweisung SpeedButton1.Glyph := nil; überflüssig, da das Bitmap mit Canvas.Draw komplett übermalt wird. Ein Überlappen kann nicht entstehen, da der Glyph - also das Bitmap - vorher auf die Größe des Icons gesetzt wurde. |
Re: SpeedButton - kein Bild?
Das kann ich jetzt so nicht bestätigen.
Ohne die Zeile
Delphi-Quellcode:
wird das letzte Bild über das erste gelegt, ich sehe also noch die Bildreste?!?
SpeedButton1.Glyph := nil;
|
Re: SpeedButton - kein Bild?
Zitat:
Gruß Neutral General |
Re: SpeedButton - kein Bild?
Ich würde Euch ja glauben, aber die Praxis zeigt mir noch Bildreste bei obigen Code?!?
|
Re: SpeedButton - kein Bild?
also ich kann sowieso kaum glauben, was ich hier sehe:
Delphi-Quellcode:
Man nillt einen Instanzenzeiger und greift dann darauf zu - halte ich für sehr gefährlich.
SpeedButton1.Glyph := nil;
SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); Lieber so:
Delphi-Quellcode:
Damit hat man definitiv ein neues Bild als Glyph erstellt, und es sollte auch keine Bildreste geben, sobald man einmal Invlaidate/Refresh/Repaint aufgerufen hat.
SpeedButton1.Glyph := nil;
SpeedButton1.Glyph := TBitmap.Create; SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); |
Re: SpeedButton - kein Bild?
Aha, kein Problem wenn das die sauberste Lösung darstellt.
|
Re: SpeedButton - kein Bild?
Tja, das kommt drauf an. Wenn bereits ein Bild da ist, muss man erstmal überlegen, ob es auch anderswo noch verwendet wird. Wenn nicht, kann man es ohne Probleme überschreiben. Man kann dann sowohl das nillen als auch das Neu-Erzeugen weglassen. Ansonsten sollte man es freigeben, damit es nicht als Speicherleiche rumtreibt.
|
Re: SpeedButton - kein Bild?
Du verwirrst mich jetzt wieder ein bisschen.
Muss ich nach dem Zuweisen des Bildes zusätzlich noch irgendwas unter finally freigeben??? Um das Bild generell wieder sauber loszuwerden reicht dann ein
Delphi-Quellcode:
SpeedButton1.Glyph := nil;
|
Re: SpeedButton - kein Bild?
Sauber freigeben kannst du mit:
Delphi-Quellcode:
Allerdings gibt es hier eine Exception, wenn dem Glyph noch kein Bitmap zugeordnet ist.
FreeAndNil(SpeedButton1.Glyph);
Außerdem sollte alles sauber freigegeben werden, wenn die Form - zu der der SpeedButton gehört - freigegeben wird, also wenn dein Programm beendet wird. Diese Lösung halte ich nicht für besonders gut:
Delphi-Quellcode:
Wenn noch Bildreste da sind, kannst du auch vorher einfach die Größe des Bitmaps auf 0 stellen, dann sollte nichts mehr vom alten Bild übrig sein:
SpeedButton1.Glyph := nil;
SpeedButton1.Glyph := TBitmap.Create; SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO);
Delphi-Quellcode:
SpeedButton1.Glyph.Width := 0;
SpeedButton1.Glyph.Height := 0; SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); |
Re: SpeedButton - kein Bild?
Zitat:
Zitat:
Noch eine Anmerkung zur Funktion ExtractAssociatedIcon: diese erwartet im zweiten Parameter einen Zeiger auf einen Zeichenpuffer. Sie liefert in diesem Puffer den vollständigen Pfad- und Dateinamen der ausführbaren Datei zurück, in dem das Icon gefunden wurde. Die Übergabe eines dynamischen Strings oder gar einer String-Eigenschaft (Edit1.Text) wird somit früher oder später zu Abstürzen führen. Richtiger wäre es, einen Puffer geeigneter Größe bereitzustellen, diesen mit dem gewünschten Dateinamen zu füllen und schließlich den Puffer an die Funktion zu übergeben:
Delphi-Quellcode:
Gruß Hawkeye
var
buf : array [0..max_path] of char; begin buf := 'yourfile.exe'; ExtractAssociatedIcon(hInstance, buf, IconIndex); end; |
Re: SpeedButton - kein Bild?
Zitat:
Weil SpeedButton1 ein Objekt ist und keine Variable. Aber mit:
Delphi-Quellcode:
sollte es klappen.
SpeedButton1.Glyph.Free;
Aber wie gesagt, viel Sinn macht das nicht, da der SpeedButton und somit auch Glyph zusammen mit der Form freigegeben wird. |
Re: SpeedButton - kein Bild?
Das ist nicht nur sinnlos, sondern führt auch beim nächsten Klick auf den Button zum Absturz der Applikation. Das Glyph-Objekt wurde vom SpeedButton erzeugt und darf auch nur von diesem freigegeben werden. Die Zuweisung
Delphi-Quellcode:
löscht nicht das Glyph-Objekt, sondern nur den Inhalt der Bitmap. Das Glyph-Objekt wird erst bei der Freigabe des Speedbuttons von diesem zerstört.
Speedbutton1.Glyph := NIL;
Gruß Hawkeye |
Re: SpeedButton - kein Bild?
Hab's jetzt wie folgt umgesetzt:
Delphi-Quellcode:
... und Bild wieder entfernen:
procedure TForm1.Button1Click(Sender: TObject);
var ICO: TIcon; Large, Small: HIcon; IconIndex: Word; buf: array[0..max_path] of char; begin ICO := TIcon.Create; try StrPCopy(buf, Edit1.Text); IconIndex := 0; ICO.Handle := ExtractAssociatedIcon(hInstance, buf, IconIndex); SpeedButton1.Glyph.Width := 0; SpeedButton1.Glyph.Height := 0; SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); //SpeedButton1.Refresh; finally ICO.Free; end; end;
Delphi-Quellcode:
Die Bildqualität ist teilweise aber ziehmlich mies (ist mir bei vorherigen Versuchen gar nicht so aufgefallen).
procedure TForm1.ButtonResetClick(Sender: TObject);
begin SpeedButton1.Glyph := nil; end; Kann man da noch was machen, die sollten eigentlich so ausschauen wie z.B. auf dem Desktop. |
Re: SpeedButton - kein Bild?
Ich glaub jetzt habe ich die Lösung:
Das mit der "miesen Bildqualität" liegt wohl am Alpha-Kanal der 32 Bit-Icons - das von dem alten Icon noch Reste übrig waren wenn ein neues drübergemalt wurde, liegt an der Transparenz der Icons. Da ein leeres Bitmap immer weiß ist, bleiben die Stellen wo eine Halbtransparenz beim Alpha-Kanal des Icons ist, beim Bitmap weiß. Lösung: Einfach das Bitmap vorher komplett in die Farbe der Form (clBtnFace) einfärben, so wird als transparente Farbe clBtnFace verwendet und nicht mehr weiß. Der Alpha-Kanal wird nun mit clBtnFace und nicht mehr in weiß dargestellt. Des Weiteren verschwindet durch das Einfärben in clBtnFace das alte Bitmap komplett und es bleiben keine Reste mehr. Somit wird die Zuweisung des Bitmaps auf NIL oder das Setzen der Größe des Bitmaps (Width und Height) auf 0 überflüssig. Außerdem kannst Du die nicht verwendeten Variablen Large, Small: HIcon; logischerweise weglassen. :wink: So sähe es dann aus:
Delphi-Quellcode:
... und Bild wieder entfernen:
procedure TForm1.Button1Click(Sender: TObject);
var ICO: TIcon; IconIndex: Word; buf: array[0..max_path] of Char; begin ICO := TIcon.Create; try StrPCopy(buf, Edit1.Text); IconIndex := 0; ICO.Handle := ExtractAssociatedIcon(hInstance, buf, IconIndex); SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.Canvas.Brush.Color := Color; //Farbe der Form SpeedButton1.Glyph.Canvas.FillRect(Rect(0, 0, SpeedButton1.Glyph.Width, SpeedButton1.Glyph.Height)); //Bitmap füllen SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); finally ICO.Free; end; end;
Delphi-Quellcode:
procedure TForm1.ButtonResetClick(Sender: TObject);
begin SpeedButton1.Glyph.Canvas.Brush.Color := Color; SpeedButton1.Glyph.Canvas.FillRect(Rect(0, 0, SpeedButton1.Glyph.Width, SpeedButton1.Glyph.Height)); end; |
Re: SpeedButton - kein Bild?
Die weißen Ränder sind jetzt weg, aber an der Bildqualität hat sich nicht's geändert.
z.B. wird das schwarze Verknüpfungssymbol von Windows grau dargestellt. Hab mal gegoogelt und den Artikel ![]() gefunden. Da steht u.a. das die ExtractAssociatedIcon-Funktion, wie gesagt, nur bedingt brauchbar ist und man besser auf die SHGetFileInfo-Funktion zurückgreifen sollte. |
Re: SpeedButton - kein Bild?
Auch hierfür gibt es eine Lösung:
Das Bitmap verwendet das untere linke Pixel als transparente Farbe. Bei einer Verknüpfung ist dieses Pixel schwarz, somit wird der schwarze Verknüpfungs-Pfeil transparent. Durch die Zeile
Delphi-Quellcode:
sollte das Problem allerdings behoben sein.
SpeedButton1.Glyph.TransparentColor := clNone;
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var ICO: TIcon; IconIndex: Word; buf: array[0..max_path] of Char; begin ICO := TIcon.Create; try StrPCopy(buf, Edit1.Text); IconIndex := 0; ICO.Handle := ExtractAssociatedIcon(hInstance, buf, IconIndex); SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.TransparentColor := clNone; SpeedButton1.Glyph.Canvas.Brush.Color := Color; SpeedButton1.Glyph.Canvas.FillRect(Rect(0, 0, SpeedButton1.Glyph.Width, SpeedButton1.Glyph.Height)); SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); finally ICO.Free; end; end; |
Re: SpeedButton - kein Bild?
... ja, so funktioniert's - Danke.
Der SpeedButton muss aber mindestens 36*36 Pixel haben um das Icon unterzubringen. Ich werde dennoch auch noch versuchen das gleiche mit SHGetFileInfo abbilden zu können, dann könnte man alternativ auch die kleineren Icons verwenden. Vielleicht hat's auch schon jemand umgesetzt. |
Re: SpeedButton - kein Bild?
Zitat:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var ICO: TIcon; SHFileInfo: TSHFileInfo; begin ICO := TIcon.Create; try FillChar(SHFileInfo, SizeOf(SHFileInfo), #0); SHGetFileInfo(PChar(Edit1.Text), 0, SHFileInfo, SizeOf(SHFileInfo), SHGFI_Icon or SHGFI_SmallIcon); //SHGFI_LargeIcon für die großen Symbole ICO.Handle := SHFileInfo.hIcon; SpeedButton1.Glyph.Width := ICO.Width; SpeedButton1.Glyph.Height := ICO.Height; SpeedButton1.Glyph.TransparentColor := clNone; SpeedButton1.Glyph.Canvas.Brush.Color := Color; SpeedButton1.Glyph.Canvas.FillRect(Rect(0, 0, SpeedButton1.Glyph.Width, SpeedButton1.Glyph.Height)); SpeedButton1.Glyph.Canvas.Draw(0, 0, ICO); finally ICO.Free; end; end; |
Re: SpeedButton - kein Bild?
... super, funzt auch.
Werde noch ein bisschen testen ob noch irgendwelche Macken auftauchen. Danke - Gruss MarLe |
Re: SpeedButton - kein Bild?
Wenn der SpeedButton kleiner ist als 36*36 Pixel
dann wird mit SHGFI_SmallIcon der SpeedButton total verhunzt?!? |
Re: SpeedButton - kein Bild?
Jaja, das leigt denke ich mal an der Umwandlung Icon -> Bitmap.
Kann es in Deinem Fall denn nicht eine ToolBar mit ToolButtons sein? Hier kannst Du mit einer ImageList arbeiten und das Icons kann direkt als Icons eingefügt werden. Da dürfte so ein Problem nicht auftauchen. Zu dem eigentlichen Problem: Habe mir gerade mit einem Trick beholfen - nicht die sauberste Lösung, aber es funktioniert: - Du weist dem SpeedButton schon zur Designzeit (also bevor Du kompilierst) im OI ein Bitmap zu, das die Abmessungen 16x16 Pixel hat. - In dem Quellcode streichst Du einfach diese beiden Zeilen:
Delphi-Quellcode:
Dann funktioniert's !
SpeedButton1.Glyph.Width := ICO.Width;
SpeedButton1.Glyph.Height := ICO.Height; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz