技術記事

Delphi 5 の TDateTimePicker 形式

古い VCL サンプルに Delphi 5 互換性を追加しているとき、新しい Delphi ではごく普通の 1 行でプロジェクトが失敗しました。コードは独自の日付パターンを直接 TDateTimePicker.Format プロパティへ代入しようとしていました。

1
DateTimePicker.Format := 'MM/dd/yyyy';

TDateTimePicker は Windows 共通コントロールの VCL ラッパーです。新しい Delphi では便利な Format プロパティが公開されていますが、Delphi 5 にはありません。Delphi 5 以前では、基礎となる共通コントロール メッセージを直接送信しない限り、通常は Windows の地域別日付設定に従います。

Delphi 5 では共通コントロール API を使う

互換性の修正は、Delphi 5 では DateTime_SetFormatCommCtrl ユニットから呼び出し、新しいコンパイラでは直接プロパティ代入を維持することです。Delphi 5 ブランチをコンパイルするときは CommCtrluses 句へ追加します。

1
2
3
4
5
{$IFDEF D5}
DateTime_SetFormat(DateTimePicker.Handle, PChar('MM/dd/yyyy'));
{$ELSE}
DateTimePicker.Format := 'MM/dd/yyyy';
{$ENDIF}

実用上の注意

形式文字列は Windows の date-time picker 構文を使います。Delphi のすべての書式トークンではありません。パターンは単純に保ち、アプリケーションを国際展開する場合は地域設定の異なるマシンでテストしてください。

Delphi 5、Delphi 6、最新の Delphi リリースで共通サンプル コードを保守する場合は、この分岐を D5のようなコンパイラ シンボルの背後に隔離します。これにより最新コードを読みやすく保ちながら、古い共通コントロールの回避策も記録できます。

互換性チェックリスト

  • Delphi 5 ブランチが CommCtrl を必要とする場所だけに DateTime_SetFormatを追加します。
  • フォーム ハンドルではなく picker のハンドルを渡します。
  • 通常の文字列リテラルまたは安定した変数を渡し、呼び出し中は形式文字列が有効であるようにします。
  • 対象の Windows ロケールで表示される日付を確認します。

ShortDateFormat だけでは不十分な理由

Delphi のグローバル日付形式変数を変更しても、Windows 共通コントロールに基づく date-time picker が確実に変わるわけではありません。picker はコントロール設定と受信したメッセージに従って描画します。そのため DateTime_SetFormat が Delphi 5 の正しい互換レイヤーです。

この違いは古いサンプル プロジェクトで重要です。そうしたプロジェクトは複数の Delphi バージョンでコンパイルされることが多いからです。Delphi 7 や Delphi 2009 では問題ない 1 行が Delphi 5 には存在しない一方で、Windows 共通コントロール メッセージは利用できる場合があります。条件付きコンパイルにより、各コンパイラが最も自然な経路を使えます。

旧バージョン互換性のテスト

回避策を適用したら、表示値と保存値の両方をテストしてください。形式はユーザーに見える内容に影響しますが、計算に使う基礎の TDateTime 値を変えるべきではありません。この分離は、発注書、請求書、スプレッドシート エクスポートなど、表示書式と数値日付値の一貫性が必要な場面で重要です。

ウィンドウ ハンドルを再作成した後のフォームも確認してください。一部の VCL コントロールは、ハンドルが破棄され再作成されるとネイティブ コントロールの状態を失うことがあります。アプリケーションが実行時にスタイルや親を変更する場合は、ハンドルが利用可能になった後で形式を適用します。

長期保守の注意

プロジェクトが Delphi 5 サポートを不要にしたら、条件分岐を削除し、直接 Format プロパティ代入だけを残します。それまでは、互換コードを無関係な業務ロジックに隠すのではなく、コントロール設定の近くに置いてください。そうすれば、この回避策が発注計算ではなく VCL コントロールの制限のために存在することが明確になります。