【Unity編輯器開發】工具開發之Windows單選或多選文件踩坑記錄


  最近在項目組做了一個導表工具,舊版本功能只能指定某個文件夾對整個文件夾下的Excel文件進行文件導表批處理,但是策划有個新需求是導出單個文件,在根據需求維護導表工具迭代時時我想何不多做個彩蛋功能,導出單個或者多個文件?那說做就做,開始踩坑。

  舊版本的文件夾選擇代碼是調用了Unity自帶的EditorUtility.OpenFolderPanel實現的。功能如下

string path = EditorUtility.OpenFolderPanel("自定義標題",Application.dataPath,"默認文件名");

  以上代碼的返回值是你選中的文件夾路徑,那選擇文件的話我第一個想法就是查看Unity是否支持選擇文件,那查看文檔后發現EditorUtility.OpenFilePanel,看名字十分符合我的需求啊,趕緊試試。

string path = EditorUtility.OpenFilePanel("自定義標題", Application.dataPath, "文件篩選后綴");

  使用后發現確實能夠選擇某一個文件正確打印這個文件的路徑,但是!不支持多選。。。那如果我是用戶,只能單選不能多選導出總感覺欠缺了點什么,那為了不讓我的策划用戶們感覺欠缺靈魂,就繼續研究。繼續研究API發現Unity自帶的EditorUtility並不支持多選這個功能,那沒辦法,不能使用拿來主義的話那就只能借助C#原生來調用Windows的文件彈窗了。

首先新建一個腳本,里面附上如下代碼

using System;
using System.Runtime.InteropServices;


//unity3d調用win32打開對話框
[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 DllTest
{
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
}

 

  其實就是C#調用了win32對應的Dll中彈窗的方法,需要注意的是OpenFileName對應的是OPENFILENAME這個結構體,這里附上結構體介紹:

附上這個結構體的介紹:

OPENFILENAME

OPENFILENAME結構包含了GetOpenFileNameGetSaveFileName函 數用來初始化打開或另存為對話框的信息。在用戶關閉對話框后,系統返回關於用戶的選擇信息到這個結構中。

typedef struct tagOFN {
DWORDlStructSize;
HWNDhwndOwner;
HINSTANCEhInstance;
LPCTSTRlpstrFilter;
LPTSTRlpstrCustomFilter;
DWORDnMaxCustFilter;
DWORDnFilterIndex;
LPTSTRlpstrFile;
DWORDnMaxFile;
LPTSTRlpstrFileTitle;
DWORDnMaxFileTitle;
LPCTSTRlpstrInitialDir;
LPCTSTRlpstrTitle;
DWORDFlags;
WORDnFileOffset;
WORDnFileExtension;
LPCTSTRlpstrDefExt;
LPARAMlCustData;
LPOFNHOOKPROClpfnHook;
LPCTSTRlpTemplateName;
#if (_WIN32_WINNT >= 0x0500)
void *pvReserved;
DWORDdwReserved;
DWORDFlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAME, *LPOPENFILENAME;

之后在你需要調用的方法里寫上代碼

       OpenFileName ofn = new OpenFileName();

            ofn.structSize = Marshal.SizeOf(ofn);

            ofn.filter = "Excel文件(*.xlsx)\0*.xlsx;*.xlsx"; //過濾器 想要顯示的文件的格式 (excel格式)         // "All Files\0*.*\0\0"; 所有格式均顯示     

            ofn.file = new string(new char[256]);      // 存放目錄路徑緩沖區  

            ofn.maxFile = ofn.file.Length;

            ofn.fileTitle = new string(new char[64]);

            ofn.maxFileTitle = ofn.fileTitle.Length;

            ofn.initialDir = Application.dataPath;        //默認路徑  

            ofn.title = "選擇多個excel";       //窗口名稱

            ofn.defExt = "XLSX";//顯示文件的類型//注意 一下項目不一定要全選 但是0x00000008項不要缺少
            ofn.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;   //OFN_EXPLORER |OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST| OFN_ALLOWMULTISELECT|OFN_NOCHANGEDIR    

            if (DllTest.GetOpenFileName(ofn))
            {
                Debug.Log("選擇的文件路徑" + ofn.file);  //顯示點擊文件路徑
            }

  好,萬事俱備只欠東風,試一試發現,誒,可以多選,但是點擊確定后輸出的只是文件夾名稱。???,驚了,再試試單選,咦,沒問題,那就有意思了,需要再去研究研究官網API。為了方便讀者查閱我就附在下面了,如果不想看直接跳過表格看我下面那段話就是解決辦法~

成員

lStructSize
指定這個結構的大小,以字節為單位。

Windows 95/98和Windows NT 4.0:特意為Windows 95/98或Windows NT 4.0,及帶有WINVER和_WIN32_WINNT >= 0x0500編譯時,為這個成員使用OPENFILENAME_SIZE_VERSION_400。

Windows 2000及更高版本:這個參數使用sizeof (OPENFILENAME) 。

hwndOwner
指向所有者對話框窗口的句柄。這個成員可以是任意有效窗口句柄,或如果對話框沒有所有者它可以為NULL。
hInstance
如果在Flags成員中設置了OFN_ENABLETEMPLATEHANDLE標記,hInstance成 員指向包含一個對話框模板的內存對象。如果OFN_ENABLETEMPLATE標記被設置,hInstance是一個指向通過lpTemplateName成 員命名的對話框模板的模塊。如果兩者都沒有被設置,這個成員被忽略。

如果OFN_EXPLORER標記被設置,系統使用Explorer風格的默認對話框的子窗口作為指定模板來建立一個對話框。如果 OFN_EXPLORER標記沒有被設置,系統使用模板建立一個舊風格的對話框。

lpstrFilter
指向一對以空字符結束的過濾字符串的一個緩沖。緩沖中的最后一個字符串必須以兩個NULL字符結束。

第一個字符串是過濾器描述的顯示字符串(例如,“文本文件”),第二個字符指定過濾樣式(例如,“*.TXT”)。要為一個顯示字符串指定多個過濾 樣式,使用分號(“;”)分隔樣式(例如,“*.TXT;*.DOC;*.BAK”)。一個樣式字符串中可以包含有效的文件名字字符及星號(*)通配符。 不能在樣式字符串中包含空格。

系統不能改變過濾器的次序。它按lpstrFilter指定的次序顯示在文件類型組合框中。

如果lpstrFilter是NULL,對話框不能顯示任何過濾器。

lpstrCustomFilter
指向一個靜態緩沖,它包含了一對以空字符結束的過濾器字符串,這個字符串是為了保留用戶選擇的過濾樣式。第一個字符串是描述定制過濾器 的顯示字符串,第二個字符串是被用戶選擇的過濾器樣式。第一次你的應用程序建立對話框,你指定的第一個字符串可以是任何非空的字符串。當用戶選擇了一個文 件時,對話框復制當前過濾樣式到第二個字符串。保留過濾樣式可以是在lpstrFilter緩沖中指定的樣式之一,或是用戶輸入的過濾器樣 式。在下一次對話框被建立時系統使用這個字符串去初始化用戶自定義的文件過濾器。如果nFilterIndex成員是0,對話框使用定制過 濾器。

如果這個成員是NULL,對話框不能保留用戶自定義過濾器樣式。

如果這個成員不是NULL,nMaxCustFilter成員的值必須指定以TCHARs為單位的lpstrCustomFilter緩 沖的大小。對於ANSI版本,是字節的個數;對於Unicode版本,是字符的個數。

nMaxCustFilter
指定特意為lpstrCustomFilter准備的以TCHARs為單位的緩沖大小。對於ANSI版 本,是字節的個數;對於Unicode版本,是字符的個數。這緩沖應該最小在40個字符長。如果lpstrCustomFilter成員是 NULL或是指向NULL的字符串,這個成員被忽略。
nFilterIndex
指定在文件類型控件中當前選擇的過濾器的索引。緩沖指向被lpstrFilter包含的一對定義了的過濾器的字符串。過 濾器的第一對字符串的索引值為1,第二對為2,等等。0索引指出是通過lpstrCustomFilter指定的定制過濾器。你可以為對話 框指定一個索引作為最初的過濾器描述及過濾器樣式。當用戶選擇了一個文件時,nFilterIndex返回當前顯示的過濾器的索引。

如果nFilterIndex是0及lpstrCustomFilter是NULL,系統使用在lpstrFilter緩 沖中的第一個過濾器。如果所有的三個成員都是0或NULL,系統不使用任何過濾器,在對話框的列表文件中不顯示任何文件。

lpstrFile
指向包含初始化文件名編輯控件使用的文件名的緩沖。如果不需要初始值,這個緩沖的第一個字符必須是NULL。當 GetOpenFileNameGetSaveFileName函 數返回成功時,這個緩沖包含驅動器,路徑,文件名,及所選擇的文件的擴展名。

如果OFN_ALLOWMULTISELECT標記被設置並且用戶選擇了多個文件,緩沖包含了當前目錄下被選擇文件的文件名。對於Explorer 風格對話框,目錄和文件名字符串是被NULL分開的,在文件名之后有一個額外的NULL。對於舊風格對話框,字符串是被空格分開的並且函數為帶有空格的文 件名使用短文件名。你可以使用FindFirstFile函 數在長短文件名之間轉換。如果用戶只選擇了一個文件,lpstrFile字符串在路徑和文件名之間沒有分隔。

如果緩沖太小,函數返回FALSE並且CommDlgExtendedError函 數返回FNERR_BUFFERTOOSMALL.。既然這樣,lpstrFile緩沖的首先兩個字節包含必需的大小(字節或字符)。

nMaxFile
指定lpstrFile緩沖的大小,以TCHARs為單位。對於ANSI版本,是字節的個數;對於 Unicode版本,是字符的個數。這個緩沖必須足夠存儲路徑和文件名字符串,包含結尾的null字符。如果緩沖太小,GetOpenFileName和GetSaveFileName函 數返回假(FALSE)緩沖最小應該在256個字符長。
lpstrFileTitle
指向接收選擇的文件的文件名和擴展名的緩沖(不帶路徑信息)。這個成員可以是NULL。
nMaxFileTitle
指定lpstrFileTitle緩沖的大小,以TCHARs為單位。對於ANSI版本,是字節的個數; 對於Unicode版本,是字節的個數。如果lpstrFileTitle是NULL,這個成員被忽略。
lpstrInitialDir
指向以空字符結束的字符串,可以在這個字符串中指定初始目錄。Pointer to a null terminated string that can specify the initial directory. 在不同的平台上,為選擇初始目錄有不同的運算法則。

Windows 2000:

  1. 如果lpstrFile包含了一個路徑,這個路徑就是初始目錄。
  2. 否則,lpstrInitialDir指定的為初始目錄。
  3. 如果lpstrInitialDir為NULL,並且當前目錄下包含有一些指定過濾器類型的文件,初始目錄就是當前目 錄。
  4. 否則,如果應用程序在過去使用過打開哐另存為對話框,使用最近選擇的路徑作為初始目錄。然而,如果一個應用程序長時間沒有運行過,它保 存的選擇的路徑將被丟棄。
  5. 否則,初始目錄是當前用戶的私人文件目錄(即我的文檔)。
  6. 否則,初始目錄是桌面文件夾。

Windows 98:

  1. lpstrInitialDir指定初始目錄。
  2. 如果lpstrInitialDir是NULL並且lpstrFile包含了一個路徑,那么這個路徑就是 初始目錄。
  3. 否則,如果當前目錄包含了一些指定的過濾類型的文件,那么初始化目錄是當前目錄。
  4. 否則,初始目錄是當前用戶的私人文件目錄(即我的文檔)。

Windows和Windows NT/ 2000的早期版本:

  1. lpstrInitialDir指定初始目錄。
  2. 如果lpstrInitialDir是NULL並且lpstrFile包含了一個路徑,那么這個路徑就是 初始目錄。
  3. 否則,初始目錄是當前目錄。
lpstrTitle
指向在對話框的標題欄中放置的字符串。如果這個成員是NULL,系統使用默認標題(另存為或打開)
Flags
位標記的設置,你可以使用來初始化對話框。當對話框返回時,它設置的這些標記指出用戶的輸入。這個成員可以是下列標記的組合。
標記 含意
OFN_ALLOWMULTISELECT 指定文件名列表框允許多選。如果同時你設置了OFN_EXPLORER標記,對話框使用Explorer風格用戶界面; 否則它使用舊風格用戶界面。

如果用戶選擇了一個以上的文件,lpstrFile緩沖返回當前目錄下所有被選擇的文件的文件名。nFileOffset成 員是到第一個文件名的偏移量(字節或字符),並且nFileExtension成員不被使用。對於Explorer風格對話框,目錄和文件 名是被NULL分隔的,在最后的文件名后帶有額外的NULL。這個格式使Explorer風格的對話框能返回包含空格的長文件名。對於舊風格對話框,目錄 和文件字符串是被空格分隔的,函數為帶有空格的文件名使用短文件名。你可以使用FindFirstFile函數在短文件名和長文件名之間 轉換。

如果你為一個舊風格對話框指定了一個定制的模板,文件名列表框的定義必須包含LBS_EXTENDEDSEL值。

OFN_CREATEPROMPT 如果用戶指定了一個不存在的文件,這個標記使用對話框能提示用戶是否新建這個文件。如果用戶選擇了新建這個文件,對話框 關閉並且函數返回指定的名字;否則,對話框繼續停留。如果你使用帶有OFN_ALLOWMULTISELECT標記的這個標記,對話框允許用戶去指定一個 不存在的文件。
OFN_DONTADDTORECENT Windows 2000:防止系統為選擇的文件增加快捷鏈接到最近使用文檔中。要找回目錄的位置,調用 還有CSIDL_RECENT標記的SHGetSpecialFolderLocation函 數。
OFN_ENABLEHOOK 激活在lpfnHook成員中指定的鈎子函數。
OFN_ENABLEINCLUDENOTIFY Windows 2000:當用戶打開一個文件夾時,引起對話框發送CDN_INCLUDEITEM通 知消息到你的OFNHookProc程 序。對話框為在最近打開的文件夾中的每一個項目發送一個通知。這些消息使你能夠控制那些在對話框中顯示的文件夾項目的列表。
OFN_ENABLESIZING Windows 2000,Windows 98:使Explorer風格的對話框可以使用鼠標或鍵盤調 整大小。缺省時,Explorer風格的打開和另存為對話框允許被調整大小,不顧這個標記是否被設置。這標記僅在你提供了一個鈎子程序或定制模板時是必需 的。舊風格的對話框不允許調整大小。
OFN_ENABLETEMPLATE 指出lpTemplateName成員是指向對話框模板資源的名字,這個模板資源在能被hInstance成 員識別的模塊中。

如果OFN_EXPLORER標記被設置,系統使用指定的模板去建立一個對話框,是默認Explorer風格對話框的子窗口。如果 OFN_EXPLORER標記沒有被設置,系統使用舊風格的對話框替代默認的對話框。

OFN_ENABLETEMPLATEHANDLE 指出hInstance成員能識別的包含預載對話框模板的數據塊。如果這個標記被指定的,系統忽略lpTemplateName。

如果OFN_EXPLORER標記被設置,系統使用指定的模板去建立一個對話框,是默認Explorer風格對話框的子窗口。如果 OFN_EXPLORER標記沒有被設置,系統使用模板去建立一個舊風格對話框替代默認對話框。

OFN_EXPLORER 指出任何打開或另存為對話框使用新的Explorer風格的用戶化模塊。關於更多的信息,參見Explorer-Style. Hook ProceduresExplorer-Style. Custom Templates

缺省下,打開和另存為對話框使用Explorer風格用戶界面,不顧這個標記是否設置。這個標記僅在你提供了一個鈎子程序或定制模板或設置了 OFN_ALLOWMULTISELECT標記時是必需的。

如果你想使用舊風格的界面,省略OFN_EXPLORER 標記,並且提供一個代替的舊風格模板或鈎子程序。如果你想用舊風格但不需要一個定制模板或鈎子程序,簡單的提供一個鈎子程序,讓它返回FALSE。

OFN_EXTENSIONDIFFERENT 指定用戶輸入的一個文件的擴展名與lpstrDefExt指定的擴展名不同。如果lpstrDefExt是 NULL,函數不使用這個標記。
OFN_FILEMUSTEXIST 指定用戶僅可以在文件名登錄字段中輸入已存在的文件的名字。如果這個標記被指定的並且用戶輸入了一個無效的名字,對話框 程序顯示一個等待消息框。如果這個標記被指定,OFN_PATHMUSTEXIST標記也被使用。
OFN_FORCESHOWHIDDEN Windows 2000:強制顯示系統和隱藏屬性的文件,從而壓倒用戶設置的顯示或不顯示隱藏文件。否 則,帶有系統和隱藏標記的文件不被顯示。
OFN_HIDEREADONLY 隱藏只讀復選框。
OFN_LONGNAMES 對於舊風格對話框,這個標記引起對話框使用長文件名。如果這個標記沒有被指定,或如果 OFN_ALLOWMULTISELECT標記也被設置,舊風格對話框為帶有空格的文件名使用短文件名(8.3格式)。

Explorer風格對話框忽略這個標記,通常顯示長文件名。

OFN_NOCHANGEDIR 如果當搜索文件時用戶改變了目錄的時候,恢復當前目錄到它的初始值。
OFN_NODEREFERENCELINKS 引導對話框為選擇的快捷方式(.LNK)文件返回路徑和文件名。如果這個值沒有被指定,對話框返回這個快捷方式所引用文 件的路徑和文件名。
OFN_NOLONGNAMES 對於舊風格對話框,這個標識引起對話框去使用短文件名(8.3格式)。

Explorer風格對話框忽略這個標記,通常顯示長文件名。

OFN_NONETWORKBUTTON 隱藏和顯示風格按鈕。
OFN_NOREADONLYRETURN 指定返回的文件不帶有只讀復選框,不是在寫保護的目錄中。
OFN_NOTESTFILECREATE 指定文件不是在對話框關閉前建立的。如果應用程序保存文件到一個建立的非映象風格共享上,這個標記應該被指定的。當一個 應用程序指定了這標記,庫不能檢查寫保護,磁盤滿,打開驅動器門或網絡保護。應用程序使用這個標記必須小心執行文件操作,因為一旦文件被關閉,它不能重新 打開。
OFN_NOVALIDATE 指定公共對話框允許在返回的文件名中有無效的字符。典型的,正在調用的程序使用一個鈎子程序通過FILEOKSTRING消 息檢查文件名。如果在編輯控件中的文本框是空的或只包含了空格,那么文件和目錄列表框是被更新的。如果編輯控件中的文本框包含了別的東西,那么nFileOffset 和nFileExtension的設置值是通過分析文本產生的。沒有默認的擴展名被添加到文本,也沒有文本被復制到lpstrFileTitle指 定的緩沖。

如果通過nFileOffset指定的值比0小,文件是無效的。否則,文件名是有效的。如果OFN_NOVALIDATE沒有被指 定,nFileExtension和nFileOffset可以被使用。

OFN_OVERWRITEPROMPT 如果選擇的文件已經存在,使用另存為對話框產生一個消息框。用戶必須確認是否復蓋這個文件。
OFN_PATHMUSTEXIST 指定用戶僅能輸入的路徑和文件名。如果這個標記被使用並且用戶在文件名輸入字段中鍵入了一個用效的路徑和文件名,對話框 函數顯示一個等待消息。
OFN_READONLY 當對話框建立時,顯示被選擇的只讀復選框。這個標記指出當對話框被關閉時只讀復選框的狀態。
OFN_SHAREAWARE 指出如果調用OpenFile函 數因為網絡共享沖突而失敗,這個錯誤被忽略並且對話框返回選擇的文件名。

如果這個標記沒有被設置,當用戶選擇的文件名發生網絡共享沖突時,對話框發送通知到你的鈎子程序。如果你設置了OFN_EXPLORER標記,對話 框發送CDN_SHAREVIOLATION消 息到鈎子程序。如果你沒有設置OFN_EXPLORER,對話框發送SHAREVISTRING注 冊的消息到鈎子程序。

OFN_SHOWHELP 使對話框顯示幫助按鈕。hwndOwner成員必須指定一個窗口,這個窗口作為接收對話框發送的HELPMSGSTRING注 冊的消息,當用戶單擊幫助按鈕時對話框發送這個消息。

當用戶單擊幫助按鈕時,一個Explorer風格的對話框發送CDN_HELP通 知消息到你的鈎子程序。

nFileOffset
指定從路徑開始到通過lpstrFile指定的文件名字符串基於0的偏移,以TCHARs為單位。對於 ANSI版本,是字節的個數;對於Unicode版本,是字符的個數。例如,如果lpstrFile指向下列的字符串,“c:\dir1 \dir2\file.ext”,這個成員包含指出“file.ext”字符串偏移的位置值13。

如果用戶選擇了多於一個的文件,nFileOffset是到第一個文件名的偏移。

nFileExtension
指定從路徑開始到通過lpstrFile指定的文件名字符串中擴展名基於0的偏移,以TCHARs為單 位。對於ANSI版本,是字節的個數;對於Unicode版本,是字節的個數。例如,如果lpstrFile指向下列的字符 串,“c:\dir1\dir2\file.ext”,這個成員包含的值是18。如果用戶沒有輸入一個擴展名並且lpstrDefExt是 NULL,這個成員指定的偏移是結束字符NULL。如果用戶在文件名中輸入一個“.”作為最后的字符,這個成員是0。
lpstrDefExt
指向包含默認擴展名的緩沖。如果用戶忘記輸入擴展名, GetOpenFileNameGetSaveFileName附 加這個擴展名到文件名中。這個字符串可以是任一長度,但但只有頭三個字符被附加。字符串不應該包含一個句點(.)。如果這個成員是NULL並且用戶忘記了 輸入一個擴展名,那么將沒有擴展名被附加。
lCustData
指定應用程序定義的數據,這數據是能被lpfnHook成員識別的系統傳到的鈎子程序。當系統發送 WM_INITDIALOG消 息到程序,消息的lParam參數指向當對話框建立時指定的OPENFILENAME結構。鈎子程序可以使用這個指針獲得lCustData的 值。
lpfnHook
指向一個鈎子程序。除非Flags成員中包含OFN_ENABLEHOOK標記,要么這個成員將被忽略。

如果在Flags成員中OFN_EXPLORER標記沒有被設置,lpfnHook指向一個OFNHookProcOldStyle鈎 子程序,這個程序有意的從對話框接收消息。鈎子程序返回FALSE傳遞一個消息到默認的對話框程序或返回TRUE丟棄消息。

如果OFN_EXPLORER被設置,lpfnHook指向一個OFNHookProc鈎 子程序。這個鈎子程序接收從對話框發出的通知消息。這個鈎子程序也接收你通過一個子對話框模板定義的附加控件的消息。鈎子程序不有意接收默認對話框的標准 控件的消息。

lpTemplateName
指向一個以空字符結束的字符串,字符串是對話框模板資源的名字,資源保存在能被hInstance成員識別的模塊中。對 於有限的對話框資源,這可以是通過 MAKEINTRESOURCE返 回的值。除非在Flags成員中設置了OFN_ENABLETEMPLATE標記,要么這個成員被忽略。

如果OFN_EXPLORER標記被設置,系統使用指定的模板去建立一個對話框,是默認Explorer風格對話框的子窗口。如果 OFN_EXPLORER標記沒有被設置,系統使用模板去建立一個舊風格的對話框來替代默認對話框。

pvReserved
保留。
dwReserved
保留。
FlagsEx
Windows 2000:設置位標記,你可以使用來初始化對話框。這個成員可以是下列標記的組合。
標記 含意
OFN_EX_NOPLACESBAR 如果這個標記被設置,則位置欄被不顯示。如果這個標記沒有設置,則Explorer風格的對話框包含一般使用文件圖標的 位置欄,例如像收藏夾和桌面。

=================================================================================這里是分割線=================================================================================================

好,那研究完文檔我就有點思路了,關注其中的lpstrFile字段,解釋為:如果OFN_ALLOWMULTISELECT標記被設置並且用戶選擇了多個文件,緩沖包含了當前目錄下被選擇文件的文件名。對於Explorer 風格對話框,目錄和文件名字符串是被NULL分開的,在文件名之后有一個額外的NULL。對於舊風格對話框,字符串是被空格分開的並且函數為帶有空格的文 件名使用短文件名。你可以使用FindFirstFile函 數在長短文件名之間轉換。如果用戶只選擇了一個文件,lpstrFile字符串在路徑和文件名之間沒有分隔。既然是用Null風格,那對於C#中的String在將字符轉換為String時是否在轉換的時候默認讀到Null就認為是字符串結束,之后返回轉換后的字符串呢?這樣剩下的數據就丟失了,為了驗證這個猜測,我們將ofn.flags進行些許修改,如下

//0x00080000 | ==  OFN_EXPLORER |對於舊風格對話框,目錄 和文件字符串是被空格分隔的,函數為帶有空格的文件名使用短文件名
//注意 一下項目不一定要全選 但是0x00000008項不要缺少
ofn.flags = 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008; //OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST| OFN_ALLOWMULTISELECT|OFN_NOCHANGEDIR

這樣的話就調用了舊風格的對話框,返回的是被空格分開的文件名,沒有Null字符不會被String強行結束,再次嘗試后果然如我所料~成功解決問題,但是文件名需要進行處理,可以用上述的FindFirstFile函數,也能自己寫一個,我就自己寫了一個,一起放出來了,大家拿去隨便用~

 //短文件名和長文件名之間 轉換。
    public string[] ParseFilePaths(string longFilePath)
    {
        string[] paths = longFilePath.Split(' ');
        string[] filepaths = null;
        if (paths.Length > 1)
        {
            filepaths = new string[paths.Length - 1];
            string prefixStr = paths[0];
            for (int i = 1; i < paths.Length; i++)
            {
                filepaths[i - 1] = prefixStr + paths[i];
            }

            return filepaths;
        }
        else
        {
            filepaths = new string[paths.Length];
            filepaths[0] = longFilePath;
            return filepaths;
        }
    }

參考文檔:https://www.cnblogs.com/U-tansuo/archive/2012/07/10/GetOpenFileName.html

     https://blog.csdn.net/u012194027/article/details/39968009

     https://docs.microsoft.com/en-us/windows/win32/api/commdlg/nf-commdlg-getopenfilenamea


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM