MFC DoModal Dialog - PullRequest
       1

MFC DoModal Dialog

5 голосов
/ 30 июня 2011

Хорошо, поэтому я признаю, что не знаю Windows API или даже MFC.

У меня появляется окно с сообщением об ошибке, когда все становится волосатым (недопустимый символ в строке имени файла), и я хочу, чтобы окно с ошибкой было модальным.

Что касается меня, я не могу понять, почему он падает, когда попадает в doModal.

Вот код, где я думаю, что это можно исправить. Этот код находится в обработчике события кнопки в главном окне.

CDialog *BadFileD = new CDialog();
BadFileD->Create(IDD_STATUS, this); 
BadFileD->DoModal();

Я просто задерживаюсь на границе?

Ответы [ 3 ]

19 голосов
/ 30 июня 2011

Диалог MFC разделяет два шаблона, модальный диалог и немодальный диалог.

(1) Модальное диалоговое использование:

CDialog dlg;
dlg.DoModal();

(2) Использование немодального диалога:

CMyDialog *pDlg = new CMyDialog();
pDlg->Create(ID_DLG, this);
pDlg->ShowWindows(SW_SHOW);

Как видите, нам нужен новый указатель, но не удалять его. Таким образом, вы должны сделать следующее в нашем CMyDialg классе:

  1. Добавьте DestroyWindow() в OnOk() и OnCancel().
  2. Добавить "delete this;" в методе PostNcDestroy().

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

8 голосов
/ 30 июня 2011

Для отображения модального диалога вы должны использовать только метод DoModal

CDialog *BadFileD = new CDialog(IDD_STATUS, this);
BadFileD->DoModal();

Вы можете прочитать замечания из article

1 голос
/ 17 сентября 2018

Если вы хотите просто отобразить сообщение об ошибке, возможно, вместо создания собственного диалога вы можете просто использовать AfxMessageBox().См. Сеть разработчиков Microsoft - AfxMessageBox .

Если вы хотите создать свое собственное диалоговое окно, обычно с проектом MFC, вы обычно:

  • создаете диалоговое окношаблон с использованием редактора ресурсов
  • создать класс, инкапсулирующий диалоговое окно с помощью мастера классов, реализующего желаемое поведение
  • вставить код для создания и отобразить диалоговое окно в соответствующем месте

Однако с помощью простого диалогового окна, не требующего поддержки класса для сложного поведения, вы можете пропустить шаг создания инкапсулирующего класса с помощью мастера классов и просто использовать CDialog напрямую.

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

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

void CViewThing::OnCommandMenuItem ()
{
    CDialog BadFileD(IDD_STATUS);
    int iRetStatus = BadFileD.DoModal();
    // check for status such as IDOK, etc.
    // do whatever is necessary.
}

То, что сделано выше, - это создание диалогового окна с использованием шаблона ресурса диалога IDD_STATUS и его отображение.как модальное диалоговое окно.Поскольку это локальный объект, когда переменная BadFileD выходит из области видимости, будет запущен деструктор диалогового окна и очищены ресурсы для вас.

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

Так что для немодального диалогового окнаПри использовании с некоторым классом представления, возможно, с набором инструментов какого-либо рода, переменная CDialog будет членом класса CView, который ее использует.После создания немодального диалогового окна оно отображается или нет с помощью функции-члена ShowWindow() класса CDialog (фактически члена класса CWnd, из которого происходит CDialog).

void CViewThing::OnCommandMenuItem ()
{
    BadFileD.Create(IDD_STATUS, this);
    BadFileD.ShowWindow(SW_SHOW);   // display the dialog
}

и в классе CViewThing у вас будет переменная-член CDialog BadFileD;.

Дополнительные соображения

Во всех приведенных выше примерах мыне использовать указатели, так что, когда переменная CDialog выходит из области видимости, либо из-за выхода из функции-члена, либо когда объект, использующий диалоговое окно, уничтожается, то и диалоговое окно тоже.Это управление объектами сделано для нас.

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

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

Однако время жизни немодального диалогового окна требуетчтобы метод DestroyWindow() использовался для уничтожения диалогового окна, когда оно больше не требуется.См. Microsoft Developer Network - уничтожение диалогового окна .

Третий сценарий использования - встраивание диалогового окна

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

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

Однако, если вы измените стиль WS_POPUP на WS_CHILD, вы можете встроить диалоговое окно в другое окно в качестве элемента управления. Вы можете удалить другие настройки стиля, такие как WS_SYSMENU, DS_MODALFRAME и WS_CAPTION и удалить строку CAPTION из шаблона диалога, чтобы дополнительно изменить диалоговое окно. Таким образом, вы получите что-то вроде:

IDD_STATUS DIALOGEX 0, 0, 435, 266
STYLE DS_SETFONT | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    LTEXT           "this is some static text to display on this dialog.",IDC_STATIC,81,63,200,32
END

Затем просто используйте получившееся диалоговое окно, аналогичное тому, как вы бы сделали немодальное диалоговое окно с ShowWindow().

Если вам нужно переместить встроенное диалоговое окно в окно контейнера, вы можете использовать метод SetWindowPos() для этого. Например, следующий код переместит окно диалогового окна в содержащем его окне на 20 пикселей слева и на 10 пикселей вверху содержащего окна.

BadFileD.SetWindowPos(NULL, 20, 10, 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...