TDateTimePicker اكتسب الخاصية Format في مكان ما بين Delphi 5 وDelphi 6. نادرا ما يوثق الحد الفاصل بين الإصدارات بطريقة يمكن الوثوق بها، وعندما تصل إليه يخبرك المترجم ببساطة أن المعرف غير موجود. السطر الذي يترجم ويعمل في كل إصدارات Delphi الأحدث لديك يفشل بصمت أو بشكل مباشر في الإصدار القديم، وذلك بحسب بنية المشروع
عنصر التحكم الأساسي هو عنصر التحكم العام في Windows DATETIMEPICK_CLASS من comctl32.dll، وكان يقبل دائما سلسلة تنسيق عبر الرسالة DTM_SETFORMAT. تغلف VCL في Delphi تلك الرسالة داخل الخاصية Format في الإصدارات الأحدث. في Delphi 5 ترسل الرسالة بنفسك عبر الغلاف الماكروي DateTime_SetFormat المعلن في CommCtrl
نمط التجميع الشرطي
الأسلوب القياسي هو كتلة شرطية للمترجم تعتمد على رمز إصدار. يعرّف Delphi 5 الرمز VER130، ويمكنك اختباره مباشرة أو تعريف الرمز D5 الخاص بك في خيارات المشروع لجعل اسم الفرع أوضح عبر قاعدة الشفرة. وفي كلتا الحالتين يستدعي فرع Delphi 5 الدالة DateTime_SetFormat مع مقبض عنصر التحكم، بينما تسند الفروع الأخرى الخاصية:
{$IFDEF D5}
DateTime_SetFormat(DateTimePicker1.Handle, PChar('MM/dd/yyyy'));
{$ELSE}
DateTimePicker1.Format := 'MM/dd/yyyy';
{$ENDIF}
أضف CommCtrl إلى عبارة uses في الوحدة التي تحتوي على فرع Delphi 5. لا حاجة إلى إضافته دائما، وإذا أردت إبقاء الاعتماد محدودا فلفّ إدخال uses في الشرط نفسه:
uses
...,
{$IFDEF D5}
CommCtrl,
{$ENDIF}
...;
صياغة سلسلة التنسيق
تتبع سلسلة التنسيق الممررة إلى DateTime_SetFormat صياغة منتقي التاريخ والوقت في Windows، لا رموز FormatDateTime في Delphi. يبدوان متشابهين لكنهما غير قابلين للتبادل. يستخدم Windows الرمز d ليوم الشهر من دون صفر بادئ، وdd لليوم مع صفر بادئ، وM لرقم الشهر، وMM للشهر مع صفر بادئ، وyy لسنة من رقمين، وyyyy لسنة من أربعة أرقام. وتستخدم حقول الوقت h/hh لساعات نظام 12 ساعة، وH/HH لساعات نظام 24 ساعة، وm/mm للدقائق، وs/ss للثواني. أما النص الحرفي فيوضع داخل علامات اقتباس مفردة داخل سلسلة التنسيق، لذا فإن 'dd/MM/yyyy' صحيح بالفعل، لكن 'dd '<literal>' MM' سيتطلب أزواجا مضمنة من علامات الاقتباس المفردة
أما FormatDateTime في Delphi فيستخدم، على العكس، d/dd/ddd/dddd لأشكال اليوم بدلالات مختلفة، ويستخدم m للشهر لا M. إذا نسخت سلسلة تنسيق من استدعاء FormatDateTime وسلمتها مباشرة إلى DateTime_SetFormat فغالبا ما ستتبدل حقول الشهر والدقيقة في الناتج. اكتب سلسلة تنسيق عنصر التحكم من الصفر اعتمادا على توثيق Windows بدلا من تحويلها من صيغة Delphi
إعدادات المنطقة و ShortDateFormat العمومية
إن تغيير المتغير العمومي ShortDateFormat في Delphi لا يؤثر في TDateTimePicker الذي تم إنشاؤه بالفعل. يقرأ منتقي التاريخ إعدادات المنطقة من Windows عند الإنشاء، ثم يعرض بعدها وفقا للرسائل التي يتلقاها، لا وفقا للمتغيرات العمومية في RTL الخاصة بـ Delphi. وهذا يعني أن ضبط ShortDateFormat في FormCreate لن يغيّر ما يعرضه عنصر التحكم. تحتاج إلى DateTime_SetFormat، أو الخاصية Format في Delphi الأحدث، لتجاوز سلسلة التنسيق الخاصة بعنصر التحكم بعد وجود المقبض
في التطبيقات المنشورة دوليا، اختبر سلسلة التنسيق على جهاز يستخدم إعدادا إقليميا غير أمريكي. يمكن لـ Windows أن يستبدل سلسلة تنسيق فارغة أو nil بالقيمة الافتراضية للمحلية، لكن سلسلة صريحة غير فارغة تتجاوز الإعداد الإقليمي بالكامل. وهذا غالبا ما تريده، لكنه يعني أن نمطا موجها إلى الإعداد الأمريكي مثل 'MM/dd/yyyy' سيظهر كما هو للمستخدمين الذين يتوقعون dd/MM/yyyy وفقا للعرف. إذا كان منتقي التاريخ موجها للمستخدم لا مجرد حقل إدخال بيانات، ففكّر في ترك العنصر على القيمة الافتراضية nil الممررة إلى DateTime_SetFormat حتى يتبع لغة المستخدم تلقائيا
إعادة إنشاء المقبض
ينتمي إعداد التنسيق إلى مقبض النافذة، لا إلى أي حقل في كائن VCL. إذا دُمِّر مقبض عنصر التحكم وأُعيد إنشاؤه، وهو ما قد تفعله VCL عندما تعيد إسناد أب عنصر التحكم أو تغيّر بعض خصائص النمط وقت التشغيل، فسيعود التنسيق إلى القيمة الافتراضية في Windows. الموضع الآمن لتطبيق DateTime_SetFormat هو معالج يعمل بعد إنشاء المقبض: تجاوز CreateWnd في صنف مشتق واستدعِها هناك، أو طبّقها في حدث OnEnter أو OnShow بعد التأكد من أن المقبض موجود. وغالبا ما يكفي ضبطها مرة واحدة في FormCreate للنماذج البسيطة، لكنه ليس موثوقا إذا كان النموذج يبدل الأنماط أو يعيد إسناد الأب وقت التشغيل
ينطبق القيد نفسه على الخاصية Format في VCL في إصدارات Delphi الأحدث، فهي داخليا تستدعي رسالة Windows نفسها وتواجه دورة حياة المقبض نفسها. الفرق أن دالة تعيين الخاصية في VCL تتحقق من تخصيص المقبض قبل الاستدعاء، ثم تعيد تطبيق التنسيق تلقائيا في CreateWnd. أما استدعاء DateTime_SetFormat الخام فلا يملك هذه الحماية، لذا يحتاج فرع Delphi 5 إلى أن يكون أدق في توقيت التنفيذ
إزالة الحل البديل
عندما يتوقف مشروع عن دعم Delphi 5، تصبح الكتلة الشرطية عبئا زائدا. أزل فرع {$IFDEF D5} وعبارة CommCtrl المحددة بالنطاق، واترك فقط الإسناد المباشر للخاصية Format. احتفظ بالإزالة في commit واحد حتى يسهل تحديدها إذا كسر مترجم لم تختبره شيئا بشكل غير متوقع. تبقى سلسلة التنسيق نفسها كما هي، ويتغير فقط أسلوب إيصالها