Елемент керування 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 з дескриптором елемента керування (handle); кожна інша гілка просто призначає властивість:
{$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 на значення за замовчуванням для локалі, але явно заданий рядок (не nil) повністю скасовує регіональні налаштування. Зазвичай це саме те, що вам потрібно, але це означає, що шаблон 'MM/dd/yyyy', орієнтований на США, з'явиться без змін для користувачів, які за традицією очікують dd/MM/yyyy. Якщо елемент вибору дати орієнтований на користувача, а не є суто полем для введення даних, розгляньте можливість використання стандартних налаштувань елемента керування (передайте nil у DateTime_SetFormat), щоб він автоматично слідував локалі користувача
Перестворення дескриптора
Налаштування формату належить дескриптору вікна, а не будь-якому полю об'єкта VCL. Якщо дескриптор елемента керування знищується та створюється заново, що VCL може зробити, коли ви змінюєте батьківський елемент або певні властивості стилю під час виконання, формат повертається до значення Windows за замовчуванням. Безпечне місце для застосування DateTime_SetFormat - це обробник, який запускається після створення дескриптора: перевизначте CreateWnd у класі-нащадку та викличте його там, або застосуйте в події OnEnter чи OnShow лише після підтвердження того, що дескриптор активний. Встановлення його один раз у FormCreate часто є достатнім для простих форм, але це ненадійно, якщо форма виконує динамічне перемикання стилів або зміну батьківського елемента
Таке ж обмеження стосується властивості VCL Format у новіших версіях Delphi; внутрішньо вона викликає те саме повідомлення Windows і стикається з таким самим життєвим циклом дескриптора. Різниця полягає в тому, що сетер властивості VCL перевіряє, чи виділено дескриптор перед наскрізним викликом, і автоматично повторно застосовує формат під час CreateWnd. Необроблений виклик DateTime_SetFormat не має такого захисту, тому гілка для Delphi 5 має бути більш обережною щодо того, коли вона запускається
Видалення обхідного рішення
Коли проєкт припиняє підтримку Delphi 5, блок умовної компіляції стає мертвим вантажем. Видаліть гілку {$IFDEF D5} та імпорт CommCtrl з обмеженою областю видимості, залишивши лише безпосереднє призначення властивості Format. Зберігайте видалення в одному коміті, щоб було легко визначити, якщо щось несподівано зламається на компіляторі, який ви не тестували. Сам рядок формату залишається тим самим; змінюється лише механізм його доставки