「MFCコントロール - DDV」の版間の差分
(ページの作成:「== 概要 == DDV (Dialog Data Validation) は、MFCアプリケーションにおけるユーザ入力データの検証機能である。<br> MFCアプリケーションにおけるデータ検証の基盤として、ユーザインターフェースを支援する機能である。<br> <br> DDX (Dialog Data eXchange) と密接に連携して動作しており、データの整合性と有効性を確保する。<br> <br> DDVの仕組みでは、<code>UpdateData(TR…」) |
(→カスタム検証) |
||
54行目: | 54行目: | ||
== カスタム検証 == | == カスタム検証 == | ||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
// カスタムバリデーション 1 | |||
void AFXAPI DDV_EmailAddress(CDataExchange* pDX, const CString& value) | void AFXAPI DDV_EmailAddress(CDataExchange* pDX, const CString& value) | ||
{ | { | ||
70行目: | 72行目: | ||
CDialog::DoDataExchange(pDX); | CDialog::DoDataExchange(pDX); | ||
DDX_Text(pDX, IDC_EDIT_EMAIL, m_strEmail); | DDX_Text(pDX, IDC_EDIT_EMAIL, m_strEmail); | ||
DDV_EmailAddress(pDX, m_strEmail); | DDV_EmailAddress(pDX, m_strEmail); | ||
80行目: | 81行目: | ||
pDX->Fail(); | pDX->Fail(); | ||
} | } | ||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// カスタムバリデーション 2 | |||
bool CMyDialog::IsValidFormat(const CString &data) | |||
{ | |||
// 例: 文字列が入力されているかどうかの検証 | |||
if (data.IsEmpty()) return false; | |||
// 例: 文字種の検証 | |||
for (int i = 0; i < data.GetLength(); i++) { | |||
if (!_istalnum(data[i]) && data[i] != '-' && data[i] != '_') { | |||
return false; | |||
} | |||
} | |||
// 例: 文字列の長さの検証 | |||
if (data.GetLength() > 50) return false; | |||
// 例: 予約語の検証 | |||
if (data.CompareNoCase(_T("admin")) == 0 || data.CompareNoCase(_T("system")) == 0) { | |||
return false; | |||
} | |||
// 例: 郵便番号フォーマットの検証 (例: 123-4567) | |||
// 文字列の長さ | |||
if (data.GetLength() != 8) return false; | |||
// 形式 (数字3文字 - 数字4文字) | |||
for (int i = 0; i < 8; i++) { | |||
if (i == 3) { | |||
if (data[i] != '-') return false; | |||
} | |||
else { | |||
if (!_istdigit(data[i])) return false; | |||
} | |||
} | |||
// 例: 電話番号フォーマットの検証 (例: 03-1234-5678) | |||
// 正規表現の使用 | |||
CRegExp regExp; | |||
regExp.Pattern = _T("^\\d{2,4}-\\d{2,4}-\\d{4}$"); | |||
return regExp.Test(data); | |||
// 例: 日付フォーマットの検証 (例: 2024/01/13) | |||
if (data.GetLength() != 10) return false; | |||
// 年月日を分解 | |||
int year = _ttoi(data.Left(4)); | |||
int month = _ttoi(data.Mid(5, 2)); | |||
int day = _ttoi(data.Mid(8, 2)); | |||
// 区切り文字 (例: /) の検証 | |||
if (data[4] != '/' || data[7] != '/') return false; | |||
// 値の範囲の検証 | |||
if (year < 1900 || year > 2100) return false; | |||
if (month < 1 || month > 12) return false; | |||
if (day < 1 || day > 31) return false; | |||
return true; | |||
} | |||
void CMyDialog::DoDataExchange(CDataExchange *pDX) | |||
{ | |||
CDialog::DoDataExchange(pDX); | |||
DDX_Text(pDX, IDC_EDIT_DATA, m_strData); | DDX_Text(pDX, IDC_EDIT_DATA, m_strData); | ||
if (pDX->m_bSaveAndValidate) { | if (pDX->m_bSaveAndValidate) { |
2025年1月13日 (月) 01:29時点における最新版
概要
DDV (Dialog Data Validation) は、MFCアプリケーションにおけるユーザ入力データの検証機能である。
MFCアプリケーションにおけるデータ検証の基盤として、ユーザインターフェースを支援する機能である。
DDX (Dialog Data eXchange) と密接に連携して動作しており、データの整合性と有効性を確保する。
DDVの仕組みでは、UpdateData(TRUE)
メソッドを実行した (コントロールからメンバ変数にデータが転送される) 場合に、指定された検証ルールに基づいてデータの妥当性がチェックされる。
検証に失敗した場合は、自動的にエラーメッセージが表示されて、該当のコントロールにフォーカスが設定される。
検証機能として、数値の範囲、文字列の長さ、必須入力等が組み込まれている。
例えば、DDV_MinMaxInt
は整数値の範囲を検証、DDV_MaxChars
は文字列の最大長を制限する。
また、カスタム検証ロジックを実装することも可能であり、アプリケーション固有の複雑な検証要件にも対応できる。
カスタム検証ロジックは、DoDataExchange
メソッド内で独自の検証関数を呼び出す、あるいは、条件分岐を使用して実装する。
エラーハンドリングにおいては、DDVは例外を使用してバリデーションの失敗を通知するため、try-catch句を使用して例外を処理することができる。
これにより、エラーメッセージを提供する、あるいは、特定の状況下での代替処理を実装することが可能になる。
また、DDVはフォーム全体の検証も可能であり、UpdateDataメソッドの実行時に全ての検証ルールが順番にチェックされて、1つでも失敗すると処理が中断される。
これにより、データの一貫性を確保して、不正なデータがアプリケーション内部に入り込むのを防ぐことができる。
文字列の長さ
void CMyDialog::DoDataExchange(CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
// 文字列の長さに検証例 (5文字以上20文字以下)
DDX_Text(pDX, IDC_EDIT_NAME, m_strName);
DDV_MaxChars(pDX, m_strName, 20);
DDV_MinChars(pDX, m_strName, 5);
}
数値範囲の検証
void CMyDialog::DoDataExchange(CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
// 数値範囲の検証例 (0〜120)
DDX_Int(pDX, IDC_EDIT_AGE, m_nAge);
DDV_MinMaxInt(pDX, m_nAge, 0, 120);
// 浮動小数範囲の検証例 (0.0〜1000000.0)
DDX_Text(pDX, IDC_EDIT_SALARY, m_dSalary);
DDV_MinMaxDouble(pDX, m_dSalary, 0.0, 1000000.0);
}
カスタム検証
// カスタムバリデーション 1
void AFXAPI DDV_EmailAddress(CDataExchange* pDX, const CString& value)
{
// コントロールからデータを取得する場合のみチェック
if (pDX->m_bSaveAndValidate) {
// 簡易的なメールアドレス確認
if (value.Find('@') == -1 || value.Find('.') == -1) {
AfxMessageBox(_T("有効なメールアドレスを入力してください"));
pDX->Fail(); // バリデーション失敗
}
}
}
void CMyDialog::DoDataExchange(CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_EMAIL, m_strEmail);
DDV_EmailAddress(pDX, m_strEmail);
// 必須入力チェック
DDX_Text(pDX, IDC_EDIT_REQUIRED, m_strRequired);
if (pDX->m_bSaveAndValidate && m_strRequired.IsEmpty()) {
AfxMessageBox(_T("この項目は必須です"));
pDX->Fail();
}
}
// カスタムバリデーション 2
bool CMyDialog::IsValidFormat(const CString &data)
{
// 例: 文字列が入力されているかどうかの検証
if (data.IsEmpty()) return false;
// 例: 文字種の検証
for (int i = 0; i < data.GetLength(); i++) {
if (!_istalnum(data[i]) && data[i] != '-' && data[i] != '_') {
return false;
}
}
// 例: 文字列の長さの検証
if (data.GetLength() > 50) return false;
// 例: 予約語の検証
if (data.CompareNoCase(_T("admin")) == 0 || data.CompareNoCase(_T("system")) == 0) {
return false;
}
// 例: 郵便番号フォーマットの検証 (例: 123-4567)
// 文字列の長さ
if (data.GetLength() != 8) return false;
// 形式 (数字3文字 - 数字4文字)
for (int i = 0; i < 8; i++) {
if (i == 3) {
if (data[i] != '-') return false;
}
else {
if (!_istdigit(data[i])) return false;
}
}
// 例: 電話番号フォーマットの検証 (例: 03-1234-5678)
// 正規表現の使用
CRegExp regExp;
regExp.Pattern = _T("^\\d{2,4}-\\d{2,4}-\\d{4}$");
return regExp.Test(data);
// 例: 日付フォーマットの検証 (例: 2024/01/13)
if (data.GetLength() != 10) return false;
// 年月日を分解
int year = _ttoi(data.Left(4));
int month = _ttoi(data.Mid(5, 2));
int day = _ttoi(data.Mid(8, 2));
// 区切り文字 (例: /) の検証
if (data[4] != '/' || data[7] != '/') return false;
// 値の範囲の検証
if (year < 1900 || year > 2100) return false;
if (month < 1 || month > 12) return false;
if (day < 1 || day > 31) return false;
return true;
}
void CMyDialog::DoDataExchange(CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_DATA, m_strData);
if (pDX->m_bSaveAndValidate) {
// カスタム検証ロジック
if (!IsValidFormat(m_strData)) {
AfxMessageBox(_T("データ形式が不正です"));
pDX->Fail();
}
}
}