نقلت Delphi XE2 والإصدارات الأحدث جزءا كبيرا من تعريفات Windows API إلى وحدة Winapi.Windows ذات النطاق المحدد، وشددت عدة تعريفات للسجلات. لذلك قد يفشل كود كان يترجم في إصدارات Delphi القديمة عندما يعرض سجل Enhanced Metafile قيمة tagLOGBRUSH32 بينما تتوقع GDI API قيمة tagLOGBRUSH أو TLogBrush.
تظهر الأعراض عادة عند إعادة تشغيل سجلات EMF أو إعادة بناء كائنات فرشاة GDI من PEMRCreateBrushIndirect. تبدو الاستدعاءات المباشرة مثل المثال التالي منطقية، لكن نوعي السجلين ليسا متوافقين في الإسناد في مترجمات Delphi الأحدث.
|
1 2 3 4 5 |
procedure VEMRCREATEBRUSHINDIRECT(Data: PEMRCreateBrushIndirect); begin GDIObjects[Data^.ihBrush] := CreateBrushIndirect(Data^.lb); //GDIObjects and CreateBrushIndirect are defined in the winapi.windows unit. end; |
يعرض المترجم الخطأ E2010 Incompatible types: 'tagLOGBRUSH' and 'tagLOGBRUSH32'تجنب تمرير السجل عبر تحويل نوع غير آمن. الإصلاح الأكثر أمانا هو إنشاء TLogBrushمحلي، ونسخ الحقول المتوافقة صراحة، ثم تمرير تلك البنية إلى CreateBrushIndirect.
|
1 2 3 4 5 6 7 8 9 |
procedure VEMRCREATEBRUSHINDIRECT(Data: PEMRCreateBrushIndirect); var LogBrush: TLogBrush; begin LogBrush.lbStyle := Data^.lb.lbStyle; LogBrush.lbColor := Data^.lb.lbColor; LogBrush.lbHatch := Data^.lb.lbHatch; GDIObjects[Data^.ihBrush] := CreateBrushIndirect(LogBrush); end; |
لماذا يكون النسخ الصريح أكثر أمانا
tagLOGBRUSH32 يستخدم في تنسيق سجل EMF حتى تبقى بيانات metafile المسلسلة ذات تخطيط حقول 32 بت ثابت. CreateBrushIndirectأما فيقبل بنية فرشاة Windows العادية المستخدمة في تعريف API الحالي. إن نسخ lbStyle، و lbColor، و lbHatch يوثق التحويل ويتجنب الاعتماد على توافق سجلات خاص بالمترجم.
يسهل أيضا مراجعة هذا النمط عند نقل كود رسومات قديم إلى Unicode Delphi أو أهداف 64 بت. إذا تغيرت أسماء الأنواع في تعريفات Windows SDK لاحقا، فإن التحويل حقلا بحقل يوضح حد البيانات المقصود.
قائمة تحقق للنقل
- أبق
Winapi.Windowsفي قائمة uses لمشاريع Delphi الحديثة. - انسخ حقول سجل EMF إلى بنية API التي يتوقعها استدعاء GDI.
- لا تستبدل ذلك بتحويل مؤشر أعمى إلا بعد التحقق من التخطيط الثنائي وعمر البيانات.
- بعد إنشاء الفرشاة، حافظ على قواعد ملكية الكائنات الموجودة لجدول
GDIObjects.
لماذا يظهر هذا أثناء ترقيات Delphi
غالبا ما يتعامل كود تشغيل EMF القديم مع سجلات Windows كما لو كانت بنى API وبنى metafile المسلسلة قابلة للتبادل. في بعض الوحدات القديمة والأسماء المستعارة الأقل صرامة كان هذا الافتراض يترجم بنجاح. تعريفات Delphi الحديثة أكثر صرامة، لذلك يكشف المترجم الحد الذي كان موجودا أصلا في Windows API.
لذلك فالخطأ ليس مشكلة صياغة فقط. إنه تحذير مفيد بأن الكود يعبر من بنية تنسيق ملف إلى استدعاء GDI حي. إبقاء التحويل صريحا يجعل الكود أكثر أمانا عند مراجعته لاحقا لبناء 64 بت أو ترحيل Unicode أو تعريفات Windows SDK محدثة.
ما يجب تجنبه
قد يبدو تحويل المؤشر وكأنه يزيل خطأ المترجم، لكنه يخفي التحويل الحقيقي ويمكن أن يصعب الصيانة لاحقا. كما أنه لا يوضح للمراجعين أي الحقول مستخدمة عمدا. النسخ حقلا بحقل قصير وحتمي وواضح بذاته، لذلك فهو الخيار الافتراضي الأفضل لكود التطبيقات وعينات المكونات.
إذا كان محلل EMF لديك يعالج سجلات كثيرة مشابهة، فضع هذا التحويل في دالة مساعدة صغيرة واختبره مع عدة أنماط فرشاة. بذلك تبقى حلقة التشغيل مقروءة مع إبقاء حد Windows API صريحا.