Поскольку в поле hdc структуры PAINTSTRUCT уже есть переменная типа HDC, то при выводе изображения по сообщению WM_PAINT не принято запрашивать контекст функцией GetDC(hWnd). Контекст запрашивается функцией Begi nPai nt(), изображение рисуется с отсечением по дефектной области, и дефектная область удаляется из контекста. После обновления окна вызывается функция EndPaintC).
Элементы компьютерной графики
Теперь нужно заменить в проекте RotateWheel обработку сообщений от таймера фрагментом кода, который приведен в листинге 3.10.
Листинг 3.10
case WM_PAINT: BeginPaint(hWnd.&ps):
Rotatel_ine(ps.hdc. ps.fErase); //Второй параметр требует закрасить фон.
EndPaint(hWnd.&ps);
return 0;
Обработка завершается оператором return 0, а не break. Нужно сразу выходить из обработчика, так как вызов функции DefWi ndowProc () уже не нужен и нет смысла тратить на нее дополнительное время.
Первый раз сообщение WM_PAINT придет при создании окна. Область отсечения в этот момент будет совпадать с рабочей областью окна, поэтому при запуске приложения, рисующего колесо по сообщению WM_PAINT, мы сразу увидим изображение колеса в центре окна. Если при регистрации оконного класса не был задан цвет фона, то параметр ps.Erase, переданный из структуры ps, заставит функцию Ro-tateLine() самостоятельно закрасить фон.
При помощи этого примера можно легко наглядно показать различия между получением контекста функциями BeginPaintO и GetDCO. Достаточно несколько раз частично перекрыть изображение колеса другим окном. Для этого можно переключать фокус ввода между двумя перекрывающимися окнами (рис. 3.3). Слева показано исходное изображение колеса, справа - изображение после нескольких переключений фокуса между верхним и нижним окнами. По каждому сообщению WM_PAINT в функции RotateLineO выполняется модель движения, изменяющая координаты и угол поворота колеса. Но, как видим, новое положение колеса нарисовано только в дефектной области (эта область закрывалась показанным здесь же вторым окном).
Рис. 3.3. Обновление части окна