عند كتابة البرامج ، تواجه دائمًا مشاكل في الاتصال بين النموذج (TForm) ورسالة مؤشر الترابط (TTHREAD). الأمر المزعج هو أن النموذج لا يمكن أن يرسل رسائل إلى مؤشر الترابط (TTREAD) (لا يحتوي مؤشر الترابط على مقبض نافذة). بعد عدة أيام من العمل الشاق ، توصلت إلى حلين وأخرجتهما لمناقشة معك.
أولاً. نعلم أن مكتبة فئة MFC في VC ++ تحتوي على رسائل معالجة (intingmessage ، endmessage) جدول التعيين (معالجة الرسائل هي في الأساس دعوة إلى طريقة أو عملية) ، بالإضافة إلى آلية توزيع الرسائل لتحقيق استقبال الرسائل ونقلها <انظر VC ++ Technical Insider> للحصول على التفاصيل. لذلك نحتاج فقط إلى إنشاء جدول رسم خرائط للرسائل للمعلومات وإنشاء آلية توزيع الرسائل المقابلة. يتيح لك ذلك معالجة الرسائل المرسلة بواسطة النموذج إلى مؤشر الترابط. الرمز التالي هو فئة تنفذ جدول تعيين الرسائل وتوزيع الرسائل (انظر <../ معالجة الرسائل تصميم (موضوع) 1/messageHandle.pas> للحصول على التفاصيل)
وحدة MessageHandle ؛
واجهة
يستخدم الرسائل والفئات والمواد الحوارات.
const pmsg_base = $ be00 ؛
PMSG_NUM = 200 ؛
{** فئة معالجة الرسائل المخصصة
*؛ الوظيفة = إنشاء جدول رسالة مخصصة وعملية بين مؤشرات الترابط
* والرسائل المخصصة مع النموذج الرئيسي (الماكرو)
*}
// مقبض معالجة الرسائل
tmessageHandle = الإجراء (رسالة var: tmessage) من الكائن ؛
tpdispatcher = فئة (tooject)
خاص
// رسالة الجدول المقابل (معرف الرسالة عبارة عن مجموعة صفيف) ؛
MessageHandles: مجموعة من tmessageHandle ؛
// احصل على معرف الصفيف من معرف الرسالة
وظيفة getIndExfrommSgid (const amessageid: الكاردينال): عدد صحيح ؛
عام
إنشاء مُنشئ ؛
تدمير المدمر.
// إرسال رسالة
الإجراء sendMessage (var message: tmessage) ؛
// إضافة رسالة مخصصة إلى الجدول المقابل للرسالة ؛
الإجراء AddHandle (const amessageid: cardinal ؛ amessageHandle: tmessageHandle) ؛
نهاية؛
//
تطبيق
{tpdispatcher}
مُنشئ tpdispatcher.create ؛
var i: integer ؛
يبدأ
SetLength (MessageHandles ، PMSG_NUM) ؛
// تهيئة قائمة انتظار الرسائل ؛
لأني: = 0 للسباق (pmsg_num) افعل
MessageHandles [i]: = nil ؛
نهاية؛
Destructor tpdispatcher.destroy ؛
يبدأ
{جدول مراسلة رسالة}}
FreeAndnil (MessageHandles) ؛
نهاية؛
الإجراء tpdispatcher.addhandle (const amessageid: الكاردينال ؛
AmessageHandle: TmessageHandle) ؛
var tid: integer ؛
يبدأ
Tid: = getIndexfrommSgid (amessageid) ؛
تأكيد ((tid> 0) أو (tid <pred (pmsg_num))) ؛
تأكيد (تم تعيينه (AmessageHandle)) ؛
MessageHandles [tid]: = AmessageHandle ؛
نهاية؛
دالة tpdispatcher.getIndExfrommSgid (const amessageid: cardinal): integer ؛
يبدأ
النتيجة: = amessageid - pmsg_base ؛
نهاية؛
الإجراء tpdispatcher.sendMessage (var message: tmessage) ؛
var tid: integer ؛
tmsghandle: tmessageHandle ؛
يبدأ
Tid: = getIndExfrommSgid (message.msg) ؛
تأكيد ((tid> 0) أو (tid <pred (pmsg_num))) ؛
tmsghandle: = messageHandles [tid] ؛
إذا تم تعيينه (tmsghandle) ثم
tmsghandle (رسالة) ؛
نهاية؛
الآن نحتاج فقط إلى تسجيل رسالة مخصصة ثم استخدام فئة توزيع الرسائل (TPDispatcher) لمعالجة رسائل سلسلة الرسائل. الرمز كما يلي <انظر ../ تصميم معالجة الرسائل (موضوع) 1/اختبار/unit1.pas> للحصول على التفاصيل:
الوحدة 1
كونست
{رسالة مؤشر ترابط طويلة الأجل مخصصة}
my_message2 = pmsg_base + 02 ؛
يكتب
tform1 = فئة (tform)
addmsglist: tbutton ؛
sendthead: tbutton ؛
sendform: tbutton ؛
إرسال آخر: tbutton ؛
الإجراء sendTheadClick (المرسل: TOBJECT) ؛
Formcreate الإجراء (المرسل: TOBJECT) ؛
الإجراء FormDestroy (المرسل: tobject) ؛
خاص
Fdispatcher: TPDispatcher ؛
Fhandle: Tphandler ؛
FTREAD: TPTHREAD
عام
{الإعلانات العامة}
نهاية؛
var
Form1: Tform1 ؛
تطبيق
{$ r *.dfm}
الإجراء tform1.SendTheAdclick (المرسل: tobject) ؛
Var Amessage: Tmessage
amessage.msg: = my_message2 ؛
amessage.wparam: = 1 ؛
fdispatcher.sendmessage (amessage) ؛
نهاية؛
نهاية؛
الإجراء tform1.formcreate (المرسل: tobject) ؛
يبدأ
{إنشاء فئة جدول خريطة رسالة}
fdispatcher: = tpdispatcher.create ؛
fhandle: = tphandler.create ؛
{إنشاء موضوع}
fThread: = tpthread.create (false) ؛
{أضف رسالة إلى جدول التعيين}
fdispatcher.addhandle (my_message2 ، fthread.domessage) ؛
نهاية؛
الإجراء tform1.formdestroy (المرسل: tobject) ؛
var i: integer ؛
يبدأ
Freeandnil (fdispatcher) ؛
Freeandnil (fhandle) ؛
لأني: = 0 إلى 3 افعل
freeandnil (fthread [i]) ؛
نهاية؛
ثانية. يمكن للنافذة التعامل مع الرسائل لأنه يحتوي على مقبض نافذة. لكي يتعامل مؤشر الترابط ، يمكننا إضافة مقبض نافذة إلى مؤشر ترابط فئة النافذة المقابلة. (رمز المصدر في <../ تصميم معالجة الرسائل (موضوع) 2 / pthread.pas>)
وحدة PTHREAD ؛
واجهة
يستخدم الفئات ، sysutils ، النوافذ ، الرسائل ، مربعات الحوار ؛
const my_message1 = $ bd00 + 01 ؛
يكتب
{** فئة مؤشر ترابط معالجة الرسائل
*؛ وظيفة = إضافة قدرة معالجة مؤشرات الترابط ،
*}
TPMSGTHREAD = فئة (tthread)
خاص
// مقبض نافذة
fwndhandle: hwnd ؛
// معلومات بيانات النافذة
fwndclass: wndclass ؛
// مؤشر وظيفة رد الاتصال على النافذة
fobjectinstance: مؤشر ؛
// تهيئة بيانات النافذة
الإجراء initwnd ؛
// إنشاء نافذة مخفية
الإجراء CreateWnd ؛
// تسجيل النافذة المخفية
الإجراءات RegistWnd ؛
الإجراءات تدمير
// وظيفة رد الاتصال النافذة
الإجراء pwndproc (var message: tmessage) ؛
محمية
التنفيذ الإجراء ؛
الإجراء doterminate.
عام
إنشاء مُنشئ (CreateSusused: Boolean) ؛
خاصية wndhandle: hwnd قراءة fwndhandle اكتب fwndhandle ؛
نهاية؛
تطبيق
const wnd_name = 'py20' ؛
{tpmsgthread}
مُنشئ tpmsgthread.create (createSuseSpended: Boolean) ؛
يبدأ
إنشاء ورث (createSusused) ؛
fwndhandle: = عدد صحيح (لا شيء) ؛
initwnd ؛
RegiStwnd ؛
CreateWnd ؛
نهاية؛
الإجراء tpmsggthread.createwnd ؛
يبدأ
إذا (wndhandle = integer (لا شيء)) ثم
Wndhandle: = CreateWindow (fwndclass.lpszclassname ، fwndclass.lpszclassname ،
WS_POPUP أو WS_CAPTION أو WS_CLIPSIBLINGS أو WS_SYSMENU
أو ws_minimizebox ،
GetSystemMetrics (SM_CXSCREEN) DIV 2 ،
GetSystemMetrics (SM_CYSCREEN) DIV 2 ،
0 ، 0 ، 0 ، 0 ، fwndclass.hinstance ، nil) ؛
// استبدال وظيفة رد الاتصال النافذة
SetWindowLong (wndhandle ، gwl_wndproc ، longint (fobjectinstance)) ؛
نهاية؛
الإجراء TPMSGTHREAD.DESTROYWND ؛
يبدأ
unregisterClass (fwndclass.lpszClassName ، fwndclass.hinstance) ؛
Destroywindow (wndhandle) ؛
نهاية؛
الإجراء tpmsgthread.doterminate ؛
يبدأ
ورث
تدمير
نهاية؛
الإجراء tpmsggthread.execute ؛
يبدأ
نهاية؛
الإجراء TPMSGTHREAD.INITWND ؛
يبدأ
fwndclass.lpszClassName: = pchar (wnd_name) ؛
fwndclass.hinstance: = مقبض ؛
fwndclass.lpfnwndproc: = dewindowproc ؛
نهاية؛
الإجراء TPMSGTHREAD.PWNDPROC (var message: tmessage) ؛
يبدأ
نهاية؛
الإجراء tpmsggthread.registwnd ؛
يبدأ
fobjectinstance: = classes.makeObjectInstance (pwndproc) ؛
if (fwndclass.hinstance <> integer (nil)) ثم
registerClass (fwndclass) ؛
نهاية؛