Unity3D quickly and efficiently call the system window on the PC side, get local files and save files to the local

              Unity3D quickly and efficiently call the system window on the PC side, get local files and save files to the local


table of Contents

1. Blog introduction

2. Content

(1) Effect display

(2) Core method

3. Open the window to get local files

4. Open the window to save

5. Package modularization

6. Push

7. Conclusion


1. Blog introduction

       Before, there are functions that need to call the Windows system window on the PC to get or save the files locally. Some information on the Internet is similar, and they are basically adjusted by win32. Here is a better way. Here is the introduction, mainly because the ones on the Internet have not been introduced in detail, and I don’t understand it well. Here is a brief introduction, and finally the functions are gathered together into a dll, which is convenient for future use. The functions will be gradually added and updated. Go to github, if you are interested, you can bookmark and follow up.


2. Content

(1) Effect display

(2) Core method

Let's put the core code up first, and then analyze it. For those of you who are watching, first glance at the code below, and then analyze it after the code.

using System.Runtime.InteropServices;
using System;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class FileDialogData
{
    public int structSize = 0;                  //结构的内存大小
    public IntPtr dlgOwner = IntPtr.Zero;       //设置对话框的句柄
    public IntPtr instance = IntPtr.Zero;       //根据flags标志的设置,确定instance是谁的句柄,不设置则忽略
    public String filter = null;                //调取文件的过滤方式
    public String customFilter = null;          //一个静态缓冲区 用来保存用户选择的筛选器模式
    public int maxCustFilter = 0;               //缓冲区的大小
    public int filterIndex = 0;                 //指向的缓冲区包含定义过滤器的字符串对
    public String file = null;                  //存储调取文件路径
    public int maxFile = 0;                     //存储调取文件路径的最大长度 至少256
    public String fileTitle = null;             //调取的文件名带拓展名
    public int maxFileTitle = 0;                //调取文件名最大长度
    public String initialDir = null;            //最初目录
    public String title = null;                 //打开窗口的名字
    public int flags = 0;                       //初始化对话框的一组位标志  参数类型和作用查阅官方API
    public short fileOffset = 0;                //文件名前的长度
    public short fileExtension = 0;             //拓展名前的长度
    public String defExt = null;                //默认的拓展名
    public IntPtr custData = IntPtr.Zero;       //传递给lpfnHook成员标识的钩子子程的应用程序定义的数据
    public IntPtr hook = IntPtr.Zero;           //指向钩子的指针。除非Flags成员包含OFN_ENABLEHOOK标志,否则该成员将被忽略。
    public String templateName = null;          //模块中由hInstance成员标识的对话框模板资源的名称
    public IntPtr reservedPtr = IntPtr.Zero;
    public int reservedInt = 0;
    public int flagsEx = 0;                     //可用于初始化对话框的一组位标志
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenDialogData : FileDialogData
{

}

/*这是C#引用非托管的C/C++的DLL的一种定义定义结构体的方式,主要是为了内存中排序,LayoutKind有两个属性Sequential和Explicit

Sequential表示顺序存储,结构体内数据在内存中都是顺序存放的Explicit表示精确布局,需要用FieldOffset()设置每个成员的位置这都是

为了使用非托管的指针准备的,知道什么意思就行,C#的CLR提供了更为灵活的自动管理方式,所以对C#来说可有可无。

CharSet=CharSet.Ansi表示编码方式
*/
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class SaveDialogData : FileDialogData
{

}

public class OpenFileDialog
{
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] OpenDialogData ofd);
}
public class SaveFileDialog
{
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetSaveFileName([In, Out] SaveDialogData ofd);
}

 

       Our core idea is to use C# to reference Comdlg32.dll, a dll written in C++ on Windows. This dll is a class library for system windows on windows. For the reference method, we use the method of [DllImport], which is the blogger. There is an introduction in the previous article. If you don’t know, you can skip over. There is also a portal at the end of this article. I won’t introduce more here. There is also a definition method [StructLayout] in the code. This feature is in the blogger’s previous page. There is also an introduction in this blog post. If you don’t know how to jump over and take a look, this feature is mainly to ensure that the order of the data structure defined by us will not be disrupted.

Core 1 : FileDialogData, this is a data structure defined by us. Of course, it is not defined casually. This is a window-related data structure in Comdlg32.dll. The structure we define must be consistent with the data structure in the library, which contains We need the relevant information of the window. Part of the data in it is set in advance before we open the window, and part of it will be assigned after we obtain or save the local file. I have written all the comments in the above code. Look at it, and if you don’t understand it, look at it from the official explanation below.

Core 2 : OpenDialogData, SaveDialogData Here we are divided into two different classes through inheritance to facilitate the assignment of different windows later.

