Как сделать диалоговое окно с

Обновлено: 15.05.2024

Предположим есть окно в котором в виде таблице отображается некий список, для каждой записи есть некий набор действий, для примера пусть будут "Edit"/"Detail"/"Delete".

При выборе пользователем пункта "Delete" необходимо показать окно с неким предупреждающим текстом, и двумя возможными действиями: "Ok"/"Cancel".

Как бы я это сделал в winforms приложении:

В рамках mvvm, необходимо сделать View, ModelView, т.е. у нас должно быть что то типа Main , MainViewModel , Dialog , DialogViewModel ;

в Main - будут кнопки которые будут прибиндины к командам из ViewModel. т.е. например так могла бы выглядеть команда для "Delete":

Как вариант можно сделать публичное свойство в DialogViewModel с типом boolean и устанавливать его в диалоге, по нажатии на любую из кнопок (Ok/Canсel) менять его значение, в главной форме смотреть значение этого свойства. Вот только меня терзают сомнения в правильности такого подхода.

Как сделать Диалоговое окно в wpf с использованием mvvm?

P.S.: код писал здесь, могут быть ошибки

Постарайтесь писать более развернутые вопросы. Для получения ответа поясните, в чем именно вы видите проблему

Вопрос то в чем? Если у вас простой диалог уточнение - то это может быть на совести вьюшки\вьюмодели целиком. Пилить каждый раз на каждый чих вьюшки и вьюмодели к ним тоже не надо. С другой стороны, если таких диалогов в целом набирается хотя бы штук 5, то наверно стоит вынести куда то в отдельный класс возможность просто во вьюмодели сказать что нужен запрос подтверждения с таким то текстом\иконкой\кнопками. И тут уж ессна надо делать нормальную модель диалога и вьюшку диалога.

@Monk что бы так тупо написать Вы сначала реализовали свой класс Dialogs (Model), представление (View), логику (ViewModel), теперь это конечно легко и тупо. а я пока не реализовал это для себя и даже не знаю как сделать, наверно придется останавливаться на публичном свойстве в диалоге и проверять его из главного окна.

2 ответа 2

Здесь есть два варианта действий:

Более простой способ, но более неудобный в случае, если вы используете TDD: Вам нет необходимости создавать ViewModel и View отдельно для диалогового окна: достаточно перед удалением проверять ответ пользователя в диалоговом окне следующим образом:

Более трудоёмкий способ, но с соблюдением всех канонов MVVM: создаёте ViewModel для вашего диалогового окна. Во ViewModel создаёте событие, например:

Событие нужно декорировать специальным аттрибутом, который позволит транслировать его в другие ViewModel-классы, не нарушая при этом принцип high-cohesion loose-coupling. Для этого используются мессенджеры. Можете попробовать Appcelerate.EventBroker. В своих проектах я использую именно его.

Далее - создаёте команду, которая ссылается на метод, вызывающий вышеупомянутое событие. Привязываете команду к кнопке в вашем диалоговом окне.

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

View в этом случае создавайте, как пару Window.xaml + Window.cs, у которого есть метод ShowDialog(), что автоматически заблокирует вызывающее окно на время открытия диалогового.

PS: первый способ не совсем правильный, потому что будет сложно тестировать результат, выбранный пользователем в MessageBox.

Добавлено Если захотите использовать это окно в разных местах вашего приложения, создайте базовый абстрактный класс, а в унаследованных VM-классах перегрузите нужные вам свойства. Например, в некоторых случаях вам может понадобиться «дернуть» несколько событий, чтобы на подтверждение среагировало несколько ViewModel. Тут всё зависит от сложности проекта.

Расположение и размер диалогового окна C++, а также расположение и размер элементов управления в нем измеряются в единицах диалогового окна. значения для отдельных элементов управления и диалогового окна отображаются в правом нижнем углу строки состояния Visual Studio при их выборе.

Если в проекте еще нет RC-файла, см. раздел Создание нового файла описания ресурсов.

Инструкции

Редактор диалоговых окон позволяет:

Создание нового диалогового окна

В представление ресурсовщелкните правой кнопкой мыши RC -файл и выберите Добавить ресурс.

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

Если рядом с типом ресурса диалогового окна отображается знак «плюс» ( + ), это означает, что доступны шаблоны диалоговых окон. Щелкните знак «плюс», чтобы развернуть список шаблонов, выберите шаблон и нажмите кнопку создать.

