TDateTimePicker získal vlastnosť Format niekde medzi Delphi 5 a Delphi 6. Presná hranica verzie je málokedy zdokumentovaná dôveryhodným spôsobom, a keď na ňu narazíte, kompilátor vám jednoducho oznámi, že identifikátor neexistuje. Riadok, ktorý sa skompiluje a funguje na každom novšom Delphi, ktoré máte, na starom zlyhá ticho alebo úplne, v závislosti od štruktúry projektu.
Základným ovládacím prvkom je spoločný ovládací prvok Windows DATETIMEPICK_CLASS z comctl32.dll, a ten vždy prijímal formátovací reťazec prostredníctvom správy DTM_SETFORMAT. VCL v Delphi obaľuje túto správu do vlastnosti Format v novších verziách. V Delphi 5 posielate správu sami pomocou makra DateTime_SetFormat deklarovaného v CommCtrl.
Vzor podmienenej kompilácie
Štandardným prístupom je blok podmienenej kompilácie kľúčovaný symbolom verzie. Delphi 5 definuje VER130; môžete naň testovať priamo alebo definovať svoj vlastný symbol D5 v možnostiach projektu, aby bol názov vetvy čitateľnejší v celej báze kódu. V každom prípade vetva pre Delphi 5 volá DateTime_SetFormat s handle ovládacieho prvku; každá iná vetva priraďuje vlastnosť:
{$IFDEF D5}
DateTime_SetFormat(DateTimePicker1.Handle, PChar('MM/dd/yyyy'));
{$ELSE}
DateTimePicker1.Format := 'MM/dd/yyyy';
{$ENDIF}
Pridajte CommCtrl do klauzuly uses pre jednotku, ktorá obsahuje vetvu Delphi 5. Nie je potrebné ju pridávať bezpodmienečne; ak uprednostňujete obmedzenie rozsahu závislosti, zabaľte položku uses do rovnakej podmienky:
uses
...,
{$IFDEF D5}
CommCtrl,
{$ENDIF}
...;
Syntax formátovacieho reťazca
Formátovací reťazec odovzdaný do DateTime_SetFormat sa riadi formátom dátumu a času systému Windows, nie formátovacími tokenmi FormatDateTime v Delphi. Tieto dva vyzerajú podobne, ale nie sú zameniteľné. Windows používa d pre deň v mesiaci (bez úvodnej nuly), dd pre deň doplnený nulou, M pre číslo mesiaca, MM pre mesiac doplnený nulou, yy pre dvojciferný rok a yyyy pre štvorciferný rok. Časové polia používajú h/hh pre 12-hodinový formát hodín, H/HH pre 24-hodinový, m/mm pre minúty, s/ss pre sekundy. Literálový text patrí do jednoduchých úvodzoviek vo formátovacom reťazci, takže 'dd/MM/yyyy' je už správne, ale 'dd '<literál>' MM' by vyžadovalo vložené dvojice jednoduchých úvodzoviek.
Regionálne nastavenia a globálna premenná ShortDateFormat
Zmena globálnej premennej ShortDateFormat v Delphi neovplyvní TDateTimePicker, ktorý už bol vytvorený. Výber dátumu (picker) načíta regionálne nastavenia zo systému Windows v čase vytvorenia a potom vykresľuje podľa správ, ktoré prijíma, nie podľa globálnych nastavení Delphi RTL. To znamená, že nastavenie ShortDateFormat vo FormCreate nezmení zobrazenie ovládacieho prvku. Na prepísanie formátovacieho reťazca samotného prvku po vytvorení handle potrebujete DateTime_SetFormat (alebo vlastnosť Format v novšom Delphi).
Pri aplikáciách nasadených v medzinárodnom meradle otestujte formátovací reťazec na počítači s iným ako americkým regionálnym nastavením. Windows môže prepísať prázdny alebo nil formátovací reťazec predvoleným nastavením národného prostredia (locale), ale explicitný reťazec, ktorý nie je nil, úplne nahrádza regionálne nastavenie. To je zvyčajne to, čo chcete, ale znamená to, že vzor zameraný na USA ako 'MM/dd/yyyy' sa zobrazí presne takto aj pre používateľov, ktorí podľa konvencie očakávajú dd/MM/yyyy. Ak je výber dátumu určený pre koncového používateľa a nie iba pre čisté zadávanie údajov, zvážte ponechanie predvoleného správania (odovzdajte nil do DateTime_SetFormat), aby automaticky sledoval nastavenie locale používateľa.
Opätovné vytvorenie handle
Nastavenie formátu patrí k handle okna, nie k poľu objektu VCL. Ak sa handle ovládacieho prvku zničí a znova vytvorí, čo môže VCL urobiť pri zmene rodiča prvku (reparenting) alebo zmene určitých vlastností štýlu za behu, formát sa vráti na predvolenú hodnotu systému Windows. Bezpečné miesto na použitie DateTime_SetFormat je v obsluhe, ktorá beží po vytvorení handle: prepíšte CreateWnd v odvodenej triede a zavolajte ho tam, alebo ho aplikujte v udalosti OnEnter alebo OnShow až po potvrdení, že handle je aktívne. Jednorazové nastavenie vo FormCreate je pre jednoduché formuláre často postačujúce, ale nie je spoľahlivé, ak formulár vykonáva dynamické prepínanie štýlov alebo zmenu rodičov ovládacích prvkov.
Rovnaké obmedzenie platí aj pre vlastnosť VCL Format v novších verziách Delphi; vnútorne volá rovnakú správu Windows a čelí rovnakému životnému cyklu handle. Rozdiel je v tom, že setter vlastnosti VCL pred volaním skontroluje, či je handle alokované, a automaticky znova použije formát pri CreateWnd. Priame volanie DateTime_SetFormat nemá takúto ochranu, takže vetva pre Delphi 5 musí byť opatrnejšia v tom, kedy sa spúšťa.
Odstránenie tohto workaroundu
Keď projekt ukončí podporu pre Delphi 5, podmienený blok sa stane zbytočnou záťažou. Odstráňte vetvu {$IFDEF D5} a obmedzený import CommCtrl, pričom ponechajte iba priame priradenie vlastnosti Format. Odstránenie uchovajte v samostatnom commite, aby bolo ľahké identifikovať, či sa niečo neočakávane nepokazilo na kompilátore, ktorý ste netestovali. Samotný formátovací reťazec zostáva rovnaký; mení sa iba mechanizmus doručenia.