Учебное пособие: Сообщения и их обработка
while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);}
// дальнейшиепродолжительныеоперации
Такой цикл сначала обработает все сообщения, накопившиеся в очереди, а затем завершиться. При использовании таких циклов надо иметь в виду следующее:
Вы можете ограничить работу интерфейса только каким–либо одним окном, может быть панелью диалога (и всеми дочерними окнами данного окна). Тогда необходимо указать вторым параметром функции PeekMessage хендл этого окна, а в цикле предусмотреть необходимую трансляцию для работы этого окна (панели диалога).
Вы можете разрешить нормальную работу всего приложения. Тогда вы должны предусмотреть в этом цикле такую–же трансляцию, как и в цикле обработки сообщений в функции WinMain (это удобно сделать, выделив всю необходимую трансляцию в отдельную процедуру) и, дополнительно, предусмотреть возможность получения WM_QUIT в таком цикле. При извлечении WM_QUIT надо либо принять меры к немедленному завершению работы приложения, либо завершить продолжительные операции и послать WM_QUIT снова. Например, так:
MSG msg;
BOOL fStop = FALSE;
// продолжительные операции (вычисления, печать ...)
while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
fStop = TRUE;
PostQuitMessage(msg.wParam); // такзавершитсяциклв WinMain
break; // а так — этот}
MyTranslation(&msg); // будем считать, что сюда мы убрали всю
// трансляцию и вызов DispatchMessage}
if (!fStop) {
// дальнейшие продолжительные операции}
Обработка состояний простоя
Третья задача — выполнение действий в состоянии простоя, очень близка к предыдущей. Часто все продолжительные операции выполняют именно в состоянии простоя. Отличие заключается в том, как именно организуется выполнение таких действий.
В предыдущем варианте фрагмент кода, выполняющий продолжительные операции, просто содержит дополнительные циклы обработки сообщений. То есть вы практически разрабатываете некоторую программу, выполняющую продолжительные вычисления, а затем не изменяя алгоритма, вставляете в него дополнительные циклы обработки сообщений. При этом небольшие сложности возникают только с обработкой сообщений.
Рассматриваемый здесь вариант — обработка состояний простоя позволяет выполнить те–же операции несколько другим способом. В цикле обработки сообщений можно легко определять моменты, когда все сообщения в очереди уже обработаны и, если это так, вызывать обработку специального сообщения (или процедуры) обслуживающего состояние простоя. Сложности будут связаны с тем, что сама по себе обработка состояния простоя не должна быть продолжительной — так как она временно останавливает цикл обработки сообщений. Если вы собираетесь организовать выполнение продолжительных операций таким способом, то вы должны разделить их на небольшие, быстро выполняемые фрагменты, которые будут последовательно вызываться при обработке состояний простоя.
Для реализации циклов с обработкой состояний простоя обычно применяют одну из двух функций: WaitMessage или GetMessage. Так как с WaitMessage мы еще не встречались, то сначала рассмотрим вариант с ней:
void WaitMessage(void);
Эта функция просто ожидает поступление в очередь нового сообщения. Причем, даже если в очереди уже есть сообщения, она все–равно будет ожидать нового, поэтому ее вызывают только когда очередь сообщений пуста.
for (;;) {
while (!PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) {
// ... выполнить операции во время простоя