次の方法で共有


TN026: DDX ルーチンと DDV ルーチン

次のテクニカル ノートは、最初にオンライン ドキュメントに含まれてから更新されていません。 その結果、一部の手順やトピックが古くなっているか、正しくない可能性があります。 最新情報については、オンライン ドキュメント インデックスで関心のあるトピックを検索することをお勧めします。

このメモでは、ダイアログ データ交換 (DDX) とダイアログ データ検証 (DDV) アーキテクチャについて説明します。 また、DDX_またはDDV_プロシージャを記述する方法と、ClassWizard を拡張してルーチンを使用する方法についても説明します。

ダイアログ データ交換の概要

すべてのダイアログ データ関数は C++ コードで実行されます。 特別なリソースや魔法のマクロはありません。 このメカニズムの中核となるのは、ダイアログ データ交換と検証を行うすべてのダイアログ クラスでオーバーライドされる仮想関数です。 これは常に次の形式で見つかります。

void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);   // call base class

    //{{AFX_DATA_MAP(CMyDialog)
        <data_exchange_function_call>
        <data_validation_function_call>
    //}}AFX_DATA_MAP
}

特別な形式の AFX コメントを使用すると、ClassWizard はこの関数内のコードを検索して編集できます。 ClassWizard と互換性のないコードは、特別な形式のコメントの外部に配置する必要があります。

上記の例では、 <data_exchange_function_call> は次の形式です。

DDX_Custom(pDX, nIDC, field);

と <data_validation_function_call> は省略可能であり、次の形式です。

DDV_Custom(pDX, field, ...);

DoDataExchange 関数には、複数のDDX_/DDV_ペアを含めることができます。

MFC で提供されるすべてのダイアログ データ交換ルーチンとダイアログ データ検証ルーチンの一覧については、「afxdd_.h」を参照してください。

ダイアログ データは、 CMyDialog クラスのメンバー データだけです。 構造体などに格納されません。

注記

この "ダイアログ データ" と呼びますが、すべての機能は CWnd から派生した任意のクラスで使用でき、ダイアログだけに限定されるわけではありません。

データの初期値は、標準の C++ コンストラクターで設定されます。通常は、 //{{AFX_DATA_INIT//}}AFX_DATA_INIT コメントを含むブロック内に設定されます。

CWnd::UpdateData は、 DoDataExchangeの呼び出しに関する初期化とエラー処理を行う操作です。

CWnd::UpdateDataはいつでも呼び出して、データ交換と検証を実行できます。 既定では、UpdateData(TRUE) は既定のCDialog::OnOK ハンドラーで呼び出され、既定のCDialog::OnInitDialogでは UpdateData(FALSE) が呼び出されます。

DDV_ ルーチンは、その フィールドのDDX_ ルーチンに直ちに従う必要があります。

しくみ

ダイアログ データを使用するために、次のことを理解する必要はありません。 ただし、これがバックグラウンドでどのように機能するかを理解することは、独自の交換または検証手順を記述するのに役立ちます。

DoDataExchangeメンバー関数は、Serialize メンバー関数とよく似ています。外部フォーム (この場合はダイアログのコントロール) との間でデータを取得または設定する役割を担います。 pDX パラメーターは、データ交換を行うためのコンテキストであり、CObject::SerializeCArchiveパラメーターに似ています。 pDX (CDataExchange オブジェクト) には、方向フラグがあるCArchiveと同じように方向フラグがあります。

  • !m_bSaveAndValidate場合は、データ状態をコントロールに読み込みます。

  • m_bSaveAndValidate場合は、コントロールからデータの状態を設定します。

検証は、 m_bSaveAndValidate が設定されている場合にのみ行われます。 m_bSaveAndValidateの値は、CWnd::UpdateDataする BOOL パラメーターによって決定されます。

他にも 3 つの興味深い CDataExchange メンバーがあります。

  • m_pDlgWnd: コントロールを含むウィンドウ (通常はダイアログ)。 これは、DDX_およびDDV_グローバル関数の呼び出し元が、すべての DDX/DDV ルーチンに 'this' を渡す必要がないようにするためです。

  • PrepareCtrl、および PrepareEditCtrl: データ交換用のダイアログ コントロールを準備します。 検証が失敗した場合にフォーカスを設定するためのコントロールのハンドルを格納します。 PrepareCtrl は非編集コントロールに使用され、 PrepareEditCtrl は編集コントロールに使用されます。

  • Fail: ユーザーに入力エラーを通知するメッセージ ボックスを表示した後に呼び出されます。 このルーチンは、最後のコントロール (最後の PrepareCtrl または PrepareEditCtrlの呼び出し) にフォーカスを復元し、例外をスローします。 このメンバー関数は、DDX_ルーチンとDDV_ ルーチンの両方から呼び出される場合があります。

ユーザー拡張機能

既定の DDX/DDV メカニズムを拡張するには、いくつかの方法があります。 次のようにすることができます。

  • 新しいデータ型を追加します。

    CTime
    
  • 新しい交換プロシージャ (DDX_) を追加します。

    void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
    
  • 新しい検証手順 (DDV_) を追加します。

    void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture);
    // make sure time is in the future or past
    
  • 任意の式を検証プロシージャに渡します。

    DDV_MinMax(pDX, age, 0, m_maxAge);
    

    このような任意の式は ClassWizard では編集できないため、特別な形式のコメント (//{{AFX_DATA_MAP(CMyClass)) の外部に移動する必要があります。

DoDataExchangeメンバー関数に、条件またはその他の有効な C++ ステートメントを含め、交換関数と検証関数の呼び出しを混在させる必要があります。

//{{AFX_DATA_MAP(CMyClass)
DDX_Check(pDX, IDC_SEX, m_bFemale);
DDX_Text(pDX, IDC_EDIT1, m_age);
//}}AFX_DATA_MAP
if (m_bFemale)
    DDV_MinMax(pDX, age, 0, m_maxFemaleAge);
else
    DDV_MinMax(pDX, age, 0, m_maxMaleAge);

上記のように、このようなコードは ClassWizard では編集できず、特別な形式のコメントの外部でのみ使用する必要があります。

ClassWizard のサポート

ClassWizard では、独自のDDX_ルーチンとDDV_ ルーチンを ClassWizard ユーザー インターフェイスに統合できるため、DDX/DDV カスタマイズのサブセットがサポートされます。 これは、プロジェクトまたは多くのプロジェクトで特定の DDX ルーチンと DDV ルーチンを再利用する予定がある場合にのみ、コストのメリットがあります。

これを行うには、DDX.CLW (以前のバージョンの Visual C++ でこの情報を APSTUDIO に格納) で特別なエントリを作成します。INI) またはプロジェクトの .CLW ファイル。 特別なエントリは、プロジェクトの [全般情報] セクションに入力できます。CLW ファイル、または \Program Files\Microsoft Visual Studio\Visual C++\bin ディレクトリの DDX.CLW ファイルの [ExtraDDX] セクション。 DDX.CLW ファイルがまだ存在しない場合は、作成が必要になる場合があります。 特定のプロジェクトでのみカスタム DDX_/DDV_ ルーチンを使用する場合は、プロジェクトの [全般情報] セクションにエントリを追加します。代わりに CLW ファイル。 多くのプロジェクトでルーチンを使用する場合は、DDX.CLW の [ExtraDDX] セクションにエントリを追加します。

これらの特殊項目の一般的な形式は次のとおりです。

ExtraDDXCount=n

ここで n は ExtraDDX の数ですか?フォームのフォローする行

ExtraDDX?=keys; vb-keys; prompt; type; initValue; DDX_Proc [; DDV_Proc; prompt1; arg1 [; prompt2; fmt2]]

どこ。 は、定義されているリスト内のどの DDX タイプを示す 1 から n の数値です。

各フィールドは 、';' 文字で区切られます。 フィールドとその目的を以下に示します。

  • キー

    この変数型を制御するダイアログが許可されていることを示す 1 文字の一覧。

    キャラクター 許可されるコントロール
    E 編集
    C [2 状態] チェック ボックス
    c [tri-state] チェック ボックス
    R グループ内の最初のラジオ ボタン
    L 並べ替えのないリスト ボックス
    l 並べ替えられたリスト ボックス
    エム コンボ ボックス (アイテムの編集を含む)
    N 並べ替えのないドロップ リスト
    n 並べ替えられたドロップダウン リスト
    1 DDX 挿入をリストの先頭に追加する必要がある場合 (既定値は末尾に追加されます)、これは通常、'Control' プロパティを転送する DDX ルーチンに使用されます。
  • vb-keys

    このフィールドは、VBX コントロールの 16 ビット製品でのみ使用されます (VBX コントロールは 32 ビット製品ではサポートされていません)

  • プロンプト

    プロパティ コンボ ボックスに配置する文字列 (引用符なし)

  • タイプ

    ヘッダー ファイルで出力する型の単一識別子。 上記の DDX_Time の例では、これは CTime に設定されます。

  • vb-keys

    このバージョンでは使用されず、常に空にする必要があります

  • initValue

    初期値 - 0 または空白。 空白の場合、実装ファイルの //{{AFX_DATA_INIT セクションに初期化行は書き込まれなくなります。 正しい初期化を保証するコンストラクターを持つ C++ オブジェクト ( CStringCTime など) には、空白のエントリを使用する必要があります。

  • DDX_Proc

    DDX_ プロシージャの単一識別子。 C++ 関数名は "DDX_" で始まる必要がありますが、 <DDX_Proc> 識別子には "DDX_" を含めないでください。 上記の例では、 <DDX_Proc> 識別子は Time になります。 ClassWizard が {{AFX_DATA_MAP セクションの実装ファイルに関数呼び出しを書き込むと、この名前がDDX_に追加され、DDX_Timeに到着します。

  • コメント

    この DDX を使用して変数のダイアログに表示するコメント。 ここに任意のテキストを配置し、通常は DDX/DDV ペアによって実行される操作を説明するテキストを提供します。

  • DDV_Proc

    エントリの DDV 部分は省略可能です。 すべての DDX ルーチンに対応する DDV ルーチンがあるわけではありません。 多くの場合、転送の不可欠な部分として検証フェーズを含める方が便利です。 ClassWizard ではパラメーターのない DDV ルーチンがサポートされていないため、DDV ルーチンにパラメーターが必要ない場合がよくあります。

  • arg

    DDV_ プロシージャの単一識別子。 C++ 関数名は "DDV_" で始まる必要がありますが、 <DDX_Proc> 識別子には "DDX_" を含めないでください。

    arg の後に 1 つまたは 2 つの DDV 引数が続きます。

    • promptN

      編集項目の上に配置する文字列 (アクセラレータの場合は >)。

    • fmtN

      arg 型の書式指定文字。次のいずれかです。

      キャラクター タイプ
      d 整数 (int)
      u int (符号なし)
      D long int (つまり、long)
      ユー long unsigned (つまり、DWORD)
      f フロート
      F ダブル
      s ひも

こちらも参照ください

番号別テクニカル ノート
カテゴリ別テクニカル ノート