一個小型庫庫,該庫可隨時調用本機文件打開,文件夾選擇和文件保存對話框。一次編寫對話框代碼,然後在所有受支持的平台上彈出本機對話框。避免將諸如WXWIDGETS和QT之類的大依賴關係鏈接。
該庫基於Michael Labbe的本機文件對話框(Mlabbe/nativalfiledialog)。
特徵:
C/C++ Source files (*.c;*.cpp)而不是(*.c;*.cpp) )Untitled.c )wchar_t )支持IFileDialogunique_ptr自動釋放語義和可選參數,適用於C ++使用此庫的人與原始本機文件對話框進行比較:
友好名稱功能是與Michael Labbe庫中API兼容的主要原因(因此,該庫可能永遠不會與之合併)。也有許多調整在此庫中引起可觀察到的差異。
本機文件對話框中添加的功能擴展:
wchar_t )支持unique_ptr自動釋放語義和可選參數還有重要的代碼折射,尤其是對於Windows實現。
Wiki跟踪依賴該庫的已知語言綁定和已知的流行項目。
#include <nfd.h>
#include <stdio.h>
#include <stdlib.h>
int main ( void )
{
NFD_Init ();
nfdu8char_t * outPath ;
nfdu8filteritem_t filters [ 2 ] = { { "Source code" , "c,cpp,cc" }, { "Headers" , "h,hpp" } };
nfdopendialogu8args_t args = { 0 };
args . filterList = filters ;
args . filterCount = 2 ;
nfdresult_t result = NFD_OpenDialogU8_With ( & outPath , & args );
if ( result == NFD_OKAY )
{
puts ( "Success!" );
puts ( outPath );
NFD_FreePathU8 ( outPath );
}
else if ( result == NFD_CANCEL )
{
puts ( "User pressed cancel." );
}
else
{
printf ( "Error: %sn" , NFD_GetError ());
}
NFD_Quit ();
return 0 ;
} NFDE中的U8 / u8是指大多數消費者可能想要的UTF-8字符( char )的API。還可以使用N / n版本,該版本使用本機字符類型(Windows上的wchar_t和其他平台上的char )。
有關您可以在args結構上設置的參數的完整列表,請參見下面的“所有選項”部分。
如果您使用的是平台抽象框架(例如SDL或GLFW),請參見下面的“使用平台抽象框架的使用”部分。






