Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / C++Builder. ╨г╤З╨╡╨▒╨╜╤Л╨╣ ╨║╤Г╤А╤Б

.pdf
Скачиваний:
0
Добавлен:
12.11.2023
Размер:
9.63 Mб
Скачать

Pen =

C reatePen(PS _ SO L ID ,

1, RGB (2 5 5 ,0 ,0 ) ) ;

B ru s h

= C r e a te S o l i d B r u s h (RGB (0 ,0 ,2 5 5 ) ) ;

S e l e c t O b j e c t ( d c , P e n ) ;

 

S e l e c t O b j e c t ( d c , B r u s h ) ;

 

R e c t a n g l e ( d c , 10, 10, 110,

1 1 0 );

D e l e t e O b j e c t ( P e n ) ;

 

D e l e t e O b j e c t ( B r u s h ) ;

 

}

При работе с этими функциями не используются преимуще­ ства объектно-ориентированного программирования. В связи с этим работать с функциями значительно сложнее, но, с другой стороны, используя эти функции, можно рисовать в окне другой программы или даже на рабочем столе Windows. Для получения ссылки на рабочий стол необходимо в обработчике события O n C reate записать оператор:

dc = G etD C ( 0 ) ;

В примере этого раздела для вывода используются функции GDI потому, что если для вывода на родном окне C++Builder и предоставляет удобное средство - методы свойства формы C anvas, то для вывода на чужом окне мы этими методами вос­ пользоваться не можем.

11.1.2. Контекст устройства и контекст воспроизведения

В предыдущем примере вы узнали, что ссылка на контекст

устройства - это величина типа HDC. Для ее получения можно вы­

звать функцию GetDC, аргументом которой является ссылка на нужное окно.

Ссылке на контекст

устройства соответствует свойство

C a n v a s - > H a n d le формы,

принтера и некоторых компонентов

C++Builder.

 

Каков же все-таки смысл контекста устройства, если он и так связан с однозначно определенным объектом - окном, областью

памяти или принтером, и зачем передавать дополнительно какуюто информацию об однозначно определенном объекте?

Для ответа на эти вопросы обратим внимание на замечатель­ ное свойство вывода в Windows, состоящее в том, что одними и теми же функциями осуществляется вывод на различные устрой­ ства. Строки программы

F o r m l - > C a n v a s - > E llip s e (0,

0,

100,

1 0 0 );

и

 

 

 

P r i n t e r - > B e g i n D o c ( ) ;

 

 

 

P r i n t e r - > C a n v a s - > E l l i p s e (0,

0,

100,

1 0 0 );

P r i n t e r - > E n d D o c ( ) ;

 

 

 

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

Даже если мы рисуем только на поле формы, мы имеем дело с различными устройствами - нам неизвестно, какова графическая плата компьютера и каковы характеристики текущей установки настроек экрана. Например, имея в своем распоряжении более 16 млн цветов, приложение не заботится об отображении этой бо­ гатой палитры на экране, располагающем всего 256 цветами. Такие вопросы приложение перекладывает на плечи операционной сис­ темы, решающей их посредством использования драйверов уст­ ройств.

Для того чтобы воспользоваться функциями воспроизведения Windows, приложению необходимо только указать ссылку на кон­ текст устройства, содержащий средства и характеристики устрой­ ства вывода.

Справочный файл Win32 Programmer's Reference фирмы Microsoft, поставляемый в составе C++Builder, о контексте устрой­ ства сообщает следующее: «Контекст устройства является струк­ турой, которая определяет комплект графических объектов и свя­ занных с ними атрибутов и графические режимы, влияющие на

вывод. Графический объект включает в себя карандаш для изо­ бражения линии, кисть для закраски и заполнения, растр для копи­ рования или прокрутки частей экрана, палитру для определения комплекта доступных цветов, области для отсечения и других опе­ раций, маршрут для операций рисования».

В OpenGL имеется аналогичное ссылке на контекст устройст­ ва понятие ссылка на контекст воспроизведения.

Графическая система OpenGL, как и любое другое приложе­ ние Windows (хоть и размещенное в DLL), также нуждается в ссылке на устройство, на которое будет осуществляться вывод. Это специальная ссылка на контекст воспроизведения - величина типа HGLRC ( H a n d le openG L R e n d e r i n g C o n te x t, ссылка на контекст воспроизведения OpenGL).

Таким образом, контекст устройства Windows содержит ин­ формацию, относящуюся к графическим компонентам GDI, а кон­ текст воспроизведения содержит информацию, относящуюся к OpenGL, т.е. играет такую же роль, что и контекст устройства для GDI. В частности, упомянутые контексты являются хранилищами состояния системы, например, хранят информацию о текущем цвете карандаша.

11.1.3. Минимальная программа OpenGL

Рассмотрев основные вопросы функционирования приложе­ ния и его взаимодействия с операционной системой, мы можем перейти к изучению собственно OpenGL. Рассмотрим пример ми­ нимальной программы, необходимой для работы приложения, ис­ пользующего функции OpenGL. Эту программу мы в дальнейшем будем использовать в качестве шаблона для написания других программ.

Пример 11.2

Для подключения библиотеки OpenGL выполните следующие действия:

- Поместите в заголовочном файле модуля две команды пре­ процессора:

#i n c l u d e < g l \ g l . h >

#i n c l u d e < g l \ g l u . h >

- Объявите в заголовочном файле модуля в секции private

переменную hrc типа HGLRC, т.е.

HGLRC h r c ;

Напомним, что hrc - это ссылка на контекст воспроизведе­ ния библиотеки OpenGL. Смысл этой величины мы рассмотрели в предыдущем разделе.

- Определите в файле реализации модуля функцию

SetDCPixelFormat:

//==========================================

/ / Формат п и к с е л а

//========================================== void __fastcall S etD C PixelF orm at(H D C hdc)

{

i n t P ix e l F o r m a t; PIXELFORMATDESCRIPTOR p f d = {

eizeof(PIXELFORMATDESCRIPTOR) ,

1,

PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,

PFD_TYPE_RGBA, 24,

0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,

32,

0 ,

0 ,

PFD_MAIN_PLANE,

0 ,

0 , 0 };

P ix e lF o r m a t = C h o o s e P ix e lF o r m a t( h d c , & p fd ); S e t P i x e lF o r m a t ( h d c , P ix e lF o r m a t, & p fd );

}

Напомним, ссылка на контекст устройства содержит характе­ ристики устройства и средства отображения. Проще говоря, полу­ чив ссылку на контекст устройства, мы берем простой либо цвет­ ной карандаш или кисть с палитрой в миллионы оттенков.

Сервер OpenGL, прежде чем приступать к работе, также дол­ жен определиться, на каком оборудовании ему придется работать. Это может быть скромная персоналка, а может бьггь и мощная графическая станция.

Прежде чем получить контекст воспроизведения, сервер OpenGL должен получить детальные характеристики используе­ мого оборудования. Эти характеристики хранятся в специальной структуре PIXELFORMATDESCRIPTOR (описание формата пиксе­ ла). Смысл этой структуры - детальное описание графической сис­ темы, на которой происходит работа. Формат пиксела определяет, например, конфигурацию буфера цвета и вспомогательных буфе­ ров.

Ниже приводятся некоторые рекомендации по поводу запол­ нения структуры PIXELFORMATDESCRIPTOR.

Константа PFD_DOUBLEBUFFER включает режим двойной буферизации, когда вывод осуществляется не на экран, а в память, затем содержимое буфера выводится на экран. Это очень полез­ ный режим: если в любом примере на анимацию убрать режим двойной буферизации и все связанные с этим режимом команды, то при выводе кадра будет заметно мерцание. Во всех последую­ щих примерах мы будем использовать этот режим.

