亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#如何使用SHBrowseForFolder導出中文文件夾詳解

2019-10-29 19:58:01
字體:
來源:轉載
供稿:網友

前言

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

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

SHBrowseForFolder是一個可以用于獲取文件夾路徑的Windows API。使用起來可以方便很多,文中將詳細介紹關于C#使用SHBrowseForFolder導出中文文件夾的相關內容 ,下面話不多說了,來一起看看詳細的介紹吧

0x00.使用SHBrowseForFolder選擇文件夾

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

底層接口 – 選擇文件夾相關

//-------------------------------------------------------------------------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 所有接口的結構體 都是參照SHBrowseForFolder函數而寫 , Win32Instance 主要是精確的獲取當前進程的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); // 關鍵轉碼部分 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("獲取文件夾目錄出錯:" + e.Message); }}

以上用到的一個GBK轉碼庫 位置查看 - github傳送門

0x01.GBK轉碼

以下是關鍵的一段代碼:

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

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
伊人久久男人天堂| 8090理伦午夜在线电影| 午夜精品久久17c| 久久久亚洲精品视频| 这里只有精品视频在线| 久久全球大尺度高清视频| 欧美激情性做爰免费视频| 久久综合色88| 中文字幕av一区二区| 91精品国产自产在线| 一区二区三区高清国产| 亚洲午夜精品久久久久久久久久久久| 91青草视频久久| 国产视频在线一区二区| 精品国产91久久久久久| 91成人精品网站| 国产精品综合网站| 国产精品黄色影片导航在线观看| 亚洲成人在线视频播放| 日韩欧美中文在线| 亚洲欧美在线免费| 欧美人成在线视频| 欧美成人免费一级人片100| 久久久91精品国产| 日韩极品精品视频免费观看| 国产精品亚洲网站| 国产精品扒开腿做爽爽爽的视频| 亚洲国产精品一区二区三区| 亚洲精品网址在线观看| 亚洲嫩模很污视频| 精品视频在线播放| 亚洲摸下面视频| 欧美色欧美亚洲高清在线视频| 色哟哟入口国产精品| 97精品国产97久久久久久春色| 日韩高清人体午夜| 欧美丝袜一区二区| 97国产精品人人爽人人做| 国产999精品视频| 国产精品露脸av在线| 精品国产美女在线| 一个人www欧美| 91精品国产91| 久久久久久久久久国产精品| 欧美在线免费观看| 久久久久久久久久国产| 超碰日本道色综合久久综合| 国产在线视频一区| 久久99精品视频一区97| 亚洲新中文字幕| 亚洲图中文字幕| 都市激情亚洲色图| 久久久午夜视频| 日韩欧美在线观看| 国产精品一区二区av影院萌芽| 国产91精品久久久久久| 亚洲天堂av在线免费观看| 青青草原成人在线视频| 亚洲第一二三四五区| 欧美成人四级hd版| 欧美裸身视频免费观看| 国产亚洲人成a一在线v站| 日韩免费观看av| 日韩欧美国产黄色| 久久久久久久久中文字幕| 国产精品日韩av| 亚洲图片在线综合| 懂色av中文一区二区三区天美| 国产一区深夜福利| 国产99视频在线观看| 亚洲毛片在线看| 96国产粉嫩美女| 亚洲系列中文字幕| 欧美成人精品激情在线观看| 中文字幕一区电影| 国产精品99免视看9| 日韩高清av在线| 成人亲热视频网站| 亚洲电影免费观看高清完整版在线| 日韩av有码在线| 91产国在线观看动作片喷水| 国产精品av在线| 欧美激情欧美激情| 日韩欧美极品在线观看| 久久久视频精品| 欧美亚洲国产精品| 九九热99久久久国产盗摄| 91国内精品久久| 在线视频欧美日韩精品| 97香蕉超级碰碰久久免费的优势| 色婷婷久久一区二区| 国产精品成熟老女人| 国产伦精品免费视频| 欧美成aaa人片免费看| 一区二区三区视频免费在线观看| 国产精品丝袜久久久久久高清| 久久亚洲国产精品| 欧美激情免费观看| 九九精品在线视频| 欧美黑人xxx| 久久成人精品电影| 另类色图亚洲色图| 国产美女被下药99| 热久久美女精品天天吊色| 欧美黑人巨大精品一区二区| 久久久这里只有精品视频| 伊人久久久久久久久久久久久| 岛国av一区二区在线在线观看| 国内精品久久久久| 国产精品视频专区| 黑人巨大精品欧美一区二区三区| 欧美成人精品激情在线观看| 久久综合亚洲社区| 成人午夜在线影院| 日韩中文在线中文网在线观看| 91美女片黄在线观看游戏| 成人写真视频福利网| 亚洲成年人在线播放| 国内精品久久久久伊人av| 久久久人成影片一区二区三区观看| 国产一区二区三区日韩欧美| 精品国产91久久久久久老师| 久久久久久中文| 亚洲mm色国产网站| 一个人看的www欧美| 热久久这里只有| 亚洲精品久久久久中文字幕欢迎你| 亚洲欧美精品中文字幕在线| 亚洲福利视频二区| 国产精品777| 日韩精品视频在线观看免费| 欧美三级免费观看| 色系列之999| 欧美乱大交xxxxx| 日韩专区在线播放| 日韩高清人体午夜| 国产成人精品视频| 国产精品自产拍在线观| 久久成人亚洲精品| 欧美日韩免费观看中文| 国产精品91在线| 国产日韩欧美影视| 欧美日韩一区免费| xx视频.9999.com| 亚洲第一页自拍| 日韩成人中文字幕在线观看| 国产ts一区二区| 国产精品视频yy9099| 国产精品天天狠天天看| 亚洲区一区二区| 久久精品国产成人| 色av吧综合网| 亚洲一区中文字幕| 日韩国产高清视频在线| 两个人的视频www国产精品| 中文字幕最新精品| 久久伊人精品一区二区三区| 91精品久久久久久久久不口人| 91在线中文字幕| 91成人在线视频| 欧美电影电视剧在线观看| 久久久精品国产| 久久精品这里热有精品| 91亚洲精品视频|