a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 編程 > C# > 正文

C#如何使用SHBrowseForFolder導(dǎo)出中文文件夾詳解

2019-10-29 19:58:01
字體:
供稿:網(wǎng)友

前言

從業(yè)以來,數(shù)次踩中編碼的坑, 這次又馬失前蹄 , 真是事不過三此非彼白.

本來這個(gè)小問題不打算拿出來說 , 但是翻看谷歌發(fā)現(xiàn)若干年前也有寥寥數(shù)人遇到碰到這個(gè)問題 ,而且都并沒有給出一個(gè)可行的解決方案 ,現(xiàn)在問題依然掛在CSDN等地方 , 似乎不會再有人去回答了, 或者其實(shí)題主們后面解決了但并沒有回頭來提供解決方案. 現(xiàn)在由我來”終結(jié)此貼”

SHBrowseForFolder是一個(gè)可以用于獲取文件夾路徑的Windows API。使用起來可以方便很多,文中將詳細(xì)介紹關(guān)于C#使用SHBrowseForFolder導(dǎo)出中文文件夾的相關(guān)內(nèi)容 ,下面話不多說了,來一起看看詳細(xì)的介紹吧

0x00.使用SHBrowseForFolder選擇文件夾

(大段代碼來襲 , 不想看可直接拉到底看關(guān)鍵的幾行)

底層接口 – 選擇文件夾相關(guān)

//-------------------------------------------------------------------------class Win32API{ // C# representation of the IMalloc interface. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000002-0000-0000-C000-000000000046")] public interface IMalloc { [PreserveSig] IntPtr Alloc([In] int cb); [PreserveSig] IntPtr Realloc([In] IntPtr pv, [In] int cb); [PreserveSig] void Free([In] IntPtr pv); [PreserveSig] int GetSize([In] IntPtr pv); [PreserveSig] int DidAlloc(IntPtr pv); [PreserveSig] void HeapMinimize(); } [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct BROWSEINFO { public IntPtr hwndOwner; public IntPtr pidlRoot; public IntPtr pszDisplayName; [MarshalAs(UnmanagedType.LPTStr)] public string lpszTitle; public int ulFlags; [MarshalAs(UnmanagedType.FunctionPtr)] public Shell32.BFFCALLBACK lpfn; public IntPtr lParam; public int iImage; } [Flags] public enum BffStyles { RestrictToFilesystem = 0x0001, // BIF_RETURNONLYFSDIRS RestrictToDomain = 0x0002, // BIF_DONTGOBELOWDOMAIN RestrictToSubfolders = 0x0008, // BIF_RETURNFSANCESTORS ShowTextBox = 0x0010, // BIF_EDITBOX ValidateSelection = 0x0020, // BIF_VALIDATE NewDialogStyle = 0x0040, // BIF_NEWDIALOGSTYLE BrowseForComputer = 0x1000, // BIF_BROWSEFORCOMPUTER BrowseForPrinter = 0x2000, // BIF_BROWSEFORPRINTER BrowseForEverything = 0x4000, // BIF_BROWSEINCLUDEFILES } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class OpenFileName { public int structSize = 0; public IntPtr dlgOwner = IntPtr.Zero; public IntPtr instance = IntPtr.Zero; public String filter = null; public String customFilter = null; public int maxCustFilter = 0; public int filterIndex = 0; public String file = null; public int maxFile = 0; public String fileTitle = null; public int maxFileTitle = 0; public String initialDir = null; public String public int flags = 0; public short fileOffset = 0; public short fileExtension = 0; public String defExt = null; public IntPtr custData = IntPtr.Zero; public IntPtr hook = IntPtr.Zero; public String templateName = null; public IntPtr reservedPtr = IntPtr.Zero; public int reservedInt = 0; public int flagsEx = 0; } public class Shell32 { public delegate int BFFCALLBACK(IntPtr hwnd, uint uMsg, IntPtr lParam, IntPtr lpData); [DllImport("Shell32.DLL")] public static extern int SHGetMalloc(out IMalloc ppMalloc); [DllImport("Shell32.DLL")] public static extern int SHGetSpecialFolderLocation(   IntPtr hwndOwner, int nFolder, out IntPtr ppidl); [DllImport("Shell32.DLL")] public static extern int SHGetPathFromIDList(   IntPtr pidl, byte[] pszPath); [DllImport("Shell32.DLL", CharSet = CharSet.Auto)] public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO bi); } public class User32 { public delegate bool delNativeEnumWindowsProc(IntPtr hWnd, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool EnumWindows(delNativeEnumWindowsProc callback, IntPtr extraData); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int GetWindowThreadProcessId(HandleRef handle, out int processId); }}//-------------------------------------------------------------------------class Win32Instance{ //------------------------------------------------------------------------- private HandleRef unityWindowHandle; private bool bUnityHandleSet; //------------------------------------------------------------------------- public IntPtr GetHandle(ref bool bSuccess) { bUnityHandleSet = false; Win32API.User32.EnumWindows(__EnumWindowsCallBack, IntPtr.Zero); bSuccess = bUnityHandleSet; return unityWindowHandle.Handle; } //------------------------------------------------------------------------- private bool __EnumWindowsCallBack(IntPtr hWnd, IntPtr lParam) { int procid; int returnVal =  Win32API.User32.GetWindowThreadProcessId(new HandleRef(this, hWnd), out procid); int currentPID = System.Diagnostics.Process.GetCurrentProcess().Id; HandleRef handle =  new HandleRef(this,   System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle); if (procid == currentPID) {  unityWindowHandle = new HandleRef(this, hWnd);  bUnityHandleSet = true;  return false; } return true; }}//-------------------------------------------------------------------------

簡單介紹一下 Win32API 所有接口的結(jié)構(gòu)體 都是參照SHBrowseForFolder函數(shù)而寫 , Win32Instance 主要是精確的獲取當(dāng)前進(jìn)程的ID

接下來是 獲取文件夾路徑的簡單例子

//-------------------------------------------------------------------------private void __SelectFolder(out string directoryPath){ directoryPath = "null"; try { IntPtr pidlRet = IntPtr.Zero; int publicOptions = (int)Win32API.BffStyles.RestrictToFilesystem | (int)Win32API.BffStyles.RestrictToDomain; int privateOptions = (int)Win32API.BffStyles.NewDialogStyle; // Construct a BROWSEINFO. Win32API.BROWSEINFO bi = new Win32API.BROWSEINFO(); IntPtr buffer = Marshal.AllocHGlobal(1024); int mergedOptions = (int)publicOptions | (int)privateOptions; bi.pidlRoot = IntPtr.Zero; bi.pszDisplayName = buffer; bi.lpszTitle = "文件夾"; bi.ulFlags = mergedOptions; Win32Instance w = new Win32Instance(); bool bSuccess = false; IntPtr P = w.GetHandle(ref bSuccess); if (true == bSuccess) {  bi.hwndOwner = P; } pidlRet = Win32API.Shell32.SHBrowseForFolder(ref bi); Marshal.FreeHGlobal(buffer); if (pidlRet == IntPtr.Zero) {  // User clicked Cancel.  return; }  byte[] pp = new byte[2048]; if (0 == Win32API.Shell32.SHGetPathFromIDList(pidlRet, pp)) {  return; } int nSize = 0; for (int i = 0; i < 2048; i++) {  if (0 != pp[i])  {  nSize++;  }  else  {  break;  } } if (0 == nSize) {  return; } byte[] pReal = new byte[nSize]; Array.Copy(pp, pReal, nSize); // 關(guān)鍵轉(zhuǎn)碼部分 Gb2312Encoding gbk = new Gb2312Encoding(); Encoding utf8 = Encoding.UTF8; byte[] utf8Bytes = Encoding.Convert(gbk, utf8, pReal); string utf8String = utf8.GetString(utf8Bytes); utf8String = utf8String.Replace("/0", ""); directoryPath = utf8String.Replace("//", "/") + "/"; } catch (Exception e) { Console.WriteLine("獲取文件夾目錄出錯(cuò):" + e.Message); }}

以上用到的一個(gè)GBK轉(zhuǎn)碼庫 位置查看 - github傳送門

0x01.GBK轉(zhuǎn)碼

以下是關(guān)鍵的一段代碼:

Gb2312Encoding gbk = new Gb2312Encoding();Encoding utf8 = Encoding.UTF8;byte[] utf8Bytes = Encoding.Convert(gbk, utf8, pReal);string utf8String = utf8.GetString(utf8Bytes);utf8String = utf8String.Replace("/0", "");

谷歌上找到的一個(gè)方案是把項(xiàng)目編碼全部改為unicode , 但是C#項(xiàng)目里貌似沒這個(gè)設(shè)定 , 所以使用SHGetPathFromIDList拿出的數(shù)據(jù)直接轉(zhuǎn)碼即可支持中文.(全部為英文的路徑也不會有影響)

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識閱讀請移步到c#教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 在线观看av不卡 | 毛片在线免费播放 | 一区二区日韩精品 | 一本色道久久加勒比88综合 | 在线观看成人av | 亚洲精品四区 | 欧美精品一区二区在线观看 | 欧美一级片免费观看 | 污片在线免费看 | 日本a天堂 | 国产精品一区二区不卡 | 国产免费又色又爽粗视频 | 国产精品视频不卡 | 精产国产伦理一二三区 | 免费观看黄色 | 欧美成人激情视频 | 日av一区 | 日韩免费激情视频 | 色网址在线 | 成人二区| 国产成人精品免费视频 | 国产一级在线观看 | 毛片a级片| 色伊人| 久久人人爽人人爽人人片av不 | 久久福利 | 成人欧美一区二区三区在线播放 | 国产精品久久久久久久久久久久久久 | 午夜精品影院 | 伊人夜夜躁av伊人久久 | 成人免费视频在线观看 | 99福利视频 | 国产精品一区二区三区不卡 | 在线视频 亚洲 | 国产探花在线看 | 亚洲精品视频导航 | 久久久精选 | 最新午夜综合福利视频 | 综合久久亚洲 | 精品96久久久久久中文字幕无 | 国产区在线 |