Tehnični članak

Format TDateTimePicker v Delphi 5: DateTime_SetFormat

TDateTimePicker je med različicama Delphi 5 in Delphi 6 pridobil lastnost Format. Točna meja različice je redko zanesljivo dokumentirana, in ko naletite nanjo, vam prevajalnik preprosto javi, da identifikator ne obstaja. Vrstica, ki se prevede in deluje v vsaki novejši različici Delphija, v stari tiho ali popolnoma odpove, odvisno od strukture projekta

Osnovna kontrola je skupna kontrola Windows DATETIMEPICK_CLASS iz knjižnice comctl32.dll, ki je vedno sprejemala niz formata prek sporočila DTM_SETFORMAT. Delphi VCL to sporočilo v novejših različicah ovije v lastnost Format. V Delphi 5 sporočilo pošljete sami prek makro ovijalnika DateTime_SetFormat, ki je deklariran v enoti CommCtrl

Vzorec pogojnega prevajanja

Standardni pristop je pogojni prevajalni blok, ki se nanaša na simbol različice. Delphi 5 definira VER130; preverite ga neposredno ali definirajte lasten simbol D5 v možnostih projekta za boljšo berljivost po kodni bazi. V vsakem primeru veja za Delphi 5 kliče DateTime_SetFormat z ročico kontrole; vse ostale veje pa dodelijo lastnost:

{$IFDEF D5}
  DateTime_SetFormat(DateTimePicker1.Handle, PChar('MM/dd/yyyy'));
{$ELSE}
  DateTimePicker1.Format := 'MM/dd/yyyy';
{$ENDIF}

Dodajte CommCtrl v stavek uses enote, ki vsebuje vejo za Delphi 5. Ni je treba dodati brezpogojno; če želite ohraniti odvisnost omejeno, ovijte vnos uses v enak pogoj:

uses
  ...,
{$IFDEF D5}
  CommCtrl,
{$ENDIF}
  ...;

Sintaksa nizov formata

Niz formata, ki ga posredujete DateTime_SetFormat, sledi obliki izbirnika datuma in časa Windows in ne žetonom FormatDateTime iz Delphija. Obliki sta si podobni, a nista zamenljivi. Windows uporablja d za dan v mesecu (brez vodilne ničle), dd za dan z vodilno ničlo, M za številko meseca, MM za mesec z vodilno ničlo, yy za dvomestno letnico in yyyy za štirimestno letnico. Časovna polja uporabljajo h/hh za 12-urni zapis, H/HH za 24-urni zapis, m/mm za minute in s/ss za sekunde. Dobesedno besedilo gre znotraj niza formata v enojne narekovaje, zato je 'dd/MM/yyyy' že pravilno, medtem ko bi 'dd '<literal>' MM' zahteval vgnezdene pare enojnih narekovajev

Delphijev FormatDateTime nasprotno uporablja d/dd/ddd/dddd za oblike dneva z drugačno semantiko in m za mesec (ne M). Če kopirate niz formata iz klica FormatDateTime in ga predate neposredno DateTime_SetFormat, bosta polji za mesec in minute v izhodu verjetno zamenjani. Niz formata za kontrolo napišite na novo glede na dokumentacijo Windows in ga ne pretvarjajte iz Delphijevega formata

Regionalne nastavitve in globalni ShortDateFormat

Sprememba Delphijeve globalne spremenljivke ShortDateFormat ne vpliva na že ustvarjeni TDateTimePicker. Izbirnik ob ustvaritvi prebere regionalne nastavitve iz sistema Windows in se nato izrisuje glede na prejeta sporočila ter ne sledi globalnim spremenljivkam Delphi RTL. To pomeni, da nastavitev ShortDateFormat v FormCreate ne bo spremenila prikaza kontrole. Za preglasitev privzetega niza formata kontrole po tem, ko ročica že obstaja, morate uporabiti DateTime_SetFormat (ali lastnost Format v novejšem Delphiju)

Za aplikacije, nameščene na mednarodnem trgu, preizkusite niz formata na računalniku z neameriškimi regionalnimi nastavitvami. Windows lahko prazen ali nil niz formata nadomesti s privzeto lokalno nastavitvijo, vendar izrecno določen niz formata, ki ni nil, v celoti preglasi regionalno nastavitev. To je navadno tisto, kar želite, a pomeni, da se bo vzorec, osredotočen na ZDA, kot je 'MM/dd/yyyy', prikazal nespremenjen tudi za uporabnike, ki po konvenciji pričakujejo dd/MM/yyyy. Če je izbirnik datuma namenjen neposredno uporabnikom in ne gre za goli vnos podatkov, razmislite o privzeti nastavitvi kontrole (predajte nil v DateTime_SetFormat), da bo samodejno sledila lokalni nastavitvi uporabnika

Ponovna ustvaritev ročice

Nastavitev formata pripada ročici okna in ne polju objekta VCL. Če se ročica kontrole uniči in znova ustvari - kar VCL stori pri spremembi starševskega okna kontrole ali spremembi določenih slogovnih lastnosti med izvajanjem - se format vrne na privzete nastavitve Windows. Varno mesto za uporabo DateTime_SetFormat je v upravljalniku, ki se zažene po ustvaritvi ročice: prepišite CreateWnd v izpeljanem razredu in ga pokličite tam, ali pa ga uveljavite v dogodku OnEnter ali OnShow šele po potrditvi, da je ročica aktivna. Enkratna nastavitev v FormCreate pogosto zadostuje za preproste obrazce, ni pa zanesljiva, če obrazec dinamično spreminja sloge ali starševstvo kontrol

Enaka omejitev velja za lastnost VCL Format v novejših različicah Delphija; interno uporablja isto sporočilo Windows in se sooča z enakim življenjskim ciklom ročice. Razlika je v tem, da nastavljalnik lastnosti VCL pred klicem preveri, ali je ročica dodeljena, in samodejno znova uveljavi format ob klicu CreateWnd. Neposredni klic DateTime_SetFormat nima takšne zaščite, zato mora biti veja za Delphi 5 bolj premišljena glede trenutka izvajanja

Odstranitev začasne rešitve

Ko projekt opusti podporo za Delphi 5, postane pogojni blok odveč. Odstranite vejo {$IFDEF D5} in omejen uvoz CommCtrl ter pustite le neposredno dodelitev lastnosti Format. Odstranitev opravite v enem samem commitu, da jo boste lažje prepoznali, če se na nepreizkušenem prevajalniku kaj nepričakovano zalomi. Sam niz formata ostaja enak; spremeni se le mehanizem dostave