Core 3 : OpenFileDialog, SaveFileDialog Here, we use C# to call the C++ method in Comdlg32.dll through external reference, and then assign window-related information to the data structure we define.

 

官方C++APIhttps://docs.microsoft.com/zh-cn/windows/win32/api/commdlg/ns-commdlg-openfilenamea


3. Open the window to get local files

        提前赋值的数据 
     
        CustomOpenData = new OpenDialogData();
        CustomOpenData.structSize = Marshal.SizeOf(CustomOpenData);
        CustomOpenData.filter =  "All Files\0*.*\0\0";
        CustomOpenData.file = new string(new char[256]);
        CustomOpenData.maxFile = CustomOpenData.file.Length;
        CustomOpenData.fileTitle = new string(new char[1000]);
        CustomOpenData.maxFileTitle = CustomOpenData.fileTitle.Length;
        CustomOpenData.initialDir = Application.dataPath.Replace('/', '\\') + "\\aaa\\";
        CustomOpenData.title = "打开项目";
        CustomOpenData.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;

Note : Here we first instantiate an OpenDialogData, which is the data structure we previously defined based on the C++ data structure in the library. The properties assigned in advance are not introduced separately here. Each item of the code above has comments. You can go and take a look.

    /// <summary>
    /// 打开窗口
    /// </summary>
    /// <returns></returns> 和该文件相关的数据
    public OpenDialogData OpenFileDlg()
    {
        if (OpenFileDialog.GetOpenFileName(CustomOpenData))
        {
            return CustomOpenData;
        }
        return null;
    }

Note: This is the most important thing, that is, this method opens the window. GetOpenFileName is a C++ method. We input the data structure as a parameter. If we select a file in the opened window and open it, return CustomOpenData will be executed. The assigned data structure is sent back. If the window is canceled, it will return null. We can view the file name, path, extension, etc. of the selected file in CustomOpenData.

 


4. Open the window to save

       There is basically no difference between saving and opening. The difference is that the initial assignment of the data structure is somewhat different. There is an extension of the save file defExt, and then the C++ method of calling is GetSaveFileName

        提前赋值的数据
       
        CustomSaveData = new SaveDialogData();
        CustomSaveData.structSize = Marshal.SizeOf(CustomSaveData);
        CustomSaveData.filter = "All files (*.*)|*.*";
        CustomSaveData.file = new string(new char[256]);
        CustomSaveData.maxFile = CustomSaveData.file.Length;
        CustomSaveData.fileTitle = new string(new char[64]);
        CustomSaveData.maxFileTitle = CustomSaveData.fileTitle.Length;
        CustomSaveData.initialDir = Application.dataPath.Replace('/', '\\') ;  // default path  
        CustomSaveData.title = "保存项目";
        CustomSaveData.defExt = "txt";
        CustomSaveData.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;
    
    打开保存窗口的方法

    public SaveDialogData SaveFileDlg()
    {
        if (SaveFileDialog.GetSaveFileName(CustomSaveData))
        {
            return CustomSaveData;
        }
        return null;
    }

5. Package modularization

        According to the above core idea, the blogger is going to expand this function and label it as Dll. It is more convenient to use. It is relatively simple at present. The calling method is as follows. Subsequent bloggers will gradually update the function, such as directly opening a text or Json can directly read internal data and so on. The dll and source code are all on github. If you are interested, you can download it.

    /// <summary>
    /// 打开本地文件
    /// </summary>
    public void OpenProject()
    {
        FileDialogMgr mgr = new FileDialogMgr();    //实例化窗口管理器
        mgr.SetFilteringWay(EnumFilteringWay.Png);  //设置过滤方式
        OpenDialogData mgrData = mgr.OpenFileDlg(); //获取本地文件的信息
    }
    /// <summary>
    /// 保存文件到本地
    /// </summary>
    public void SaveProject()
    {
        FileDialogMgr mgr = new FileDialogMgr();    //实例化窗口管理器
        mgr.SetFileExtension("txt");                //设置保存文件的后缀
        SaveDialogData mgrData = mgr.SaveFileDlg(); //获取保存文件的信息
    }

6. Push

github:https://github.com/KingSun5/FileDialogMgr

dllImport introduction: https://blog.csdn.net/Mr_Sun88/article/details/100626798

StructLayout introduction: https://blog.csdn.net/Mr_Sun88/article/details/101323222


7. Conclusion

       If you think the blogger’s article is well written, you might as well pay attention to the blogger. Github clicks on Star, star, star, and likes the blog post. The blogger’s ability is limited. If there are any errors in the text, please comment and criticize.

       QQ exchange group: 806091680 (Chinar)

       This group was created by CSDN blogger Chinar, recommend it! I am also in the group!

 

Guess you like

Origin blog.csdn.net/Mr_Sun88/article/details/100681423