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 за избор на дата и час, а не токените на Delphi FormatDateTime. Двете изглеждат сходно, но не са взаимозаменяеми. Windows използва d за ден от месеца (без водеща нула), dd за ден с водеща нула, M за номер на месеца, MM за месец с водеща нула, yy за двуцифрена година и yyyy за четирицифрена година. Полетата за време използват h/hh за 12-часов формат, H/HH за 24-часов формат, m/mm за минути, s/ss за секунди. Буквалният текст се поставя в единични кавички вътре в низа за форматиране, така че 'dd/MM/yyyy' вече е правилно, но 'dd '<literal>' MM' би изисквало вложени двойки единични кавички
Delphi's FormatDateTime, за разлика от това, използва d/dd/ddd/dddd за форми на деня с различна семантика и m за месец (не M). Ако копирате низ за форматиране от извикване на FormatDateTime и го предадете директно на DateTime_SetFormat, полетата за месец и минута вероятно ще бъдат разменени в изхода. Напишете низа за форматиране на контролата от нулата въз основа на документацията на Windows, вместо да конвертирате от формат на Delphi
Регионални настройки и глобалната ShortDateFormat
Промяната на глобалната променлива ShortDateFormat на Delphi не засяга вече създаден TDateTimePicker. Контролата чете регионалните настройки от Windows по време на създаването си и след това се изобразява според съобщенията, които получава, а не според глобалните променливи на Delphi RTL. Това означава, че задаването на ShortDateFormat във FormCreate няма да промени това, което контролата показва. Нуждаете се от DateTime_SetFormat (или свойството Format в по-нов Delphi), за да презапишете собствения низ за форматиране на контролата, след като манипулаторът съществува
За приложения, разпространявани в международен план, тествайте низа за форматиране на машина с регионална настройка, различна от САЩ. Windows може да презапише празен или nil низ за форматиране с настройката по подразбиране за локала, но изричен низ, различен от nil, напълно замества регионалната настройка. Обикновено това е, което искате, но означава, че ориентиран към САЩ модел като 'MM/dd/yyyy' ще се появи такъв, какъвто е, за потребители, които очакват dd/MM/yyyy по конвенция. Ако контролата за избор на дата е насочена към потребителя, а не е чисто поле за въвеждане на данни, помислете дали да не оставите контролата по подразбиране (подайте nil на DateTime_SetFormat), така че автоматично да следва локала на потребителя
Повторно създаване на манипулатора
Настройката на формата принадлежи на манипулатора на прозореца, а не на някое поле на VCL обект. Ако манипулаторът на контролата бъде унищожен и създаден отново, което VCL може да направи, когато промените родителя на контрола или промените определени свойства на стила по време на изпълнение, форматът се връща към този по подразбиране за Windows. Безопасното място за прилагане на DateTime_SetFormat е в манипулатор (handler), който се изпълнява след създаването на манипулатора на прозореца: заменете CreateWnd в производен клас и го извикайте там, или го приложете в събитието OnEnter или OnShow само след като потвърдите, че манипулаторът е активен. Задаването му веднъж във FormCreate често е достатъчно за прости форми, но не е надеждно, ако формата прави динамично превключване на стилове или промяна на родителя на контроли
Същото ограничение важи и за свойството Format на VCL в по-новите версии на Delphi; вътрешно то извиква същото съобщение на Windows и се сблъсква със същия жизнен цикъл на манипулатора. Разликата е, че методът за задаване на свойството на VCL проверява дали манипулаторът е разпределен, преди да го извика, и прилага формата автоматично отново при CreateWnd. Суровото извикване на DateTime_SetFormat няма такава защита, така че клонът за Delphi 5 трябва да бъде по-внимателен относно това кога се изпълнява
Премахване на заобиколното решение
Когато даден проект спре да поддържа Delphi 5, условният блок става мъртво тегло. Премахнете клона {$IFDEF D5} и импорта на CommCtrl с ограничен обхват, оставяйки само директното присвояване на свойството Format. Запазете премахването в един commit, така че да е лесно да се идентифицира, ако нещо неочаквано се счупи на компилатор, който не сте тествали. Самият низ за форматиране остава същият; променя се само механизмът на доставяне