}
Реакция на изменение экспонируемого свойства FillColor должна теперь переехать в CPP-файл. Вот ее тело.
void COpenGL::OnFillColorChanged()
{
if (m_clrFillColor & 0x80000000)
m_clrFillColor = GetSysColor (m_clrFillColor & 0x1f);
SetBkColor();
}
Вы помните, что изображение OpenGL может быть создано в окне, которое прошло специальную процедуру подготовки. Цель — создать и сделать активным контекст передачи OpenGL (HGRC). Вы также помните, что подготовку контекста надо рассматрвать как некий обязательный ритуал, в котором порядок действий определен. Повторим его:
¨ Установка стиля окна;
¨ Обработка сообщения WM_ERASEBACKGROUND и отказ от стирания фона;
¨ Установка pixel-формата;
¨ Создание контекста устройства (HDC) и контекста передачи (HGLRC);
¨ Специфическая обработка сообщения WM_SIZE;
¨ Обработка сообщения WM_PAINT;
¨ Освобождение контекстов при закрытии окна.
Введите коды в уже существующую заготовку функции OnCreate. Здесь производится основная часть действий для подготовки окна OpenGL:
PIXELFORMATDESCRIPTOR pfd = // Описатель формата
{
sizeof(PIXELFORMATDESCRIPTOR),// Размер структуры
1, // Номер версии
PFD_DRAW_TO_WINDOW | // Поддержка GDI
PFD_SUPPORT_OPENGL | // Поддержка OpenGL
PFD_DOUBLEBUFFER, // Двойная буферизация
PFD_TYPE_RGBA, // Формат RGBA, не палитра
24, // Глубина цвета
0, 0, 0, 0, 0, 0, // Биты Color отсутствуют
0, // Нет буфера прозрачности
0, // Бит сдвига
0, 0, 0, 0, 0, // Нет буфера Accumulation
32, // 32-битный Z-буфер
0, // Нет буфера Stencil
0, // Нет буфера Auxiliary
PFD_MAIN_PLANE, // Основной слой рисования
0, // Зарезервировано
0, 0, 0 // Маски слоев отсутствуют
};
m_hdc = GetDC(); // Добываем дежурный контекст и просим выбрать ближайший формат
int iD = ChoosePixelFormat(m_hdc, &pfd);
if (!iD)
{
ATLTRACE("\nChoosePixelFormat error");
return -1;
}
if ( !SetPixelFormat (m_hdc, iD, &pfd) ) // Пытаемся установить этот формат
{
ATLTRACE("\nSetPixelFormat error");
return -1;
}
if ( !(m_hRC = wglCreateContext (m_hdc))) // Пытаемся создать контекст передачи OpenGL
{
ATLTRACE("\nwglCreateContext error");
return -1;
}
if ( !wglMakeCurrent (m_hdc, m_hRC)) // Пытаемся выбрать его в качестве текущего
{
ATLTRACE("\nwglMakeCurrent error");
return -1;
}
//===== Теперь можно посылать команды OpenGL
glEnable(GL_LIGHTING); // Будет освещение
glEnable(GL_LIGHT0); // Только 1 источник
glEnable(GL_DEPTH_TEST); // Учитывать глубину (ось Z)
glEnable(GL_COLOR_MATERIAL);// Учитывать цвет материала поверхности
SetBkColor(); // Устанавливаем цвет фона
DrawScene(); // Создаем изображение и запоминаем в списке
bHandled = TRUE;
return 0;
Реакция на WM_ERASEBKGND, как было отмечено, должна установить в TRUE выходной параметр bHandled, что трактуется системой как: <Сообщение обработано и может быть убрано из очереди>. Сделайте это. Реакция на WM_SIZE должна учитывать изменение размеров окна и корректировать прямоугольник просмотра и матрицу проецирования. Введите внутрь OnSize такой код:
UINT cx = LOWORD(lParam), cy = HIWORD(lParam);
glViewport(0, 0, cx, cy); // Установка прямоугольника просмотра
double dAspect = cx<=cy ? double(cy)/cx : double(cx)/cy; // Вычисление диспропорции окна
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective (m_AngleView, dAspect, 0.1, 100.); // Режим перспективной проекции
bHandled = TRUE;
return 0;
При закрытии окна внедренного объекта необходимо освободить память, занимаемую контекстом передачи и отказаться от услуг таймера, с помощью которого мы будем производить анимацию вращения изображения. Введите в класс обработчик сообщения WM_DESTROY и измените ее стартовый код как показано ниже.
KillTimer(1); // Останавливаем таймер анимации
wglMakeCurrent(0, 0); // Отсоединяем контекст от потока
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.