В редакторе диалоговых оконоткроется диалоговое окно создать.

Также можно открыть существующие диалоговые окна в редакторе диалоговых окон для редактирования.

Создание диалогового окна, которое пользователь не может выйти

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

В области Свойства диалогового окна задайте для false свойства системного меню значение.

Этот параметр отключает системное меню диалогового окна и кнопку Закрыть .

В форме диалогового окна удалите кнопки Отмена и ОК .

Во время выполнения пользователь не может закрыть модальное диалоговое окно с такими характеристиками.

Чтобы включить тестирование этого типа диалогового окна, функция тестового диалогового окна обнаруживает, что нажата клавиша ESC . Клавиша ESC также называется виртуальным ключом VK_ESCAPE. Независимо от того, как будет работать диалоговое окно во время выполнения, можно завершить тестовый режим, нажав клавишу ESC.

Для создания диалогового окна, которое пользователи не могут выйти из приложения MFC, необходимо переопределить поведение OnOK по умолчанию и OnCancel , так как даже если удалить связанные кнопки, диалоговое окно по-прежнему может быть закрыто нажатием клавиши Ввод или ESC.

Указание расположения и размера диалогового окна

В окне Свойства можно задать свойства, чтобы указать, где будет отображаться диалоговое окно на экране.

Логическое свойство центра .

Если задать значение true, диалоговое окно всегда будет отображаться в центре экрана. Если для этого свойства задано значение false, можно задать свойства кспос и ИПОС .

Свойства кспос и ИПОС , которые используются для явного определения того, где появится диалоговое окно.

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

Свойство абсолютного соответствия, которое влияет на положение.

Если значение равно true, координаты задаются относительно экрана. Если значение равно false, координаты задаются относительно окна владельца диалогового окна.

Проверка диалогового окна

При разработке диалогового окна можно смоделировать и протестировать его поведение во время выполнения, не компилируя программу. В этом режиме можно выполнять следующие действия:

вводить текст, выбирать пункты в полях со списками, включать и отключать параметры, выбирать команды;

тестировать последовательность табуляции;

проверять группировку элементов управления, например переключателей и флажков;

тестировать сочетания клавиш, используемые для доступа к элементам управления в диалоговом окне.

Подключения к коду диалогового окна, созданному с помощью мастеров, не включаются в имитацию.

При тестировании диалогового окна его положение обычно определяется относительно главного окна программы. Если для свойства абсолютное отображение диалогового окна задано значение true, то в диалоговом окне отображается положение относительно левого верхнего угла экрана.

Когда Редактор диалоговых окон является активным окном, перейдите вдиалоговое окно Проверкаформата> меню.

Чтобы завершить моделирование, нажмите клавишу ESC или нажмите кнопку Закрыть в тестируемом диалоговом окне.

Диалоговые окна существуют модальные(modal dialog box создаются функцией DialogBox)и немодальные (modeless dialog box создаются функцией CreateDialog). Эти две функции загружают шаблон диалогового окна из исполняемого файла прикладной программы и создают выскакивающее окно, которое соответствует спецификации шаблона. Имеются и другие функции, которые создают диалоговое окно, используя шаблоны в памяти; они передают дополнительную информацию в процедуру диалогового окна, как создается диалоговое окно.

Чтобы создать или модальное, или немодальное диалоговое окно, прикладная программа должна снабдить блок диалога шаблоном, чтобы описать стиль и содержание диалогового окна; приложение должно также снабдить диалоговое окно процедурой, чтобы выполнять задачи. Шаблон диалогового окна (dialog box template) - бинарное описание диалогового окна и органов управления, которое оно содержит. Разработчик может создать этот шаблон как ресурс, который будет загружен из исполняемого файла прикладной программы, или создать в памяти, пока прикладная программа выполняется. Процедура диалогового окна (dialog box procedure) - определяемая программой функция повторного вызова, которую система вызывает, когда операционная система получает ввод данных для диалогового окна или задачу для выполнения в блоке диалога. Хотя процедура диалогового окна подобна оконной процедуре, у нее нет тех же самых обязанностей.

