日時指定コントロールでのコールバック フィールドの使い方

日時指定フィールドを定義する標準書式指定文字に加えて、カスタム書式指定文字列の特定の部分をコールバック フィールドとして指定することによって、出力をカスタマイズできます。 コールバック フィールドを宣言するには、書式指定文字列の本文の任意の場所に 1 つ以上の "X" 文字 (ASCII コード 88) を含めます。 たとえば、次の文字列 "'Today is: 'yy'/'MM'/'dd' (Day 'X')'" を指定すると、日時指定コントロールに、年の後ろに月、日、最後に年の通算日が続く現在の値が表示されます。

Note

コールバック フィールド内の X の数は、表示される文字数に対応していません。

"X" 文字を繰り返すことによって、カスタム文字列内の複数のコールバック フィールドを区別できます。 そのため、書式指定文字列 "XXddddMMMdd'、'yyyXXX" には、"XX" と "XXX" という 2 つの一意のコールバック フィールドが含まれています。

Note

コールバック フィールドは有効なフィールドとして扱われるため、アプリケーションが DTN_WMKEYDOWN 通知メッセージを処理する準備をする必要があります。

日時指定コントロールへのコールバック フィールドの実装は、次の 3 つの部分で構成されます。

  • カスタム書式指定文字列の初期化

  • DTN_FORMATQUERY 通知の処理

  • DTN_FORMAT 通知の処理

カスタム書式指定文字列の初期化

CDateTimeCtrl::SetFormat の呼び出しを使用して、カスタム文字列を初期化します。 詳細については、「日時指定コントロールでのカスタム書式指定文字列の使用」を参照してください。 カスタム書式指定文字列を設定する一般的な場所は、含まれるダイアログ クラスの OnInitDialog 関数または含まれるビュー クラスの OnInitialUpdate 関数です。

DTN_FORMATQUERY 通知の処理

コントロールが書式指定文字列を解析し、コールバック フィールドを検出すると、アプリケーションが DTN_FORMAT 通知メッセージと DTN_FORMATQUERY 通知メッセージを送信します。 コールバック フィールド文字列が通知と一緒に含まれているため、問い合わせるコールバック フィールドを特定できます。

現在のコールバック フィールドに表示される文字列の最大許容サイズ (ピクセル単位) を取得するための DTN_FORMATQUERY 通知が送信されます。

この値を正確に計算するには、コントロールの表示フォントを使用して、フィールドに置き換わる文字列の高さと幅を計算する必要があります。 実際の文字列の計算は、GetTextExtentPoint32 Win32 関数の呼び出しを使用して簡単に実現できます。 サイズが決定したら、値をアプリケーションに渡して、ハンドラー関数を終了します。

次の例は、コールバック文字列のサイズを指定する 1 つのメソッドです。

void CMyDialog::OnDtnFormatqueryDatetimepicker1(NMHDR *pNMHDR, LRESULT *pResult)
{
   LPNMDATETIMEFORMATQUERY pDTFormatQuery =
       reinterpret_cast<LPNMDATETIMEFORMATQUERY>(pNMHDR);
   CDC *pDC = NULL;
   CFont *pFont = NULL;
   CFont *pOrigFont = NULL;

   //  Prepare the device context for the GetTextExtentPoint32 call.
   pDC = GetDC();
   if (NULL == pDC)
   {
      return;
   }

   pFont = GetFont();
   if (NULL == pFont)
   {
      pFont = new CFont();
      VERIFY(pFont->CreateStockObject(DEFAULT_GUI_FONT));
   }

   pOrigFont = pDC->SelectObject(pFont);

   // Check to see if this is the callback segment desired. If so,
   // use the longest text segment to determine the maximum
   // width of the callback field, and then place the information into
   // the NMDATETIMEFORMATQUERY structure.
   if (!_tcscmp(_T("X"), pDTFormatQuery->pszFormat))
   {
      ::GetTextExtentPoint32(pDC->m_hDC, _T("366"), 3, &pDTFormatQuery->szMax);
   }

   // Reset the font in the device context then release the context.
   pDC->SelectObject(pOrigFont);
   ReleaseDC(pDC);

   *pResult = 0;
}

現在のコールバック フィールドのサイズを計算したら、そのフィールドの値を指定する必要があります。 これは、DTN_FORMAT 通知のハンドラーで行われます。

DTN_FORMAT 通知の処理

この DTN_FORMAT 通知は、アプリケーションが置き換える文字列を要求するために使用されます。 次の例は、可能性のある 1 つのメソッドを示しています。

void CMyDialog::OnDtnFormatDatetimepicker1(NMHDR *pNMHDR, LRESULT *pResult)
{
   LPNMDATETIMEFORMAT pDTFormat = reinterpret_cast<LPNMDATETIMEFORMAT>(pNMHDR);

   COleDateTime oCurTime;

   m_DateTimeCtrl.GetTime(oCurTime);

   _itot_s(oCurTime.GetDayOfYear(), pDTFormat->szDisplay,
           sizeof(pDTFormat->szDisplay) / sizeof(TCHAR), 10);

   *pResult = 0;
}

Note

NMDATETIMEFORMAT 構造体へのポインターは、通知ハンドラーの第 1 パラメーターを適切な型にキャストすることによって見つかります。

関連項目

CDateTimeCtrl の使い方
コントロール