2017-02-25 2 views
0

Ich versuche, SHGetFileInfo zu verwenden, um das Symbol für Dateien und Ordner zu erhalten. Ich habe festgestellt, dass es in einem Fall nicht funktioniert: der OneDrive-Ordner, der sich in meinem Benutzerprofilordner befindet. In diesem Fall ist der Aufruf erfolgreich zu SHGetFileInfo, aber ich habe das Standardsymbol für eine ausführbare Datei:SHGetFileInfo gibt das falsche Symbol für den OneDrive-Ordner zurück

What I get instead of the OneDrive icon

Hier ist, wie nenne ich die Funktion:

HIMAGELIST imageList; 
SHFILEINFO shfi; 

// Get the path to the OneDrive folder 
LPTSTR src = _T("%USERPROFILE%\\OneDrive"); 
TCHAR dest[MAX_PATH]; 
ExpandEnvironmentStrings(src, dest, MAX_PATH); 

// Load the image from the OneDrive folder 
ZeroMemory(&shfi, sizeof(shfi)); 
imageList = (HIMAGELIST)SHGetFileInfo(
    dest, 
    FILE_ATTRIBUTE_NORMAL, 
    &shfi, 
    sizeof(shfi), 
    SHGFI_ICON | SHGFI_SYSICONINDEX); 

Und hier ist, wie ich bin zeichnen Sie das Symbol: made

case WM_PAINT: 
{ 
    PAINTSTRUCT ps; 
    HDC hdc = BeginPaint(hwnd, &ps); 
    ImageList_Draw(imageList, shfi.iIcon, hdc, 0, 0, ILD_NORMAL); 
    EndPaint(hwnd, &ps); 
} 
break; 

ich ein kurzes umluftunabhängigem Beispiel für die Anwendung auf Pastebin: http://pastebin.com/bdTvEQT5

In diesem kurzen, in sich geschlossenen Beispiel habe ich der Kürze wegen keinen Fehlerüberprüfungscode eingegeben. Außerdem habe ich den Speicherort des Ordners für das Beispiel fest codiert. In meiner realen App zähle ich die Ordner im Dateisystem auf und erhalte so den Speicherort des OneDrive-Ordners. Der Symbolextraktionscode muss mit jedem aufgelisteten Ordner funktionieren.

Was mache ich falsch?

+0

Sie übergeben das (falsche) 'FILE_ATTRIBUTE_NORMAL'-Flag, haben aber das Glück, das' SHGFI_USEFILEATTRIBUTES'-Flag zu setzen, so dass es ignoriert wird. Der Ordner * OneDrive * ist keine Datei. Sie müssen zur Dokumentation zurückkehren. – IInspectable

+0

Sie überprüfen keine Rückgabewerte, daher wissen Sie nicht, ob die API-Aufrufe erfolgreich sind oder nicht –

+0

Bitte hosten Sie Ihren Code nicht auf einer externen Website. Es gehört in die eigentliche Frage kopiert/eingefügt. –

Antwort

0

Ihr Code funktioniert gut für mich auf Windows 10 (15031). Sie verwenden nie shfi.hIcon, so dass Sie nicht benötigen, obwohl es nicht verhindert, dass es in meinem Fall funktioniert, aber Sie lecken ein Symbol.

%USERPROFILE%\OneDrive ist möglicherweise nicht der Speicherort des OneDrive-Ordners. Verwenden Sie niemals Umgebungsvariablen, wenn es Shell-Funktionen gibt, die Ihnen den Pfad mitteilen können!

Sie können nicht davon ausgehen, dass es einen OneDrive-Ordner an erster Stelle gibt. Wenn OneDrive nicht verwendet wurde, ist der Ordner unter Windows 8.1 nicht vorhanden. Daher sollten Sie Fehler von SHGetFileInfo behandeln!

Ich würde empfehlen, dass Sie Ihren Code so etwas wie dies zu ändern:

PIDLIST_ABSOLUTE pidl; 
HRESULT hr = SHGetKnownFolderIDList(FOLDERID_SkyDrive, 0, NULL, &pidl); // Note: Change the flags if you want to create the folder if it does not exist 
if (SUCCEEDED(hr)) 
{ 
    imageList = (HIMAGELIST) SHGetFileInfo((LPTSTR) pidl, 0, &shfi, sizeof(shfi), SHGFI_PIDL | SHGFI_SYSICONINDEX); 
    ILFree(pidl); 
} 
if (!imageList) 
{ 
    // Fall back to a plain folder icon 
    imageList = (HIMAGELIST) SHGetFileInfo(TEXT("DoesNotMatter"), FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); 
} 

ich das Ergebnis nicht erklären kann und den Mangel an Fehlerprüfung sieht sicherlich nicht helfen. Ich vermute, es eine davon ist:

  • Sie nicht rufen CoInitialize/OleInitialize vor SHGetFileInfo aufrufen. MSDN sagt, Sie müssen, aber es scheint unwahrscheinlich, dass es die richtige Bildliste, aber den falschen Symbolindex zurückgeben würde.
  • Die bekannte OneDrive-Ordnerregistrierung ist beschädigt.
  • Die Bildliste des Shell-Systems ist beschädigt.
+0

Danke, dass Sie sich die Zeit genommen haben. Zu sagen, dass mein Code für dich funktioniert hat, war eine große Hilfe. Das Problem war tatsächlich eine beschädigte OneDrive-Installation. Der Ordner tauchte immer noch auf, aber es hat nicht funktioniert. Ich habe OneDrive neu installiert und jetzt erscheint das Symbol, ohne meinen Code zu ändern. Der Grund, warum ich keine bekannten Ordner verwendet habe, ist, dass der Code in einer Dateibrowser-ähnlichen App verwendet werden soll. Daher muss ich die Symbole aus Ordnern abrufen, die aus dem Dateisystem aufgelistet werden. Ich verwende keine Umgebungsvariablen und mache keine Annahmen darüber, wo die Ordner sein sollen. – Ove

+0

@Ove: Ihre [mcve] macht Annahmen über den Speicherort eines bekannten Ordners, der woanders eingerichtet werden könnte. Dieser Code sollte neu geschrieben werden, um die Shell-Funktionen zu verwenden, um seine PIDL nachzuschlagen. Sie können diesen Hinweis ignorieren, wenn Ihre Eingabe das Ergebnis der Aufzählung des Dateisystems ist, wie in Ihrem speziellen Anwendungsfall. Diese Fragen und Antworten wissen jedoch nichts über Ihre endgültige Bewerbung und die Frage könnte verbessert werden. – IInspectable

Verwandte Themen