AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

PickIconDialog

Ein Thema von FAlter · begonnen am 17. Okt 2007 · letzter Beitrag vom 19. Okt 2007
Antwort Antwort
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#1

PickIconDialog

  Alt 17. Okt 2007, 20:30
Hi,

Bei meinem TIcon-speicern-Problem bin ich auf einen Code mit PickIconDialog gestoßen, der nicht funktionierte - ganz offensichtlich ein Unicode-Problem. Die Suche in der DP hat mir gezeigt, dass auch andere ein PickIconDialog-Unicode-Problem hatten. Dort wurde es mit bedingter Compilierung gelöst. Ich habe das ganze so angepasst, dass zur Laufzeit die richtige Version verwendet wird.

Die Units SysUtils (RaiseLastOSError) Windows (Load und FreeLibrary, GetProcAddress) werden benötigt.

Delphi-Quellcode:
function PickIconDlg(hwndOwner: HWND; var lpstrFile: String;
  var lpdwIconIndex: LongInt): Boolean;
var
  Lib: THandle;
  PickIconDlgA: function(hwndOwner:HWND; lpstrFile: PAnsiChar; nMaxFile: DWORD;
    var lpdwIconIndex: LongInt): Longint; stdcall;
  PickIconDlgW: function(hwndOwner:HWND; lpstrFile: PWideChar; nMaxFile: DWORD;
    var lpdwIconIndex: LongInt): Longint; stdcall;
  WinVersion: DWord;
  WindowsMajorVersion: Byte;
  Unicode: Boolean;
  idx, Size: Integer;
  AnsiBuffer: AnsiString;
  WideBuffer: WideString;
begin
  Lib := LoadLibrary('SHELL32');
  if Lib <> 0 then
  try
    WinVersion := GetVersion;
    WindowsMajorVersion := Lo(WinVersion);

    Unicode := (WinVersion < $80000000) { NT-System } and
    (WindowsMajorVersion >= 5); { ab 2000 }

    idx := Length(lpstrFile);

    //size := Max(idx, MAX_PATH);
    if MAX_PATH > idx then
      size := MAX_PATH
    else
      size := idx;

    if Unicode then
    begin
      @PickIconDlgW := GetProcAddress(Lib, 'PickIconDlg');
      if not Assigned(@PickIconDlgW) then
        @PickIconDlgW := GetProcAddress(Lib, Pointer(62));
      if not Assigned(@PickIconDlgW) then
        RaiseLastOSError;

      WideBuffer := lpstrFile;
      SetLength(WideBuffer, size + 1);
      WideBuffer[idx+1] := #0;

      Result := PickIconDlgW(hwndOwner, PWideChar(WideBuffer), size,
        lpdwIconIndex) <> 0;
      if Result then
        lpstrFile := PWideChar(WideBuffer);
    end
    else
    begin
      @PickIconDlgA := GetProcAddress(Lib, Pointer(62));
      if not Assigned(@PickIconDlgA) then
        RaiseLastOSError;

      AnsiBuffer := lpstrFile;
      SetLength(AnsiBuffer, size + 1);
      AnsiBuffer[idx+1] := #0;

      Result := PickIconDlgA(hwndOwner, PAnsiChar(AnsiBuffer), size,
        lpdwIconIndex) <> 0;
      if Result then
        lpstrFile := PAnsiChar(AnsiBuffer);
    end;
  finally
    if not FreeLibrary(Lib) then
      RaiseLastOSError;
  end
  else
    RaiseLastOSError;
end;
Hintergrund: Ab Windows 2000 (NT 5.0) ist der PickIconDialog Unicode, vorher war er ANSI. Daher wird bei NT-Systemen mit einer Major-Version von 5 oder höher der Code für Unicode ausgeführt, sonst der für ANSI. Des weiteren ist er bei älteren Systemen als nur per Index erreichbar, weshalb auf diesen zugegriffen wird, wenn GetProcAddress mit Namen fehlschlägt.

Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#2

Re: PickIconDialog

  Alt 18. Okt 2007, 18:48
die MSDN (*) schreibt, dass die Funktion erst ab Windows XP existiert.
Übrigens: Der letzte Rückgabewert geschrieben in lpdwIconIndex muss ein Integer sein laut Definition.
Am besten wäre es, wenn die Funktion über LoadLibrary und so geladen wird.

(*)
Die MSDN konnte den Eintrag nicht finden. Ich habe daher im Cache von Google gesucht und gefunden:
http://209.85.135.104/search?q=cache...ient=firefox-a
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#3

Re: PickIconDialog

  Alt 18. Okt 2007, 22:34
Hi,

Zitat von Dezipaitor:
die MSDN (*) schreibt, dass die Funktion erst ab Windows XP existiert.
Keine Ahnung, wusste davon nichts. Der Code funktioniert auch z. B. unter Windows 98 (selbst getestet; dort aber eben mit ANSI). Was wohl erst seit XP geht ist:

Delphi-Quellcode:
function ...
external 'SHELL32.DLLname 'PickIconDlg';
Daher verwendete man zuvor nur index. Natürlich erhält man da - und nicht ohne Grund - ne Meldung von wegen Platformunabhängigkeit. Eventuell sollte man daher die OS-Unterscheidung nur machen, wenn GetProcAdress nil zurückliefert bei 'PickIconDlg'. Dann müsste man LoadLibrary nehmen, damits nicht beim Programmstart ne hübsche Meldung gibt bei altem OS.

Zitat:
Übrigens: Der letzte Rückgabewert geschrieben in lpdwIconIndex muss ein Integer sein laut Definition.
Geändert nach Longint.

Zitat:
Am besten wäre es, wenn die Funktion über LoadLibrary und so geladen wird.
Siehe oben. Heute Abend ist mir das aber zu spät, noch was großes zu ändern.

Gute Nacht
FAlter
Felix Alter
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#4

Re: PickIconDialog

  Alt 19. Okt 2007, 09:46
Die Plattformunabhängigkeit bezieht sich auf Linux und Windows und hat nichts mit der Windows Version zu tun.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#5

Re: PickIconDialog

  Alt 19. Okt 2007, 11:34
Ich schätze, dass die MSDN WinXP als Minimum angibt, weil die Funktion davor als inoffiziel gilt.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#6

Re: PickIconDialog

  Alt 19. Okt 2007, 11:36
Hi,

Zitat von Luckie:
Die Plattformunabhängigkeit bezieht sich auf Linux und Windows und hat nichts mit der Windows Version zu tun.
Und ich kann mich darauf verlassen, dass die 62 auch für alle zukünftigen Windows-Versionen gilt?

Zitat von Dezipaitor:
Ich schätze, dass die MSDN WinXP als Minimum angibt, weil die Funktion davor als inoffiziel gilt.
Vermutlich, denn vorher war sie auch nicht über ihren Namen ansprechbar. Und eben das ANSI-oder-Unicode.Problem. Eine offizielle Funktion hätte damals wohl beide Varianten gehabt.

[edit]

Zitat von TurboDelphi-Hilfe:
Return Value

Returns 1 if successful, or 0 if it fails.
Was heißt das, if it fails? Kann man gar nicht zwischen Fehler und Abbrechen geklickt unterscheiden?

[/edit]

Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#7

Re: PickIconDialog

  Alt 19. Okt 2007, 11:53
Auf die Nummer 62 kannst du dich nur dann verlassen, wenn es in der MSDN so steht.
Da für ältere Windowsversionen wohl eh kein Update mehr kommt, wird das auch nicht geändert.


Zu Abbrechen - überprüfe mal mit GetLastError, ob abgebrochen wurde. Oder den Parameter mit dem Bildindex - vielleicht ist dieser -1 ?.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#8

Re: PickIconDialog

  Alt 19. Okt 2007, 12:27
Hi,

habe jetzt den LoadLibrary-Ansatz verfolgt. Bei neuem OS wird der Index nur verwendet, wenn GetProcAddress mit Angabe des Namen fehlschlägt.

Im Gegensatz zu anderen Funktionen steht unter ms-help://borland.bds4/shellcc/platform/shell/reference/functions/pickicondlg.htm (PickIconDialog+F1) nicht da, dass GetLastError einen weiterbringt. Also keine Möglichkeit, einen Fehler zu erkennen. Existiert allerdings z. B. die Datei nicht, gibts ne MessageBox, und danach wird die SYSTEM32.DLL selbst angezeigt (und natürlich der zurückgegebene Dateiname wird zu <System32-Verzeichnis>\System32.dll). Eventuell gibt es ja außer Abbrechen gar keinen "Fehlerfall".

Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
Antwort Antwort

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:17 Uhr.
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