如果您的項目使用Cmake,只需將以下幾行添加到您的cmakelists.txt:
add_subdirectory(path/to/nativefiledialog-extended)
target_link_libraries(MyProgram PRIVATE nfd)
確保您還具有所需的依賴關係。
當包含作為子標記時,未構建示例程序,並且默認情況下禁用了安裝目標。添加-DNFD_BUILD_TESTS=ON構建示例程序, -DNFD_INSTALL=ON啟用安裝目標。
如果要構建獨立的靜態庫,請執行以下命令(從項目root目錄開始):
對於GCC和Clang:
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
對於MSVC:
mkdir build
cd build
cmake ..
cmake --build . --config Release
以上命令將製作一個build目錄,並在此處構建項目(以發布模式)。如果您正在開發NFDE,則可能需要執行-DCMAKE_BUILD_TYPE=Debug / --config Debug ,以構建庫的調試版本。
當作為獨立庫構建時,會構建示例程序,並且默認情況下啟用了安裝目標。添加-DNFD_BUILD_TESTS=OFF禁用構建示例程序和-DNFD_INSTALL=OFF以禁用安裝目標。
在Linux上,如果要使用FlatPak桌面門戶而不是GTK,請添加-DNFD_PORTAL=ON 。 (否則,將使用GTK。)有關更多信息,請參見下面的“使用”部分。
有關一些示例構建命令,請參見CI構建文件。
Visual Studio的最新版本具有IDE中內置的CMAKE支持。您應該能夠在項目根目錄中“打開文件夾”,而Visual Studio將適當識別和配置項目。從那裡,您將能夠為Debug vs Release設置配置,以及X86與X64的配置。有關更多信息,請參見Microsoft文檔頁面。已經對此進行了測試以在Visual Studio 2019上工作,並且可能在Visual Studio 2017上工作。
src/include您的包含搜索路徑。nfd.lib或nfd_d.lib添加到要鏈接的靜態庫列表(分別用於發布或調試)。build/<debug|release>/<arch>添加到庫搜索路徑。 確保系統上安裝了libgtk-3-dev 。
確保系統上安裝了libdbus-1-dev 。
在MacOS上,將AppKit和UniformTypeIdentifiers添加到框架列表中。
在Windows(MSVC和MINGW)上,確保您正在針對ole32.lib , uuid.lib和shell32.lib進行構建。
要打開對話框,您可以在結構上設置選項,然後將該結構傳遞給NFDE函數,例如:
nfdopendialogu8args_t args = { 0 };
args . filterList = filters ;
args . filterCount = 2 ;
nfdresult_t result = NFD_OpenDialogU8_With ( & outPath , & args );所有選項都是可選的,可以單獨設置(零初始化設置所有選項以合理默認值),除了filterList和filterCount之外,必須設置或兩者都不設置。
NFDE的未來版本可能會在參數結構的末尾添加其他選項,而不會撞擊主要版本編號,因此為了確保向後API兼容性,您不應假設結構具有特定的長度或字段數。您可以假設結構的零限制將繼續將所有選項設置為合理的默認設置,因此將{0}分配給結構是可以接受的。對於那些構建NFDE的共享庫,內部版本索引( NFD_INTERFACE_VERSION )確保向後ABI兼容性,預計將對消費者透明。
opendialog / opendialogmultiph :
typedef struct {
const nfdu8filteritem_t * filterList ;
nfdfiltersize_t filterCount ;
const nfdu8char_t * defaultPath ;
nfdwindowhandle_t parentWindow ;
} nfdopendialogu8args_t ;Savedialog :
typedef struct {
const nfdu8filteritem_t * filterList ;
nfdfiltersize_t filterCount ;
const nfdu8char_t * defaultPath ;
const nfdu8char_t * defaultName ;
nfdwindowhandle_t parentWindow ;
} nfdsavedialogu8args_t ;PickFolder / PickFoldermultiple :
typedef struct {
const nfdu8char_t * defaultPath ;
nfdwindowhandle_t parentWindow ;
} nfdpickfolderu8args_t ;filterList和filterCount :將它們設置為自定義文件過濾器(它顯示為Windows和Linux上的下拉菜單,但只是隱藏了MacOS上的文件)。將filterList設置為指針,以啟用過濾器項目數組的開始,並將filterCount到該數組中的過濾器項目數量。有關詳細信息,請參見下面的“文件過濾器語法”部分。defaultPath :將其設置為對話框應打開的默認文件夾(在Windows上,如果有最近使用的文件夾,則它將打開到該文件夾而不是您通過的文件夾,除非NFD_OVERRIDE_RECENT_WITH_DEFAULT build構建選項設置為ON)。defaultName :(僅適用於Savedialog)將其設置為應該在對話框上預先填充的文件名。parentWindow :將此設置為此對話框的父窗口的本機窗口句柄。有關詳細信息,請參見“使用平台抽象框架的使用”部分。即使您不使用平台抽象框架,也可以通過手柄傳遞。 有關示例代碼(C和C ++),請參見test目錄。
如果打開構建test目錄的選項( -DNFD_BUILD_TESTS=ON ),則build/bin將包含編譯的測試程序。
還有一個SDL2示例,需要使用-DNFD_BUILD_SDL2_TESTS=ON分別啟用。它需要安裝在計算機上的SDL2。
編譯的示例(包括SDL2示例)也被上傳為github動作的手工藝品,可以從那裡下載。
文件可以通過文件擴展程序組過濾:
nfdu8filteritem_t filters [ 2 ] = { { "Source code" , "c,cpp,cc" }, { "Headers" , "h,hpp" } };文件過濾器是一對包含友好名稱和規範的字符串(多個文件擴展程序是逗號分隔的)。
調用庫時,可以將文件過濾器的列表作為參數傳遞。
通配符濾波器總是添加到每個對話框中。
注意:在MACOS上,文件對話框沒有友好的名稱,也無法在過濾器之間切換,因此將過濾器規範組合在一起(例如“ C,CPP,CC,CC,H,HPP”)。過濾器規範也永遠不會明確顯示給用戶。這是通常的MacOS行為,用戶期望這一點。
注2:您必須確保規範字符串是非空字符串,並且每個文件擴展名至少具有一個字符。否則,可能會發生壞事(即不確定的行為)。
注3:在Linux上,當用戶按下“保存”按鈕時,將附加文件擴展名(如果丟失)。即使顯示了覆蓋提示,並且用戶按“ CANCAL”顯示了附加的文件擴展名,即使顯示了覆蓋提示。
注4:在Windows上,默認文件夾參數僅在沒有最近使用的文件夾時才使用,除非NFD_OVERRIDE_RECENT_WITH_DEFAULT構建選項設置為ON。否則,默認文件夾將是上次使用的文件夾。在內部,Windows實現了IFILEDIALOG :: SETDEFAULTFOLDER(ISHELLITEM)。這是通常的Windows行為,用戶期望它。
支持多個選擇的文件打開對話框會產生一個路徑集,這是平台特定集合的薄抽象。有兩種方法可以迭代路徑集:
此方法確實在路徑集中確實像數組一樣訪問,並且最容易使用。但是,在某些平台(Linux,可能是Windows)上,總共需要O(n 2 )時間才能迭代整個路徑集,因為基礎平台特定的實現使用了鏈接列表。
參見test_opendialogmultiple.c。
該方法使用枚舉對象來迭代路徑集中的路徑。保證總共需要O(n)時間才能迭代整個路徑集。
請參閱test_opendialogmultiple_enum.c。
該API是實驗性的,可能會改變。
您可以在包括nfd.h / nfd.hpp之前定義以下宏:
NFD_NATIVE :在包含nfd.h之前定義此問題以製作本機函數(例如NFD_OpenDialog )的非填充功能名稱和Typedef(例如NFD_OpenDialogN )別名,而不是utf-8函數的別名(例如NFD_OpenDialogU8 )。該宏不影響C ++包裝器nfd.hpp 。NFD_THROWS_EXCEPTIONS :(僅C ++)在包含nfd.hpp之前定義此問題,以使NFD::Guard Construction Throw Throw std::runtime_error如果NFD_Init失敗。否則,將無法檢測到NFD::Guard建築中的故障。 nfd.h可能定義的宏:
NFD_DIFFERENT_NATIVE_FUNCTIONS :定義函數的本機和UTF-8版本不同(即windows編譯);沒有另外定義。如果未定義NFD_DIFFERENT_NATIVE_FUNCTIONS ,則功能的UTF-8版本是本機版本的別名。如果您正在編寫想要根據本機函數和UTF-8函數相同的函數來提供過載的函數,這可能很有用。 (本機是Windows的UTF-16( wchar_t )和Mac/Linux的UTF-8( char )。) 眾所周知,NFDE可以與SDL2和GLFW合作,還應與其他平台抽象的雜物合作。本節說明瞭如何在此類框架中正確使用NFDE。
parentWindow參數允許用戶將對話框作為父。
如果使用SDL2,請包括<nfd_sdl2.h> ,並調用以下功能設置父窗口句柄:
NFD_GetNativeWindowFromSDLWindow ( sdlWindow /* SDL_Window* */ , & args . parentWindow );如果使用GLFW3,請定義GLFW本機訪問頁面上描述的適當的GLFW_EXPOSE_NATIVE_*宏,然後包含<nfd_glfw3.h>並調用以下功能以設置父窗口hander:
NFD_GetNativeWindowFromGLFWWindow ( glfwWindow /* GLFWwindow* */ , & args . parentWindow );如果您正在使用另一個平台抽象框架,或者不使用任何此類框架,則可以手動設置args.parentWindow 。
支持Win32(Windows),可可(MacOS)和X11(Linux)Windows。通過一個Wayland(Linux)窗口當前什麼都不做(即對話框的作用,就好像沒有父母一樣),但是將來可能會添加支持。
要製作一個窗口(在這種情況下,文件對話框)停留在另一個窗口上方,我們需要將底部窗口聲明為頂部窗口的父。如果用戶在對話框打開時,用戶單擊“父”窗口,則可以防止對話框窗口在父窗口後面消失。將對話框保留在窗口上方調用的是所有受支持的操作系統上的預期行為,因此,如果可能的話,建議通過父窗口句柄。
您應該在初始化框架後初始化NFDE,並且可能在降低框架之前將NFDE降低。這是因為某些框架期望在“乾淨的板岩”上初始化,並且它們可能以與NFDE不同的方式配置系統。 NFD_Init通常非常小心,不要在必要時破壞現有配置,並且NFD_Quit將配置完全恢復到初始化之前的配置。
SDL2的示例:
// Initialize SDL2 first
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) != 0) {
// display some error here
}
// Then initialize NFDe
if (NFD_Init() != NFD_OKAY) {
// display some error here
}
/*
Your main program goes here
*/
NFD_Quit(); // deinitialize NFDe first
SDL_Quit(); // Then deinitialize SDL2
在Linux上,您可以使用門戶實現,而不是GTK,該實現將打開由OS選擇的“本機”文件選擇器或用戶自定義的。用戶必須具有xdg-desktop-portal ,並安裝了合適的後端(這是由最常見的桌面發行版預裝),否則將返回NFD_ERROR 。
要使用門戶實現,請添加-DNFD_PORTAL=ON to build命令。
*注意:僅在org.freedesktop.portal.filechooser接口版本> = 3上支持文件夾選擇器,該版本對應於XDG-DESKTOP-PORTAL版本> = 1.7.1。 NFD_PickFolder()將在運行時查詢接口版本,並在版本太低時返回NFD_ERROR 。
與Windows和MacOS不同,Linux沒有將文件選擇器烘烤到操作系統中。想要文件選擇器的Linux應用程序通常與提供一個的庫(例如GTK,如上面的Linux屏幕截圖)鏈接。這是許多應用程序使用的最可接受的解決方案,但可能會使文件選擇器在非GTK發行版上看起來外觀。
Flatpak於2015年推出,隨之而來的是一個標準化的接口來打開文件選擇器。使用此接口的應用程序不需要隨附文件選擇器,並且可以使用Flatpak提供的應用程序。該界面被稱為桌面門戶,其使用擴展到非Flatpak應用程序。現在,大多數主要的桌面Linux發行版都安裝了桌面門戶,其中適合該發行版主題的文件選擇器。如果需要,用戶還可以安裝其他門戶後端。目前有三個已知的後端具有文件選擇器支持:GTK,KDE和LXQT; GNOME和XAPP後端取決於GTK ONE的功能。 XAPP後端是為肉桂,伴侶和XFCE設計的。其他桌面環境似乎目前沒有門戶後端。
Info.plist文件中定義數據類型。 (可以通過添加-DNFD_USE_ALLOWEDCONTENTTYPES_IF_AVAILABLE=OFF來強迫NFDE使用允許的filetypes,但不建議您支持舊的macOS版本。GetOpenFileName 。 (沒有計劃支持這一點;無論如何您都不應該使用Windows XP。)請使用GitHub問題跟踪器報告錯誤或為此存儲庫做出貢獻。隨時提交任何類型的錯誤報告。
Bernard Teo(ME)和其他所有內容都不是Michael Labbe的本地文件對話框。
Michael Labbe的本機文件對話框以及該庫的其他貢獻者。
此讀數的大部分也已從原始本機文件對話框存儲庫中復制。
此存儲庫中的所有內容均以ZLIB許可證分配,原始本機文件對話框也是如此。
我不提供任何付費支持。邁克爾·拉貝(Michael Labbe)在撰寫本文時似乎為他的圖書館提供了付費支持。