欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2018年11月05日 09:57:39   作者:RECT  
這篇文章主要給大家介紹了關(guān)于C#如何使用SHBrowseForFolder導出中文文件夾的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習合作工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

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

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

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

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 title = null;
 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 主要是精確的獲取當前進程的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("獲取文件夾目錄出錯:" + e.Message);
 }
}

以上用到的一個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", "");

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

總結(jié)

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

相關(guān)文章

  • C#實現(xiàn)控制電腦注銷,關(guān)機和重啟

    C#實現(xiàn)控制電腦注銷,關(guān)機和重啟

    這篇文章主要為大家介紹了C#如何實現(xiàn)控制電腦注銷,關(guān)機和重啟功能,本案例涉及的知識點包含:Process、Shell32.dll、User32.dll、Struct數(shù)據(jù)結(jié)構(gòu),感興趣的可以了解一下
    2022-09-09
  • C#如何遠程讀取服務器上的文本內(nèi)容

    C#如何遠程讀取服務器上的文本內(nèi)容

    這篇文章主要介紹了C#如何遠程讀取服務器上的文本內(nèi)容,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • C#基于XNA生成隨機顏色的方法

    C#基于XNA生成隨機顏色的方法

    這篇文章主要介紹了C#基于XNA生成隨機顏色的方法,涉及XNA Color類的使用技巧,需要的朋友可以參考下
    2015-06-06
  • C#實現(xiàn)Xml序列化與反序列化的方法

    C#實現(xiàn)Xml序列化與反序列化的方法

    這篇文章主要介紹了C#實現(xiàn)Xml序列化與反序列化的方法,將序列化與反序列化的方法封裝入一個類文件中,包含了較為詳盡的注釋說明,非常具有實用價值,需要的朋友可以參考下
    2014-12-12
  • c#解析jobject的數(shù)據(jù)結(jié)構(gòu)

    c#解析jobject的數(shù)據(jù)結(jié)構(gòu)

    這篇文章介紹了c#解析jobject數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • WPF使用WinSCP實現(xiàn)FTP下載

    WPF使用WinSCP實現(xiàn)FTP下載

    這篇文章主要為大家詳細介紹了WPF如何使用WinSCP實現(xiàn)FTP下載,文中的示例代碼講解詳細,對我們學習或工作有一定幫助,感興趣的小伙伴可以了解一下
    2023-01-01
  • c#之獲取本機主機名的四種方式總結(jié)

    c#之獲取本機主機名的四種方式總結(jié)

    這篇文章主要介紹了c#之獲取本機主機名的四種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • C#多線程處理多個隊列數(shù)據(jù)的方法

    C#多線程處理多個隊列數(shù)據(jù)的方法

    這篇文章主要介紹了C#多線程處理多個隊列數(shù)據(jù)的方法,涉及C#線程與隊列的相關(guān)操作技巧,需要的朋友可以參考下
    2015-07-07
  • c#如何獲取json數(shù)組里指定參數(shù)

    c#如何獲取json數(shù)組里指定參數(shù)

    這篇文章主要介紹了c#如何獲取json數(shù)組里指定參數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • C#實現(xiàn)在線點餐系統(tǒng)

    C#實現(xiàn)在線點餐系統(tǒng)

    這篇文章主要為大家詳細介紹了C#實現(xiàn)在線點餐系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11

最新評論