Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi IconHandle von Icon Datei (https://www.delphipraxis.net/200497-iconhandle-von-icon-datei.html)

EWeiss 25. Apr 2019 20:17

IconHandle von Icon Datei
 
Meine Funktion..

Delphi-Quellcode:
function TSkinPopUpMenu.GetHIconFromFile(AFileName: PWideChar; ASmall: Boolean; AIndex: Integer)
  : HIcon;
var
  LDummy: HIcon;
  LInfo: TSHFileInfo;
begin
  Result := 0;

  If ExtractIconEx(AFileName, -1, Result, LDummy, 0) <> 0 then
  begin
    If ASmall then
      ExtractIconEx(AFileName, AIndex, LDummy, Result, 1)
    else
      ExtractIconEx(AFileName, AIndex, Result, LDummy, 1);
  end
  else
  begin
    SHGetFileInfo(PWideChar(ExtractFileExt(AFileName)), FILE_ATTRIBUTE_NORMAL, LInfo,
      SizeOf(LInfo), IfThen(ASmall, SHGFI_SMALLICON, SHGFI_LARGEICON)
      or SHGFI_ICON or SHGFI_LINKOVERLAY or SHGFI_USEFILEATTRIBUTES);
    Result := LInfo.HIcon;
  end;
end;
Aufruf..
Delphi-Quellcode:
  if ImageIconPath <> '' then
  begin
    FIcon[ButtonCount].ImageIcon := GetHIconFromFile(ImageIconPath, true);
    if (FIcon[ButtonCount].ImageIcon <> 0) then
      btnMenu[ButtonCount].ImageDrop(HButton, FIcon[ButtonCount], X, Y, W, H);
  end;
Freigeben..
Delphi-Quellcode:
  if ButtonCount > 0 then
  begin
    for IntI := 0 to ButtonCount - 1 do
    begin
      btnMenu[IntI].ImageDropRemove(btnMenu[IntI].Handle);
      btnMenu[IntI].DestroyWindow;
      btnMenu[IntI] := nil;
    end;
    SetLength(btnMenu, 0);
    SetLength(FIcon, 0);
    ButtonCount := 0;
  end;
Funktioniert soweit alles..
Aber!

Wenn ich das PopuMenu ca.. 30 > 40 mal hintereinander aufrufe dann schlägt das fehl.
Delphi-Quellcode:
If ExtractIconEx(AFileName, -1, Result, LDummy, 0) <> 0 then


und kracht dann in
Delphi-Quellcode:
Result := LInfo.HIcon;


Warum? Wenn doch alle Icon Handles freigegeben werden.
Delphi-Quellcode:
procedure TSkinPushButton.ImageDropRemove(WinHandle: HWND);
begin

  if ImgDrop <> 0 then
  begin
    DestroyIcon(ImgDrop);
    SkinEngine.SetImageProperty(WinHandle, PROP_IMAGE_DROP, 0);
  end;
end;
gruss

Dalai 25. Apr 2019 21:28

AW: IconHandle von Icon Datei
 
Du extrahierst zwei Icons pro Aufruf von ExtractIconEx, also musst du auch beide zerstören. Oder du castest so, dass nur ein Icon extrahiert wird:
Delphi-Quellcode:
ExtractIconEx(PChar(AFileName), AIndex, Result, HICON(nil^), 1);
Auch der Aufruf von ExtractIconEx(PChar(AFileName), -1, ...) könnte Icons extrahieren; die Doku zu MSDN-Library durchsuchenExtractIconEx ist da leider nicht präzise genug. Geht's dabei nur um Ermittlung der Anzahl der vorhandenen Icons, setze beide HIcon-Parameter auf NULL (siehe oben).

Grüße
Dalai

EWeiss 25. Apr 2019 21:36

AW: IconHandle von Icon Datei
 
Zitat:

Zitat von Dalai (Beitrag 1430985)
Du extrahierst zwei Icons pro Aufruf von ExtractIconEx, also musst du auch beide zerstören. Oder du castest so, dass nur ein Icon extrahiert wird:
Delphi-Quellcode:
ExtractIconEx(PChar(AFileName), AIndex, Result, HICON(nil^), 1);
Auch der Aufruf von ExtractIconEx(PChar(AFileName), -1, ...) könnte Icons extrahieren; die Doku zu MSDN-Library durchsuchenExtractIconEx ist da leider nicht präzise genug. Geht's dabei nur um Ermittlung der Anzahl der vorhandenen Icons, setze beide HIcon-Parameter auf NULL (siehe oben).

Grüße
Dalai

Ich kann jetzt nicht erkennen wo ich 2 Icons pro Aufruf extrahiere..
Du meinst das LDummy + Result?

ja ich sehe es gerade ;)
Danke.. kann mir dann das LDummy sparen..

