2008-12-22 3 views
5

Я хочу показать немодальное диалоговое окно на экране и отобразить в нем некоторую информацию.Как я могу показать немодальный диалог и отобразить в нем информацию сразу?

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

function() 
{ 
showdialog(XXX). 
//heavy work. 
update the dialog.. 
//heavy work. 
update the dialog... 
} 

кажется диалоговое окно отображается, но он не рисует какую-либо информацию в нем. Он только рисует всю информацию, когда функция закончена.

Как изменить диалог моделирования, чтобы он сразу отобразил информацию?

ответ

5

Есть несколько вещей, которые вы можете сделать.

(1) Вы можете пост диалоговое сообщение внутри CDialog :: OnInitDialog способом, а затем обработать длинную функцию обработчика сообщений этого опубликованное сообщение. Таким образом, сначала будет отображаться диалог, а затем длинная функция будет запущена.

(2) Второй вариант - убедиться, что цикл сообщения получает некоторое время обработки. Так что, если ваши длинные функции своего рода петля просто добавить случайный вызов к ProcessMessages, чтобы убедиться, что очередь сообщений хранятся пустой:

void ProcessMessages() 
{ 
    MSG msg; 
    CWinApp* pApp = AfxGetApp(); 
    while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) 
    { 
     pApp->PumpMessage(); 
    } 
} 

Edit: Это, конечно, можно использовать нити такой ситуация, но это не всегда без риска и сложности.

Использование потоков с GUI средства, имеющие дело с несколькими очередями сообщений, которые затем означает использование API, как PostThreadMessage и вводит новый набор вопросов, быть осторожными.

Для примера одного такого вопроса относится к этой ссылке:

http://msdn.microsoft.com/en-us/library/ms644946(VS.85).aspx

где говорит:

Сообщение, отправленное PostThreadMessage является не связан с окном. В качестве общего правила сообщения, которые не являются , связанные с окном, не могут быть , отправленные функцией DispatchMessage . Поэтому, если поток получателя находится в модальном цикле (как используется MessageBox или DialogBox), сообщения будут потеряны. Для перехвата сообщений потоков в модальном цикле используйте привязку к конкретному потоку.

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

+2

IMO Функция ProcessMessage() - способ добавить отзывчивость к приложению MFC. – Hapkido

+2

Я бы тоже использовал параметр ProcessMessage;) – jussij

+0

Я категорически не согласен. 1) Метод пользовательского интерфейса не должен выполнять много «другой» работы, проблемы должны быть разделены. 2) Простая рабочая нить может использоваться в большинстве этих ситуаций, не нужно использовать несколько насосов. Почему вы пытаетесь отпугнуть OP от потоков? –

2

Как правило, тяжелые вычисления никогда не должны помещаться в поток графического интерфейса пользователя. Так как это диалоговое окно с моделью, диалог не будет содержать цикл сообщений.Решение ProcessMessage() будет работать, но IMO не подходит. Мое предложение: 1) Создайте новую тему в OnInitDialog() 2) Проведите отдельное сообщение с сообщением о потоке в диалоговом окне, когда произойдет что-то интересное. Одна из этих интересных вещей заключается в том, что работа выполнена.

Обратите внимание, что это будет означать, что вам необходимо выполнить надлежащую синхронизацию.

4

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

Это превосходит реализацию ProcessMessages по нескольким причинам:

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

  • Пользовательский интерфейс остается отзывчивым при выполнении фактических расчетов. ProcessMessages разрешает множественные обновления пользовательского интерфейса во время единой функции вычисления, но пользовательский интерфейс по-прежнему будет заблокирован во время фактических вычислений.

Dialog Код:

#define WM_NEW_COUNT (WM_USER + 0x101) 

BEGIN_MESSAGE_MAP() 
    ON_MESSAGE(WM_NEW_COUNT, OnNewCount) 
END_MESSAGE_MAP() 

BOOL CMyDialog::OnInitDialog() 
{ 
    CWinThread* pThread = AfxBeginThread(MyCountFunc, this->GetSafeHwnd()); 
    return TRUE; 
} 

LRESULT CMyDialog::OnNewCount(WPARAM wParam, LPARAM) 
{ 
    int newCount = (int)wParam; 

    // m_count is DDX member, e.g. for label 
    m_count = newCount; 

    UpdateData(FALSE); 

    return 0; 
} 

Рабочего поток:

UINT MyCountFunc(LPVOID lParam) 
{ 
    HWND hDialogWnd = (HWND)lParam; 

    for (int i=0; i < 100; ++i) 
    { 
     PostMessage(hDialogWnd, WM_NEW_COUNT, i, NULL); 
    } 
} 
1

Не пытайтесь сделать вашу тяжелую работу сразу. Имейте в диалоговом сообщении сообщение в диапазоне WM_APP в OnInitDialog. Обработчик WM_APP может выполнять часть тяжелой работы, затем делать еще одно сообщение PostMessage и возвращаться. Таким образом, вы позволяете насосу сообщений обрабатывать оконные сообщения между вашими кусками обработки.