TDateTimePicker je dobio svojstvo Format negde između Delphi 5 i Delphi 6. Tačna granica verzije je retko dokumentovana na pouzdan način, a kada naiđete na nju, kompajler vam jednostavno javlja da identifikator ne postoji. Linija koda koja se kompajlira i radi na svakoj novijoj verziji Delphi-ja tiho ili potpuno otkazuje na starijoj, u zavisnosti od toga kako je projekat strukturisan.
Prateća kontrola je standardna Windows-ova DATETIMEPICK_CLASS kontrola iz comctl32.dll, koja je oduvek prihvatala string formata preko poruke DTM_SETFORMAT. Delphi-jev VCL obmotava tu poruku u svojstvo Format na novijim verzijama. Na Delphi 5 verziji, sami šaljete poruku preko makro omotača DateTime_SetFormat deklarisanog u CommCtrl jedinici.
Šablon uslovnog kompajliranja
Standardan pristup je uslovni blok kompajlera zasnovan na simbolu verzije. Delphi 5 definiše VER130; možete testirati direktno njega ili definisati sopstveni simbol D5 u opcijama projekta kako bi oznaka grane bila čitljivija u celom kodu. U oba slučaja, grana za Delphi 5 poziva DateTime_SetFormat sa handle-om kontrole; sve ostale grane dodeljuju vrednost svojstvu:
{$IFDEF D5}
DateTime_SetFormat(DateTimePicker1.Handle, PChar('MM/dd/yyyy'));
{$ELSE}
DateTimePicker1.Format := 'MM/dd/yyyy';
{$ENDIF}
Dodajte CommCtrl u uses odeljak za jedinicu koja sadrži granu za Delphi 5. Nema potrebe da je dodajete bezuslovno; ako želite da ograničite zavisnost, umotajte unos u uses u isti uslov:
uses
...,
{$IFDEF D5}
CommCtrl,
{$ENDIF}
...;
Sintaksa stringa formata
String formata koji se prosleđuje funkciji DateTime_SetFormat prati Windows-ov format za izbor datuma i vremena, a ne Delphi-jeve tokene za FormatDateTime. Ova dva izgledaju slično, ali se ne mogu koristiti naizmenično. Windows koristi d za dan u mesecu (bez nule na početku), dd za dan sa nulom na početku, M za broj meseca, MM za mesec sa nulom na početku, yy za dvocifrenu godinu i yyyy za četvorocifrenu godinu. Vremenska polja koriste h/hh za sate u 12-časovnom formatu, H/HH za 24-časovni format, m/mm za minute i s/ss za sekunde. Bukvalni tekst ide unutar jednostrukih navodnika u stringu formata, tako da je 'dd/MM/yyyy' već ispravno, ali bi 'dd '<literal>' MM' zahtevalo ugrađene parove jednostrukih navodnika.
Delphi-jev FormatDateTime, nasuprot tome, koristi d/dd/ddd/dddd za oblike dana sa različitom semantikom i m za mesec (ne M). Ako kopirate string formata iz poziva FormatDateTime i predate ga direktno funkciji DateTime_SetFormat, polja za mesece i minute će verovatno biti zamenjena na izlazu. Napišite string formata kontrole od nule prema Windows dokumentaciji umesto da ga konvertujete iz Delphi formata.
Regionalna podešavanja i globalni ShortDateFormat
Izmena Delphi-jeve globalne promenljive ShortDateFormat ne utiče na već kreiranu komponentu TDateTimePicker. Izbornik čita regionalna podešavanja iz Windows-a u vreme kreiranja i nakon toga vrši renderovanje prema porukama koje prima, a ne prema globalnim promenljivama Delphi RTL-a. To znači da podešavanje ShortDateFormat u FormCreate neće promeniti ono što kontrola prikazuje. Potrebna vam je funkcija DateTime_SetFormat (ili svojstvo Format na novijem Delphi-ju) da biste zaobišli sopstveni string formata kontrole nakon što handle postoji.
Za aplikacije koje se distribuiraju međunarodno, testirajte string formata na mašini sa regionalnim podešavanjima koja nisu iz SAD. Windows može zameniti prazan ili nil string formata sa podrazumevanom vrednošću lokaliteta, ali eksplicitni non-nil string u potpunosti zamenjuje regionalna podešavanja. To je obično ono što želite, ali to znači da će obrazac specifičan za SAD, poput 'MM/dd/yyyy', izgledati baš tako i korisnicima koji konvencionalno očekuju dd/MM/yyyy. Ako je izbornik datuma okrenut korisniku, a ne čisto polje za unos podataka, razmislite o tome da ostavite podrazumevanu vrednost kontrole (prosledite nil funkciji DateTime_SetFormat) kako bi automatski pratio lokalitet korisnika.
Ponovno kreiranje handle-a
Podešavanje formata pripada handle-u prozora, a ne bilo kom polju VCL objekta. Ako se handle kontrole uništi i ponovo kreira, što VCL može učiniti kada promenite roditeljsku kontrolu (reparenting) ili izmenite određena svojstva stila u vreme izvršavanja, format se vraća na podrazumevane Windows vrednosti. Bezbedno mesto za primenu funkcije DateTime_SetFormat je u rukovaocu koji se izvršava nakon kreiranja handle-a: nadjačajte CreateWnd u klasi potomku i pozovite ga tamo, ili ga primenite u događaju OnEnter ili OnShow tek nakon potvrde da je handle aktivan. Jednokratno podešavanje u FormCreate je često dovoljno za jednostavne forme, ali nije pouzdano ako forma vrši dinamičku promenu stilova ili preraspodelu kontrola.
Isto ograničenje važi i za VCL svojstvo Format na novijim verzijama Delphi-ja; interno ono šalje istu Windows poruku i suočava se sa istim životnim ciklusom handle-a. Razlika je u tome što postavljač VCL svojstva proverava da li je handle alociran pre slanja poruke i automatski ponovo primenjuje format u metodi CreateWnd. Direktan poziv funkcije DateTime_SetFormat nema takvu zaštitu, pa grana za Delphi 5 mora biti pažljivija u pogledu trenutka pokretanja.
Uklanjanje privremenog rešenja (workaround)
Kada projekat prestane da podržava Delphi 5, uslovni blok postaje suvišan teret. Uklanjanje {$IFDEF D5} grane i opseg uvoza CommCtrl, ostavljajući samo direktnu dodelu vrednosti svojstvu Format. Zadržite uklanjanje u jednom commit-u kako bi ga bilo lakše identifikovati ako se nešto neočekivano pokvari na kompajleru koji niste testirali. Sam string formata ostaje isti; menja se samo mehanizam isporuke.