» » » Алекс Jenter - Программирование на Visual C++. Архив рассылки


Авторские права

Алекс Jenter - Программирование на Visual C++. Архив рассылки

Здесь можно скачать бесплатно "Алекс Jenter - Программирование на Visual C++. Архив рассылки" в формате fb2, epub, txt, doc, pdf. Жанр: Программирование. Так же Вы можете читать книгу онлайн без регистрации и SMS на сайте LibFox.Ru (ЛибФокс) или прочесть описание и ознакомиться с отзывами.
Рейтинг:
Название:
Программирование на Visual C++. Архив рассылки
Автор:
Издательство:
неизвестно
Год:
неизвестен
ISBN:
нет данных
Скачать:

99Пожалуйста дождитесь своей очереди, идёт подготовка вашей ссылки для скачивания...

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.

Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.

Как получить книгу?
Оплатили, но не знаете что делать дальше? Инструкция.

Описание книги "Программирование на Visual C++. Архив рассылки"

Описание и краткое содержание "Программирование на Visual C++. Архив рассылки" читать бесплатно онлайн.



РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.






Вот и всё. Никакой дополнительной инициализации механизм DDX в WTL не требует. Чтобы выполнить обмен данными, используйте функцию DoDataExchange. Вот её прототип:

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

Параметр bSaveAndValidate задаёт направление обмена (FALSE или DDX_LOAD соответствует записи значений из переменных в контролы, а TRUE или DDX_SAVE – из контролов в переменные). Второй параметр задаёт идентификатор контрола, с которым необходимо произвести обмен. Значение по умолчанию (-1) соответствует всем контролам, упомянутым в карте DDX. Функция DoDataExchange возвращает TRUE, если обмен данными был успешным, или FALSE в противном случае.

ПРИМЕЧАНИЕ

В MFC обмен данными осуществляет функция CWnd::UpdateData, похожая на DoDataExchange из wtl. Отличие в том, что функция UpdateData не позволяет задавать идентификатор контрола. Вместо этого она всегда воздействует на все контролы, прописанные в функции CWnd::DoDataExchange. Реализация в wtl несколько гибче, но было бы ещё лучше, если бы разработчики WTL предусмотрели разбиение карты DDX на подкарты (как это сделано для карт сообщений). Часто в реальной программе требуется выполнить обмен данными не с одним контролом и не со всеми контролами, а с некоторым их подмножеством.

Иногда в процессе обмена данными возникают ошибки. Их делят на две разновидности: ошибки обмена (data exchange errors) и ошибки валидации (data validation errors). Ошибки обмена возникают, когда контрол не содержит значения, соответствующего типу связанной с ним переменной (например, поле ввода, связанное с переменной типа int, содержит пробелы или другие нецифровые символы). Ошибки валидации фиксируются в случае несоответствия передаваемого значения и наложенных на него ограничений (максимальная длина строки, минимальное и максимальное значение числа). В случае возникновения ошибки обмена вызывается виртуальная функция OnDataExchangeError, а при возникновении ошибки валидации – виртуальная функция OnDataValidateError. Дальнейший процесс обмена данными прерывается, а DoDataExchange возвращает FALSE, сигнализируя о неуспехе операции.

Класс CWinDataExchange<> предоставляет свои реализации функций OnDataExchangeError и OnDataValidateError. Они обе совершенно одинаковы.

// Overrideables

void OnDataExchangeError(UINT nCtrlID, BOOL /*bSave*/) {

 // Override to display an error message

 ::MessageBeep((UINT)-1);

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

 ::SetFocus(pT->GetDlgItem(nCtrlID));

}


void OnDataValidateError(UINT nCtrlID, BOOL /*bSave*/, _XData& /*data*/) {

 // Override to display an error message

 ::MessageBeep((UINT)-1);

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

 ::SetFocus(pT->GetDlgItem(nCtrlID));

}

Как видим, эти функции издают звуковой сигнал и устанавливают фокус ввода на контрол, в котором содержится неверное значение. Вы можете изменить это поведение на любое другое. Обратите внимание на структуру _XData, которая передаётся в функцию OnDataValidateError. Она содержит информацию об ограничении, которое было нарушено. Вот как описана эта структура в файле atlddx.h.

// Helpers for validation error reporting

enum _XDataType {

 ddxDataNull = 0,

 ddxDataText = 1,

 ddxDataInt = 2,

 ddxDataFloat = 3,

 ddxDataDouble = 4

};


struct _XTextData {

 int nLength;

 int nMaxLength;

};


struct _XIntData {

 long nVal;

 long nMin;

 long nMax;

};


struct _XFloatData {

 double nVal;

 double nMin;

 double nMax;

};


struct _XData {

 _XDataType nDataType;

 union {

  _XTextData textData;

  _XIntData intData;

  _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. Но рассчитывается этот размер по меньшей мере странно:

#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; \

 }

Другими словами, за размер буфера принимается размер переменной var, которая связывается с контролом. Отсюда следует два вывода. Во-первых, переменная var может быть только статическим массивом, а динамическим – нет. Во-вторых, в программе, использующей набор символов Unicode, этот размер будет всегда определяться неправильно. Выход в том и в другом случае – отказаться от макроса DDX_TEXT и обратиться к функции DDX_Text напрямую, передав ей правильный размер. Замечу также, что при передаче строки из переменной в контрол размер буфера значения не имеет, так что если вы передаёте данные только в этом направлении, DDX_TEXT использовать можно.

С набором символов Unicode связана ещё одна интересная проблема. Посмотрим на следующую карту DDX:


На Facebook В Твиттере В Instagram В Одноклассниках Мы Вконтакте
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!

Похожие книги на "Программирование на Visual C++. Архив рассылки"

Книги похожие на "Программирование на Visual C++. Архив рассылки" читать онлайн или скачать бесплатно полные версии.


Понравилась книга? Оставьте Ваш комментарий, поделитесь впечатлениями или расскажите друзьям

Все книги автора Алекс Jenter

Алекс Jenter - все книги автора в одном месте на сайте онлайн библиотеки LibFox.

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Отзывы о "Алекс Jenter - Программирование на Visual C++. Архив рассылки"

Отзывы читателей о книге "Программирование на Visual C++. Архив рассылки", комментарии и мнения людей о произведении.

А что Вы думаете о книге? Оставьте Ваш отзыв.