共用方式為


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預設會在預設CDialog::OnOK處理程式中呼叫 (TRUE),預設UpdateDataCDialog::OnInitDialog會呼叫 (FALSE) 。

DDV_例程應緊接該 欄位的DDX_例程。

其運作方式

您不需要瞭解下列專案,即可使用對話數據。 不過,瞭解這在幕後的運作方式可協助您撰寫自己的交換或驗證程式。

成員 DoDataExchange 函式與成員函式非常類似 Serialize - 負責從外部表單取得或設定數據(在此案例中為控件在對話框中的控件)從 類別中的成員數據。 pDX 參數是執行資料交換的內容,與 參數CObject::Serialize類似 CArchivepDX (a CDataExchange 物件) 具有方向旗標,就像CArchive有方向旗標:

  • 如果 !m_bSaveAndValidate為 ,則會將數據狀態載入控件。

  • 如果 m_bSaveAndValidate為 ,則從控件設定數據狀態。

只有在設定時 m_bSaveAndValidate ,才會進行驗證。 的值 m_bSaveAndValidate 是由 BOOL 參數決定為 CWnd::UpdateData

還有其他三個有趣的 CDataExchange 成員:

  • m_pDlgWnd:包含控制件的視窗(通常是對話框)。 這是為了防止DDX_和DDV_全域函式的呼叫端將 『this』 傳遞給每個 DDX/DDV 例程。

  • PrepareCtrlPrepareEditCtrl:準備數據交換的對話控制件。 儲存控件在驗證失敗時設定焦點的句柄。 PrepareCtrl 用於非編輯控制項,並 PrepareEditCtrl 用於編輯控制項。

  • Fail:在顯示消息框之後呼叫,提醒使用者輸入錯誤。 此例程會將焦點還原至最後一個控件(或的最後一個呼叫PrepareCtrlPrepareEditCtrl),並擲回例外狀況。 您可以從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 無法編輯這類任意運算式,因此應該移至特殊格式批注之外(W{{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 自定義的子集,可讓您將自己的DDX_和DDV_例程整合到 ClassWizard 使用者介面中。 如果您打算在項目或許多專案中重複使用特定的 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]]

在哪裡? 是數位 1 - n ,表示正在定義的清單中哪個 DDX 類型。

每個欄位都會以 ';' 字元分隔。 欄位及其用途如下所述。

  • 鑰匙

    單一字元清單,指出允許哪個對話框控制此變數類型。

    字元 允許的控制件
    E 編輯…
    C 雙狀態複選框
    c [三狀態] 複選框
    R 群組中的第一個單選按鈕
    L 非排序列表框
    l 已排序的清單框
    下拉式方塊 (含編輯專案)
    非排序的下拉式清單
    n 已排序的下拉式清單
    1 如果應該將 DDX 插入新增至清單前端(預設值為新增至尾部),這通常用於傳輸 『Control』 屬性的 DDX 例程。
  • vb-keys

    此字段僅適用於 VBX 控件的 16 位產品(32 位產品不支援 VBX 控件)

  • prompt

    要放在 [屬性] 下拉式方塊中的字串 (沒有引號)

  • type

    要發出頭檔中之型別的單一標識碼。 在上述範例中,使用 DDX_Time,這會設定為 CTime。

  • vb-keys

    未用於此版本,且應一律為空白

  • initValue

    初始值 - 0 或空白。 如果是空白,則實作檔案的 《11){{AFX_DATA_INIT 區段中不會寫入任何初始化行。 空白項目應該用於 C++ 物件(例如 CStringCTime等等),其建構函式會保證正確的初始化。

  • DDX_Proc

    DDX_程式的單一標識碼。 C++ 函式名稱的開頭必須是 「DDX_」,但不包含DDX_Proc>標識碼中的 <「DDX_」。 在上述範例中 <,DDX_Proc> 標識符會是 Time。 當 ClassWizard 將函式呼叫寫入 {{AFX_DATA_MAP 區段中的實作檔案時,它會將此名稱附加至DDX_,因而到達DDX_Time。

  • comment

    要在此 DDX 的變數對話框中顯示的批注。 將您想要的任何文字放在這裡,並且通常會提供描述 DDX/DDV 配對所執行作業的專案。

  • DDV_Proc

    專案的 DDV 部分是選擇性的。 並非所有 DDX 例程都有對應的 DDV 例程。 通常,將驗證階段納入為傳輸不可或缺的一部分更為方便。 當您的 DDV 例程不需要任何參數時,通常是這種情況,因為 ClassWizard 不支援不含任何參數的 DDV 例程。

  • arg

    DDV_程式的單一標識碼。 C++ 函式名稱的開頭必須是 「DDV_」,但不包含DDX_Proc>標識碼中的 <「DDX_」。

    arg 後面接著 1 或 2 個 DDV 自變數:

    • promptN

      要放在編輯專案上方的字串(搭配和 用於快捷鍵)。

    • fmtN

      arg 類型的格式字元,其中一個:

      字元 類型
      d int
      u 不帶正負號的整數
      D long int (也就是 long)
      U long unsigned (也就是 DWORD)
      f float
      F double
      s string

另請參閱

依編號顯示的技術提示
依分類區分的技術提示