Delphi-Quellcode:
function TSkinPopUpMenu.GetHIconFromFile(AFileName: PWideChar; ASmall: Boolean; AIndex: Integer)
  : HIcon;
var
  LInfo: TSHFileInfo;
begin
  Result := 0;

  If ExtractIconEx(AFileName, -1, Result, HICON(nil^), 0) <> 0 then // << denke das sollte so ausreichen
  begin
    If ASmall then
      ExtractIconEx(AFileName, AIndex, HICON(nil^), Result, 1)
    else
      ExtractIconEx(AFileName, AIndex, Result, HICON(nil^), 1);
  end
  else
  begin
    SHGetFileInfo(PWideChar(ExtractFileExt(AFileName)), FILE_ATTRIBUTE_NORMAL, LInfo,
      SizeOf(LInfo), IfThen(ASmall, SHGFI_SMALLICON, SHGFI_LARGEICON)
      or SHGFI_ICON or SHGFI_LINKOVERLAY or SHGFI_USEFILEATTRIBUTES);
    Result := LInfo.HIcon;
  end;
end;

Habe das PopupMenu jetzt 100 mal geöffnet und geschlossen scheint zu funktionieren.. ;)
Na ja wer macht das schon bei normaler Bedienung.

gruss

Dalai 25. Apr 2019 23:25

AW: IconHandle von Icon Datei
 
Zitat:

Zitat von EWeiss (Beitrag 1430986)
Du meinst das LDummy + Result?

Jep, genau das.

Zitat:

Delphi-Quellcode:
function TSkinPopUpMenu.GetHIconFromFile(AFileName: PWideChar; ASmall: Boolean; AIndex: Integer)
  : HIcon;
var
  LInfo: TSHFileInfo;
begin
  Result := 0;

  If ExtractIconEx(AFileName, -1, Result, HICON(nil^), 0) <> 0 then // << denke das sollte so ausreichen
  begin
    If ASmall then
      ExtractIconEx(AFileName, AIndex, HICON(nil^), Result, 1)
    else
      ExtractIconEx(AFileName, AIndex, Result, HICON(nil^), 1);
  end
  else
  begin
    SHGetFileInfo(PWideChar(ExtractFileExt(AFileName)), FILE_ATTRIBUTE_NORMAL, LInfo,
      SizeOf(LInfo), IfThen(ASmall, SHGFI_SMALLICON, SHGFI_LARGEICON)
      or SHGFI_ICON or SHGFI_LINKOVERLAY or SHGFI_USEFILEATTRIBUTES);
    Result := LInfo.HIcon;
  end;
end;

Geht's denn beim ersten Aufruf von ExtractIconEx um die Ermittlung der Anzahl von Icons? Dann solltest du keinen Parameter für ein HICON übergeben.

Vielleicht kann eine Untersuchung auf Speicherlecks nicht schaden, mit einer Software, die auch Windows Handles mit untersucht; leider weiß ich nicht, was es da gibt, was für aktuellere/neuere Delphis taugt. FastMM bzw. ReportMemoryLeaksOnShutdown meldet nicht freigegebene Icons eben nicht, wie ich selber schon in einem ähnlichen Zusammenhang festgestellt habe.

Grüße
Dalai

EWeiss 25. Apr 2019 23:33

AW: IconHandle von Icon Datei
 
Zitat:

Geht's denn beim ersten Aufruf von ExtractIconEx um die Ermittlung der Anzahl von Icons? Dann solltest du keinen Parameter für ein HICON übergeben.
Nein.. Es wird ein Icon für das Menu übergeben.. diese sind unterschiedlich.. hänge gleich mal einen Shot an.
Sorry ja dann dürfte das ausreichen oder?
Delphi-Quellcode:
If ExtractIconEx(AFileName, -1, HICON(nil^), HICON(nil^), 0) <> 0 then


Zitat:

ReportMemoryLeaksOnShutdown meldet nicht freigegebene Icons eben nicht, wie ich selber schon in einem ähnlichen Zusammenhang festgestellt habe.
Ja das war mein Problem habe nicht bedacht das ich so wie du bemerkt hast 2 Icons extrahiere.
Aber! Seltsam ist das schon denn die Icons liegen nur im Format 16x16 vor direkt von einem Icon File nicht aus einer EXE-Datei!
Habe auch im Taskmanager nicht feststellen können das sich der Speicher erhöht der blieb immer konstant.

Also das LDummy hätte eigentlich gar kein Icon ausgeben dürfen.
Weil kein Large Icon in der Icon Datei existiert.

Diese Icons werden addiert + die Icons für die Pfeile.
Danke nochmal für deine Hilfe.

Wenn ein Icon übergeben wird, wird dieses als Overlay auf den Button gezeichnet.
Delphi-Quellcode:
  if ImageIconPath <> '' then
   begin
     FIcon[ButtonCount].ImageIcon := GetHIconFromFile(ImageIconPath, true);
     if (FIcon[ButtonCount].ImageIcon <> 0) then
       btnMenu[ButtonCount].ImageDrop(HButton, FIcon[ButtonCount], X, Y, W, H);
   end;
und später mit
Delphi-Quellcode:
btnMenu[IntI].ImageDropRemove(btnMenu[IntI].Handle);


gelöscht..

gruss

Dalai 26. Apr 2019 00:06

AW: IconHandle von Icon Datei
 
Zitat:

Zitat von EWeiss (Beitrag 1430990)
Nein.. Es wird ein Icon für das Menu übergeben.. diese sind unterschiedlich.. hänge gleich mal einen Shot an.

Die Intention der Funktion GetHIcon insgesamt ist mir schon klar. Es ging mir nur um den darin enthaltenen Aufruf
Delphi-Quellcode:
if ExtractIconEx(..., -1, ...) <> 0
. Das eigentliche Extrahieren der Icons erfolgt ja erst danach in einem weiteren Aufruf von ExtractIconEx (sofern der erste Aufruf klappte).

Anders ausgedrückt: Sofern das erste ExtractIconEx klappt, rufst du es danach nochmals auf. Wenn man die Doku zu MSDN-Library durchsuchenExtractIconEx ganz genau nimmt, holen beide Aufrufe (der mit -1 als Index und der mit dem eigentlichen Index) jeweils ein Icon:
Zitat:

nIconIndex
If this value is a negative number and either phiconLarge or phiconSmall is not NULL, the function begins by extracting the icon whose resource identifier is equal to the absolute value of nIconIndex.
Leider ist aus der Doku nicht ersichtlich, ob auch ein Icon geholt wird, wenn man
Delphi-Quellcode:
ExtractIconEx(AFileName, -1, Result, HICON(nil^), 0)
ruft, also nIconIndex=-1 und nIcons=0, aber trotzdem ein Ziel (hier Result) angegeben wurde.

Zitat:

Habe auch im Taskmanager nicht feststellen können das sich der Speicher erhöht der blieb immer konstant.
Schau lieber auf die Anzahl der Handles, ggf. im Process Explorer bzw. Process Hacker.

Zitat:

Danke nochmal für deine Hilfe.
Keine Ursache. Ich wusste nur deshalb um das Problem, weil ich es selbst schon hatte :).

Grüße
Dalai

EWeiss 26. Apr 2019 00:09

AW: IconHandle von Icon Datei
 
Zitat:

Die Intention der Funktion GetHIcon insgesamt ist mir schon klar. Es ging mir nur um den darin enthaltenen Aufruf if ExtractIconEx(..., -1, ...) <> 0. Das eigentliche Extrahieren der Icons erfolgt ja erst danach in einem weiteren Aufruf von ExtractIconEx (sofern der erste Aufruf klappte).
Sorry hatte dich nicht richtig verstanden habe es oben editiert.. aber hier nochmal..
Delphi-Quellcode:
If ExtractIconEx(AFileName, -1, HICON(nil^), HICON(nil^), 0) <> 0 then


oder besser so!
Delphi-Quellcode:
If ExtractIconEx(AFileName, -1, -1, -1) <> 0 then




gruss

Dalai 26. Apr 2019 00:19

AW: IconHandle von Icon Datei
 
Zitat:

Zitat von EWeiss (Beitrag 1430992)
Sorry hatte dich nicht richtig verstanden habe es oben editiert.. aber hier nochmal..
Delphi-Quellcode:
If ExtractIconEx(AFileName, -1, HICON(nil^), HICON(nil^), 0) <> 0 then

Ja, so meinte ich das.

Zitat:

oder besser so!
Delphi-Quellcode:
If ExtractIconEx(AFileName, -1, -1, -1) <> 0 then

Keine Ahnung, was dann passiert. Deutet die API die HICON-Parameter dann als NULL? Wäre ich mir nicht sicher genug, um es so zu benutzen.

Grüße
Dalai

EWeiss 26. Apr 2019 00:24

AW: IconHandle von Icon Datei
 
Zitat:

Keine Ahnung, was dann passiert. Deutet die API die HICON-Parameter dann als NULL? Wäre ich mir nicht sicher genug, um es so zu benutzen.
Ich mache es wie im ersten Beispiel dann bin ich auf der sicheren Seite. Danke!

gruss

Dalai 26. Apr 2019 00:27

AW: IconHandle von Icon Datei
 
Mir fällt gerade ein, dass es wohl gar nicht geht, eine Konstante (hier -1) als
Delphi-Quellcode:
var
-Parameter zu übergeben. Und die beiden HICON-Parameter von ExtractIconEx sind im Delphi als var deklariert. D.h. der Compiler müsste meckern, wenn 3x -1 übergeben wird.

Grüße
Dalai


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:22 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz