هل سبق لك أن استخدمت Adobe Photoshop؟ بالنسبة للرجال العاديين ، فإن الإضافات هي مجرد كتل رمز متوفرة للتطبيق من الخارج (على سبيل المثال ، في DLL). الفرق بين المكون الإضافي و DLL العادي هو أن المكون الإضافي لديه القدرة على توسيع وظائف التطبيق الأصل. على سبيل المثال ، ليس لدى Photoshop نفسها كمية كبيرة من وظائف معالجة الصور. تمنح إضافة المكونات الإضافية تأثيرًا رائعًا مثل الضبابية والبقعة وجميع الأنماط الأخرى ، ولا يوجد أي منها تطبيق الوالد نفسه.
هذا جيد جدًا لبرامج معالجة الصور ، ولكن لماذا تحتاج إلى إنفاق الكثير من الجهد لإكمال التطبيقات التجارية التي تدعم الإضافات؟ لنفترض ، دعنا نعطي مثالاً ، أن تطبيقك سيولد بعض التقارير. سيستمر عملاؤك بالتأكيد في طلب التحديثات أو إضافة تقارير جديدة. يمكنك استخدام مولد تقرير خارجي مثل تقرير Smith ، وهو حل غير شبيه جدًا ، يتطلب نشر ملفات إضافية ، وتدريب إضافي للمستخدمين ، وما إلى ذلك. يمكنك أيضًا استخدام QuickReport ، ولكن هذا سيضعك في كابوس التحكم في الإصدار - إذا كنت ترغب في إعادة بناء طلبك في كل مرة تقوم فيها بتغيير الخط.
ومع ذلك ، طالما قمت بإعداد التقرير في البرنامج المساعد ، يمكنك استخدامه. هل تحتاج إلى تقرير جديد؟ لا مشكلة ، ما عليك سوى تثبيت DLL وستراها في المرة القادمة التي يبدأ فيها التطبيق. مثال آخر هو تطبيق يعالج البيانات من الأجهزة الخارجية (مثل ماسحات الباركود). من خلال كتابة روتين معالجة واجهة الجهاز كمكون إضافي ، يمكنك تحقيق أقصى قدر من قابلية التوسع دون إجراء أي تغييرات على تطبيق الأصل.
ابدء
أهم شيء قبل البدء في كتابة التعليمات البرمجية هو معرفة الميزات التي يحتاج تطبيقك إلى تمديدها. وذلك لأن المكون الإضافي يتفاعل مع تطبيق الأصل من خلال واجهة محددة ، والتي سيتم تعريفها وفقًا لاحتياجاتك. في هذه المقالة ، سنقوم بإنشاء 3 مكونات إضافية لعرض عدة طرق يتفاعل المكون الإضافي مع تطبيق الأصل.
سنجعل المكون الإضافي في DLL. قبل القيام بذلك ، على الرغم من ذلك ، يتعين علينا صنع قذيفة لتحميلها واختبارها. يوضح الشكل 1 برنامج الاختبار بعد تحميل المكون الإضافي الأول. لا ينجز المكون الإضافي الأول أي شيء كبير ، وفي الواقع ، كل ما يفعله هو إرجاع سلسلة تصف نفسها. ومع ذلك ، فإنه يؤكد نقطة مهمة-ستعمل بشكل صحيح مع أو بدون تطبيقات المكونات. إذا لم يكن هناك مكون إضافي ، فلن يظهر في قائمة المكونات الإضافية المثبتة ، ولكن لا يزال بإمكان التطبيق إجراء وظائف بشكل طبيعي.
الفرق الوحيد بين مكونات المكونات الإضافية والتطبيقات العادية هو وحدة حارم في ملف مصدر المشروع الذي يظهر في جملة استخدامات والرمز الذي يقوم بتحميل ملف الإضافات. أي تطبيق يمرر معلمات السلسلة بينه وبين وحدة DLL؟ لاختبار هذه القشرة ، تحتاج إلى نسخ ملف Delphimm.Dll من دليل Delphi/Bin إلى المسار الوارد في متغير بيئة المسار أو الدليل الذي يوجد فيه التطبيق. يجب أيضًا توزيع الملف في نفس الوقت عند إصدار الإصدار النهائي.
يتم تحميل المكون الإضافي في قذيفة الاختبار هذه من خلال عملية loadplugins ، والتي تسمى في الحدث formcreate في النافذة الرئيسية ، انظر الشكل 2. تستخدم هذه العملية وظائف FindFirst و FindNext للعثور على ملفات البرنامج المساعد في الدليل الذي يوجد فيه التطبيق. بعد العثور على ملف ، استخدم عملية LoadPlugins الموضحة في الشكل 3 لتحميله.
{البحث عن ملفات البرنامج المساعد في دليل التطبيق}
الإجراء tfrmmain.loadplugins ؛
var
SR: tsearchrec ؛
المسار: سلسلة.
وجدت: عدد صحيح.
يبدأ
المسار: = extractFilePath (application.exename) ؛
يحاول
وجدت: = findFirst (path + cplugin_mask ، 0 ، sr) ؛
بينما يتم العثور عليها = 0 تبدأ
LoadPlugin (SR) ؛
وجدت: = findNext (sr) ؛
نهاية؛
أخيراً
FindClose (SR) ؛
نهاية؛
نهاية؛
{تحميل المكون الإضافي المحدد.
الإجراء tfrmmain.loadPlugin (sr: tsearchrec) ؛
var
الوصف: سلسلة ؛
libhandle: عدد صحيح.
DisclseProc: tplugindescribe ؛
يبدأ
libhandle: = loadlibrary (pchar (sr.name)) ؛
إذا كان libhandle $#@60 ؛ $#@62 ؛
يبدأ
DisclseProc: = getProcaddress (libhandle ، cplugin_describe) ؛
إذا تم تعيينه (DiscriptionProc) ثم
DescriptionProc (الوصف) ؛
memplugins.lines.add (الوصف) ؛
نهاية
آخر
يبدأ
messagedlg ('file "' + sr.name + '" ليس مكونًا مكونًا صالحًا. "،
mtinformation ، [mbok] ، 0) ؛
نهاية؛
نهاية
آخر
messagedlg ('حدث خطأ في تحميل المكون الإضافي " + +
sr.name + '".' ، mterror ، [mbok] ، 0) ؛
نهاية؛
توضح طريقة LoadPlugin جوهر آلية المكونات الإضافية. أولاً ، المكوّن المكون من DLL. ثانياً ، يتم تحميله ديناميكيًا من خلال واجهة برمجة تطبيقات التحميل. بمجرد تحميل DLL ، نحتاج إلى طريقة للوصول إلى الإجراءات والوظائف التي تحتوي عليها. توفر API GetProcaddress هذه الآلية ، التي تُرجع مؤشرًا إلى الروتين المطلوب. في عرضنا البسيط ، يحتوي المكون الإضافي فقط على إجراء يسمى DistancePlugin ، المحدد بواسطة cplugin_describe الثابت (حالة اسم الإجراء مهمة للغاية ، ويجب أن يكون الاسم الذي تم تمريره إلى getProcaddress هو نفسه تمامًا مثل الاسم الروتيني المضمن في DLL) . إذا لم يتم العثور على روتين مطلوب في DLL ، فسيقوم GetProcaddree بإرجاع NIL ، لذلك سوف توافق على استخدام الوظيفة المعينة لتحديد قيمة الإرجاع.
من أجل تخزين المؤشرات إلى وظيفة بطريقة سهلة الاستخدام ، من الضروري إنشاء نوع محدد للمتغيرات المستخدمة. لاحظ أن قيمة الإرجاع لـ getProcaddress يتم تخزينها في متغير ، DistracteProc ، تنتمي إلى نوع tplugindescribe. هنا بيانها:
يكتب
tplugindescribe = الإجراء (var desc: string) ؛
نظرًا لأن الإجراء موجود داخل DLL ، فإنه يجمع جميع إجراءات التصدير من خلال تحويلات المكالمات القياسية ، لذلك يلزم مؤشر STDCALL. تستخدم هذه العملية معلمة var ، والتي تحتوي على وصف البرنامج المساعد عند إرجاع العملية.
للاتصال بالعملية التي حصلت عليها للتو ، استخدم المتغير الذي يحفظ العنوان كاسم العملية ، يليه أي معلمات. في حالتنا ، البيان:
DescriptionProc (الوصف)
سيتم استدعاء عملية الوصف التي تم الحصول عليها في المكون الإضافي وسيتم ملء متغير الوصف بسلسلة تصف وظيفة المكون الإضافي.
المكونات الإضافية
لقد أنشأنا تطبيق الأصل ، وقد حان الوقت لإنشاء المكون الإضافي الذي نريد تحميله. ملف البرنامج المساعد هو Delphi DLL قياسي ، لذلك نقوم بإنشاء مشروع DLL جديد من Delphi IDE وحفظه. نظرًا لأن وظيفة المكونات الإضافية التي تم تصديرها ستستخدم معلمات السلسلة ، فيجب وضع وحدة المشاريع أولاً في جملة استخدام المشروع. يسرد الشكل 4 ملف مصدر المشروع الخاص بمكوننا البسيط.
يستخدم
حليمة ، sysutils ، الفصول ،
الرئيسي في "main.pas" ؛
{$ e plg.}
صادرات
تصف plugin ؛
يبدأ
نهاية.
على الرغم من أن البرنامج المساعد هو ملف DLL ، فليس هناك حاجة لإعطائه امتداد .DLL. في الواقع ، يتمثل أحد الأسباب في منحنا سببًا لتغيير الامتداد: عندما يبحث تطبيق الوالدين عن الملف المراد تحميله ، يمكن أن يكون الامتداد الجديد بمثابة قناع ملف محدد. باستخدام ملحق آخر (يستخدم مثالنا *.plg) ، يمكنك أن تكون واثقًا إلى حد ما من أن التطبيق سيقوم فقط بتحميل الملفات المقابلة. يمكن أن يحقق مؤشر التجميع $ x هذا التغيير ، أو يمكنك تعيين الامتداد من خلال صفحة تطبيق مربع حوار خيارات المشروع.
رمز المكون الإضافي للمثال الأول بسيط للغاية. يوضح الشكل 5 الرمز الموجود في وحدة جديدة. لاحظ أن النموذج الأولي لـ DiscriptionPlugin يتوافق مع نوع tplugindescribe في تطبيق shell ، ويستخدم كلمة محفوظة التصدير الإضافية لتحديد أن العملية سيتم تصديرها. سيظهر اسم العملية المصدر أيضًا في قسم الصادرات في رمز مصدر المشروع الرئيسي (المدرج في الشكل 4).
الوحدة الرئيسية ؛
واجهة
الإجراء وصف plugin (var desc: string) ؛
التصدير
تطبيق
الإجراء وصف plugin (var desc: string) ؛
يبدأ
DESC: = 'Test Plugin v1.00' ؛
نهاية؛
نهاية.
قبل اختبار هذا البرنامج المساعد ، انسخه إلى مسار التطبيق الرئيسي. تتمثل أسهل طريقة في إنشاء مكون إضافي في الدليل الفرعي للدليل المنزلي ، ثم تعيين مسار الإخراج على المسار الرئيسي (يمكن أيضًا استخدام الدلائل/الشرطية في مربع حوار خيارات المشروع لهذا الإعداد).
تصحيح
الآن اسمحوا لي أن أقدم ميزة أفضل في Delphi 3: القدرة على تصحيح DLLs من IDE. في مشروع DLL ، يمكنك تحديد برنامج كمضيف من خلال مربع RUN Paramates. بعد ذلك ، يمكنك تعيين نقاط التوقف في رمز DLL الخاص بك والضغط على F9 لتشغيله - تمامًا كما ستفعل في تطبيق عادي. ستقوم Delphi بتشغيل البرنامج المضيف المحدد ، ومن خلال تجميع DLL بمعلومات التصحيح ، توجهك إلى نقطة الإيقاف في رمز DLL.