Une petite bibliothèque C qui invoque portable le fichier natif ouvrir, le dossier Sélectionnez et l'enregistrement des fichiers. Écrivez un code de dialogue une fois et faites-le faire apparaître les boîtes de dialogue natives sur toutes les plates-formes prises en charge. Évitez de lier de grandes dépendances comme WxWidgets et Qt.
Cette bibliothèque est basée sur la boîte de dialogue de fichiers native de Michael Labbe (MLABBE / NativeFileDialog).
Caractéristiques:
C/C++ Source files (*.c;*.cpp) au lieu de (*.c;*.cpp) ) sur les plates-formes qui le prennent en chargeUntitled.c )wchar_t ) sur WindowsIFileDialog moderne de Vista sur Windowsunique_ptr autoComparaison avec la boîte de dialogue du fichier natif d'origine:
La fonctionnalité des noms amicaux est la principale raison de la rupture de la compatibilité des API avec la bibliothèque de Michael Labbe (et donc cette bibliothèque ne sera probablement jamais fusionnée avec elle). Il existe également un certain nombre de réglages qui provoquent des différences observables dans cette bibliothèque.
Fonctionnalités ajoutées dans la boîte de dialogue de fichiers native étendue:
wchar_t ) sur Windowsunique_ptr sans autoIl y a également une réfractorisation de code importante, en particulier pour l'implémentation de Windows.
Le wiki garde une trace des liaisons linguistiques connues et des projets populaires connus qui dépendent de cette bibliothèque.
#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 ;
} L' U8 / u8 dans NFDE se réfère à l'API pour les caractères UTF-8 ( char ), ce que la plupart des consommateurs veulent probablement. Une version N / n est également disponible, qui utilise le type de caractères natif ( wchar_t sur Windows et char sur d'autres plates-formes).
Pour la liste complète des arguments que vous pouvez définir sur la structure args , consultez la section "Toutes les options" ci-dessous.
Si vous utilisez un cadre d'abstraction de plate-forme tel que SDL ou GLFW, consultez également la section "Utilisation avec une plate-forme d'abstraction" ci-dessous.






Si votre projet utilise CMake, ajoutez simplement les lignes suivantes à vos CMakelists.txt:
add_subdirectory(path/to/nativefiledialog-extended)
target_link_libraries(MyProgram PRIVATE nfd)
Assurez-vous que vous avez également les dépendances nécessaires.
Lorsqu'ils sont inclus comme sous-projet, les exemples de programmes ne sont pas construits et la cible d'installation est désactivée par défaut. Ajouter -DNFD_BUILD_TESTS=ON pour créer des exemples de programmes et -DNFD_INSTALL=ON pour activer la cible d'installation.
Si vous souhaitez construire la bibliothèque statique autonome, exécutez les commandes suivantes (à partir du répertoire racine du projet):
Pour GCC et Clang:
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
Pour MSVC:
mkdir build
cd build
cmake ..
cmake --build . --config Release
Les commandes ci-dessus feront un répertoire build et construisent le projet (en mode de libération) là-bas. Si vous développez NFDE, vous voudrez peut-être faire -DCMAKE_BUILD_TYPE=Debug / --config Debug pour créer une version de débogage de la bibliothèque à la place.
Lors de la construction en tant que bibliothèque autonome, des exemples de programmes sont construits et la cible d'installation est activée par défaut. Ajouter -DNFD_BUILD_TESTS=OFF pour désactiver les programmes d'échantillons de construction et -DNFD_INSTALL=OFF pour désactiver la cible d'installation.
Sur Linux, si vous souhaitez utiliser le portail de bureau FlatPak au lieu de GTK, ajoutez -DNFD_PORTAL=ON . (Sinon, GTK sera utilisé.) Voir la section "Utilisation" ci-dessous pour plus d'informations.
Voir le fichier CI Build pour quelques exemples de commandes de construction.
Les versions récentes de Visual Studio ont un support CMake intégré à l'IDE. Vous devriez être en mesure d'ouvrir un «dossier» dans le répertoire des racines du projet, et Visual Studio reconnaîtra et configurera le projet de manière appropriée. À partir de là, vous pourrez définir des configurations pour le débogage vs version et pour x86 vs x64. Pour plus d'informations, consultez la page Microsoft Docs. Cela a été testé pour fonctionner sur Visual Studio 2019, et cela fonctionne probablement également sur Visual Studio 2017.
src/include à votre chemin de recherche inclue.nfd.lib ou nfd_d.lib à la liste des bibliothèques statiques pour lier (pour la libération ou le débogage, respectivement).build/<debug|release>/<arch> au chemin de recherche de la bibliothèque. Assurez-vous que libgtk-3-dev est installé sur votre système.
Assurez-vous que libdbus-1-dev est installé sur votre système.
Sur MacOS, ajoutez AppKit et UniformTypeIdentifiers à la liste des cadres.
Sur Windows (MSVC et MINGW), assurez-vous que vous construisez contre ole32.lib , uuid.lib et shell32.lib .
Pour ouvrir une boîte de dialogue, vous définissez des options sur une structure, puis transmettez cette structure à une fonction NFDE, par exemple:
nfdopendialogu8args_t args = { 0 };
args . filterList = filters ;
args . filterCount = 2 ;
nfdresult_t result = NFD_OpenDialogU8_With ( & outPath , & args ); Toutes les options sont facultatives et peuvent être définies individuellement (zéro initialisation définit toutes les options sur des défauts raisonnables), à l'exception de filterList et filterCount qui doit être à la fois ou les deux laissés par une gauche.
Les versions futures de NFDE peuvent ajouter des options supplémentaires à la fin de la structure des arguments sans heurter le numéro de version majeur, donc pour assurer la compatibilité en arrière de l'API, vous ne devez pas supposer que la structure a une longueur ou un nombre spécifique de champs. Vous pouvez supposer que la zéro-initialisation de la structure continuera de définir toutes les options sur des défauts raisonnables, donc l'attribution {0} à la structure est acceptable. Pour ceux qui construisent des bibliothèques partagées de NFDE, la compatibilité ABI vers l'arrière est assurée par un index de version interne ( NFD_INTERFACE_VERSION ), qui devrait être transparent pour les consommateurs.
OpenDialog / OpenDialogMultiple :
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 et filterCount : Définissez-les pour personnaliser le filtre de fichiers (il apparaît comme un menu déroulant sur Windows et Linux, mais cache simplement des fichiers sur macOS). Définissez filterList sur un pointeur jusqu'au début du tableau des éléments de filtre et filterCount le nombre d'éléments de filtre dans ce tableau. Voir la section "Syntaxe du filtre de fichiers" ci-dessous pour plus de détails.defaultPath : Définissez ceci sur le dossier par défaut auquel la boîte de dialogue doit ouvrir (sur Windows, s'il existe un dossier récemment utilisé, il s'ouvre sur ce dossier au lieu du dossier que vous passez, sauf si l'option NFD_OVERRIDE_RECENT_WITH_DEFAULT Build est définie).defaultName : (pour SAVEDIALOG UNIQUEMENT) Définissez ceci sur le nom du fichier qui doit être pré-rempli dans la boîte de dialogue.parentWindow : Réglez ceci sur la poignée de fenêtre native du parent de cette boîte de dialogue. Voir la section "Utilisation avec une plate-forme d'abstraction" pour plus de détails. Il est également possible de passer une poignée même si vous n'utilisez pas de cadre d'abstraction de plate-forme. Voir le répertoire test par exemple le code (à la fois C et C ++).
Si vous avez activé l'option pour créer le répertoire test ( -DNFD_BUILD_TESTS=ON ), build/bin contiendra les programmes de test compilés.
Il existe également un exemple SDL2, qui doit être activé séparément avec -DNFD_BUILD_SDL2_TESTS=ON . Il nécessite que SDL2 soit installé sur votre machine.
Des exemples compilés (y compris l'exemple SDL2) sont également téléchargés sous forme d'artefacts sur les actions GitHub, et peuvent être téléchargés à partir de là.
Les fichiers peuvent être filtrés par des groupes d'extension de fichiers:
nfdu8filteritem_t filters [ 2 ] = { { "Source code" , "c,cpp,cc" }, { "Headers" , "h,hpp" } };Un filtre de fichier est une paire de chaînes comprenant le nom amical et la spécification (plusieurs extensions de fichiers sont séparées par les virgules).
Une liste des filtres de fichiers peut être adoptée comme argument lors de l'invoquer la bibliothèque.
Un filtre générique est toujours ajouté à chaque boîte de dialogue.
Remarque: Sur macOS, les boîtes de dialogue des fichiers n'ont pas de noms amicaux et il n'y a aucun moyen de basculer entre les filtres, de sorte que les spécifications du filtre sont combinées (par exemple "C, CPP, CC, H, HPP"). La spécification du filtre n'est pas non plus explicitement indiquée à l'utilisateur. C'est le comportement de macOS habituel et les utilisateurs s'y attendent.
Remarque 2: Vous devez vous assurer que la chaîne de spécification n'est pas vide et que chaque extension de fichier a au moins un caractère. Sinon, de mauvaises choses pourraient s'ensuivre (c'est-à-dire un comportement non défini).
Remarque 3: Sur Linux, l'extension de fichier est ajoutée (en cas de manque) lorsque l'utilisateur appuye sur le bouton "Enregistrer". L'extension de fichier annexe restera visible pour l'utilisateur, même si une invite d'écrasement est affichée et que l'utilisateur appuie ensuite "Annuler".
Remarque 4: Sur Windows, le paramètre de dossier par défaut n'est utilisé que s'il n'y a pas de dossier récemment utilisé, sauf si l'option NFD_OVERRIDE_RECENT_WITH_DEFAULT Build est définie sur ON. Sinon, le dossier par défaut sera le dossier qui a été utilisé pour la dernière fois. En interne, l'implémentation Windows appelle IfileDialog :: setDefaultFolder (Ishellitem). C'est le comportement habituel de Windows et les utilisateurs l'attendent.
Une boîte de dialogue ouverte de fichiers qui prend en charge plusieurs sélections produit un chemin de chemin, qui est une mince abstraction par rapport à la collection spécifique à la plate-forme. Il existe deux façons d'itérer sur un chemin de chemin:
Cette méthode a un accès de type tableau sur le Pathset et est la plus facile à utiliser. Cependant, sur certaines plates-formes (Linux, et éventuellement Windows), il faut O (n 2 ) de temps au total pour itérer l'intégralité du chemin de chemin, car l'implémentation spécifique à la plate-forme sous-jacente utilise une liste liée.
Voir test_opendialogmultiple.c.
Cette méthode utilise un objet Enumerator pour itérer les chemins dans le Pathset. Il est garanti de prendre un temps (n) au total pour itérer l'intégralité du chemin.
Voir test_opendialogmultiple_enum.c.
Cette API est expérimentale et sujet à changer.
Vous pouvez définir les macros suivantes avant d'inclure nfd.h / nfd.hpp :
NFD_NATIVE : Définissez ceci avant d'inclure nfd.h pour faire des alias de fonctions non-Suffixés et de typeSeds (par exemple NFD_OpenDialog ) pour les fonctions natives (par exemple NFD_OpenDialogN ) au lieu d'alias pour les fonctions UTF-8 (par exemple NFD_OpenDialogU8 ). Cette macro n'affecte pas l'emballage C ++ nfd.hpp .NFD_THROWS_EXCEPTIONS : (C ++ uniquement) Définissez ceci avant d'inclure nfd.hpp pour fabriquer NFD::Guard Construction Throw std::runtime_error si NFD_Init échoue. Sinon, il n'y a aucun moyen de détecter l'échec dans NFD::Guard Construction. Macros qui pourraient être définies par nfd.h :
NFD_DIFFERENT_NATIVE_FUNCTIONS : Défini si les versions natives et UTF-8 des fonctions sont différentes (c'est-à-dire la compilation pour Windows); non défini autrement. Si NFD_DIFFERENT_NATIVE_FUNCTIONS n'est pas défini, les versions UTF-8 des fonctions sont des alias pour les versions natives. Cela peut être utile si vous écrivez une fonction qui souhaite fournir des surcharges selon que les fonctions natives et les fonctions UTF-8 sont les mêmes. (Native est UTF-16 ( wchar_t ) pour Windows et UTF-8 ( char ) pour Mac / Linux.) NFDE est connu pour travailler avec SDL2 et GLFW, et devrait également fonctionner avec d'autres Framworks d'abstraction de plate-forme. Cette section explique comment utiliser correctement NFDE avec de tels cadres.
L'argument parentWindow permet à l'utilisateur de donner à la boîte de dialogue un parent.
Si vous utilisez SDL2, incluez <nfd_sdl2.h> et appelez la fonction suivante pour définir la poignée de la fenêtre parent:
NFD_GetNativeWindowFromSDLWindow ( sdlWindow /* SDL_Window* */ , & args . parentWindow ); Si vous utilisez GLFW3, définissez les macros GLFW_EXPOSE_NATIVE_* décrits sur la page d'accès native GLFW, puis incluez <nfd_glfw3.h> et appelez la fonction suivante pour définir la poignée de la fenêtre parent:
NFD_GetNativeWindowFromGLFWWindow ( glfwWindow /* GLFWwindow* */ , & args . parentWindow ); Si vous utilisez un autre cadre d'abstraction de plate-forme ou non un tel framework, vous pouvez définir manuellement args.parentWindow .
Win32 (Windows), Cocoa (MacOS) et X11 (Linux) Windows sont pris en charge. Passer une fenêtre Wayland (Linux) ne fait actuellement rien (c'est-à-dire que le dialogue agit comme s'il n'avait pas de parent), mais le support est susceptible d'être ajouté à l'avenir.
Pour faire une fenêtre (dans ce cas la boîte de dialogue du fichier) rester au-dessus d'une autre fenêtre, nous devons déclarer la fenêtre inférieure comme parent de la fenêtre supérieure. Cela empêche la fenêtre de dialogue de disparaître derrière la fenêtre parent si l'utilisateur clique sur la fenêtre parent pendant l'ouverture de la boîte de dialogue. Garder la boîte de dialogue au-dessus de la fenêtre qui l'a invoquée est le comportement attendu sur tous les systèmes d'exploitation pris en charge, et donc passer la poignée de la fenêtre parent est recommandé si possible.
Vous devez initialiser NFDE après l'initialisation du cadre, et vous devez probablement désinitialiser NFDE avant de désinitialiser le cadre. En effet, certains frameworks s'attendent à être initialisés sur une "ardoise propre", et ils peuvent configurer le système d'une manière différente de NFDE. NFD_Init est généralement très prudent de ne pas perturber la configuration existante sauf si nécessaire, et NFD_Quit redonne la configuration exactement à ce qu'elle était avant l'initialisation.
Un exemple avec 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
Sur Linux, vous pouvez utiliser l'implémentation du portail au lieu de GTK, qui ouvrira le sélecteur de fichiers "natif" sélectionné par le système d'exploitation ou personnalisé par l'utilisateur. L'utilisateur doit avoir xdg-desktop-portal et un backend approprié installé (ceci est préinstallé avec les distros de bureau les plus courants), sinon NFD_ERROR sera renvoyé.
Pour utiliser l'implémentation du portail, ajoutez -DNFD_PORTAL=ON la commande build.
* Remarque: le sélecteur de dossiers est pris en charge uniquement sur Org.Freedesktop.portal.FileChoOser Interface version> = 3, ce qui correspond à XDG-Desktop-Portal version> = 1.7.1. NFD_PickFolder() interrogera la version d'interface à l'exécution et renvoie NFD_ERROR si la version est trop faible.
Contrairement à Windows et à MacOS, Linux n'a pas de sélecteur de fichiers cuit dans le système d'exploitation. Les applications Linux qui souhaitent un sélecteur de fichiers sont généralement liées à une bibliothèque qui en fournit une (comme GTK, comme dans la capture d'écran Linux ci-dessus). Il s'agit d'une solution principalement acceptable que de nombreuses applications utilisent, mais peuvent rendre le sélecteur de fichiers à l'étranger sur les distros non GTK.
Flatpak a été introduit en 2015, et avec elle est venue une interface standardisée pour ouvrir un sélecteur de fichiers. Les applications utilisant cette interface n'avaient pas besoin de venir avec un sélecteur de fichiers et pouvaient utiliser celle fournie par FlatPak. Cette interface est devenue connue sous le nom de portail de bureau, et son utilisation s'est étendue aux applications non FlatPak. Désormais, la plupart des principales distros de Linux de bureau sont livrées avec le portail de bureau installé, avec des sélecteurs de fichiers qui correspondent au thème de la distribution. Les utilisateurs peuvent également installer un autre backend de portail si vous le souhaitez. Il existe actuellement trois backends connus avec le support de sélecteur de fichiers: GTK, KDE et LXQT; GNOME et XAPP Les backends dépendent de celui GTK pour cette fonctionnalité. Le backend Xapp a été conçu pour la cannelle, le compagnon et le XFCE. D'autres environnements de bureau ne semblent pas avoir actuellement de backend de portail.
Info.plist conformément à la documentation Apple. (Il est possible de forcer NFDE à utiliser les pertes en ajoutant -DNFD_USE_ALLOWEDCONTENTTYPES_IF_AVAILABLE=OFF à votre commande Cmake Build, mais cela n'est pas recommandé. Si vous avez besoin de prendre en charge les versions macointes plus anciennes, vous devez définir la bonne cible de déploiement à la place.)GetOpenFileName . (Il n'est pas prévu de prendre en charge cela; vous ne devriez pas encore utiliser Windows XP.)Veuillez utiliser le suivi du problème GitHub pour signaler les bogues ou pour contribuer à ce référentiel. N'hésitez pas à soumettre des rapports de bogues de toute nature.
Bernard Teo (ME) et d'autres contributeurs pour tout ce qui n'était pas de la boîte de dialogue de fichiers native de Michael Labbe.
Michael Labbe pour sa bibliothèque de dialogue de fichiers natif impressionnants et les autres contributeurs de cette bibliothèque.
Une grande partie de cette lecture a également été copiée à partir de la lecture du référentiel de dialogue de fichiers natif d'origine.
Tout dans ce référentiel est distribué sous la licence ZLIB, tout comme la bibliothèque de dialogue de fichiers native d'origine.
Je ne fournit aucun soutien payant. Michael Labbe semble fournir un soutien rémunéré à sa bibliothèque au moment de la rédaction du moment de la rédaction.