Константу PFD_GENERIC_ACCELERATED имеет смысл ус­ танавливать только в случае, если компьютер оснащен графиче­ ским акселератором.

Таким образом, в функции SetDCPixelFormat полям структуры присваиваются желаемые значения, затем вызовом функции ChoosePixelFormat осуществляется запрос системе, поддерживается ли на данном рабочем месте выбранный формат пиксела, и, наконец, вызовом функции SetPixelFormat уста­ навливается формат пиксела в контексте устройства. Функция

C h o o s e P i x e l F o r m a t

возвращает индекс формата пиксела, ко­

торый

нам

нужен

в

качестве

аргумента

функции

S e t P i x e l F o r m a t .

Заполнив поля структуры PIXELFORMATDESCRIPTOR, мы определяемся со своими пожеланиями к графической системе, на которой будет происходить работа приложения, OpenGL подбира­ ет наиболее подходящий к нашим пожеланиям формат и устанав­ ливает уже его в качестве формата пиксела для последующей ра­ боты. Наши пожелания корректируются сервером OpenGL приме­ нительно к реальным характеристикам системы.

- Создайте обработчик события O n C r e a t e формы:

v o id __f a s t c a l l T F o rm l: : F o rm C r e a te (T O b je c t * S en d er)

{

S e tD C P ix e lF o r m a t( C a n v a s - > H a n d le ) ;

h r c = w g lC r e a te C o n te x t( C a n v a s - > H a n d l e ) ;

}

Первая строка - обращение к описанной в этом же модуле пользовательской процедуре, задающей формат пиксела. Во вто­ рой строке обработчика O n C r e a t e задается величина типа

HGLRC, т.е. создается контекст воспроизведения. Аргументом функции w g l C r e a t e C o n t e x t является ссылка на контекст уст­ ройства, на который будет осуществляться вывод. В нашем случае устройством вывода будет служить окно формы. Для получения этого контекста OpenGL необходима величина типа HDC. Здесь,

как и во многих

других примерах, мы используем факт, что

C a n v a s - > H a n d l e

и есть ссылка на контекст устройства, связан­

ная с окном формы.

 

Несколько слов по поводу обозначений функций OpenGL. Функции и процедуры, имеющие отношение только к Windowsверсии OpenGL, обычно имеют приставку w g l, как например w g l C r e a t e C o n t e x t , но могут и не иметь такой приставки, Как например S w a p B u f f e r s . Собственно команды OpenGL имеют

приставки g l или g lu в зависимости от размещения в библиоте­ ках opengl32.dll и glu32.dll, соответственно.

Итак, контекст воспроизведения создан, и теперь можно осу­ ществлять вывод командами OpenGL.

- Создайте обработчик события O nP aint формы:

v o id __f a s t c a l l T F o rm l: : F o rm P a in t(T O b ject *Sender)

{

/ /

У становить

к о н тек ст

 

 

 

 

 

 

w g lM ak e C u rren t (C anvas-> H andle, h rc )

;

 

 

g l C l e a r C o l o r ( 0 . 5 ,

0 . 5 ,

0 .7 5 ,

1 . 0 ) ;

/ /

цвет

фона

/ /

О чистка

буфера

ц вета

 

 

 

 

 

g l C l e a r (GL_COLOR_BUFFER_BIT) ;

 

 

 

 

/ /

Содержимое

буфера

на

экран

 

 

 

S w a p B u ffe rs(C a n v a s - > H a n d le ) ;

 

 

 

 

w g lM ak e C u rren t (0,

0 ) ;

/ /

освободить

контекст

}

 

 

 

 

 

 

 

 

 

 

 

Первая строка делает контекст воспроизведения текущим, т.е.

занимает его

для

последующего

вывода.

Далее

функция

g lC le a r C o lo r

определяет цвет фона. Все 4 аргумента имеют

