Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
WinAPI.docx
Скачиваний:
49
Добавлен:
16.12.2018
Размер:
3.43 Mб
Скачать

4.7.2 Случайные прямоугольники

В любой графической системе есть своя забавная программа, которая работает непрерывно, просто выводя причудливые серии изображений, имеющих случайные размеры и цвета. Такую программу можно сделать и в Windows. Но это не так просто, как кажется. Надеемся, что вы сможете реализовать это, но только не вставкой цикла while (TRUE) в обработку сообщения WM_PAINT. Конечно, такой вариант будет работать, но ваша программа перестанет реагировать на другие сообщения. Ее нельзя будет завершить или свернуть.

Единственно возможная альтернатива состоит в установке таймера Windows для посылки сообщений WM_TIMER в функцию вашего окна. При обработке каждого сообщения WM_TIMER вы получаете контекст устройства с помощью функции GetDC, рисуете случайный прямоугольник, и затем освобождаете контекст устройства функцией ReleaseDC. Правда это уменьшает привлекательность вашей программы, поскольку она рисует случайные прямоугольники не так быстро, как возможно. Она ждет очередного сообщения WM_TIMER, а это зависит от точности системных часов.

В Windows существует достаточно "мертвого времени" — времени, когда все очереди сообщений пусты, и Windows только и делает, что ожидает ввода с клавиатуры или мыши. Можем ли мы как-нибудь получить управление в течение "мертвого времени" и нарисовать прямоугольник, возвращая управление, как только в очереди сообщений программы появятся сообщения? Да, в этом и состоит одна из основных задач функции PeekMessage. Ниже приведен пример обращения к функции PeekMessage:

PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);

Первые четыре параметра функции (указатель на структуру MSG, описатель окна и два значения, указывающих диапазон сообщений) идентичны параметрам функции GetMessage. Установка второго, третьего и четвертого параметров в NULL или 0, означает, что мы хотим получать из функции PeekMessage все сообщения для всех окон программы. Последний параметр установлен в PM_REMOVE, чтобы сообщения удалялись из очереди. Чтобы сообщения не удалялись из очереди, вы можете установить его в PM_NOREMOVE. Поэтому функция PeekMessage имеет префикс "peek", а не "get". Это позволяет программе проверять следующее сообщение в очереди без его удаления.

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

Напротив, функция PeekMessage всегда сразу возвращает управление независимо от того, есть ли сообщения в очереди или нет. Если в очереди сообщений есть хоть одно сообщение, то возвращаемое функцией PeekMessage значение равно TRUE (не ноль). Если же в очереди нет сообщений, то это значение равно FALSE (0).

Это позволяет нам переписать обычный цикл сообщений:

while(GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

таким образом:

while(TRUE)

{

if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))

{

if(msg.message == WM_QUIT)

break;

TranslateMessage(&msg);

DispatchMessage(&msg);

}

else

{

[другие строки программы для выполнения работы]

}

}

return msg.wParam;

Обратите внимание, что сообщение WM_QUIT проверяется особо. Вы не должны это делать в обычном цикле сообщений, поскольку функция GetMessage возвращает FALSE (0) при извлечении сообщения WM_QUIT. А возвращаемое значение функции PeekMessage показывает, извлечено ли сообщение из очереди. Поэтому проверка сообщения WM_QUIT необходима.

Если значение, возвращенное функцией PeekMessage равно TRUE, то сообщение обрабатывается обычным образом. В противном случае программа может выполнить какую-либо работу (например, нарисовать очередной случайный прямоугольник) перед тем, как вернуть управление Windows.

(В документации по Windows сказано, что вы не можете использовать функцию PeekMessage для удаления из очереди сообщения WM_PAINT, хотя на самом деле особой проблемы в этом нет. Более того, функция GetMessage тоже не удаляет сообщение WM_PAINT из очереди сообщений. Есть только один путь удалить сообщение WM_PAINT из очереди. Это можно осуществить, сделав действительным недействительный регион рабочей области окна. Для этого используются функции ValidateRect, ValidateRgn или пара функций BeginPaint и EndPaint. Если вы стандартным образом обрабатываете сообщение WM_PAINT после его извлечения из очереди функцией PeekMessage, то у вас не будет никаких проблем. Вы не можете использовать приведенный ниже код для очистки очереди сообщений:

while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));

Эта инструкция извлекает и уничтожает все сообщения из очереди сообщений за исключением WM_PAINT. Если в очереди окажется сообщение WM_PAINT, вы получите бесконечный цикл.)

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

Программа применяет функции SetRect и FillRect, которые были описаны выше, с координатами прямоугольника и цветом сплошной кисти, вычисленными на основе случайных величин, полученных от функции rand языка C.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]