Шаблон диалогового окна - это двоичные данные, который описывают диалоговое окно, определяя его высоту, ширину, стиль и органы управления, который он содержит. Чтобы создать диалоговое окно, система или загружает его шаблон из ресурсов в исполняемом файле приложения, или использует шаблон, переданный приложением для неё в глобальной памяти. В любом случае, приложение при создании диалогового окна должно предоставлять шаблон. Разработчик создает ресурсы шаблона, используя компилятор ресурса или редактор диалогового окна. Компилятор ресурса преобразует описание текста в двоичный ресурс, а редактор диалогового окна сохраняет в интерактивном режиме созданное диалоговое окно как двоичный ресурс.

Органы управления диалогового окна

Шаблон устанавливает позицию, ширину, высоту, стиль, идентификаторы и класс окна для каждого органа управления в диалоговом окне. Система создает каждый орган управления путем передачи их данных в функцию CreateWindowEx. Органы управления создаются по порядку, в котором они определены в шаблоне. Шаблон должен определять соответствующее число, тип и порядок органов управления, чтобы гарантировать, что пользователь сможет сделать ввод необходимых данных, чтобы завершить задачу, связанную с диалоговым окном.

Для каждого органа управления шаблон устанавливает значения стиля, которые определяют внешний вид и работу органа управления. Каждый орган управления - это дочернее окно и, поэтому, должно иметь стиль WS_CHILD. Чтобы гарантировать, что орган управления видимый, когда на экране показывается диалоговое окно, каждый орган управления должен иметь также и стиль WS_VISIBLE. Другие, обычно используемые стили окна - это WS_BORDER для органов управления, которые не обязательно имеют рамки, WS_DISABLED для органов управления, которые должны быть блокированы, когда создается первоначальное диалоговое окно и WS_TABSTOP и WS_GROUP для органов управления, к которым можно обращаться, используя клавиатуру. Стили WS_TABSTOP и WS_GROUP используются совместно с клавиатурным интерфейсом диалога, рассмотренным позже в этой главе.

Система преобразует значения координат позиции, размеры ширины и высоты из базовых единиц измерения диалогового окна в пиксели, перед передачей их в функцию CreateWindowEx. Когда система создает орган управления, она определяет диалоговое окно как родительское окно. Это означает, что система всегда воспринимает координаты позиции органа управления как рабочие координаты, относительно верхнего левого угла рабочей области диалогового окна.

Чтобы разрешить пользователю закрыть диалоговое окно, шаблон должен установить, по крайней мере, одну командную кнопку и присвоить ей идентификатор управления IDCANCEL. Чтобы разрешить пользователю выбирать между завершением и отменой задачи связанной с диалоговым окном, шаблон должен установить две командные кнопки. с надписями ОК и Отменить (Cancel), с управляющими идентификаторами IDOK и IDCANCEL, соответственно.

Шаблон устанавливает также и необязательный текст и данные для создания органа управления. Текст обычно предназначен для обозначения кнопок управления или установки начального содержания текста статического органа управления. Данные для создания - это один или несколько байтов данных, которые система передает оконной процедуре органа управления, когда элемент управления создается. Данные для создания полезны для органов управления, которые требуют дополнительной информации о их начальном содержании или стиле, чем это дается другими данными. Например, прикладная программа может использовать данные для создания, чтобы установить начальные параметры и диапазон управления полосой прокрутки.

Процедуры диалогового окна

Каждая процедура диалогового окна имеет нижеследующую форму:

Параметры процедуры служат одной и той же цели, что и в оконной процедуре, параметр hwndDlg получает дескриптор окна блока диалога.

Модальные диалоговые окна блокируют работу всех остальных окон до тех пока они не будут закрыты. При создании модального диалогового окна, система делает его активным окном. Диалоговое окно остается активным до тех пор, пока процедура диалогового окна не вызовет функцию EndDialog, или система не активизирует окно в другом приложении. Ни пользователь, ни приложение не могут сделать окно владельца активным, пока модальное диалоговое окно не разрушится.

Пример WinAPI приложения. Нет главного окна. Все приложение построено на диалоговых окнах.

Для создания своих диалоговых окон используется компонент AlertDialog в связке с классом фрагмента DialogFragment . Рассмотрим их применение.

Вначале добавим в проект новый класс фрагмента, который назовем CustomDialogFragment :

Класс фрагмента содержит всю стандартную функциональность фрагмента с его жизненным циклом, но при этом наследуется от класса DialogFragment , который добавляет ряд дополнительных функций. И для его создания мы можем использвоать два способа:

Переопределение метода onCreateDialog() , который возвращает объект Dialog .

Использование стандартного метода onCreateView() .

