[API] SHGetFileInfo 宣告使用字碼 Unicode/Auto 無法正確取得檔案圖示的程式碼變更

話說我在網站上有放個原始碼分享,其中有個函數是取得檔案圖示的功能:
在該範例中原先的宣告與程式碼使用 ANSI (目前已依照本篇更改為新的原始碼) :
VBNET 原始碼
<Runtime.InteropServices.DllImport(“shell32.DLL", CharSet:=Runtime.InteropServices.CharSet.Ansi)> _
Private Function SHGetFileInfo( _
ByVal pszPath As String, _
ByVal dwFileAttributes As Integer, _
ByRef psfi As SHFILEINFO, _
ByVal cbFileInfo As Integer, _
ByVal uFlags As Integer _
) As Integer
End Function

Private Function SHGetFileIconHandle(ByVal strFile As String, Optional ByVal lpiIcon As Integer = 0, Optional ByVal nFlags As enuIconSizeIndex = enuIconSizeIndex.SHGFI_LARGEICON Or enuIconSizeIndex.SHGFI_USEFILEATTRIBUTES, Optional ByVal HandleIcon As enuHandleIcon = enuHandleIcon.hIcon) As Integer
Dim shinfo As SHFILEINFO = New SHFILEINFO
shinfo.iIcon = lpiIcon
shinfo.szDisplayName = New String(Chr(0), 260)
shinfo.szTypeName = New String(Chr(0), 80)
Dim hImageList As Integer = SHGetFileInfo(strFile, 0, shinfo, System.Runtime.InteropServices.Marshal.SizeOf(shinfo), nFlags)
Select Case HandleIcon
Case enuHandleIcon.hIcon
Return shinfo.hIcon.ToInt32
Case enuHandleIcon.iIcon
Return shinfo.iIcon
Case enuHandleIcon.hImageList
Return hImageList
End Select
End Function

後來發現這段程式碼在繁中作業系統下碰上簡中的目錄或檔案名稱會死得很難看,不論是目錄還是檔案,都會抓不到圖示,甚至發生路徑錯誤,例如下圖 0. 簡體中文 開頭的那個目錄及檔案:
直接將宣告改為 Charset.Auto / Charset.Unicode 的話,會所有的圖示都抓不到,而變成 Null 參照:
既然看起來像是 Null 參照,可以從幾個方面去猜測,其中一種猜測方式是猜 Unicode 傳進去的 wChar 缺兩個 Chr(0) ,以致無法正確判讀字串尾端,因此採用人工添加,修改的部分如下述程式碼紅色的部分:
VBNET 原始碼
<Runtime.InteropServices.DllImport(“shell32.DLL", CharSet:=Runtime.InteropServices.CharSet.Auto)> _

Dim shinfo As SHFILEINFO = New SHFILEINFO
strFile &= Chr(0)
shinfo.iIcon = lpiIcon
果然改完程式碼後,就能正確抓到目錄及檔案的圖示。
另外在原先程式碼內加上全路徑文字盒,來針對網路芳鄰的 UNC 路徑功能進行測試,也是可以正常抓到檔案圖示:
因此下次 VBNET 呼叫 API 使用 Auto 或 Unicode 碰到字串部分可能不正確時,可以考慮試試在字串尾端人工加上 Chr(0) 來測試看看。
Categories: 技術分享 | 1 則迴響

文章導覽

One thought on “[API] SHGetFileInfo 宣告使用字碼 Unicode/Auto 無法正確取得檔案圖示的程式碼變更

  1. keda

    嗨,我是C#的初學者,想請問說我把宣告改為CharSet.Auto後,可以把日文或是簡體的字型及圖示表示出來,但無法顯示出檔案或是資料夾的TypeName,如果宣告時不加入CharSet的話可以顯示出TypeName,但在遇日文或是簡體的檔案或資料夾會出現控制碼錯誤,請問有無其它的方式?謝謝

    喜歡

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s

在 WordPress.com 建立免費網站或網誌.

%d 位部落客按了讚: