مكتبة C الصغيرة التي تستدعي ملفًا أصليًا مفتوحًا ، وحوار تحديد المجلد والملف. اكتب رمز الحوار مرة واحدة وجعله يطفو على الحوار الأصلي على جميع الأنظمة الأساسية المدعومة. تجنب ربط تبعيات كبيرة مثل WXWidgets و QT.
تعتمد هذه المكتبة على مربع حوار ملف Michael Labbe الأصلي (Mlabbe/NativeFileDialog).
سمات:
C/C++ Source files (*.c;*.cpp) بدلاً من (*.c;*.cpp) .Untitled.c )wchar_t ) دعم على WindowsIFileDialog على Windowsunique_ptr والمعلمات الاختيارية ، لأولئك الذين يستخدمون هذه المكتبة من C ++مقارنة مع مربع حوار الملف الأصلي الأصلي:
ميزة الأسماء الودية هي السبب الرئيسي لكسر توافق API مع مكتبة Michael Labbe (وبالتالي ربما لن يتم دمج هذه المكتبة معها). هناك أيضًا عدد من التعديلات التي تسبب اختلافات يمكن ملاحظتها في هذه المكتبة.
تم تمديد الميزات المضافة في مربع الحوار المحلي:
wchar_t ) دعم على Windowsunique_ptr والمعلمات الاختيارية والمعلمات الاختياريةهناك أيضًا انكسار رمز مهم ، خاصة بالنسبة لتنفيذ Windows.
يتتبع الويكي روابط اللغة المعروفة والمشاريع الشائعة المعروفة التي تعتمد على هذه المكتبة.
#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 ;
} تشير U8 / u8 في NFDE إلى API لأحرف UTF-8 ( char ) ، والتي ربما يريدها معظم المستهلكين. يتوفر إصدار N / n أيضًا ، والذي يستخدم نوع الحرف الأصلي ( wchar_t على Windows و char على منصات أخرى).
للحصول على القائمة الكاملة للوسائط التي يمكنك تعيينها على بنية args ، راجع قسم "All Options" أدناه.
إذا كنت تستخدم إطار عمل تجريد النظام الأساسي مثل SDL أو GLFW ، فابحث أيضًا قسم "الاستخدام مع إطار تجريد النظام الأساسي" أدناه.






إذا كان مشروعك يستخدم cmake ، فما عليك سوى إضافة الأسطر التالية إلى cmakelists.txt:
add_subdirectory(path/to/nativefiledialog-extended)
target_link_libraries(MyProgram PRIVATE nfd)
تأكد من أن لديك أيضًا التبعيات المطلوبة.
عندما يتم تضمينها على أنها محمية فرعية ، لا يتم تصميم برامج العينة ويتم تعطيل هدف التثبيت افتراضيًا. أضف -DNFD_BUILD_TESTS=ON تشغيل برامج عينة و -DNFD_INSTALL=ON لتمكين هدف التثبيت.
إذا كنت ترغب في إنشاء المكتبة الثابتة المستقلة ، قم بتنفيذ الأوامر التالية (بدءًا من دليل جذر المشروع):
لـ 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 لديها دعم cmake مدمج في IDE. يجب أن تكون قادرًا على "فتح المجلد" في دليل جذر المشروع ، وسيقوم Visual Studio بالتعرف على المشروع وتكوينه بشكل مناسب. من هناك ، ستتمكن من تعيين تكوينات لإصدار Debug vs ، و 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 ، يتم ضمان توافق ABI للخلف من خلال مؤشر الإصدار الداخلي ( NFD_INTERFACE_VERSION ) ، والذي من المتوقع أن يكون شفافًا للمستهلكين.
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 و filterCount : قم بتعيينها لتخصيص مرشح الملف (يظهر كقائمة منسدلة على Windows و Linux ، ولكن ببساطة يخفي الملفات على MacOS). قم بتعيين filterList على مؤشر إلى بداية مجموعة عناصر التصفية filterCount إلى عدد عناصر التصفية في تلك الصفيف. راجع قسم "بناء جملة الملفات" أدناه للحصول على التفاصيل.defaultPath : قم بتعيين هذا على المجلد الافتراضي الذي يجب أن يفتحه مربع الحوار (على Windows ، إذا كان هناك مجلد تم استخدامه مؤخرًا ، فهو يفتح على هذا المجلد بدلاً من المجلد الذي تمريره ، ما لم يتم تعيين خيار بناء NFD_OVERRIDE_RECENT_WITH_DEFAULT على تشغيله).defaultName : (من أجل حفظها فقط) قم بتعيين هذا على اسم الملف الذي يجب أن يكون مملوءًا مسبقًا في مربع الحوار.parentWindow : اضبط هذا على مقبض النافذة الأصلية لمدى الحوار هذا. راجع قسم "الاستخدام مع إطار تجريد النظام الأساسي" للحصول على التفاصيل. من الممكن أيضًا تمرير مقبض حتى لو لم تستخدم إطارًا للتجريد من النظام الأساسي. راجع دليل test على سبيل المثال رمز (كلا C و C ++).
إذا قمت بتشغيل خيار إنشاء دليل 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" } };مرشح الملف هو زوج من الأوتار التي تضم الاسم الودي والمواصفات (امتدادات الملفات المتعددة مفصولة بفاصلة).
يمكن تمرير قائمة مرشحات الملفات كوسيطة عند استدعاء المكتبة.
تتم إضافة مرشح بطاقة Wildcard دائمًا إلى كل مربع حوار.
ملاحظة: في MacOS ، لا تحتوي مربعات حوار الملفات على أسماء ودية ولا توجد طريقة للتبديل بين المرشحات ، بحيث يتم الجمع بين مواصفات المرشح (على سبيل المثال "C ، CPP ، CC ، H ، HPP"). لا يتم عرض مواصفات المرشح بشكل صريح للمستخدم. هذا هو سلوك MacOS المعتاد ويتوقع المستخدمون ذلك.
ملاحظة 2: يجب عليك التأكد من أن سلسلة المواصفات غير فارغة وأن كل ملحق ملف له حرف واحد على الأقل. خلاف ذلك ، قد تتلاشى الأشياء السيئة (أي السلوك غير المحدد).
ملاحظة 3: في Linux ، يتم إلحاق ملحق الملف (إذا فقد) عندما يضغط المستخدم على زر "حفظ". سيبقى ملحق الملف المرسل مرئيًا للمستخدم ، حتى إذا تم عرض موجه في الكتابة فوقه ، ثم يضغط المستخدم على "إلغاء".
ملاحظة 4: على Windows ، يتم استخدام معلمة المجلد الافتراضي فقط إذا لم يكن هناك مجلد لم يتم استخدامه مؤخرًا ، إلا إذا تم تعيين خيار بناء NFD_OVERRIDE_RECENT_WITH_DEFAULT على تشغيله. خلاف ذلك ، سيكون المجلد الافتراضي هو المجلد الذي تم استخدامه آخر مرة. داخليًا ، يستدعي تطبيق Windows IfileDialog :: setDefaultFolder (Ishellitem). هذا هو سلوك Windows المعتاد ويتوقع المستخدمون ذلك.
يؤدي مربع حوار فتح الملف الذي يدعم التحديد المتعدد إلى إنتاج مسار ، وهو عبارة عن تجريد رفيع على المجموعة الخاصة بالنظام الأساسي. هناك طريقتان للتكرار عبر المسار:
هذه الطريقة لا تشبه الصفيف على Pathset ، وهي الأسهل للاستخدام. ومع ذلك ، على منصات معينة (Linux ، وربما Windows) ، يستغرق الأمر (n 2 ) الوقت في المجموع لتكرار المسار بأكمله ، لأن التنفيذ الأساسي الخاص للنظام الأساسي يستخدم قائمة مرتبطة.
انظر test_opendialogmultiple.c.
تستخدم هذه الطريقة كائن التعداد لتكرار المسارات في Pathset. من المضمون أن تأخذ وقتًا (ن) في المجموع لتكرار المسار بأكمله.
انظر test_opendialogmultiple_enum.c.
واجهة برمجة التطبيقات هذه تجريبية ، وتخضع للتغيير.
يمكنك تحديد وحدات الماكرو التالية قبل تضمين nfd.h / nfd.hpp :
NFD_NATIVE : حدد هذا قبل تضمين nfd.h لجعل أسماء الوظائف غير المقلدة و typedefs (مثل NFD_OpenDialog ) الأسماء الأسماء للوظائف الأصلية (مثل NFD_OpenDialogN CON) بدلاً من الأسماء المستعارة لوظائف UTF-8 (مثل NFD_OpenDialogU8 ). هذا الماكرو لا يؤثر على c ++ غلاف nfd.hpp .NFD_THROWS_EXCEPTIONS : (c ++ فقط) حدد هذا قبل تضمين nfd.hpp لجعل NFD::Guard Construction رمي std::runtime_error إذا فشل NFD_Init . خلاف ذلك ، لا توجد طريقة للكشف عن الفشل في بناء NFD::Guard . وحدات الماكرو التي يمكن تعريفها بواسطة nfd.h :
NFD_DIFFERENT_NATIVE_FUNCTIONS : محددة إذا كانت الإصدارات الأصلية و UTF-8 من الوظائف مختلفة (أي تجميع للنظام النووي) ؛ لم يتم تعريفها خلاف ذلك. إذا لم يتم تعريف NFD_DIFFERENT_NATIVE_FUNCTIONS ، فإن إصدارات UTF-8 من الوظائف هي أسماء مستعارة للإصدارات الأصلية. قد يكون هذا مفيدًا إذا كنت تكتب وظيفة ترغب في توفير عمليات تحميل زائدة اعتمادًا على ما إذا كانت الوظائف الأصلية ووظائف UTF-8 هي نفسها. (الأصلي هو UTF-16 ( wchar_t ) لنظام التشغيل Windows و UTF-8 ( char ) لـ Mac/Linux.) من المعروف أن NFDE تعمل مع SDL2 و GLFW ، ويجب أن تعمل أيضًا مع إطارات تجريد المنصات الأخرى. يشرح هذا القسم كيفية استخدام NFDE بشكل صحيح مع هذه الأطر.
تتيح وسيطة parentWindow للمستخدم إعطاء مربع الحوار أحد الوالدين.
في حالة استخدام SDL2 ، قم بتضمين <nfd_sdl2.h> واتصل بالوظيفة التالية لتعيين مقبض النافذة الأصل:
NFD_GetNativeWindowFromSDLWindow ( sdlWindow /* SDL_Window* */ , & args . parentWindow ); في حالة استخدام GLFW3 ، حدد وحدات الماكرو GLFW_EXPOSE_NATIVE_* الموضحة في صفحة الوصول الأصلي GLFW ، ثم قم بتضمين <nfd_glfw3.h> واتصل بالوظيفة التالية لتعيين مقبض النافذة الأصل:
NFD_GetNativeWindowFromGLFWWindow ( glfwWindow /* GLFWwindow* */ , & args . parentWindow ); إذا كنت تستخدم إطارًا آخر للتجريد من النظام الأساسي ، أو لا تستخدم أي إطار من هذا القبيل ، فيمكنك تعيين args.parentWindow يدويًا.
يتم دعم Win32 (Windows) و Cocoa (MacOS) و X11 (Linux). لا يفعل نافذة 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 ، والذي سيفتح مختار الملف "الأصلي" الذي تم تحديده بواسطة نظام التشغيل أو مخصص من قبل المستخدم. يجب أن يكون لدى المستخدم xdg-desktop-portal وخلفية مناسبة مثبتة (يأتي هذا مثبتًا مسبقًا مع أكثر توزيعات سطح المكتب الشائعة) ، وإلا سيتم إرجاع NFD_ERROR .
لاستخدام تنفيذ البوابة ، أضف -DNFD_PORTAL=ON الأمر.
*ملاحظة: يتم دعم منتقي المجلد فقط على org.freedesktop.portal.filechooser jettifice إصدار> = 3 ، والذي يتوافق مع إصدار XDG-desktop-portal> = 1.7.1. سيقوم NFD_PickFolder() بالاستعلام عن إصدار الواجهة في وقت التشغيل ، وإرجاع NFD_ERROR إذا كان الإصدار منخفضًا جدًا.
على عكس Windows و MacOS ، لا يحتوي Linux على مختار ملف مخبوز في نظام التشغيل. عادةً ما ترتبط تطبيقات Linux التي تريد اختيار ملفات مع مكتبة توفر واحدة (مثل GTK ، كما في لقطة الشاشة Linux أعلاه). هذا هو الحل المقبول في الغالب الذي تستخدمه العديد من التطبيقات ، ولكن قد يجعل مختار الملف يبدو أجنبيًا على توزيعات غير GTK.
تم تقديم Flatpak في عام 2015 ، ومعها جاءت واجهة موحدة لفتح ملف محدد ملفات. لا تحتاج التطبيقات التي تستخدم هذه الواجهة إلى الحصول على مختار ملف ، ويمكن أن تستخدم التسلط الذي توفره FlatPak. أصبحت هذه الواجهة معروفة باسم بوابة سطح المكتب ، وتم توسيع استخدامها إلى تطبيقات غير متوفرة. الآن ، تأتي معظم توزيعات Linux الرئيسية الرئيسية مع تثبيت بوابة سطح المكتب ، مع مختارات الملفات التي تتناسب مع موضوع التوزيعات. يمكن للمستخدمين أيضًا تثبيت الواجهة الخلفية بوابة مختلفة إذا رغبت في ذلك. يوجد حاليًا ثلاثة نماذج معروفة مع دعم الملفات: GTK ، KDE ، و LXQT ؛ يعتمد الخلفية الخلفية Gnome و XAPP على GTK واحد لهذه الوظيفة. تم تصميم الواجهة الخلفية XAPP للقرفة ، ماتي ، XFCE. لا يبدو أن بيئات سطح المكتب الأخرى لديها حاليا بوابة خلفية.
Info.plist وفقًا لوثائق Apple. (من الممكن إجبار NFDE على استخدام ExherFileTypes عن طريق إضافة -DNFD_USE_ALLOWEDCONTENTTYPES_IF_AVAILABLE=OFF إلى أمر إنشاء CMAKE الخاص بك ، ولكن هذا غير مستحسن.GetOpenFileName . (لا توجد خطط لدعم هذا ؛ يجب ألا تظل تستخدم Windows XP على أي حال.)يرجى استخدام متتبع قضية Github للإبلاغ عن الأخطاء أو للمساهمة في هذا المستودع. لا تتردد في تقديم تقارير الأخطاء من أي نوع.
Bernard Teo (ME) وغيرهم من المساهمين في كل ما لم يكن من مربع حوار ملف Michael Labbe الأصلي.
Michael Labbe لمكتبة الحوار المحلية الرائعة الخاصة به ، والمساهمين الآخرين في تلك المكتبة.
تم نسخ الكثير من هذا ReadMe أيضًا من مستودع حوار الملف الأصلي الأصلي.
يتم توزيع كل شيء في هذا المستودع بموجب ترخيص ZLIB ، وكذلك مكتبة مربعات الحوار الأصلية الأصلية.
أنا لا أقدم أي دعم مدفوع. يبدو أن مايكل لاببي يقدم الدعم المدفوع لمكتبته في وقت كتابة هذا التقرير.