日時指定コントロールでのコールバック フィールドの使い方
日時指定フィールドを定義する標準書式指定文字に加えて、カスタム書式指定文字列の特定の部分をコールバック フィールドとして指定することによって、出力をカスタマイズできます。 コールバック フィールドを宣言するには、書式指定文字列の本文の任意の場所に 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 パラメーターを適切な型にキャストすることによって見つかります。