тип C lcam p f, соответствующий вещественным числам в пределах от нуля до единицы. Первые три параметра задают долю красного, зеленого и синего в результирующем цвете.

Следующую строку будем понимать как очистку экрана и ок­ рашивание его заданным цветом.

В режиме двойной буферизации (см. функцию SetD CPixelForm at) все рисование осуществляется в задний буфер кадра, он яв­ ляется текущим на всем процессе воспроизведения. По команде S w a p B u ffers текущее содержимое переднего буфера подменя­ ется содержимым заднего буфера кадра, но текущим буфером по­ сле этого все равно остается задний.

При завершении работы программы необходимо освободить контекст воспроизведения.

ния. Для обеспечения этой независимости в ней, в частности, оп­ ределены собственные типы. Их префикс - "GL", например G L int.

В каждой среде программирования в заголовочных файлах эти типы переопределяются согласно собственным типам среды. Разберем, как это делается в C++Builder.

Заголовочный файл C++Builder g l . h начинается с переопре­ деления стандартных типов C++, например:

t y p e d e f

int G L in t;

t y p e d e f

unsigned int G L uint;

t y p e d e f

float G L f lo a t;

t y p e d e f

double G Ldouble;

Рекомендуется использовать с самого начала знакомства именно типы библиотеки OpenGL, даже если вы наизусть знаете их родные для C++ аналоги. Наверняка вам рано или поздно при­ дется разбираться в чужих программах или переносить свои про­ граммы в другую среду программирования или даже в другую операционную систему.

Не все из типов OpenGL удается точно перевести. Например, G Lclam pf - вещественное число в пределах от нуля до единицы - в C++ определен просто как f l o a t . Поэтому обычно в програм­ мах устанавливают «ручную» проверку на вхождение величины такого типа в требуемый диапазон.

В ряду типов OpenGL особо надо сказать о типе GLboolean:

t y p e d e f unsigned char GLboolean;

Соответственно, определены две константы GL_FALSE=CL GL TRUE=1.

I L L S . Tun TColor и цвет в OpenGL

В этом разделе вам необходимо будет самостоятельно напи­ сать программу, которая будет окрашивать форму в выбранный цвет с использованием функции OpenGL g lC le a rC o lo r. Здесь на форму необходимо поместить кнопку, при нажатии на которую

появляется стандартный диалог Windows выбора цвета. После вы­ бора окно окрашивается в выбранный цвет, для чего используются команды OpenGL.

Цвет, возвращаемый диалогом, хранится в свойстве C o lo r

компонента класса T C o lo rD ia lo g . Значение OxOOFFFFFF этого свойства соответствует белому цвету, OxOOFFOOOO - синему,

OxOOOOFFOO - зеленому, OxOOOOOOFF - красному. То есть для выделения красной составляющей цвета необходимо вырезать первый слева байт, второй байт даст долю зеленого, третий - сине­ го. Максимальное значение байта - 2 55, минимальное - ноль. Цвета же OpenGL располагаются в интервале от нуля до единицы.

В программе введите функцию, определяющую тройку со­ ставляющих цветов для OpenGL по заданному аргументу типа

T C o lo r:

/ / ==================================================

/ /

П еревод

ц в е т а и з T C o lo r в OpenGL

v o id

__f a s t c a l l

T F o rm l: : C o lorT oG L (T C olor c, G L f lo a t

&R,

G L f lo a t

&G,

G L f lo a t &B)

{

R = C% 256/255. ;

G = ( ( c /2 5 6 ) % 2 5 6 )/ 2 5 5 . ; В = ( c / 0 x l 0 0 0 0 ) /2 5 5 . ;

}

Таким образом, из аргумента вырезаются нужные байты и масштабируются в интервал [0 ; 1].

Упражнение

1. Самостоятельно напишите программу, которая будет окр шивать форму в выбранный цвет с использованием функции

OpenGL g l C l e a r C o l o r .

Соседние файлы в папке книги