Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Замечание
Следующая техническая заметка не была обновлена, так как она была впервые включена в онлайн-документацию. В результате некоторые процедуры и темы могут быть устаревшими или неверными. Для получения последних сведений рекомендуется искать интересующую тему в индексе веб-документации.
Это примечание описывает архитектуру обмена данными диалоговых окон (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
(FALSE) вызывается в UpdateData
по умолчанию.
Подпрограмма DDV_ должна сразу идти после подпрограммы DDX_ для этого поля.
Как это работает
Чтобы использовать данные диалога, вам не нужно понимать следующее. Однако понимание того, как это работает за кулисами, поможет вам написать собственную процедуру обмена или проверки.
Функция-член DoDataExchange
очень похожа на функцию-член Serialize
— она отвечает за получение или установку данных во внешнюю форму (в данном случае контроли в диалоговом окне) из/в членов данных класса. Параметр pDX — это контекст для обмена данными и аналогичен параметру CArchive
CObject::Serialize
.
PDX (CDataExchange
объект) имеет флаг направления, так же как CArchive
имеет флаг направления.
Если
!m_bSaveAndValidate
, загрузите состояние данных в элементы управления.Если
m_bSaveAndValidate
, задайте состояние данных из элементов управления.
Проверка происходит только в том случае, если m_bSaveAndValidate
задано значение. Значение m_bSaveAndValidate
определяется параметром типа BOOL CWnd::UpdateData
.
Есть три других интересных CDataExchange
члена:
m_pDlgWnd
: окно (обычно диалоговое окно), содержащее элементы управления. Это предотвращает необходимость передачи 'this' в каждую подпрограмму DDX/DDV при вызове глобальных функций DDX_ и DDV_.Элементы
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, позволяя интегрировать собственные DDX_ и DDV_ подпрограммы в пользовательский интерфейс ClassWizard. Это полезно, только если планируется повторно использовать определенные подпрограммы DDX и DDV в проекте или во многих проектах.
Для этого специальные записи создаются в DDX.CLW (предыдущие версии Visual C++ хранили эти сведения в APSTUDIO.INI) или в .CLW файле вашего проекта. Специальные записи можно ввести либо в разделе [Общие сведения] вашего проекта .CLW-файл, либо в разделе [ExtraDDX] файла DDX.CLW в директории \Program Files\Microsoft Visual Studio\Visual C++\bin. Возможно, потребуется создать файл DDX.CLW, если он еще не существует. Если вы планируете использовать пользовательские подпрограммы DDX_/DDV_ только в определенном проекте, добавьте записи в раздел [Общие сведения] файла .CLW вашего проекта. Если вы планируете использовать подпрограммы во многих проектах, добавьте записи в раздел [ExtraDDX] DDX.CLW.
Общий формат этих специальных записей:
ExtraDDXCount=n
где n — число строк ExtraDDX?, которые следует учитывать в форме
ExtraDDX?=keys; vb-keys; запрос; тип; initValue; DDX_Proc [; DDV_Proc; prompt1; arg1 [; prompt2; fmt2]]
где? — число 1 — n , указывающее, какой тип DDX в списке определяется.
Каждое поле разделено символом ";". Поля и их назначение описаны ниже.
Ключи
Список отдельных символов, указывающих, для каких элементов управления диалога разрешен этот тип переменной.
Персонаж Разрешенное управление Е редактировать С Флажок для выбора с двумя состояниями с Флажок трёхпозиционный Р первая радиокнопка в группе L поле несортированного списка l поле с сортировкой списка M поле со списком (с возможностью редактирования) Н несортированный раскрывающийся список н отсортированный выпадающий список 1 Если элемент DDX нужно добавить в начало списка (по умолчанию добавляется в конец). Обычно это используется для подпрограмм DDX, которые передают свойство 'Control'. vb-keys
Это поле используется только в 16-разрядном продукте для элементов управления VBX (элементы управления VBX не поддерживаются в 32-разрядном продукте).
подсказка
Строка для размещения в комбо-списке свойств (без кавычек)
тип
Один идентификатор для типа, который будет выдаваться в файле заголовка. В нашем примере выше с DDX_Time это значение будет иметь значение CTime.
vb-keys
Не используется в этой версии и всегда должен быть пустым
initValue
Начальное значение — 0 или пустое. Если она пуста, строка инициализации не будет записана в разделе //{{AFX_DATA_INIT файла реализации. Пустая запись должна использоваться для объектов C++ (например
CString
,CTime
и т. д.), которые имеют конструкторы, гарантирующие правильную инициализацию.DDX_Proc
Один идентификатор для процедуры DDX_. Имя функции C++ должно начинаться с "DDX_", но не включать "DDX_" в <идентификатор DDX_Proc> . В указанном выше <примере идентификатор DDX_Proc> будет называться Время. Когда ClassWizard записывает вызов функции в файл реализации в разделе {{AFX_DATA_MAP, он добавляет это имя к DDX_, в итоге получая DDX_Time.
комментарий
Комментарий для отображения в диалоговом окне для переменной, связанной с этим DDX. Поместите любой текст, который вы хотите здесь, и обычно укажите что-то, что описывает операцию, выполняемую парой DDX/DDV.
DDV_Proc
Часть DDV записи является необязательной. Не все подпрограммы DDX имеют соответствующие подпрограммы DDV. Часто более удобно включить этап проверки в качестве неотъемлемой части передачи. Это часто происходит, когда подпрограмма DDV не требует каких-либо параметров, так как ClassWizard не поддерживает подпрограммы DDV без каких-либо параметров.
arg
Единственный идентификатор для процедуры DDV_. Имя функции C++ должно начинаться с "DDV_", но не включать "DDX_" в <идентификатор DDX_Proc> .
arg предшествует 1 или 2 аргумента DDV:
запрос N
Строка для размещения над элементом редактирования (с использованием & для ускорителя).
fmtN
Формат символа для типа arg, одно из следующих элементов:
Персонаж Тип d инт u целое число без знака Д long int (т. е. длинный) У long unsigned (т. е. DWORD) f плавать Ф двойной s струна
См. также
Технические примечания по номеру
Технические заметки по категориям