Для создания диалогового окна в методе onCreateDialog() применяется класс AlertDialog.Builder . С помощью своих методов он позволяет настроить отображение диалогового окна:

setTitle : устанавливает заголовок окна

setView : устанавливает разметку интерфейса окна

setIcon : устанавливает иконку окна

setPositiveButton : устанавливает кнопку подтверждения действия

setNeutralButton : устанавливает "нейтральную" кнопку, действие которой может отличаться от действий подтверждения или отмены

setNegativeButton : устанавливает кнопку отмены

create : создает окно

Для вызова этого диалогового окна в файле activity_main.xml определим кнопку:

В коде MainActivity определим обработчик нажатия кнопки, который будет запускать диалоговое окно:

Для вызова диалогового окна создается объект фрагмента CustomDialogFragment, затем у него вызывается метод show() . В этот метод передается менеджер фрагментов FragmentManager и строка - произвольный тег.

И поле нажатия на кнопку мы сможем ввести данные в диалоговое окно:

DialogFragment и AlertDialog в Android и Java

Теперь немного кастомизируем диалоговое окно:

Диалоговые окна в Android и Java

Здесь добавляетcя иконка, которая в качестве изображения использует встроенный ресурс android.R.drawable.ic_dialog_alert и устанавливаются две кнопки. Для каждой кнопки можно установить текст и обработчик нажатия. В данном случае для обработчика нажатия передается null, то есть обработчик не установлен.

Теперь добавим в папку res/layout новый файл dialog.xml :

И изменим создание диалогового окна:

Метод setView() устанавливает в качестве интерфейса окна ранее добавленный ресурс layout dialog.xml .

Создание диалоговых окон в Android

При этом, как можно увидеть на скриншоте, кнопки и заголовок с иконкой не входят в разметку.

Как правило, «пользовательские» диалоговые окна в MFC состоят из ресурса диалогового окна, создаваемого обычным образом, и связанного с ним класса C++, порождаемого от CDialog . Заметим, что ClassWizard способен колдовать только над теми диалоговыми окнами, ресурсы которых имеют численные идентификаторы (и вообще существенно ограничивает степень свободы программиста при их разработке, о чем еще будет сказано ниже).

Вначале мы рассмотрим «собственные» методы класса CDialog .

Конструирование (construction)

Связывает класс C++ с заданным ресурсом диалогового окна, имеющим строковое имя pszResName или численный идентификатор uResID . Параметр pParentWnd определяет будущее окно-владелец конструируемого диалогового окна («будущее» — так как вызов конструктора еще не создает самого окна); если значение этого параметр задается равным NULL, то владельцем диалогового окна станет главное окно приложения.

Обе эти формы конструктора применяются при создании модальных диалоговых окон и, как правило, вызываются из конструктора потомка CDialog с указанием конкретного имени или идентификатора ресурса. Например:

Существует также «защищенный» ( protected ) конструктор

предназначенный для создания немодальных диалоговых окон, который обязательно должен быть переопределен в классе-потомке.

Инициализация (initialization)

Используется только для немодальных диалоговых окон.

Данный метод создает немодальное диалоговое окно на основании ресурса со строковым именем pszResName или численным идентификатором uResID и отображает его на экране. Окно-владелец создаваемого диалогового окна определяется значением параметра pParentWnd ; если это значение задано равным NULL, то владельцем становится главное окно приложения. При успешном создании окна метод возвращает ненулевое значение.

Заметим, что если в соответствующем ресурсе не указан стиль Visible , то для отображения созданного окна на экране может потребоваться вызов методов ShowWindow и UpdateWindow .

Операции (operations)

Активизирует, передавая ему фокус ввода, следующий (относительно имеющего этот фокус в момент вызова) элемент управления в диалоговом окне, имеющий стиль WS_TABSTOP.

Активизирует, передавая ему фокус ввода, предыдущий (относительно имеющего этот фокус в момент вызова) элемент управления в диалоговом окне, имеющий стиль WS_TABSTOP.

Активизирует, передавая ему фокус ввода, элемент управления определяемый параметром pWnd .

Возвращает идентификатор кнопки по умолчанию. Если такая кнопка в диалогом окне отсутствует, метод возвращает значение 0. В противном случае, младшее слово результата содержит ее идентификатор, а старшее — значение DC_HASDEFID. Таким образом, получение этого идентификатора может выглядеть так:

Виртуальные методы (overridables)

Этот метод предназначен для реализации обмена данными с диалоговым окном, который включает в себя инициализацию элементов управления перед отображением окна на экране и сохранение введенных пользователем значений после его закрытия. В этом же методе может выполняться и проверка корректности пользовательского ввода при попытке закрытия диалогового окна «командой» с идентификатором IDOK. Объект класса CDataExchange , указатель на который передается через параметр pDX , содержит информацию о «направлении» обмена и несколько вспомогательных методов, используемых MFC в процессе его выполнения и проверки корректности ввода пользователя.

Заметим, что реализация метода DoDataExchange , наследуемая классом CDialog от своего непосредственного предка — класса CWnd , не выполняет абсолютно никаких действий; тем не менее, ее вызов из DoDataExchange классов-потомков CDialog присутствует во всех примерах, приводимых в MSDN. Отметим также, что данный метод не должен вызываться приложением явно; вместо этого, необходимо пользоваться методом

задавая параметр bSaveAndValidate равным FALSE для инициализации элементов управления и TRUE — для сохранения введенных пользователем значений и проверки их корректности. Более подробно механизмы обмена данными и проверки корректности пользовательского ввода рассматриваются ниже в соответствующих частях данной темы.

Вызывается в ответ на «команду» с идентификатором IDCANCEL или нажатие пользователем клавиши Esc . Реализация этого метода закрывает диалоговое окно с «результатом завершения», равным IDCANCEL.

«Прямое» обращение к элементам управления

Помимо перечисленных выше, класс CDialog наследует от своего непосредственного предка (класса CWnd ) несколько методов, предназначенных для «прямого» обращения к расположенными на диалоговом окне элементами управления.

Назначает состояние флажка или радиокнопки с идентификатором nID в соответствии с параметром fuCheck , который может принимать одно из следующих значений:

BST_UNCHECKED неотмеченное; BST_CHECKED отмеченное; BST_INDETERMINATE неопределенное (данный вариант применим только для флажков, имеющих стиль окна BS_3STATE или BS_AUTO3STATE).

Возвращает значение BST_UNCHECKED, BST_CHECKED или BST_INDETERMINATE, которое соответствует текущему состоянию флажка или радиокнопки с идентификатором nID — отмеченному, неотмеченному или неопределенному.

Метод позволяет установить в отмеченное состояние заданную радиокнопку в группе, автоматически автоматически переводя текущую отмеченную радиокнопку из этой группы в неотмеченное состояние. Параметры idcFirst и idcLast определяют идентификаторы соответственно первой и последней кнопок группы, а параметр idcCheck — идентификатор радиокнопки, состояние которой необходимо установить в отмеченное.

Возвращает идентификатор текущей отмеченной радиокнопки в группе, первая и последняя кнопка которой задаются идентификаторами idcFirst и idcLast соответственно.

Метод назначает элементу управления с идентификатором nID текст в соответствии со строкой pszSrc .

Первый вариант этого метода копирует текст элемента управления с идентификатором nID в строку pszDest ; через параметр cchMax необходимо передать максимально допустимую длину текста с учетом завершающего нуля. Второй вариант метода аналогичен, но текст копируется в объект класса CString , ссылка на который передается через параметр strDest . Оба варианта метода возвращают длину скопированной строки без учета завершающего нуля.

Метод преобразует целое число uValue в строковое представление и назначает получившийся текст элементу управления с идентификатором nID . Если значение параметра fSigned отлично от нуля, то число интерпретируется как имеющее знак, а в противном случае — как беззнаковое.

Метод преобразует текст элемента управления с идентификатором nID в число и возвращает получившееся значение; при этом в переменную по адресу pfSuccess (если этот адрес отличен от NULL) записывается ненулевое значение в случае успешно выполненного преобразования, либо 0 — в случае ошибки. Если значение параметра fSigned отлично от нуля, то текст интерпретируется как строковое представление числа со знаком, а в противном случае — как беззнакового. Заметим, что при ошибках преобразования данный метод возвращает нулевое значение, поэтому использование параметра pfSuccess является единственным надежным способом определить, был ли весь текст элемента управления успешно преобразован в число.

Механизм, предназначенный для осуществления этого обмена, носит официальное наименование dialog data exchange (сокращенно — DDX) и состоит из набора глобальных функций DDX_* , которые необходимо вызывать в реализации метода DoDataExchange . Строго говоря, DDX предлагает даже не один, а два способа обмена данными.

Первый способ заключается в связывании с элементами управления так называемых «переменных-значений». При вызове метода UpdateData для инициализации элементов управления (то есть, с параметром bSaveAndValidate равным FALSE) текущие значения этих переменных будут использоваться для назначения текста полей ввода, установки состояния флажков, выделения строк в списках, etc. При вызове же UpdateData для сохранения и проверки пользовательского ввода (то есть, с параметром bSaveAndValidate равным TRUE) в эти переменные будут скопированы текущие «значения» связанных с ними элементов управления — «текст полей ввода, состояние флажков…» Заметим, что в подавляющем большинстве случаев такие «переменные-значения» являются полями класса-потомка CDialog , инкапсулирующего соответствующее диалоговое окно.

Рассмотрим небольшой пример. Допустим, мы связали некую целочисленную переменную с флажком, имеющим идентификатор IDC_CHECK_CONFIRM. Если к моменту вызова метода OnInitDialog эта переменная имеет значение BST_CHECKED, то при первоначальном отображении диалогового окна на экране данный флажок будет находиться в отмеченном состоянии. После того, как пользователь снимет с флажка отметку и закроет диалоговое окно нажатием на кнопку OK , наша переменная будет иметь значение BST_UNCHECKED.

Все функции DDX, предназначенные для реализации данного способа, имеют следующий обобщенный прототип:

и отличаются, как нетрудно видеть, только содержательной частью имени и типом переменной, ссылка на которую передается через параметр refValue и которая будет связана с элементом управления, имеющим идентификатор nID . Через параметр pDX необходимо передать именно тот указатель на объект класса CDataExchange , который был получен методом DoDataExchange .

Ниже приведена таблица, в которой перечислены полные имена функций DDX и типы переменных, используемые каждой из них для обмена данными; последняя колонка содержит описание этих данных и вид элемента управления, с которым используется та или иная функция.

Имя функции Тип
переменной
Описание данных
DDX_CBIndex int Индекс строки, выделенной в выпадающем списке.
DDX_CBString CString Текст строки, выделенной в выпадающем списке. При инициализации элемента управления выделяется первая строка, начинающаяся с символов, содержащихся в связанной переменной.
DDX_CBStringExact CString Текст строки, выделенной в выпадающем списке. При инициализации элемента управления выделяется строка, в точности соответствующая содержанию связанной переменной; если такой строки в списке нет — не выделяется ничего.
DDX_Check int Состояние флажка (BST_UNCHECKED, BST_CHECKED или BST_INDETERMINATE).
DDX_DateTimeCtrl CTime
COleDateTime
Дата/время, которые выбраны в элементе управления Date and Time Picker, преобразованные к одному из перечисленных типов.
DDX_LBIndex int Индекс строки, выделенной в списке.
DDX_LBString CString Текст строки, выделенной в списке. При инициализации элемента управления выделяется первая строка, начинающаяся с символов, содержащихся в связанной переменной.
DDX_LBStringExact CString Текст строки, выделенной в списке. При инициализации элемента управления выделяется строка, в точности соответствующая содержанию связанной переменной; если такой строки в списке нет — не выделяется ничего.
DDX_MonthCalCtrl CTime
COleDateTime
Дата, которая выбрана в элементе управления Month Calendar, преобразованная к одному из перечисленных типов.
DDX_Radio int Индекс отмеченной радиокнопки в группе. Для корректной работы данной функции первая (и только первая) радиокнопка группы и следующий за этой группой элемент управления должны иметь стиль WS_GROUP (флажок Group на вкладке General диалогового окна Properties в редакторе ресурсов); при этом переменная должна быть связана с первой радиокнопкой группы.
DDX_Scroll int Текущая позиция ползунка в элементе управления Scroll Bar.
DDX_Slider int Текущая позиция ползунка в элементе управления Trackbar.
DDX_Text BYTE
short
int
UINT
long
DWORD
CString
float
double
COleCurrency
COleDateTime
Текст поля ввода, преобразованный к одному из перечисленных типов.

Второй способ обмена данными, предоставляемый DDX, заключается в использовании одной единственной универсальной функции

связывающей элемент управления, имеющий идентификатор nID , с переменной, которая является объектом класса-потомка CWnd . В библиотеке MFC реализованы классы CComboBox , CButton , CDateTimeCtrl , etc, инкапсулирующие все основные элементы управления; установив соответствующую связь, приложение может манипулировать ими, используя методы этих классов. Например:

