تتطلب برمجة بنية البرنامج الإضافي حاوية مكون إضافي للتحكم في تشغيل كل ملف DLL، وترتيب كل نظام فرعي مقسم إلى ملف مكتبة DLL. يحتاج كل برنامج DLL إلى حجز وظائف الواجهة للحاوية. بشكل عام، تتضمن وظائف الواجهة: الوظائف التي تبدأ في استدعاء مكتبة DLL والوظائف التي تغلق مكتبة DLL. من خلال وظيفة الواجهة، يمكن لحاوية المكونات الإضافية تمرير المعلمات إلى وحدة DLL لتحقيق التحكم الديناميكي. سأشرح تفاصيل التنفيذ المحددة وأعطي رمز الاستجابة أدناه.
قد تحتاج أولاً إلى فهم بنية UNIT وبنية المشاريع في DELPHI. لا تناقش هذه المقالة التفاصيل النظرية لبرمجة DLL بشكل متعمق، ولكنها توضح فقط بعض الرموز العملية التي كنت أدرسها في كتاب "DELPHI In-deep Programming" للكاتب Liu Yi.
أنا أيضًا في المرحلة التمهيدية لـ DELPHI وأشعر أن هناك بعض الأشياء التي تستحق المناقشة في تطوير DLL هذا، لذا أكتب هذا المقال وآمل أن تتمكن من تقديم اقتراحات سخية لما لا أفعله جيدًا.
مقدمة لبرنامج العينة
لتسهيل القراءة، سأستخدم جزءًا من كود البرنامج الخاص بنظام MIS لتوضيح بعض طرق برمجة المكونات الإضافية. نموذج البرنامج عبارة عن تطبيق نموذجي لنظام إدارة قواعد البيانات (DBMS) لبنية C/S، وسيكون تركيزنا على بيانات التحكم الخاصة ببرنامج الإطار (المشار إليه فيما يلي باسم Hall) والتحكم في الاستجابة لبرنامج المكونات الإضافية لـ dll.
1. هيكل البرنامج
يتم إنشاء قاعة حاوية المكونات الإضافية باستخدام مشروع مستقل. النافذة الرئيسية للقاعة تعادل نموذج حاوية MDI في برنامج MDI. سيتم استدعاء وظائف الواجهة في Dll بشكل صريح في القاعة.
يستخدم كل برنامج إضافي مشروعه الخاص بشكل مستقل. يختلف مشروع DLL عن المشروعات العادية، حيث يقوم بإنشاء معالج Dll، والملفات التي تم إنشاؤها بواسطة التجميع المقابل لها اللاحقة DLL.
=550) window.open('/upload/20080315181507424.jpg');" src="http://files.VeVB.COm/upload/20080315181507424.jpg" onload="if(this.width>'550')this.width='550';if(this.height>'1000')this.height='1000';" border=0>
2. تصميم الواجهة
في برنامج المثال Narcissus، نحتفظ بوظيفتين للواجهة:
ShowDLLForm
تقوم هذه الوظيفة بتمرير مؤشر التطبيق إلى إطار DLL التابع، وسيقوم برنامج DLL بشكل حيوي بإنشاء مثيل لنموذج DLL. يمكنك أيضًا تمرير بعض منطق الأعمال إلى نافذة DLL الفرعية في شكل معلمات، مثل اسم النموذج، واسم المستخدم الذي تم تسجيل دخوله حاليًا، وما إلى ذلك. استخدم هذه الوظيفة لإنشاء مثيل نموذج DLL عند استدعائه للمرة الأولى.
FreeDLLForm
ستعرض هذه الوظيفة إصدار مثيل نافذة DLL، وتستدعي أسلوب FreeDLLForm لكل نموذج DLL لتحرير المثيل الذي تم إنشاؤه عند الخروج من التطبيق، وإلا فسوف يتسبب ذلك في حدوث خطأ للقراءة فقط في الذاكرة. وبالمثل، يمكنك أيضًا تمرير بعض منطق الأعمال الذي يجب تنفيذه عند تحرير النموذج إلى نموذج DLL في شكل معلمات.
3. طريقة التصحيح
لا يمكن تنفيذ برنامج نموذج DLL مباشرة ويحتاج إلى حاوية مكون إضافي لاستدعائه. لذلك، نحتاج أولاً إلى تنفيذ برنامج Hall الأساسي، ثم حفظ Hall.exe في دليل ثابت. قم بإجراء الإعدادات التالية لكل مشروع DLL:
1) افتح مشروع DLL
2) حدد القائمة تشغيل المعلمات
3) قم بالتصفح للوصول إلى حاوية Hall.exe الخاصة بنا في النافذة المنبثقة
بهذه الطريقة، سيتم استدعاء برنامج Hall تلقائيًا عند تصحيح أخطاء برنامج DLL، وسيتم تصحيح أخطاء برنامج DLL باستخدام واجهة الاتصال المحجوزة في Hall.
التنفيذ الأساسي لبرنامج المكونات الإضافية
لا تختلف طريقة تصميم برنامج DLL كثيرًا عن طريقة WINAPP العادية، فيما عدا أنه يتم حفظ جميع النوافذ في مكتبة DLL باعتبارها "موردًا" خاصًا ويجب استدعاؤها يدويًا، على عكس WINAPP حيث يتم إنشاء المشاريع تلقائيًا. طريقة الإعلان عن وظائف الواجهة بسيطة للغاية
1) قم بإعلان الوظيفة في قسم التنفيذ بالوحدة
2) أضف علامة stdcall في نهاية بيان إعلان الوظيفة
3) قبل عبارة البدء لرمز المشروع (مصدر عرض المشروع)، استخدم عبارة الصادرات للإعلان عن واجهة الوظيفة
من أجل جعل الكود موجزًا، أود شخصيًا إضافة وحدة وحدة (ملف جديد - وحدة) بشكل مستقل في المشروع، ثم تحديد جميع الهيئات الوظيفية التي سيتم إخراجها في هذه الوحدة وحدة النموذج المشار إليه. لقد قمت بتسمية هذه الوحدة UnitEntrance، وقمت بتهيئة النافذة التي سيتم عرضها في وظيفة ShowDLLForm واستدعيت طريقة العرض لعرضها. ستمرر HALL اسم المستخدم الذي تم تسجيل الدخول إليه كمعلمة. بعد الحصول على اسم المستخدم، يمكنك إجراء بعض التحكم في الأذونات. وهو ما ينعكس في تهيئة الواجهة المتفوقة.
الرمز هو كما يلي
وحدة UnitOfficeEntrance;
واجهة
الاستخدامات
Windows، الرسائل، SysUtils، Variants، Classes، Graphics، Controls، Forms؛
وظيفة ShowDLLForm(Ahandle: Thandle; ACaption: string; AUserID: string):boolean;stdcall;
وظيفة FreeDLLForm(Ahandle: Thandle; ACaption: string; AUserID: string):boolean;stdcall;
تطبيق
يستخدم UnitOfficialMainForm؛ // التغيير إلى وحدة MAINFORM
فار
DLL_Form:TFormOfficialMain; // تغيير اسم MAINFORM
//----------------------------------------
// الاسم: ShowDLLForm
// Func: يستدعي المكون الإضافي DLL وظيفة الإدخال
// الفقرة: مقبض البرنامج المرفق AHandle، عنوان ACaption لهذا النموذج
//ر تيرن: غير متاح
//المصادقة: CST
//التاريخ: 2005-6-3
//----------------------------------------
وظيفة ShowDLLForm(Ahandle: Thandle; ACaption: string; AUserID: string):boolean;
يبدأ
النتيجة:=صحيح؛
يحاول
Application.Handle:=AHandle; // مثبت في حاوية البرنامج الرئيسية
DLL_Form:=TFormOfficialMain.Create(Application); // تغيير إلى اسم MAINFORM
يحاول
مع DLL_Form القيام به
يبدأ
تسمية توضيحية := ACaption;
StatusBar.Panels.Items[0].Text := AUserID;
// تكوين واجهة المستخدم
يعرض ؛
نهاية؛
يستثني
على البريد: استثناء القيام به
يبدأ
dll_form.Free;
نهاية؛
نهاية؛
يستثني
النتيجة:=خطأ؛
نهاية؛
نهاية؛
//----------------------------------------
// الاسم: FreeDLLForm
// Func: يستدعي المكون الإضافي DLL وظيفة التصدير
// الفقرة: مقبض البرنامج المرفق AHandle
// Rtrn: صحيح/خطأ
//المصادقة: CST
//التاريخ: 11-6-2005
//----------------------------------------
الدالة FreeDLLForm(Ahandle: Thandle; ACaption: string; AUserID: string):boolean;
يبدأ
Application.Handle:=AHandle; // مثبت في حاوية البرنامج الرئيسية
إذا كان DLL_Form.Showing ثم DLL_Form.Close؛ // إذا تم فتح النافذة وإغلاقها أولاً، فيمكن أن يؤدي تشغيل FORM.CLOSEQUERY إلى إلغاء عملية الإغلاق
إن لم يكن DLL_Form.Showing بعد ذلك
يبدأ
DLL_Form.Free;
النتيجة:=صحيح؛
النهاية //لا تزال مفتوحة، تشير إلى CLOSEQUERY.CANCLOSE=FALSE
آخر
يبدأ
النتيجة:=خطأ؛
نهاية؛
نهاية؛
نهاية.
رمز ملف مشروع DLL هو كما يلي:
مسؤول المكتبة؛
{ ملاحظة مهمة حول إدارة ذاكرة DLL: يجب أن يكون ShareMem هو ملف
الوحدة الأولى في فقرة الاستخدامات الخاصة بمكتبتك ومشروعك (اختر
مصدر عرض المشروع) يستخدم جملة إذا قام DLL الخاص بك بتصدير أي إجراءات أو
الوظائف التي تمرر السلاسل كمعلمات أو نتائج دالة
ينطبق على كافة السلاسل التي تم تمريرها من وإلى DLL الخاص بك - حتى تلك التي
متداخلة في السجلات والفئات ShareMem هي وحدة الواجهة
مدير الذاكرة المشتركة BORLNDMM.DLL، والذي يجب نشره على طول
مع DLL الخاص بك لتجنب استخدام BORLNDMM.DLL، قم بتمرير معلومات السلسلة
باستخدام معلمات PChar أو ShortString }
الاستخدامات
سيسوتيلس,
الطبقات،
UnitOfficialDetailForm في 'UnitOfficialDetailForm.pas' {FormOfficialDetail}،
UnitOfficialMainForm في 'UnitOfficialMainForm.pas' {FormOfficialMain}،
UnitOfficeEntrance في "UnitOfficeEntrance.pas"،
UnitOfficialClass في '../../Public/Library/UnitOfficialClass.pas'،
UnitMyDataAdatper في "../../Public/Library/UnitMyDataAdatper.pas"،
UnitMyHeaders في '../../Public/Library/UnitMyHeaders.pas'؛
{$R *.res}
تصدير ShowDLLForm,FreeDLLForm; // وظيفة الواجهة
يبدأ
نهاية.
بمجرد أن يستدعي برنامج المكون الإضافي نافذة DLL، سيظل مثيل النافذة أعلى نافذة HALL، لذلك لا داعي للقلق بشأن الانسداد.
تنفيذ برامج الحاويات
1. مقدمة لوظائف الواجهة
هناك طريقتان لاستدعاء الوظائف في مكتبة DLL: الاستدعاء الصريح والضمني أكثر مرونة، لذلك نستخدم الاستدعاء الصريح. في دلفي، تحتاج إلى الإعلان عن نوع الوظيفة لوظيفة الواجهة، ثم إنشاء مثيل لنوع الوظيفة. المثيل هو في الواقع مؤشر للوظيفة، من خلال المؤشر، يمكننا الوصول إلى الوظيفة، وتمرير المعلمات، والحصول عليها قيمة الإرجاع. أضف إعلان فئة الوظيفة في قسم الواجهة في ملف الوحدة:
يكتب
// حدد نوع وظيفة الواجهة، وتأتي وظيفة الواجهة من واجهة DLL
TShowDLLForm = Function(Ahandle:THandle; ACaption: String; AUserID:string):Boolean;stdcall;
TFreeDLLForm = Function(Ahandle:THandle; ACaption: String; AUserID:string):boolean;stdcall;
يتطلب عرض وظائف مكتبة الاتصال الخطوات التالية:
1) تحميل ملف مكتبة DLL
2) الحصول على عنوان الوظيفة
3) تنفيذ الوظيفة
4) قم بتحرير مكتبة DLL
وبعد ذلك سنناقش هذه الخطوات بالتفصيل.
2. قم بتحميل ملف مكتبة DLL
يمكن تحميل مكتبة DLL في الذاكرة عن طريق استدعاء وظيفة واجهة برمجة التطبيقات LoadLibrary. ولن نناقش هنا تأثير مكتبة DLL على إدارة الذاكرة. معلمة LoadLibrary هي مسار عنوان ملف DLL. إذا نجح التحميل، فسيتم إرجاع متغير النوع CARDINAL كمقبض لمكتبة DLL؛ إذا كان الملف الهدف غير موجود أو تسببت أسباب أخرى في تحميل DLL إذا فشل الملف، سيتم إرجاع 0.
3. إنشاء مثيل لوظائف الواجهة
وظيفة API للحصول على مؤشر وظيفة الواجهة هي GetProcAddress (مؤشر ملف المكتبة، اسم الوظيفة). إذا تم العثور على الوظيفة، فسيتم إرجاع مؤشر الوظيفة. إذا فشلت، فسيتم إرجاع NIL.
حدد متغير مؤشر دالة باستخدام نوع الوظيفة المحدد أعلاه، ثم استخدم عامل التشغيل @ للحصول على عنوان الوظيفة، بحيث يمكنك استخدام متغير المؤشر للوصول إلى الوظيفة. الرمز الرئيسي هو كما يلي:
…
فار
ShowDLLForm: TShowDLLForm؛ // مثيل وظيفة واجهة DLL
FreeDLLForm: TFreeDLLForm؛
يبدأ
يحاول
يبدأ
APlugin.ProcAddr := LoadLibrary(PChar(sPath));
APlugin.FuncFreeAddr := GetProcAddress(APlugin.ProcAddr,'FreeDLLForm');
APlugin.FuncAddr := GetProcAddress(APlugin.ProcAddr ,'ShowDLLForm');
@ShowDLLForm:=APlugin.FuncAddr;
@FreeDLLForm:=APlugin.FuncFreeAddr;
إذا ShowDllForm(Self.Handle, APlugin.Caption, APlugin.UserID) ثم
النتيجة:=صحيح
…
4. طريقة تنفيذ محددة
من أجل إدارة المكونات الإضافية بطريقة منظمة وتسهيل توسيع النظام في المستقبل، يمكننا دمج معلومات DLL المتاحة المسجلة في قاعدة البيانات، ثم الوصول إلى برنامج DLL ديناميكيًا عن طريق الاستعلام عن سجلات قاعدة البيانات.
1) تصميم جدول وحدة النظام
بالنسبة لأنظمة MIS، يمكنك استخدام شروط DBS الحالية لإنشاء جدول وحدة النظام لتسجيل ملفات DLL والمعلومات ذات الصلة المعينة لوحدات النظام.
نوع دور اسم الحقل
فهرس المعرف التلقائي
modAlias الوحدة النمطية الاسم المستعار VARCHAR
اسم الوحدة النمطية modName VARCHAR
يشكل modWndClass معرفًا فريدًا VARCHAR
مسار modFile DLL VARCHAR
modMemo note TEXT
・يتم استخدام الأسماء المستعارة للوحدة لتوحيد قواعد التسمية أثناء مرحلة تصميم البرمجة، خاصة كمرجع لأعضاء الفريق أثناء تطوير الفريق.
・سيتم تمرير اسم الوحدة كمعلمة ACAPTION إلى الدالة SHOWDLLFORM كعنوان لنافذة DLL.
・المعرف الفريد للنموذج هو CLASSNAME للنافذة الرئيسية في وحدة DLL الفرعية، والذي يُستخدم لتحديد النافذة التي سيتم التحكم فيها في وقت التشغيل.
・يحفظ مسار DLL اسم ملف DLL، والذي سيتم تحويله إلى مسار مطلق في البرنامج.
2) بنية بيانات المعلومات الإضافية
يمكن أن يؤدي تحديد واجهة البيانات التي تسجل المعلومات ذات الصلة بالمكونات الإضافية إلى التحكم مركزيًا في المكونات الإضافية لـ DLL. أضف الكود التالي إلى قسم الواجهة:
يكتب
// تحديد فئة معلومات البرنامج المساعد
TMyPlugins = class
تسمية توضيحية: سلسلة // عنوان نموذج DLL
DllFileName:String; // مسار ملف DLL
WndClass:String; // تحديد النموذج
معرف المستخدم:سلسلة;
ProcAddr:THandle; // تم تحميل مقبض المكتبة بواسطة LOADLIBRARY
FuncAddr:Pointer; //SHOWDLLFORM مؤشر الوظيفة
FuncFreeAddr:Pointer; //FREEDLLFORM مؤشر الوظيفة
نهاية؛
…
قم بإنشاء مثيل TMyPlugins لكل مكون إضافي. سيتم مناقشة طرق التهيئة لهذه المثيلات أدناه.
3) وظيفة تحميل المكونات في
في هذا المثال، يتم تحميل نافذة DLL وعرضها في الحدث الذي يؤدي إلى فتح النافذة الفرعية في HALL. بعد تشغيل حدث الزر، حدد أولاً ما إذا كان قد تم تحميل DLL وفقًا لمثيل بنية المكون الإضافي، وإذا تم تحميله، فتحكم في عرض النافذة أو إغلاقها، وإذا لم يتم تحميلها، فانتقل إلى جدول البيانات قم بتعيين الحقول إلى بنية المكون الإضافي، ثم قم بتنفيذ التحميل.
الرمز الجزئي هو كما يلي
…
//----------------------------------------
// الاسم: OpenPlugin
// الوظيفة: عملية التحكم في معلومات البرنامج الإضافي: التهيئة ==》تعيين الأذونات==》تحميل نافذة DLL
//الفقرة: APlugin-TMyPlugins; sAlias alias;
//ر تيرن: غير متاح
//المصادقة: CST
//التاريخ: 2005-6-2
//----------------------------------------
الإجراء TFormHall.OpenPlugin(AFromActn: TAction ;APlugin:TMyPlugins; sAlias:string; sUserID:string);
فار hWndPlugin:HWnd;
يبدأ
// تحديد ما إذا كان قد تم تحميل نافذة البرنامج الإضافي hWndPlugin:=FindWindow(PChar(APlugin.WndClass),nil);
إذا كان hWndPlugin <> 0، فسيتم تحميل نافذة البرنامج الإضافي
يبدأ
إذا لم يكن IsWindowVisible(hWndPlugin) إذن
يبدأ
AFromActn.Checked := صحيح؛
ShowWindow(hWndPlugin,SW_SHOWDEFAULT); //Display
نهاية
آخر
يبدأ
AFromActn.checked := خطأ؛
ShowWindow(hWndPlugin,SW_HIDE);
نهاية؛
خروج؛ // اترك عملية إنشاء البرنامج الإضافي
نهاية؛
// تهيئة مثيل فئة المكون الإضافي
إذا لم يكن تهيئة MyPlugins (APlugin، sAlias) ثم
يبدأ
showmessage('حدث خطأ أثناء تهيئة فئة المكون الإضافي.');
مخرج؛
نهاية؛
// احصل على قيمة الإذن الحالية
APlugin.UserID := sUserID;
// تحميل نافذة DLL
إذا لم يكن LoadShowPluginForm(APlugin) إذن
يبدأ
showmessage('حدث خطأ أثناء تحميل البرنامج الإضافي للمركز.');
مخرج؛
نهاية؛
نهاية؛
//----------------------------------------
// الاسم: تهيئة MyPlugins
// الوظيفة: تهيئة مثيل MYPLUGIN (التسمية التوضيحية | DllFileName | IsLoaded)
//الفقرة: APlugin-TMyPlugins
//ر تيرن: غير متاح
//المصادقة: CST
//التاريخ: 2005-6-2
//----------------------------------------
وظيفة TFormHall.InitializeMyPlugins(APlugin:TMyPlugins; sAlias:String):Boolean;
فار
strSQL:سلسلة؛
myDA:TMyDataAdapter;
يبدأ
النتيجة:=خطأ؛
myDA:=TMyDataAdapter.Create;
strSQL:='SELECT * FROM SystemModuleList WHERE modAlias='+QuotedStr(sAlias);
يحاول
myDA.RetrieveData(strSQL);
يستثني
على E: استثناء القيام به
يبدأ
النتيجة:=خطأ؛
myDA.Free;
مخرج؛
نهاية؛
نهاية؛
يحاول
يبدأ
مع myDA.MyDataSet افعل
يبدأ
إذا لم يكن فارغا ثم
يبدأ
APlugin.Caption:= FieldByName('modName').Value;
APlugin.DllFileName := FieldByName('modFile').Value;
APlugin.WndClass := FieldByName('modWndClass').Value;
النتيجة:=صحيح؛
نهاية؛
يغلق؛
نهاية؛ //نهاية مع...افعل...
النهاية؛ // نهاية المحاولة
يستثني
على E: استثناء القيام به
يبدأ
النتيجة:=خطأ؛
myDA.Free;
مخرج؛
النهاية؛ // نهاية الاستثناء
النهاية؛ // نهاية المحاولة... باستثناء
myDA.Free;
نهاية؛
//----------------------------------------
// الاسم: LoadShowPluginForm
// Func: قم بتحميل البرنامج الإضافي DLL وعرض النافذة
//الفقرة: APlugin-TMyPlugins
//Rtrn: تم الإنشاء الحقيقي بنجاح
//المصادقة: CST
//التاريخ: 2005-6-2
//----------------------------------------
وظيفة TFormHall.LoadShowPluginForm (const APlugin:TMyPlugins):boolean;
فار
ShowDLLForm: TShowDLLForm؛ // مثيل وظيفة واجهة DLL
FreeDLLForm: TFreeDLLForm؛
sPath:string; // المسار الكامل لملف DLL
يبدأ
يحاول
يبدأ
sPath:=ExtractFilepath(Application.ExeName)+ 'plugins/' + APlugin.DllFileName;
APlugin.ProcAddr := LoadLibrary(PChar(sPath));
APlugin.FuncFreeAddr := GetProcAddress(APlugin.ProcAddr,'FreeDLLForm');
APlugin.FuncAddr := GetProcAddress(APlugin.ProcAddr ,'ShowDLLForm');
@ShowDLLForm:=APlugin.FuncAddr;
@FreeDLLForm:=APlugin.FuncFreeAddr;
إذا ShowDllForm(Self.Handle, APlugin.Caption, APlugin.UserID) ثم
النتيجة:=صحيح
آخر
النتيجة:=خطأ؛
نهاية؛
يستثني
على E: استثناء القيام به
يبدأ
النتيجة:=خطأ؛
ShowMessage('حدث خطأ أثناء تحميل وحدة البرنامج الإضافي، يرجى التحقق مما إذا كانت الملفات الموجودة في دليل PLUGINS كاملة.');
نهاية؛
نهاية؛
نهاية؛
…
4) التحكم في نافذة DLL
كما يوضح الكود الموجود في 3) فإن فتح وإغلاق نافذة DLL يتم فقط في طبقة العرض التقديمي، ولا يؤدي إغلاق النافذة إلى تحرير نافذة DLL فعليًا، بل يستدعي فقط وظيفة API FindWindow للحصول على مقبض النموذج وفقًا للنافذة المعرف (أي Form.name). استخدم معلمة nCmdShow الخاصة بالدالة SHOWWINDOW التي تتحكم في عرض/إخفاء النافذة.
في الواقع، هذه نقطة ضعف في تنفيذ برنامجي. إذا تم استخدام طريقة Self.Close في نافذة DLL، فسوف يتسبب ذلك في حدوث خطأ في الذاكرة، ولا توجد طريقة لحلها بسبب الإمكانيات المحدودة، لذلك الملاذ الأخير. لذلك، يجب إخفاء زر الإغلاق الخاص بالنافذة الرئيسية لكل برنامج DLL. :-ص
5) الافراج عن مكتبة DLL
عند خروج البرنامج، يجب تحرير مكتبة DLL واحدة تلو الأخرى وفقًا لمثيل معلومات المكون الإضافي. وظيفة تحرير مكتبة DLL هي كما يلي:
الإجراء TFormHall.ClosePlugin(aPLG:TMyPlugins);
فار
FreeDLLForm:TFreeDLLForm;
يبدأ
إذا كان aPLG.ProcAddr = 0 ثم قم بالخروج؛
إذا كان aPLG.FuncFreeAddr = لا شيء، ثم قم بالخروج؛
@FreeDLLForm:=aPLG.FuncFreeAddr;
إذا لم يكن FreeDLLForm(Application.Handle,'','') إذن
showMessage('يخطئ');
نهاية؛
ملخص
تأثير تشغيل هذا البرنامج النموذجي هو كما يلي:
=550) window.open('/upload/20080315181507979.jpg');" src="http://files.VeVB.COm/upload/20080315181507979.jpg" onload="if(this.width>'550')this.width='550';if(this.height>'1000')this.height='1000';" border=0>
من بين الطرق المذكورة أعلاه، نظرًا لوجود العديد من المشكلات التي لم يتم حلها بسبب القدرة المحدودة، فقد اعتمدت بعض أساليب التستر التي لا تبدو معقولة، وآمل أن يتمكن الجميع من تصميم حل أفضل بعد المحاولة قليلاً طريقة رائعة لمعرفة المزيد.