最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

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

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

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

0x00.使用SHBrowseForFolder選擇文件夾

(大段代碼來(lái)襲 , 不想看可直接拉到底看關(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;
 }
}
//-------------------------------------------------------------------------

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

接下來(lái)是 獲取文件夾路徑的簡(jiǎn)單例子

//-------------------------------------------------------------------------
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)碼庫(kù) 位置查看 - github傳送門(mén)

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)目里貌似沒(méi)這個(gè)設(shè)定 , 所以使用SHGetPathFromIDList拿出的數(shù)據(jù)直接轉(zhuǎn)碼即可支持中文.(全部為英文的路徑也不會(huì)有影響)

總結(jié)

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

相關(guān)文章

  • C#實(shí)現(xiàn)從PDF中提取表格的方法詳解

    C#實(shí)現(xiàn)從PDF中提取表格的方法詳解

    PDF是辦公中比較常見(jiàn)的一種文件格式,在工作中應(yīng)用也越來(lái)越普遍。今天為大家介紹一種通過(guò)C#/VB.NET代碼從PDF中提取表格內(nèi)容的方法,感興趣的可以動(dòng)手嘗試一下
    2022-08-08
  • 探秘Unity游戲開(kāi)發(fā)中的狀態(tài)設(shè)計(jì)模式

    探秘Unity游戲開(kāi)發(fā)中的狀態(tài)設(shè)計(jì)模式

    這篇文章主要介紹了探秘Unity游戲開(kāi)發(fā)中的狀態(tài)設(shè)計(jì)模式,狀態(tài)模式是Unity游戲開(kāi)發(fā)中常用的一種設(shè)計(jì)模式,可以幫助開(kāi)發(fā)者更好地管理游戲?qū)ο鬆顟B(tài),提高游戲的可維護(hù)性和可擴(kuò)展性
    2023-05-05
  • C#接口歸納總結(jié)實(shí)例詳解

    C#接口歸納總結(jié)實(shí)例詳解

    本篇文章通過(guò)實(shí)例代碼對(duì)接口做了詳解,需要的朋友可以參考下
    2017-04-04
  • .NET 某云采購(gòu)平臺(tái)API 掛死問(wèn)題解析

    .NET 某云采購(gòu)平臺(tái)API 掛死問(wèn)題解析

    這篇文章主要介紹了.NET 某云采購(gòu)平臺(tái)API 掛死問(wèn)題解析,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • 詳解c# 線程同步

    詳解c# 線程同步

    這篇文章主要介紹了c# 線程同步的相關(guān)資料,文中講解非常細(xì)致,示例代碼幫助大家更好的理解和學(xué)習(xí)c# 多線程,感興趣的朋友可以了解下
    2020-07-07
  • C# 啟動(dòng) SQL Server 服務(wù)的實(shí)例

    C# 啟動(dòng) SQL Server 服務(wù)的實(shí)例

    下面小編就為大家分享一篇C# 啟動(dòng) SQL Server 服務(wù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • C#/VB.NET實(shí)現(xiàn)從PPT中提取圖片的示例代碼

    C#/VB.NET實(shí)現(xiàn)從PPT中提取圖片的示例代碼

    PPT是用于制作幻燈片(演示文稿)的應(yīng)用軟件,每張幻燈片中都可以包含文字、圖形、圖形、表格、聲音和影像等多種信息。本文主要介紹了如何實(shí)現(xiàn)從PPT中提取圖片的功能,需要的可以參考一下
    2023-03-03
  • C#將部分Controls數(shù)據(jù)導(dǎo)入對(duì)象并存入ini中的操作方法

    C#將部分Controls數(shù)據(jù)導(dǎo)入對(duì)象并存入ini中的操作方法

    在Winform設(shè)計(jì)中,經(jīng)常需要將控件數(shù)據(jù)導(dǎo)出到屬性或字段中,本文詳細(xì)介紹了如何優(yōu)化這一過(guò)程,包括控件和屬性的遍歷,以及使用FieldInfo的getSet函數(shù)和Ini類庫(kù)來(lái)實(shí)現(xiàn)數(shù)據(jù)的有效存儲(chǔ)和轉(zhuǎn)換,感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • XAML如何獲取元素的位置

    XAML如何獲取元素的位置

    這篇文章主要為大家詳細(xì)介紹了XAML如何獲取元素的位置,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • C#獲取本地IP的四種方式示例詳解

    C#獲取本地IP的四種方式示例詳解

    這篇文章主要介紹了C#獲取本地IP的四種方式示例詳解, 文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07

最新評(píng)論

祁阳县| 商城县| 鹤庆县| 枣阳市| 平乡县| 固安县| 铁岭市| 金堂县| 独山县| 翁源县| 南城县| 通榆县| 北碚区| 杨浦区| 化隆| 重庆市| 临高县| 海阳市| 甘洛县| 武夷山市| 吉林省| 姚安县| 西华县| 商都县| 东兴市| 景洪市| 三原县| 克拉玛依市| 上思县| 鹤峰县| 集安市| 鸡泽县| 长宁区| 肇州县| 横峰县| 勃利县| 东乌珠穆沁旗| 溆浦县| 五大连池市| 洛宁县| 东乌珠穆沁旗|