Заметим, что оба рассмотренных выше способа не являются взаимоисключающими — с одним и тем же элементом управления могут быть связаны как «переменная-значение», так и объектная переменная. Это позволяет, в частности, избежать вызовов метода UpdateData в случае, когда требуется узнать или изменить состояние только одного элемента управления. При использовании подобного приема рекомендуется выполнить все вызовы DDX_Control (поскольку они подменяют оконные функции соответствующих элементов управления) до обращения к остальным функциям DDX

Для осуществления такой проверки предназначен механизм, называемый в официальной документации dialog data validation (сокращенно — DDV). Подобно DDX он состоит из набора глобальных функций DDV_* , которые необходимо вызывать в реализации метода DoDataExchange . Однако, в отличие от DDX, функции DDV взаимодействуют не с элементами управления, а с теми «переменными-значениями», которые с этими элементами связаны. По этой причине (и в силу других особенностей реализации механизмов обмена данными и их проверки) вызов функции DDV должен следовать непосредственно за соответствующим вызовом функции DDX.

Таким образом, в корректной реализация метода DoDataExchange должна выполняться следующая последовательность действий:

  1. Вызов метода DoDataExchange , унаследованного от непосредственного предка.
  2. Последовательный вызов функций DDX_Control для связывания требуемых элементов управления с соответствующими объектными переменными.
  3. Последовательный вызов пар функций DDX/DDV, первая из которых связывает требуемый элемент управления с соответствующей «переменной-значением», а вторая — проверяет значение этой переменной на допустимость. Естественно, что если такая проверка не требуется, вызов функции DDV может быть опущен.

Ниже подробно рассматриваются функции DDV; сразу оговорим, что первым параметром в любую из них необходимо передавать именно тот указатель на объект класса CDataExchange , который был получен методом DoDataExchange .

Предназначена для проверки значения bValue на принадлежность заданному диапазону, нижняя граница которого определяется параметром bMin , а верхняя — параметром bMax . В подавляющем большинстве случаев, эта функция используется в паре с DDX_Text для тех полей ввода, в которых задаются не строковые, а числовые значения.

Существует еще несколько аналогичных функций, предназначенных для проверки численных значений различных типов на принадлежность заданному диапазону; их имена вместе с именами типов проверяемых величин приведены в таблице ниже:

Имя функции Тип величины
DDV_MinMaxDWord DWORD
DDV_MinMaxInt int
DDV_MinMaxLong long
DDV_MinMaxUnsigned unsigned
DDV_MinMaxFloat float
DDV_MinMaxDouble double

Как и DDV_MinMaxByte , каждая из этих функций используется в паре с DDX_Text для проверки корректности содержимого полей ввода.

Предназначена для проверки даты/времени timeValue на принадлежность заданному диапазону, нижняя граница которого определяется объектом класса CTime , адресуемым параметром pMinTime , а верхняя — параметром pMaxTime . Эта функция используется в паре с DDX_DateTimeCtrl применительно к элементам управления Date and Time Picker.

Данный вариант функции полностью аналогичен предыдущему, за исключением того, что оперирует величинами типа COleDateTime .

Как и DDV_MinMaxDateTime , эта функция проверяет указанную дату на принадлежность заданному диапазону; отличие состоит в том, что она используется в паре с DDX_MonthCalCtrl применительно к элементам управления Month Calendar.

Данный вариант функции полностью аналогичен предыдущему, за исключением того, что оперирует величинами типа COleDateTime .

Предназначена для проверки того, находится ли текущая позиция ползунка, значение которой передается через параметр dwValue , в диапазоне от dwMin до dwMax . Эта функция используется в паре с DDX_Slider применительно к элементам управления Trackbar.

Еще раз подчеркнем, что проверка корректности пользовательского ввода производится после переноса данных из элемента управления в связанную с ним переменную; причем, если этот процесс будет прерван где-то на середине, часть связанных переменных получит новые значения, а часть будет по-прежнему сохранять старые. Именно по этой причине и рекомендуется связывать элементы управления только с полями класса-потомка CDialog , соответствующего тому диалоговому окну, которое содержит эти элементы — «внешняя сторона» будет находиться в корректном состоянии вне зависимости от того, допускает пользователь ошибки при вводе информации или нет:

Читайте также: