2017-02-25 81 views
0

我正在嘗試使用SHGetFileInfo獲取文件和文件夾的圖標。我注意到它在一種情況下不起作用:位於我的用戶配置文件夾中的OneDrive文件夾。在這種情況下,調用的SHGetFileInfo成功,但我得到了默認圖標的可執行文件:SHGetFileInfo返回OneDrive文件夾的錯誤圖標

What I get instead of the OneDrive icon

這裏是我如何調用該函數:

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); 

這裏是怎麼了繪製的圖標:http://pastebin.com/bdTvEQT5

012:

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

我上引擎收錄做了簡短的自包含例如用於該應用

在這個簡短的獨立示例中,爲了簡潔,我省略了任何錯誤檢查代碼。另外,爲了示例的目的,我對文件夾的位置進行了硬編碼。在我的真實應用程序中,我列舉了文件系統中的文件夾,這就是我如何獲取OneDrive文件夾的位置。圖標提取代碼需要與枚舉的任何文件夾一起使用。

我在做什麼錯?

+0

您正在傳遞錯誤的FILE_ATTRIBUTE_NORMAL標誌,但有幸忘記設置SHGFI_USEFILEATTRIBUTES標誌,因此將被忽略。 * OneDrive *文件夾不是文件。你需要回到文檔。 – IInspectable

+0

您不檢查返回值,因此不知道API調用是否成功 –

+0

請不要將您的代碼託管在外部站點上。它屬於複製/粘貼在實際問題中。 –

回答

0

您的代碼在Windows 10(15031)上可以正常工作。你永遠不會使用shfi.hIcon,所以你不需要SHGFI_ICON,雖然它不妨礙它在我的情況下工作,但你正在泄漏一個圖標。

%USERPROFILE%\OneDrive可能不是OneDrive文件夾的位置。如果有shell功能可以告訴你路徑,切勿使用環境變量!

您不能假定首先存在OneDrive文件夾。如果OneDrive尚未使用,則該文件夾在Windows 8.1上不存在,因此您應該處理來自SHGetFileInfo的故障!

我會建議你改變你的代碼是這樣的:

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); 
} 

我無法解釋你所看到的結果,缺乏錯誤檢查的肯定無助。我猜這就是其中之一:

  • 你是不是叫SHGetFileInfo之前調用CoInitialize/OleInitialize。 MSDN確實說你必須但它似乎不太可能會返回正確的圖像列表,但錯誤的圖標索引。
  • OneDrive已知文件夾註冊已損壞。
  • shell系統映像列表損壞。
+0

感謝您花時間研究這一點。說我的代碼爲你工作是一個巨大的幫助。問題實際上是OneDrive安裝損壞。該文件夾仍然出現,但它不起作用。我重新安裝了OneDrive,現在這個圖標顯示出來了,而無需修改我的代碼。 我之所以沒有使用已知文件夾的原因是,該代碼旨在用於類似文件瀏覽器的應用程序,所以我需要從文件系統中枚舉的文件夾中獲取圖標。我沒有使用環境變量或假定文件夾應該在哪裏。 – Ove

+0

@Ove:您的[mcve]確實對已知文件夾的位置進行了假設,可以將其設置在其他位置。該代碼應該重寫爲使用shell函數來查找其PIDL。如果您的輸入是枚舉文件系統的結果,您可以忽略此建議,就像在您的特定用例中那樣。然而,這個問答對您的最終申請一無所知,問題可以改進。 – IInspectable

相關問題