内容简介:Unity项目开发笔记(十七)从业以来,数次踩中编码的坑, 这次又马失前蹄 , 真是事不过三此非彼白.本来这个小问题不打算拿出来说 , 但是翻看谷歌发现若干年前也有寥寥数人遇到碰到这个问题 ,而且都并没有给出一个可行的解决方案 ,现在问题依然挂在CSDN等地方 , 似乎不会再有人去回答了, 或者其实题主们后面解决了但并没有回头来提供解决方案. 现在由我来”终结此贴”
Unity项目开发笔记(十七)
从业以来,数次踩中编码的坑, 这次又马失前蹄 , 真是事不过三此非彼白.
本来这个小问题不打算拿出来说 , 但是翻看谷歌发现若干年前也有寥寥数人遇到碰到这个问题 ,而且都并没有给出一个可行的解决方案 ,现在问题依然挂在CSDN等地方 , 似乎不会再有人去回答了, 或者其实题主们后面解决了但并没有回头来提供解决方案. 现在由我来”终结此贴”
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 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 所有接口的结构体 都是参照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拿出的数据直接转码即可支持中文.(全部为英文的路径也不会有影响)
-EOF-
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Node.js折腾记一:读指定文件夹,输出该文件夹的文件树
- tar打包如何不打包某一个文件夹(排除某些文件夹)
- Scala在资源文件夹中获取文件的文件路径
- C/C++遍历文件夹和文件
- QT选择目录等常用文件/文件夹操作
- 如何使用Python删除一个文件或文件夹
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
计算机科学概论(第11版)
J. Glenn Brookshear / 刘艺、肖成海、马小会、毛倩倩 / 人民邮电出版社 / 2011-10-1 / 69.00元
本书多年来一直深受世界各国高校师生的欢迎,是美国哈佛大学、麻省理工学院、普林斯顿大学、加州大学伯克利分校等许多著名大学的首选教材,对我国的高校教学也产生了广泛影响。 本 书以历史眼光,从发展的角度、当前的水平以及现阶段的研究方向等几个方面,全景式描绘了计算机科学各个子学科的主要领域。在内容编排上,本书很好地兼顾了 学科广度和主题深度,把握了最新的技术趋势。本书用算法、数据抽象等核心思想贯穿各......一起来看看 《计算机科学概论(第11版)》 这本书的介绍吧!