Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
Для активизации DDX требуется перегрузить виртуальную функцию CDialog::DoDataExchange. В нее надо внести специальные функции DDX, предназначенные для обмена данными между ЭУ и переменными-членами различных типов данных. Например, в нашем классе CMyDialog функция-член DoDataExchange может быть реализована так:
void CMyDialog::DoDataExchange( CDataExchange* pDX ) { DDX_Text( pDX, IDC_NAME, m_strName ); DDX_Text( pDX, IDC_PHONE, m_strPhone ); } |
MFC вызывает DoDataExchange один раз при создании диалогового окна (из обработчика сообщения WM_INITDIALOG) и еще раз при нажатии кнопки OK. Параметр pDX указывает на объект класса CDataExchange, который, например, задает функциям наподобие DDX_Text направление копирования данных – из ЭУ в переменные-члены или наоборот. Т. о., одного вызова DoDataExchange достаточно для передачи данных во все ЭУ, данные от которых требуется получать в данном окне. Список функций передачи данных DDX приведен в табл. 8.1.
Таблица 8.1. Функции диалогового информационного обмена (DDX)
Функция DDX | Описание связи ЭУ и переменных-членов |
DDX_Text | Элемент редактирование и переменная-член одного из следующих типов: BYTE, int, short, UINT, long, DWORD, CString, string, float, double, COleDateTime, COleCurrency |
DDX_Check | Кнопка с независимой фиксацией и переменная int |
DDX_Radio | Группа кнопок с независимой фиксацией и переменная int |
DDX_LBIndex | Список и переменная int |
DDX_LBString | Список и переменная CString |
DDX_LBStringExact | Список и переменная CString |
DDX_CBIndex | Комбинированный список и переменная int |
DDX_CBString | Комбинированный список и переменная CString |
DDX_CBStringExact | Комбинированный список и переменная CString |
DDX_Scroll | Полоса прокрутки и переменная int |
Кроме DDX, в MFC есть родственный механизм DDV – диалоговый информационный обмен с проверкой данных (Dialog Data Validation, DDV). Он позволяет перед закрытием диалогового окна проверить данные ЭУ на корректность. Функции DDV делятся на две группы: проверка численных значений на попадание в диапазон и проверка переменных типа CString для того, чтобы строки были заданной длины. Ниже приведен пример функции DoDataExchange, в которой DDX_Text применяется для связи строки ввода и целочисленной переменной, а DDV_MinMaxInt – для проверки попадания значения этой переменной в диапазон от 0 до 100 (проверка выполняется только при нажатии кнопки OK):
void CMyDialog::DoDataExchange( CDataExchange* pDX ) { DDX_Text( pDX, IDC_COUNT, m_nCount ); DDV_MinMaxInt( pDX, m_nCount, 0, 100 ); } |
Если значение m_nCount будет меньше 0 или больше 100, то DDV_MinMaxInt установит фокус ввода строку ввода и выведет сообщение об ошибке. Для данного ЭУ вызов функции DDV должен следовать непосредственно после вызова функции DDX, чтобы MFC смогла правильно установить фокус ввода при обнаружении ошибки.
Сами средства DDX/ DDV реализованы внутри CDialog. Когда диалоговое окно создается, CDialog::OnInitDialog вызывает функцию CWnd::UpdateData с параметром FALSE. В свою очередь, UpdateData создает объект CDataExchange и передает указатель на него функции диалогового окна DoDataExchange. Внутри DoDataExchange вызываются функции DDX для инициализации ЭУ значениями из переменных-членов. Позднее, когда пользователь нажимает OK, из CDialog::OnOK вызывается UpdateData с параметром TRUE, что приводит к копированию функциями DDX данных из ЭУ в переменные-члены. Если в DoDataExchange есть вызовы функций DDV, то именно на этом этапе они проверяют корректность введенных пользователем данных. Описанный порядок работы DDX/DDV объясняет, почему из перегруженных функций OnOK и OnInitDialog обязательно надо вызывать эти функции из базового класса – иначе не будет вызвана UpdateData и DDX/DDV не будет работать.
1.4.1 Поддержка механизма DDX/DDV в ClassWizard'е
Если при разработке приложения вы пользуетесь мастерами MFC, то вы можете не добавлять в DoDataExchange вызовы функций DDX/DDV вручную, а делать это с помощью ClassWizard. ClassWizard может даже автоматически добавлять в описание класса диалогового окна все необходимые для DDX/DDV переменные-члены. Ниже описан порядок добавления в класс диалогового окна переменной-члена и ее связи с ЭУ через механизм DDX/ DDV:
1) Вызовите ClassWizard (командой меню View) и перейдите на закладку Member Variables (рис. 8.4).
|
|
Рис. 8.4. Окно ClassWizard'а: закладка с переменными-членами класса диалогового окна. | Рис. 8.5. Диалоговое окно ClassWizard для добавления новой переменной-члена в диалоговый класс. |
2) В списке Class Name выберите имя класса диалогового окна.
3) В списке Control ID выделите идентификатор ЭУ, который вы хотите связать с переменной членом, и нажмите кнопку Add Variable.
4) В диалоговом окне Add Member Variable (рис. 8.5) введите имя новой переменной-члена и выберите ее тип в списке Variable Type. Затем нажмите кнопку OK.
Если вы посмотрите на исходный текст класса диалогового окна после закрытия окна ClassWizard, то увидите, что ClassWizard добавил в класс переменную-член, а в функцию DoDataExchange поместил вызов функции DDX для связи переменной-члена с ЭУ. Если переменная числовая (как на рис. 8.4), то в нижней части закладки Member Variables окна ClassWizard вы можете указать минимальное и максимальное значение диапазона, попадание в который будет контролироваться с помощью функции DDV_MinMax.
1.5 Взаимодействие с элементами управления диалогового окна
Несмотря на удобство средств DDX/DDV, полностью отказаться от обращения к ЭУ с помощью классов-оболочек ЭУ удается далеко не всегда. Например, может потребоваться вызывать функции CListBox для заполнения списка строками из OnInitDialog. Для этого необходим указатель на объект CListBox, представляющий список – ЭУ окна. Как его получить?
Указатель типа (CWnd*) для любого ЭУ окна можно получить функцией CWnd::GetDlgItem. Например, для включения запрещенной кнопки с независимой фиксацией IDC_CHECK, можно записать следующие вызовы:
CWnd* pWnd = GetDlgItem( IDC_CHECK ); pWnd->EnableWindow( TRUE ); |
Этот исходный текст правилен, т. к. GetDlgItem возвращает указатель на CWnd, а функция EnableWindow является членом класса CWnd. Теперь рассмотрим следующий фрагмент текста:
CListBox* pListBox = (CListBox*)GetDlgItem( IDC_LIST ); pListBox->AddString( "Первый элемент" ); pListBox->AddString( "Второй элемент" ); pListBox->AddString( "Третий элемент" ); |
Здесь для вызова функций-членов CListBox потребовалось выполнить преобразование типа для указателя, полученного от GetDlgItem. Явное преобразование типа указателей – плохой стиль программирования, и если ЭУ с идентификатором IDC_LIST в окне не окажется, может произойти серьезная ошибка доступа по нулевому указателю.
Лучшим решением является присоединение оконного дескриптора ЭУ к классу-оболочке ЭУ с помощью CWnd::Attach. Сначала надо создать объект класса ЭУ (например, CListBox), а затем динамически присоединить к нему ЭУ, например:
CListBox wndListBox; wndListBox. Attach( GetDlgItem( IDC_LIST )->m_hWnd ); wndListBox. AddString( "Первый элемент" ); wndListBox. AddString( "Второй элемент" ); wndListBox. AddString( "Третий элемент" ); wndListBox. Detach(); |
Т. к. объект CListBox был создан в стеке, очень важно вызывать Detach до того, как объект CListBox будет уничтожен. Иначе деструктор CListBox удалит ЭУ и список исчезнет из диалогового окна.
Чтобы не писать вызовы функций присоединения/отсоединения ЭУ от объекта-оболочки, можно сопоставить их с помощью функции DDX_Control. Например, чтобы связать переменную-член m_wndListBox класса CListBox со списком с идентификатором IDC_LIST, в DoDataExchange надо внести вызов:
DDX_Control( pDX, IDC_LIST, m_wndListBox ); |
Теперь добавлять строки в список можно, просто вызывая AddString у m_wndListBox:
m_wndListBox. AddString( "Первый элемент" ); m_wndListBox. AddString( "Второй элемент" ); m_wndListBox. AddString( "Третий элемент" ); |
Вызовы DDX_Control в функцию DoDataExchange удобно добавлять с помощью ClassWizard. Для этого надо перейти на закладку Member Variables и с помощью кнопки Add Variable добавить в класс переменную-член. Но в окне Add Member Variable (рис. 8.5) в списке Category надо вместо Value выбрать Control. Затем в списке Variable Type выберите класс ЭУ и нажмите кнопку OK. Если после выхода из ClassWizard вы посмотрите на исходный текст диалогового класса, то увидите, что ClassWizard добавил в класс переменную-член, а также вызов функции DDX_Control для связи этой переменной с элементом управления.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |




