TDateTimePicker, Delphi 5 ile Delphi 6 arasında bir yerlerde bir Format özelliği kazandı. Kesin sürüm sınırı nadiren güvenebileceğiniz bir şekilde belgelenmiştir ve bu sınıra çarptığınızda derleyici size sadece tanımlayıcının mevcut olmadığını söyler. Sahip olduğunuz her yeni Delphi sürümünde derlenen ve çalışan satır, projenin nasıl yapılandırıldığına bağlı olarak eski sürümde sessizce veya tamamen başarısız olur
Altta yatan kontrol, comctl32.dll içindeki Windows DATETIMEPICK_CLASS ortak kontrolüdür (common control) ve DTM_SETFORMAT mesajı aracılığıyla her zaman bir format dizisini kabul etmiştir. Delphi'nin VCL'i, daha yeni sürümlerde bu mesajı Format özelliğine sarar. Delphi 5'te ise mesajı CommCtrl içinde bildirilen DateTime_SetFormat makro sarmalayıcısı (wrapper) aracılığıyla kendiniz gönderirsiniz
Koşullu derleme kalıbı
Standart yaklaşım, bir sürüm sembolüne anahtarlanmış derleyici koşullu (compiler-conditional) bir bloktur. Delphi 5, VER130 tanımlar; doğrudan buna karşı test edebilir veya dallanma etiketini kod tabanında daha okunaklı hale getirmek için proje seçeneklerinde kendi D5 sembolünüzü tanımlayabilirsiniz. Her iki durumda da, Delphi 5 dalı kontrol tanıtıcısı (handle) ile DateTime_SetFormat işlevini çağırır; diğer tüm dallar ise özelliği atar:
{$IFDEF D5}
DateTime_SetFormat(DateTimePicker1.Handle, PChar('MM/dd/yyyy'));
{$ELSE}
DateTimePicker1.Format := 'MM/dd/yyyy';
{$ENDIF}
Delphi 5 dalını içeren birim (unit) için uses ifadesine CommCtrl ekleyin. Bunu koşulsuz olarak eklemeye gerek yoktur; bağımlılığın kapsamını sınırlı tutmayı tercih ederseniz, uses girdisini aynı koşul bloğuna sarın:
uses
...,
{$IFDEF D5}
CommCtrl,
{$ENDIF}
...;
Format dizisi sözdizimi (syntax)
DateTime_SetFormat işlevine iletilen format dizisi, Delphi'nin FormatDateTime belirteçlerini değil, Windows tarih-saat seçici formatını izler. İkisi benzer görünür ancak birbirinin yerine kullanılamaz. Windows, ayın günü için d (başında sıfır olmadan), sıfır dolgulu gün için dd, ay numarası için M, sıfır dolgulu ay için MM, iki haneli yıl için yy ve dört haneli yıl için yyyy kullanır. Saat alanlarında 12 saatlik format için h/hh, 24 saatlik format için H/HH, dakikalar için m/mm, saniyeler için s/ss kullanılır. Format dizisinin içinde metin değişmezleri (literal text) tek tırnak içine alınır, yani 'dd/MM/yyyy' zaten doğrudur, ancak 'dd '<literal>' MM' gömülü tek tırnak çiftleri gerektirir
Buna karşılık Delphi'nin FormatDateTime işlevi, farklı semantiklere sahip gün biçimleri için d/dd/ddd/dddd kullanır ve ay için m (M değil) kullanır. Bir format dizisini bir FormatDateTime çağrısından kopyalayıp doğrudan DateTime_SetFormat işlevine verirseniz, çıktıda büyük ihtimalle ay ve dakika alanları yer değiştirmiş olacaktır. Kontrolün format dizisini bir Delphi formatından dönüştürmek yerine Windows belgelerine bakarak sıfırdan yazın
Bölgesel ayarlar ve küresel ShortDateFormat
Delphi'nin küresel ShortDateFormat değişkenini değiştirmek, önceden oluşturulmuş bir TDateTimePicker'ı etkilemez. Seçici, bölgesel ayarları oluşturma anında Windows'tan okur ve daha sonra Delphi RTL küresellerine göre değil, aldığı mesajlara göre işlem (render) yapar. Bu, FormCreate içinde ShortDateFormat ayarının, kontrolün ne görüntülediğini değiştirmeyeceği anlamına gelir. Tanıtıcı (handle) oluşturulduktan sonra kontrolün kendi format dizisini geçersiz kılmak (override) için DateTime_SetFormat (veya daha yeni Delphi'lerde Format özelliği) gereklidir
Uluslararası düzeyde dağıtılan uygulamalar için, format dizisini ABD dışı bölgesel ayara sahip bir makinede test edin. Windows, boş veya nil olan bir format dizisini yerel varsayılan (locale default) değer ile geçersiz kılabilir, ancak açık bir şekilde belirtilen nil olmayan (non-nil) bir dizi, bölgesel ayarı tamamen ezer. Genellikle istediğiniz budur, ancak bu, 'MM/dd/yyyy' gibi ABD odaklı bir kalıbın, geleneksel olarak dd/MM/yyyy bekleyen kullanıcılar için olduğu gibi görüneceği anlamına gelir. Eğer tarih seçici salt bir veri giriş alanından çok kullanıcıya dönük (user-facing) bir alansa, kontrolün varsayılan değerde kalmasını sağlayarak (DateTime_SetFormat işlevine nil ileterek) kullanıcının bölgesel ayarını otomatik olarak izlemesini düşünebilirsiniz
Handle (Tanıtıcı) yeniden oluşturulması
Format ayarı herhangi bir VCL nesne alanına değil, pencere tanıtıcısına (window handle) aittir. Çalışma zamanında bir kontrolün ebeveynini değiştirdiğinizde (reparent) veya belirli stil özelliklerini değiştirdiğinizde VCL'nin yapabildiği gibi, kontrolün tanıtıcısı yok edilip yeniden oluşturulursa format Windows varsayılanına döner. DateTime_SetFormat uygulamak için güvenli yer, tanıtıcı oluşturulduktan sonra çalışan bir işleyicidir (handler): alt bir sınıfta CreateWnd'yi geçersiz kılın (override) ve orada çağırın veya yalnızca tanıtıcının canlı olduğunu onayladıktan sonra OnEnter veya OnShow olayına uygulayın. Basit formlar için bunu FormCreate içinde bir kez ayarlamak genellikle yeterlidir, ancak form dinamik stil geçişleri veya kontrolün ebeveynini değiştirme (reparenting) işlemleri yapıyorsa güvenilir değildir
Aynı kısıtlama daha yeni Delphi sürümlerindeki VCL Format özelliği için de geçerlidir; dahili olarak aynı Windows mesajını çağırır ve aynı handle yaşam döngüsüyle karşı karşıyadır. Aradaki fark, VCL özellik ayarlayıcısının (setter) çağrı yapmadan önce tanıtıcının ayrılıp (allocated) ayrılmadığını kontrol etmesi ve CreateWnd anında formatı otomatik olarak yeniden uygulamasıdır. Ham (raw) DateTime_SetFormat çağrısı böyle bir korumaya sahip değildir, bu nedenle Delphi 5 dalının ne zaman çalışacağı konusunda daha dikkatli olması gerekir
Geçici çözümü kaldırma
Bir proje Delphi 5 desteğini bıraktığında koşullu blok ölü ağırlık haline gelir. {$IFDEF D5} dalını ve kapsamlı CommCtrl içe aktarımını (import) kaldırarak geriye yalnızca doğrudan Format özellik atamasını bırakın. Test etmediğiniz bir derleyicide beklenmedik bir şekilde bir şey bozulursa tanımlamayı kolaylaştırmak için kaldırma işlemini tek bir işlem (commit) içinde tutun. Format dizisinin kendisi aynı kalır; yalnızca teslim mekanizması değişir