На этом шаге мы рассмотрим реализацию пользователем механизма DDX/DDV.
Вы можете определить собственные DDX/DDV-функции. В качестве параметров DDX-функции следует передавать указатель на объект CDataExchange, идентификатор элемента управления и переменную класса диалога. DDV-функции передают указатель на объект CDataExchange и переменную-член класса диалога. Другие параметры описывают условия проверки; так, например, функция DDVMinMaxInt() получает наибольшее и наименьшее допустимые значения целого числа. DDV-функцию располагают всегда непосредственно после вызова DDX-функции, с которой она связана.
Необходимость в собственных DDV-функциях иногда возникает в случае, когда требуется проверить введенные значения, сравнивая их не с константами, а с переменными, или когда проверки следует проводить лишь при некотором условии. Так, например, в приведенном ниже фрагменте кода применяются различные варианты контроля в зависимости от состояния флажка IDC_FEMALE, показывающего, с какой из двух переменных нужно сравнить введенное значение переменной m_age.
//{{AFX_DATA_MAP(CMyClass) DDX_Check(pDX, IDC_FEMALE, m_bFemale); DDX_Text(pDX, IDC_EDIT1, m_age); //}}AFX_DATA_MAP if (m_bFemale) DDV_MinMax(pDX, m_age, 0, m_maxFemaleAge); else DDV_MinMax(pDX, m_age, 0, m_maxMaleAge);
Из примера также видно, что все нестандартные DDX/DDV-функции должны располагаться вне блока //{{AFX_, в котором находится код, обслуживаемый ClassWizard.
Добавим собственные функции проверки значений, вводимых пользователем в поле UserID.
void PASCAL DDV_Required(CDataExchange * pDX, CString str);
Рис.1. Добавление описания глобальной функции
void PASCAL DDV_Required(CDataExchange * pDX, CString str) { if (pDX->m_bSaveAndValidate && str. IsEmpty()) { AfxMessageBox("Please enter the User ID."); pDX->Fail(); } }
Рис.2. Добавление текста функции
Заметьте, что для подтверждения выполнения проверки данных проверяется значение переменной-члена CDataExchange::m_bSaveAndValidate. Кроме того, обратите внимание, как посредством функции CDataExchange::Fail() можно обойти стандартную проверку и оставить фокус ввода в элементе управления, не прошедшем контроль.
DDX_Text(pDX, IDC_USERID, m_strUserID); DDV_MaxChars(pDX, m_strUserID, 15);
Рис.3. Выделение строк
DDV_Required(pDX, m_strUserID);
void CConnectDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CConnectDialog) DDX_Text(pDX, IDC_PASSWORD, m_strPassword); DDV_MaxChars(pDX, m_strPassword, 15); DDX_Text(pDX, IDC_ACCESS, m_nAccess); DDV_MinMaxInt(pDX, m_nAccess, 1, 5); DDX_Check(pDX, IDC_CHECKCONTROL, m_bConnect); //}}AFX_DATA_MAP DDX_Text(pDX, IDC_USERID, m_strUserID); DDV_MaxChars(pDX, m_strUserID, 15); DDV_Required(pDX, m_strUserID); }
Рис.4. Функция DoDataExchange()
Текст измененного приложения можно взять здесь (48,3 Кб).
На следующем шаге мы рассмотрим реализацию функции OnInitDialog().