Вы можете рисовать в синхронизированных интервалах, создавая таймер при помощи функции SetTimer. При помощи использования таймера, равномерно отправляя сообщения WM_TIMER оконной процедуре, приложение может выполнить простую анимацию в рабочей области наряду с тем, что другое приложение продолжает "выполняется".
В примере ниже, приложение заставляет звезду в рабочей области прыгать из стороны в сторону. Каждый раз, когда оконная процедура получает сообщение WM_TIMER, процедура стирает звезду в текущей позиции, вычисляет новую позицию и рисует звезду внутри новой позиции. Процедура запускает таймер при помощи вызова функции SetTimer, в ходе обработки сообщения WM_CREATE.
RECT rcCurrent = {0,0,20,20}; POINT aptStar[6] = {10,1, 1,19, 19,6, 1,6, 19,19, 10,1}; int X = 2, Y = -1, idTimer = -1; BOOL fVisible = FALSE; HDC hdc; LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; RECT rc; switch (message) { case WM_CREATE: // Вычисляем начальную точку. GetClientRect(hwnd, &rc); OffsetRect(&rcCurrent, rc.right / 2, rc.bottom / 2); // Инициализируем частный контекст устройства (DC). hdc = GetDC(hwnd); SetViewportOrgEx(hdc, rcCurrent.left, rcCurrent.top, NULL); SetROP2(hdc, R2_NOT); // Запускаем таймер. SetTimer(hwnd, idTimer = 1, 10, NULL); return 0L; case WM_DESTROY: KillTimer(hwnd, 1); PostQuitMessage(0); return 0L; case WM_SIZE: switch (wParam) { case SIZE_MINIMIZED: // Запускаем таймер, если окно свернуто. KillTimer(hwnd, 1); idTimer = -1; break; case SIZE_RESTORED: // Перемещаем звезду назад в рабочую область, // если необходимо. if (rcCurrent.right > (int) LOWORD(lParam)) { rcCurrent.left = (rcCurrent.right = (int) LOWORD(lParam)) - 20; } if (rcCurrent.bottom > (int) HIWORD(lParam)) { rcCurrent.top = (rcCurrent.bottom = (int) HIWORD(lParam)) - 20; } // Передаем управление следующему оператору case. case SIZE_MAXIMIZED: // Запускаем таймер, если он был остановлен. if (idTimer == -1) SetTimer(hwnd, idTimer = 1, 10, NULL); break; } return 0L; case WM_TIMER: // Скрываем звезду, если она видна. if (fVisible) Polyline(hdc, aptStar, 6); // Заставляем прыгнуть звезду к стороне, если необходимо. GetClientRect(hwnd, &rc); if (rcCurrent.left + X < rc.left || rcCurrent.right + X > rc.right) X = -X; if (rcCurrent.top + Y < rc.top || rcCurrent.bottom + Y > rc.bottom) Y = -Y; // Показываем звезду в её новой позиции. OffsetRect(&rcCurrent, X, Y); SetViewportOrgEx(hdc, rcCurrent.left, rcCurrent.top, NULL); fVisible = Polyline(hdc, aptStar, 6); return 0L; case WM_ERASEBKGND: // Стираем звезду. fVisible = FALSE; return DefWindowProc(hwnd, message, wParam, lParam); case WM_PAINT: // Показываем звезду, если её не видно. Используем BeginPaint, // чтобы очистить регион обновления. BeginPaint(hwnd, &ps); if (!fVisible) fVisible = Polyline(hdc, aptStar, 6); EndPaint(hwnd, &ps); return 0L; } return DefWindowProc(hwnd, message, wParam, lParam); }
|
Это приложение использует частный контекст устройства, чтобы минимизировать время, требуемое для подготовки контекста устройства к рисованию. Оконная процедура извлекает и инициализирует частный контекст устройства, обрабатывая сообщение WM_CREATE, устанавливая рабочий режим бинарного растра, давая возможность тому, чтобы звезда стиралась и рисовалась используя один и тот же вызов функции Polyline. Оконная процедура также устанавливает точку, являющуюся началом координат давать возможность звезде рисоваться, используя тот же самый набор точек независимо от позиции звезды в рабочей области.
Приложение использует сообщение WM_PAINT, чтобы рисовать звезду всякий раз, когда окно должно обновиться. Оконная процедура рисует звезду только тогда, если, она не видима; то есть, только тогда, если она была стерта в соответствии с сообщением WM_ERASEBKGND. Оконная процедура перехватывает сообщение WM_ERASEBKGND, чтобы установить переменную fVisible, но передает сообщение в функцию DefWindowProc для того, чтобы система смогла рисовать фон окна.
Приложение использует сообщение WM_SIZE, чтобы остановить таймер, когда окно свернуто и повторно запустить таймер, когда свернутое окно восстановлено. Оконная процедура также использует это сообщение, чтобы обновить текущую позицию звезды, если размер окна был уменьшен вследствие чего звезда больше не находится в рабочей области. Приложение отслеживает текущую позицию звезды при помощи использования структуры, указанной переменной rcCurrent, которой, определяется ограничивающий прямоугольник для звезды. Сохранение всех углов прямоугольника в рабочей области удерживает звезду в области. Оконная процедура первоначально выравнивает по центру звезду в рабочей области, обрабатывая сообщение WM_CREATE.