Вход/Регистрация
Программирование на Visual C++. Архив рассылки
вернуться

Jenter Алекс

Шрифт:

_XFloatData floatData;

 };

};

Соответственно, в функции OnDataValidateError нужно проанализировать значение поля nDataType и выбрать в зависимости от него структуру textData, intData или floatData, которая и будет содержать информацию о нарушенном ограничении.

ПРИМЕЧАНИЕ

MFC не позволяет повлиять на отображение ошибки валидации. Если вы используете функции DDV_*, вы всегда будете получать сообщение об ошибке валидации в виде message box'а. Изменить это поведение нельзя, можно только отказаться от DDV_* и использовать для валидации функции "собственного изготовления".

Как это всё работает

Теперь посмотрим, как механизм DDX выглядит "изнутри". К счастью, в его реализации нет ничего сложного. От класса CWinDataExchange<> ваш класс наследует функции DDX_Text, DDX_Int, DDX_Float, DDX_Control, DDX_Check и DDX_Radio, которые и выполняют собственно обмен данными. Некоторые из них перегружены, а DDX_Int и вовсе оформлена как шаблон, что позволяет работать с самыми разными целыми типами.

После обработки препроцессором карта DDX превращается в функцию DoDataExchange. Макросы BEGIN_DDX_MAP и END_DDX_MAP создают пролог и эпилог этой функции. "Заготовка" карты:

BEGIN_DDX_MAP(CMyDialog)

 // Другие макросы карты DDX

END_DDX_MAP

превращается в:

BOOL DoDataExchange(BOOL bSaveAndValidate = FALSE, UINT nCtlID = (UINT)-1) {

 bSaveAndValidate;

 nCtlID;

 // Другие макросы карты DDX

 return TRUE;

}

Что касается остальных макросов DDX_*, то все они реализованы примерно одинаково. Сначала они сравнивают свой идентификатор контрола nID с идентификатором nCtlID, который был передан в функцию DoDataExchange. Если идентификаторы равны или nCtlID равен -1, макрос вызывает соответствующую функцию DDX_*. Далее проверяется возвращаемое значение, и если оно равно FALSE, обмен данными прекращается. Рассмотрим для примера макросы DDX_TEXT и DDX_TEXT_LEN. Обратите внимание, что они используют одну и ту же функцию DDX_Text, но передают ей разные параметры.

#define DDX_TEXT(nID, var) \

 if (nCtlID == (UINT)-1 || nCtlID == nID) \

 { \

if (!DDX_Text(nID, var, sizeof(var), bSaveAndValidate)) \

return FALSE; \

 }

#define DDX_TEXT_LEN(nID, var, len) \

 if (nCtlID == (UINT)-1 || nCtlID == nID) \

 { \

if (!DDX_Text(nID, var, sizeof(var), bSaveAndValidate, TRUE, len)) \

return FALSE; \

 }

Теперь мы знаем, как устроены карты DDX. Это может помочь нам писать их более эффективно. Например, мы можем написать в карте DDX следующее:

BEGIN_DDX_MAP(CMyDialog)

 ...

 for (int i=0; i<100; i++)

DDX_INT(IDC_BASE+i, m_numbers[i]);

 ...

 END_DDX_MAP

Это гораздо удобнее, чем вставлять в карту 100 записей.

Использование DDX_TEXT

Если с макросами DDX_INT, DDX_UINT и DDX_FLOAT проблем обычно не возникает, то макрос DDX_TEXT может стать источником неприятностей. Чтобы с ними разобраться, рассмотрим реализацию функции DDX_Text.

BOOL DDX_Text(UINT nID, LPTSTR lpstrText, int nSize, BOOL bSave, BOOL bValidate = FALSE, int nLength = 0) {

 T* pT = static_cast<T*>(this);

 BOOL bSuccess = TRUE;

 if (bSave) {

HWND hWndCtrl = pT->GetDlgItem(nID);

int nRetLen = ::GetWindowText(hWndCtrl, lpstrText, nSize);

if (nRetLen < ::GetWindowTextLength(hWndCtrl)) bSuccess = FALSE;

 }

 …

 return bSuccess;

}

Как видим, размер буфера задаётся параметром nSize. Но рассчитывается этот размер по меньшей мере странно:

  • Читать дальше
  • 1
  • ...
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: