Глава 17. Интерфейс с графическими устройствами

             Многим типам приложений Windows для организации полного  ин-
        терфейса пользователя нужны только окна, блоки диалога и управля-
        ющие элементы.  Но некоторым приложениям  (например,  программами
        рисования и манипулирования изображениями) требуется наличие гра-
        фических средств для заполнения окон.  Эта графика может  быть  в
        форме линий, форм, текста и побитовых образов.

             Для предоставления  приложениям  графических  функциональных
        возможностей Windows имеет набор функций,  называемый интерфейсом
        с  графическим устройством - GDI.  GDI можно представить себе как
        графическую машину,  которую используют  приложения  Windows  для
        отображения и манипулирования графикой. Функции GDI предоставляют
        вашему приложению возможности рисования,  которые не  зависят  от
        используемого дисплея. Например, вы можете использовать одни и те
        же функции для организации вывода на дисплей EGA,  на дисплей VGA
        и даже на принтер PostScript.

             Аппаратная независимость   реализуется  через  использование
        драйверов устройств,  которые переводят функции  GDI  в  команды,
        воспринимаемые используемым устройством вывода. Это означает, что
        вам не нужно беспокоиться о том,  как конкретное устройство рабо-
        тает с  графическим  образом.  Вы  сообщаете драйверу,  что нужно
        что-то сделать, и он работает с устройством как нужно.

                             Запись на устройство вывода
        -----------------------------------------------------------------

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

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

             Контекст дисплея можно представить себе как холст для  рисо-
        вания. Окно это - картинка, включающая рамку. Вместо рисования на
        картине в рамке вы рисуете на холсте,  а уже затем устанавливаете
        его в рамку. Аналогично этому, вы рисуете в контексте дисплея ок-
        на.  Контекст дисплея обладает рядом инструментов рисования, нап-
        ример, ручки,  кисти и шрифты. Контекст дисплея - это управляемый
        Windows элемент,  похожий на элемент окна с тем исключением,  что
        контекст    дисплея    не    имеет    соответствующего   элемента
        ObjectWindows.

             Нужно помнить  о  том,  что контекст устройства представляет
        собой только часть устройства, на котором вы реально рисуете. Хо-
        тя вы  можете  рассматривать  вывод в терминах всего окна (рамки,
        меню, области клиента) или печатаемой страницы, контекст устройс-
        тва охватывает только ту часть,  где вы рисуете - область клиента
        окна или печатаемую часть страницы.

             Контекст устройства - это элемент, управляемый Windows (ана-
        логично оконному  элементу,  только  контекст устройства не имеет
        соответствующего объекта ObjectWindows).

                         Чем отличаются контексты устройства?
        -----------------------------------------------------------------

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

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

                            Управление контекстом дисплея
        -----------------------------------------------------------------

             Для организации рисования в контексте дисплея сначала  нужно
        получить  контекст дисплея для нужного окна.  Требования к памяти
        со стороны контекста дисплея очень велики, поэтому можно одновре-
        менно организовать доступ только к пяти контекстам дисплея в каж-
        дом сеансе Windows.  Это значит, что каждое окно не может поддер-
        живать свой собственный контекст дисплея. Оно получает его только
        в случае необходимости и освобождает при первой возможности.  Это
        может несколько обескуражить вас, но вы не можете управлять атри-
        бутами контекста дисплея.  Другое окно и даже  другое  приложение
        может  сменить атрибуты контекста дисплея.  Кроме того,  средства
        рисования не являются частью памяти контекста дисплея.  Они могут
        быть выбраны в контекст дисплея каждый раз при его получении.


                             Работа с контекстом дисплея
        -----------------------------------------------------------------

             Обычно нужно  определять  поле  оконного  объекта для записи
        описателя текущего контекста  дисплея,  аналогично  тому,  как  в
        HWindow сохраняется описатель окна:

             type
               TMyWindows = object(TWindow)
                  TheDC: HDC;
                   .
                   .
                   .
               end;

             Чтобы получить  для окна контекст дисплея,  вызовите функцию
        Windows GetDC:

             TheDC := GetDC(HWindow);

             Затем вы можете выполнить операцию изображения  в  контексте
        дисплея. Вы  можете  использовать  описатель  контекста дисплея в
        графических функциях Windows:

             LineTo(TheDC, Msg.LParamLo, Msg.LParamHi);

             Как только вы закончите работу с контекстом дисплея, освобо-
        дите его с помощью вызова функции ReleaseDC:

             ReleaseDC(HWindow, TheDC);

             Не вызывайте GetDC в строке дважды, не включив между вызова-
        ми вызов ReleaseDC. В итоге это приведет к сбою системы при рабо-
        те программы, так как она исчерпает все доступные контексты дисп-
        лея.

                        Что содержится в контексте устройства?
        -----------------------------------------------------------------

             Контекст устройства  содержит набор изобразительных средств,
        таких как перья,  кисти и шрифты.  Реально  эти  инструментальные
        средства не  существуют.  Они  просто  представляют собой удобный
        способ предположений об определенной группе  изобразительных  ха-
        рактеристик.

             Перо, например,  это просто удобный способ интерпретации ха-
        рактеристик линий  на  устройстве.  Графическая линия между двумя
        точками имеет три характеристики: ширину, цвет и стиль (например,
        пунктирная линия и линия из точек), которые совместно можно расс-
        матривать как "перо".  Эти логические группы изобразительных  ха-
        рактеристик значительно упрощают графику в Windows.

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

                                  Побитовая графика
        -----------------------------------------------------------------

             Действительная поверхность контекста дисплея называется  по-
        битовым отображением  (битовым  массивом).  Побитовые отображения
        представляют конфигурацию памяти конкретного устройства. Следова-
        тельно,  они зависят от вида адресуемого устройства.  Это создает
        проблему, поскольку охраненные для  одного  устройства  побитовые
        отображения  будут  несовместимы с другим устройством.  GDI имеет
        ряд средств для разрешения этой проблемы, включая аппаратно-неза-
        висимые побитовые отображения. Имеются следующие функции GDI, ко-
        торые создают    побитовые    отображения:    CreateCompatibleDC,
        CreateCompatibleBitmap и CreateDIBitmap.  Имеются следующие функ-
        ции GDI  по  манипулированию  побитовыми  отображениями:  BitBlt,
        StretchBlt, StretchDIBits и SetDIBitsToDevice.

                               Изобразительные средства
        -----------------------------------------------------------------

             Чтобы выполнить большую часть фактического изображения, кон-
        текст дисплея  использует  три  инструментальных средства:  перо,
        кисть и шрифт.

                                      Перья

             Перо используется для изображения линий,  дуг и ломаных  ли-
        ний, представляющих собой множественные линейные сегменты.  Атри-
        буты пера включают в себя его цвет,  ширину  и  стиль  (например,
        пунктирная линия или линия из точек).

                                      Кисти

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

                                     Шрифты

             Инструментальное средство  шрифта используется при изображе-
        ния в контексте дисплея текста.  Оно задаете высоту  шрифта,  его
        ширину, семейство и имя гарнитуры.

             Все три  инструментальных средства используют для заполнения
        пробелов атрибут фонового цвета контекста дисплея.  Изобразитель-
        ные инструментальные  средства  подробнее  освещаются  в  разделе
        "Изобразительные средства" данной главы.


                                         Цвет
        -----------------------------------------------------------------

             Цвет, который устройство использует для рисования,  хранится
        в цветовой палитре. Если вы желаете добавить цвет, которого нет в
        цветовой  палитре,  то его можно добавить.  Более часто вы будете
        настраивать драйвер устройства на аппроксимацию нужного цвета пу-
        тем  смешивания цветов палитры.  Работа с цветовой палитрой более
        подробно рассматривается в разделе  данной  главы  "Использование
        цветовой палитры".

                                  Режимы отображения
        -----------------------------------------------------------------

             Очень трудно выбрать устройство рисования, когда заранее не-
        известно,  какое устройство будет использоваться для отображения.
        Большинство приложений игнорируют эту  проблему  и  предполагают,
        что  вполне удовлетворительно будет работать единица рисования по
        умолчанию (один элемент изображения).  Однако, некоторые приложе-
        ния требуют,  чтобы отображение точно воспроизводило размеры нуж-
        ного образа.  Для таких приложений GDI допускает различные режимы
        отображения,  некоторые из которых не зависят от аппаратуры. Каж-
        дый из методов распределения имеет  свою  единицу  размерности  и
        систему координатной ориентации. Режим распределения по умолчанию
        устанавливает начало координат в  левом  верхнем  углу  контекста
        дисплея с положительным направлением оси X вправо и положительным
        направлением оси Y вниз.  Каждый контекст дисплея имеет  атрибуты
        распределения для интерпретации задаваемых вами координат.

             Иногда нужно транслировать логические координаты, используе-
        мые вами для рисования,  в физические координаты побитового отоб-
        ражения. Для большинства приложений начало координат для экрана -
        это его левый верхний угол,  но для окна началом  координат будет
        левый  верхний угол области клиента.  Некоторые окна прокручивают
        свою поверхность клиента так,  что начало координат не будет даже
        находиться  в  области  клиента.  Некоторые  функции GDI работают
        только в конкретной системе координат, поэтому преобразование ко-
        ординат просто необходимо. В GDI имеется ряд функций для подобно-
        го пересчета координат:  ScreenToClient, ClientToScreen, DPToLP и
        LPToDP.

                                  Обрезание областей
        -----------------------------------------------------------------

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

                         Инструментальные средства рисования
        -----------------------------------------------------------------

             Контекст дисплея  управляет  отображением графики на экране.
        Для иного способа отображения графики можно  изменить  инструмен-
        тальные средства,  с помощью которых создается изображение. Атри-
        буты инструментальных средств задают проявление изображений с по-
        мощью функций GDI,  например,  LineTo,  Rectange и TextOut. Перья
        задают внешний вид линий,  кисти задают внешний  вид  закрашенных
        областей и шрифт задает внешний вид изображаемого текста.

             Для задания атрибутов инструмента программа Windows выбирает
        логический инструмент в контекст дисплея.  Логический  инструмент
        создается  вашей  программой  путем заполнения полей определенной
        записи, TLogPen, TLogBrush или TLogFont. Текущий инструмент - это
        инструмент, определенный  в  Windows,  представляющий самый общие
        варианты атрибута, например, непрерывное черное перо, серая кисть
        или системный шрифт.

                          Основные инструментальные средства
        -----------------------------------------------------------------

             Основные инструментальные средства  создаются  функцией  GDI
        GetStockObject. Например:

             var
               TheBrush: HBrush
             begin
               TheBrush:=GetStockObject(LtGray_Brush);
                .
                .
                .
             end;

        где LtGray_Brush - это целая  константа,  определенная  в  модуле
        WinTypes в ObjectWindows. Приведем список всех имеющихся констант
        основного инструментального средства:

                         Основные инструменты рисования      Таблица 17.1
        +-------------------+------------------+------------------------+
        |     Кисти         |     Перья        |      Шрифты            |
        +-------------------+------------------+------------------------|
        |   White_Brush     |   White_Pen      |    OEM_Fixed_Font      |
        |   LtGray_Brush    |   Black_Pen      |    ANSI_Fixed_Font     |
        |   Gray_Brush      |   Null_Pen       |    ANSI_Var_Font       |
        |   DkGray_Brush    |                  |    System_Font         |
        |   Black_Brush     |                  |    Device_Default_Font |
        |   Null_Brush      |                  |    System_Fixed_Font   |
        |   Hoolow_Brush    |                  |                        |
        +-------------------+------------------+------------------------+

             В отличие  от  логических  инструментальных средств основные
        инструментальные средства не удаляются после использования.

                         Логические инструментальные средства
        -----------------------------------------------------------------

             Записи логических   инструментов,   TLogPen,   TLogBrush   и
        TLogFont,  содержат поля для хранения каждого атрибута инструмен-
        та.  Например,  TLogPen.lopnColor  содержит значение цвета ручки.
        Каждый тип записи определяет свой  собственный  набор  атрибутов,
        соответствующий типу инструмента.

                                   Логические перья
        -----------------------------------------------------------------

             Вы можете  создавать  логические  перья  с  помощью  функций
        Windows CreatePen или CreatePenInderect. Например:

             ThePen := CreatePen(ps_Dot, 3, RGB(0, 0, 210));
             ThePen := CreatePenInderect(@ALogPen);

             Определение записи TLogPen имеет следующий вид:

             TLogPen = record
                lopnStyle: Word;
                lopnWidth: TPoint;
                lopnColor: Longint;
             end;

             Поле стиля,  lopnStyle,  содержит константу,  задающую стиль
        линии.


        -----------------------------------------------------------------
             Константа                     Результат
        -----------------------------------------------------------------
            PS_SOLID            -------------------------------------
            PS_DASH             -------------------------------------
            PS_DOT              .
            PS_DASHDOT          .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
            PS_DASHDOTDOT       -------------
            PS_NULL
        -----------------------------------------------------------------

                              Рис.17.1 Стили линий для пера.

             Поле толщины,  lopnWidth, содержит точку, координата x кото-
        рой задает толщину линии в координатах устройства. На экране VGA,
        если задано значение 0, то будет рисоваться линия толщиной в один
        элемент изображения.  Значение координаты  y  игнорируется.  Поле
        цвета, lopnColor, содержит значение Longint, байты которого зада-
        ют величины интенсивности основных цветов (красного,  зеленого  и
        синего),  смешение которых и дает нужный цвет. Значение lopnColor
        должно иметь вид $00bbggrr,  где bb - значение синего цвета, gg -
        значение зеленого цвета,  а rr - значение красного цвета. Доступ-
        ный диапазон интенсивности для каждого первичного цвета от  0  до
        255,  или  от  0 до FF в шестнадцатиричном исчислении.  Следующая
        таблица показывает некоторые примеры значений цвета:

                             Примеры значений цвета
                                            Таблица 17.2
                         +--------------+--------------+
                         |   Значение   |   Цвет       |
                         +--------------+--------------|
                         |  $00000000   |  черный      |
                         |  $00FFFFFF   |  белый       |
                         |  $000000FF   |  красный     |
                         |  $0000FF00   |  зеленый     |
                         |  $00FF0000   |  синий       |
                         |  $00808080   |  серый       |
                         +--------------+--------------+

             В качестве  альтернативы для воспроизведения цвета можно ис-
        пользовать  функцию  RGB.  RGB(0,0,0)  возвратит   черный   цвет,
        RGB(255,0,0) возвратит красный и т.д.


                                   Логические кисти
        -----------------------------------------------------------------

             Вы можете  создавать  логические  кисти  с  помощью  функций
        Windows           CreateHatchBrush,           CreatePatternBrush,
        CreateDIBPatternBrush или CreateBrushInderect. Например:

             TheBrush := CreateHatchBrush(hs_Vertical, RGB(0, 255, 0));
             TheBrush := CreateBrushInderect(@ALogBrush);

             Определение записи TLogBrush имеет следующий вид:

             TLogBrush = record
               lbStyle: Word;
               lbColor: Longint;
               lbHatch: Integer;
             end;

             Поле стиля, lbStyle, содержит константы, задающие стиль кис-
        ти:

             * bs_DIBPattern указывает,  что образец кисти задан аппарат-
               но-независимым побитовым отображением.

             * bs_Hatched задает один из  заранее  определенных  образцов
               штриховки (см. lbHatch).

             * bs_Hollow - это пустая кисть.

             * bs_Pattern  использует левый верхний угол 8 на 8 элементов
               побитового отображения,  которое находится в этот момент в
               памяти.

             * bs_Solid - это непрерывная кисть.

             Поле lbColor  содержит  значение  цвета,  аналогично  записи
        TLogPen.  Это поле игнорируется кистями со  стилями  bs_Hollow  и
        bs_Pattern.

             Поле lbHatch  содержит  целую  константу,  задающую  образец
        штриховки для   кисти   со   стилем   bs_Hatched.   Если    стиль
        bs_DIBPattern, то lbHatch содержит описатель побитового отображе-
        ния.


        -----------------------------------------------------------------
              Константа                      Результат
        -----------------------------------------------------------------

                              //////////////////////////////////////
            HS_BDIAGONAL      //////////////////////////////////////
                              //////////////////////////////////////

                              ++++++++++++++++++++++++++++++++++++++
            HS_CROSS          ++++++++++++++++++++++++++++++++++++++
                              ++++++++++++++++++++++++++++++++++++++

                              xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            HS_DIAGCROSS      xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                              xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

                              \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
            HS_FDIAGONAL      \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
                              \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

                              --------------------------------------
            HS_HORIZONTAL     --------------------------------------
                              --------------------------------------

                              ||||||||||||||||||||||||||||||||||||||
            HS_VERTICAL       ||||||||||||||||||||||||||||||||||||||
                              ||||||||||||||||||||||||||||||||||||||

        -----------------------------------------------------------------

             Рис. 17.2 Стили штриховки для кисти.

                                  Логические шрифты
        -----------------------------------------------------------------

             Вы можете создавать  логические  шрифты  с  помощью  функций
        Windows CreateFont или CreateFontInderect.

             Определение записи TLogBrush следующее:

             TLogFont = record
                 lfHight: Integer;
                 lfWidht: Integer;
                 lfEscapement: Integer;
                 lfOrientation: Integer;
                 lfWeight: Integer;
                 lfItalic: Byte;
                 lfUnderline: Byte;
                 lfStrikeOut: Byte;
                 lfCharSet: Byte;
                 lfOutPrecision: Byte;
                 lfClipPrecision: Byte;
                 lfQuality: Byte;
                 lfPitchAndFamily: Byte;
                 lfFaceName: array[0lf_FaceSize - 1] of Byte;
             end;

             При использовании TLogFont для создания  шрифта  вы  задаете
        атрибуты нужного вам шрифта. Однако, ваша программа не использует
        эту информацию для генерации шрифта на экране.  Вместо этого  она
        отображает запрос  экранного шрифта  в текущий экранный шрифт се-
        анса Windows.

             Поле lfHight задает необходимую высоту шрифта.  Нулевое зна-
        чение  устанавливает размер по умолчанию.  Положительное значение
        есть высота элемента в логических единицах.  Отрицательное значе-
        ние воспринимается как положительное.

             Поле lfWidht  задает  нужную ширину букв в единицах устройс-
        тва. Если  задан  ноль,  то  коэффициент относительного удлинения
        сохраняется.

             Для поворачиваемого  текста  lfEscapement  задает значение в
        десятых долях градуса, на которое поворачивается текст против ча-
        совой  стрелки.  lfOrientation делает аналогичный поворот каждого
        символа.

             Параметр lfWeight задает нужный  вес  символов.  В  качестве
        значений   можно   использовать  константы  fw_Light,  fw_Normal,
        fw_Bold и fw_DontCare.

             Для трех  атрибутов  шрифта  -   lfItalic,   lfUnderline   и
        lfStrikeOut  - нужно задать ненулевые значения.

             В поле lfCharSet требуется задать конкретный набор символов,
        ANSI_CharSet, OEM_CharSet или Symbol_CharSet. Набор символов ANSI
        содержится  в "Руководстве пользователя по Microsoft Windows",  в
        Приложении B. OEM_CharSet является системно-зависимым.

             Поле lfOutPrecision задает,  как точно  создаваемый  Windows
        шрифт должен соответствовать запросам на размеры и позиционирова-
        ние. Значение  поля  по  умолчанию  -  Out_Default_Precis.   Поле
        lfClipPrecision задает  способ рассмотрения частично видимых сим-
        волов. Значение поля по умолчанию Clip_Default_Precis.

             Поле lfQuality показывает как точно предоставляемый  Windows
        шрифт соответствует запрошенным атрибутам шрифта.  Может быть ус-
        тановлено    значение    Default_Quality,    Draft_Quality    или
        Proof_Quality.  Для значения Proof_Quality жирные,  подчеркнутые,
        наклонные шрифты и шрифты с надпечаткой синтезируются,  даже если
        их нет.  Поле lfPitchAndFamily задает шаг и семейство шрифта. Оно
        может быть результатом логической операции  or  между  константой
        шага и константой семейства.

                   Константы шага и семейства шрифта  Таблица 17.3
              +---------------------+----------------------------+
              |  Константы шага     |     Константы семейства    |
              +---------------------+----------------------------|
              |   Default_Pitch     |      ff_Modern             |
              |   Fixed_Pitch       |      ff_Roman              |
              |   Variable_Pitch    |      ff_Script             |
              |                     |      ff_Swiss              |
              |                     |      ff_Decorative         |
              |                     |      ff_DontCare           |
              +---------------------+----------------------------+

             И, наконец,  lfFaceName - это строка,  которая задает запро-
        шенный вид букв.  Если задано значение 0, то вид букв будет стро-
        иться на основании значений других полей TLogFont.  Приведем нес-
        колько примеров исходного кода, определяющего записи TLogFont:

             procedure MyWindow.MakeFont;
             var
               MyLogFont: TLogFont;
             begin
               with MyLogFont do
               begin
                 lfHight := 30;
                 lfWidht := 0;
                 lfEscapement := 0;
                 lfOrientation := 0;
                 lfWeight := fw_Bold;
                 lfItalic := 0;
                 lfUnderline := 0;
                 lfStrikeOut := 0;
                 lfCharSet := ANSI_CharSet;
                 lfOutPrecision := Out_Default_Precis;
                 lfClipPrecision := Clip_Default_Precis;
                 lfQuality := Default_Quality;
                 lfPitchAndFamily := Variable_Pitch or ff_Swiss;
                 StrCopy(@FaceName, 'Helv');
              end;
              TheFont := CreateFontInderect(@MyLogFont);
             end;

             procedure MyWindow.MakeFont;
             var
               MyLogFont: TLogFont;
             begin
               with MyLogFont do
               begin
                 lfHight := 10;
                 lfWidht := 0;
                 lfEscapement := 0;
                 lfOrientation := 0;
                 lfWeight := fw_Normal;
                 lfItalic := Ord(True);
                 lfUnderline := Ord(True);
                 lfStrikeOut := 0;
                 lfCharSet := ANSI_CharSet;
                 lfOutPrecision := Out_Default_Precis;
                 lfClipPrecision := Clip_Default_Precis;
                 lfQuality := Default_Quality;
                 lfPitchAndFamily := Fixed_Pitch or ff_DontCare;
                 StrCopy(@FaceName, 'Courier');
              end;
              TheFont := CreateFontInderect(@MyLogFont);
             end;

             procedure MyWindow.MakeFont;
             var
               MyLogFont: TLogFont;
             begin
               with MyLogFont do
               begin
                  lfHight:=30;
                  lfWidht:=0;
                  lfEscapement:=0;
                  lfOrientation:=0;
                  lfWeight:=fw_Normal;
                  lfItalic:=0;
                  lfUnderline:=0;
                  lfStrikeOut:=0;
                  lfCharSet:=Symbol_CharSet;
                  lfOutPrecision:=Out_Default_Precis;
                  lfClipPrecision:=Clip_Default_Precis;
                  lfQuality:=Proof_Quality;
                  lfPitchAndFamily:=Fixed_Pitch or ff_Roman;
                  StrCopy(@FaceName, 'Rmn');
              end;
                TheFont:=CreateFontInderect(@MyLogFont);
             end;


                Использование изобразительных инструментальных средств
        -----------------------------------------------------------------

             Контекст дисплея позволяет вам рисовать в окне и, кроме это-
        го,  он содержит инструментальные средства рисования: перья, кис-
        ти, шрифты и палитры, которые вы используете для рисования текста
        и изображений.  При рисовании линии в контексте дисплея линия вы-
        водится со следующими атрибутами текущего пера: цвет, стиль (неп-
        рерывная,  пунктирная и т.п.) и толщина. При закрашивании области
        она выводится со следующими атрибутами текущей кисти:  образец  и
        цвет. При рисовании текста в контексте дисплея он выведется с ат-
        рибутами текущего шрифта:  шрифт (Modern,  Roman,  Swiss и т.п.),
        размер,  стиль (наклонный, жирный и т.п.). Палитра содержит набор
        текущих доступных цветов.

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

             Для изменения  набора инструментальных средств по умолчанию,
        нужно создать новый инструментальный элемент и выбрать его в кон-
        текст дисплея.  Например, при выборе новой ручки старая автомати-
        чески удаляется.  Мы рекомендуем вам сохранять старые  инструмен-
        тальные средства  и повторно устанавливать их после окончания ис-
        пользования новых:

             var
                NewPen, OldPen: HPen;
                TheDC: HDC;
             begin
                { задать ширину пера 10 }
                NewPen := CreatePen(ps_Solid, 10, RGB(0, 0, 0));
                TheDC := GetDC(AWindow^.HWindow);
                OldPen := SelectObject(TheDC, NewPen);
                { выполнить черчение }
                SelectObject(TheDC, OldPen);
                ReleaseDC(AWindow^.HWindow, TheDC);
                DeleteObject(NewPen);
             end;

             Как показано в данном примере,  новый  инструмент  рисования
        должен  быть создан,  а затем удален.  Подобно контексту дисплея,
        элементы хранятся в памяти Windows.  Если их не удалить, это при-
        водит  к  потерям памяти и возможности возникновения сбоя.  Как и
        для контекста дисплея, вы должны хранить описатели инструменталь-
        ных средств  рисования  в переменных типа HPen,  HBrush,  HFont и
        HPalette.

             Функция Windows DeleteObject удаляет инструментальные средс-
        тва  рисования  из  памяти Windows.  Ни в коем случае не удаляйте
        инструментальные средства рисования, которые выбраны в данный мо-
        мент в контекст дисплея!

             Контекст дисплея  может хранить только по одному инструменту
        рисования каждого типа в данный  момент  времени,  поэтому  нужно
        отслеживать   доступные  инструментальные  средства  отображения.
        Очень важно удалить их все до завершения работы  вашего  приложе-
        ния. Один  из методов,  (использован в примере Главы 2) состоит в
        определении поля объекта окна с именем ThePen для хранения описа-
        теля текущего пера. Когда пользователь выбирает новый стиль пера,
        создается новое перо,  а старое удаляется. Следовательно, оконча-
        тельное  перо будет удалено методом основного окна CanClose.  Вам
        не нужно удалять набор  инструментальных  средств  по  умолчанию,
        поставляемый во вновь полученном контексте дисплея.

             Есть два способа создания новых инструментальных средств ри-
        сования.  Самый простой способ состоит в использовании существую-
        щего альтернативного инструмента,  называемого основным или опор-
        ным. Список основных инструментальных средств приведен в  Таблице
        17.1.

             Для установки основного инструментального средства в объекте
        контекста дисплея используются методы SetStockPen, SetStockBrush,
        SetStockFont и SetStockPalette. Например:

             ThePen:=GetStockObject(Black_Pen);

             Не удаляйте основные инструменты из памяти Windows, посколь-
        ку вы будете настраивать их. Иногда возникает ситуация, когда нет
        основного инструмента, который имел бы нужный вам атрибут. Напри-
        мер,  все основные перья воспроизводят тонкие линии, а вам требу-
        ется толстая.  В этом случае имеется два способа создания настро-
        енных инструментальных средств рисования.  Один способ состоит  в
        вызове  функций Windows CreatePen,  CreateFont,  CreateSolidBrush
        или CreateDIBPatternBrush.  Эти функции используют параметры, ко-
        торые описывают нужный инструмент, и возвращают описатель инстру-
        ментального   средства,   который    используется    в    вызовах
        SelectObject.

             Другой способ создания настроенных инструментальных средств
        состоит  в построении описания атрибутов логического инструмента.
        Логический  инструмент  реализуется  структурами  данных  Windows
        TLogPen,  TLogBrush,  TLogFont и TLogPalette.  Например,  TLogPen
        имеет поля для хранения толщины цвета  и  стиля.  После  создания
        записи данных логического инструмента,  она передается в качестве
        параметра      в      CreatePenInderect,     CreateBrushInderect,
        CreateFontInderect или CreatePalette. Эти функции возвращают опи-
        сатели инструментального средства которые могут быть использованы
        в вызовах SelectObject.  В данном примере  устанавливается  синее
        перо для изображения в контексте дисплея окна:

             procedure SampleWindow.ChangePenToBlue;
             var
                ALogPen: TLogPen;
                ThePen: HPen;
             begin
                ALogPen.lopnColor:=RGB(0, 0, 255);
                ALogPen.lopnStyle:=ps_Solid;
                ALogPen.lopnWidth.X:=0;
                ALogPen.lopnWidth.Y:=0;
                ThePen:=CreatePenInderect(@ALogPen);
                SelectObject(TheDC, ThePen);
             end;

                             Отображение графики в окнах
        -----------------------------------------------------------------

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

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

                                   Изображение окон
        -----------------------------------------------------------------

             Когда возникает необходимость нарисовать окно, оно становит-
        ся запрещенным.  Это значит что изображение дисплея не  соответс-
        твует  действительности и должно быть изменено.  Это происходит в
        момент первоначального отображения окна,  восстановления из  пик-
        тограммы  или  удаления  другого окна,  которое перекрывало часть
        данного окна.  Во всех этих случаях  Windows  посылает  сообщение
        wm_Paint соответствующему приложению. Это сообщение автоматически
        вызывает метод Paint  вашего  окна.  Один  из  параметров  Paint,
        PaintDC, представляет собой контекст дисплея, который использует-
        ся для рисования.

             Метод TWindow Paint  ничего  не  рисует,  поскольку  объекты
        TWindow не имеют графики для рисования.  В типе вашего окна опре-
        делим метод Paint, который будет вызывать методы и функции, изоб-
        ражающие в окне текст и графику.

             Единственное, что  вы  можете  сделать с контекстом дисплея,
        это выбрать в него новый инструмент  рисования,  например,  перья
        других цветов или кисти других образцов. Вам придется указать эти
        инструменты в контексте дисплея рисования вашего метода Paint.

             После завершения  работы метода Paint контекст дисплея рисо-
        вания автоматически освобождается.

                                  Стратегия графики
        -----------------------------------------------------------------

             Метод Paint отвечает за рисование текущего содержимого  окна
        в любой момент времени, включая первое появление этого окна. Сле-
        довательно,  метод Paint должен уметь рисовать  все  "постоянные"
        изображения окна. Кроме того, он должен уметь восстанавливать лю-
        бые изображения,  добавленные в окно после его первого появления.
        Для  воспроизведения этой "динамической" графики метод Paint дол-
        жен иметь доступ к инструкциям или данным, с помощью которых было
        создано изображение.

             Вы можете  выбрать один из двух возможных вариантов.  Первый
        подход состоит в выделении нескольких графических методов  и  при
        динамическом  рисовании вызывать их из метода Paint.  Другой под-
        ход, показанный в примере Главы 3, состоит в хранении данных, от-
        носящихся  к  графическому контексту окна,  в полях объекта этого
        окна.  Эти данные могут включать, например, координаты, формулы и
        побитовые распределения. Затем метод Paint повторно вызывает гра-
        фические функции,  которые нужны для преобразования этих данных в
        изображения.

             Используя эти  стратегии  и способность объекта хранить свои
        собственные данные и функции вы можете разрабатывать очень разви-
        тые и впечатляющие графические приложения.

                                  Рисование в окнах
        -----------------------------------------------------------------

             Для рисования  любого  текста или изображения в объекте окна
        сначала нужно получить контекст дисплея. После рисования контекст
        дисплея нужно освободить. (В одном сеансе Windows доступны только
        пять элементов контекста дисплея.) Вы можете использовать  описа-
        тель  контекста дисплея  в  качестве  аргумента любой графической
        функции Windows.

                         Вызов графических функций окна

             Одно из правил GDI состоит в том, что для работы функций не-
        обходимо в качестве аргумента задавать контекст  дисплея.  Обычно
        вы  будете  вызывать эти функции из методов типа окна.  Например,
        TextOut - это функция рисования текста на контексте дисплея в за-
        данном месте:

             TheDC := GetDC(HWindow);
             TextOut(TheDC, 50, 50, 'Sample Text', 11);
             ReleaseDC(HWindow, TheDC);

                               Графические функции GDI
        -----------------------------------------------------------------

             Данный раздел описывает различные вызовы API, которые вы мо-
        жете использовать для рисования изображений в окне.

                              Функции изображения текста
        -----------------------------------------------------------------

             Функция рисования текста использует для  рисования  заданный
        текущий  шрифт контекста дисплея.  Функция TextOut рисует текст в
        заданной точке.  TextOut выравнивает текст в зависимости от теку-
        щих значений флагов форматирования текста.  По умолчанию происхо-
        дит выравнивание слева.  Текущий метод выравнивания можно посмот-
        реть  с помощью функции GetTextAlign и установить с помощью функ-
        ции SetTextAlign.

             Функция TextOut - это самая часто используемая функция рисо-
        вания текста. Используя установленные по умолчанию флаги формати-
        рования текста,  данный метод Paint рисует выравненный слева мас-
        сив  символов,  левый  верхний  угол  которого  имеет  координаты
        (10,15).

             procedure TMyWindow.Paint(PaintDC: HDC;
                                       var PaintINfo: TPaintStruct);
             var
                MyTextString: array[020] of Char;
             begin
                StrCopy(MyTextString, 'Hello, World');
                TextOut(PaintDC, 10, 15, MyTextString,
                                       StrLen(MyTextString));
             end;

             +--------------------------------
             |
             |       (10, 15)
             |    * Hello Word
             |
             |

             Рис. 17.3 Результат выполнения функции TextOut.


                               Функции рисования линий
        -----------------------------------------------------------------

             Функции рисования линии используют  для  рисования  заданное
        текущее перо контекста дисплея.  Большинство линий рисуется с ис-
        пользованием функций MoveTo и LineTo. Эти функции воздействуют на
        атрибут контекста  дисплея  - текущую позицию.  Если использовать
        аналогию с карандашом и листом бумаги,  то  текущая  позиция  это
        точка, где карандаш касается бумаги.

                             Функции MoveTo и LineTo

             Функция MoveTo перемещает текущую позицию в заданные коорди-
        наты.  Функция LineTo рисует линию из текущей позиции к  точке  с
        заданными координатами.  Заданные координаты затем становятся те-
        кущей позицией.  Следующий метод Paint рисует линию от  (100,150)
        до (10,15).

              procedure TMyWindow.Paint(PaintDC: HDC; var PaintINfo:
                                        TPaintStruct);
              begin
                MoveTo(PaintDC, 100, 150);
                LineTo(PaintDC, 10, 15);
              end;

             +--------------------------------
             |
             |       (10, 15)
             |    *
             |     \
             |      \
             |       \
             |        \
             |         * (100, 150)

             Рис. 17.4. Результат выполнения функции LineTo.

                                Функция PolyLine

             Функция Polyline рисует последовательность линий,  соединяю-
        щих заданные точки.  По действию она аналогична выполнению после-
        довательности функций MoveTo и LineTo, однако, Polyline выполняет
        эту  операцию  намного быстрее и никак не воздействует на текущую
        позицию пера. Следующий метод Paint рисует прямой угол.

             procedure TMyWindow.Paint(PaintDC: HDC; var PaintInfo:
                                       TPaintStruct);
             var
              Points: array[02] of TPoint;
             begin
              Points[0].X:=10;
              Points[0].Y:=15;
              Points[1].X:=10;
              Points[1].Y:=150;
              Points[2].X:=100;
              Points[2].Y:=150;
              Polyline(PaintDC, @Points, 3);
             end;

             +--------------------------------
             |
             |       (10, 15)
             |    *
             |    |
             |    |
             |    |
             |    |
             |    +-----* (100, 150)


             Рис. 17.5. Результат выполнения функции Polyline.

                                   Функция Arc

             Функция Arc рисует дуги по периметру эллипса,  ограниченного
        заданным прямоугольником. Дуга начинается в точке пересечения эл-
        липса и линии из центра эллипса в заданную точку начала. Дуга ри-
        суется против часовой стрелки до тех пор,  пока она  не достигнет
        точки  пересечения  эллипса с линией из центра эллипса к заданной
        точке конца.

             Следующий метод Paint рисует верхнюю четверть  окружности  с
        началом в (40,25) и окончанием в (10,25),  используя ограничиваю-
        щий прямоугольник (10,10),  (40,40),  начальную точку (0,0) и ко-
        нечную точку (50,0). Действие производится даже в том случае, ес-
        ли заданная начальная и конечная точка не лежат на дуге.

             procedure TMyWindow.Paint(PaintDC: HDC;
                                       var PaintInfo: TPaintStruct);
             begin
                Arc(PaintDC, 10, 10, 40, 40, 50, 0, 0, 0);
             end;


                                  Изображение фигур
        -----------------------------------------------------------------

             Функции изображения  фигур используют текущее перо заданного
        контекста дисплея для изображения периметра и текущую  кисть  для
        закраски внутренней области. На текущую позицию они не влияют.

                                Функция Rectangle

             Функция Rectangle рисует прямоугольник от его левого верхне-
        го угла к правому нижнему.  Например,  следующий оператор  метода
        Paint рисует прямоугольник от (10,15) до (100,150).

             Rectangle(PaintDC, 10, 15, 100, 150);

             +--------------------------------
             |
             |  (10, 15)
             |    *-----*
             |    |#####|
             |    |#####|
             |    |#####|
             |    |#####|
             |    *-----* (100, 150)


             Рис. 17.6. Результат выполнения функции Rectangle.

                                Функция RoundRect

             Функция RoundRect рисует прямоугольник со скругленными угла-
        ми.  Скругления углов определены как четверти эллипса.  Например,
        следующий оператор метода Paint рисует прямоугольник  от  (10,15)
        до  (100,150),  углы  которого будут скруглены четвертями эллипса
        шириной 9 и высотой 11.

             RoundRect(PaintDC, 10, 15, 100, 150, 9, 11);

                                 Функция Ellipse

             Функция Ellipse рисует эллипс, задаваемый ограничивающим его
        прямоугольником.  Следующий пример рисует эллипс в прямоугольнике
        от (10,15) до (110,70).

             Ellipse(PaintDC, 10, 50, 100, 150);

                               Функции Pie и Chord

             Функции Pie и Chord рисуют секторы эллипса. Они рисуют дугу,
        подобно функции Arc. Однако, результатом Pie и Chord будут облас-
        ти. Функция Pie соединяет центр эллипса с его граничными точками.
        Следующая функция Pie рисует верхнюю четверть круга, заключенного
        в прямоугольник от (10,10) до (40,40).

             Pie(PaintDC, 10, 10, 40, 40, 50, 0, 0, 0);

             Функция Chord соединяет две граничные точки дуги.

             Chord(PaintDC, 10, 10, 40, 40, 50, 0, 0, 0);

                                 Функция Polygon

             Функция Polygon рисует непрерывную  последовательность  сег-
        ментов линий,  аналогично функции Polyline, но в конце работы за-
        мыкает область,  рисуя линию от последней заданной точки к первой
        заданной точке. И, наконец, он заполняет полученный многоугольник
        текущей кистью, используя установленный режим закрашивания много-
        угольника. Следующий метод Paint рисует и закрашивает прямоуголь-
        ный треугольник.

             procedure TMyWindow.Paint(PaintDC: HDC;
                                       var PaintInfo: TPaintStruct);
             var
              Points: array[02] of TPoint;
             begin
              Points[0].X:=10;
              Points[0].Y:=15;
              Points[1].X:=10;
              Points[1].Y:=150;
              Points[2].X:=100;
              Points[2].Y:=150;
              Polygon(PaintDC, @Points, 3);
             end;

             +--------------------------------
             |
             |  (10, 15)
             |    *
             |    |\
             |    |#\
             |    |##\
             |    |###\
             |    *-----* (100, 150)
               (10, 150)

             Рис. 17.7. Результат выполнения функции Polygon.


                                 Использование палитр
        -----------------------------------------------------------------

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

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

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

                                  Установка палитры
        -----------------------------------------------------------------

             Логические палитры являются инструментами рисования,  такими
        же  как  перья  и  кисти,  описанные  в разделе "Инструментальные
        средства изображения".  Для создания логической палитры использу-
        ется  функция  CreatePalette,  которая  берет указатель на запись
        данных LogPalette,  создает новую палитру и возвращает ее  описа-
        тель, который  передается  в  SelectPalette  для выбора палитры в
        контекст дисплея.  Запись TLogPalette содержит поля номера версии
        Windows (в настоящее время $0300), число элементов палитры и мас-
        сив элементов палитры.  Каждый элемент палитры - это запись  типа
        TPaletteEntry. Тип TPaletteEntry имеет три байтовых поля для спе-
        цификации цвета (peRed,  peGreen и peBlue) и одно поле для флагов
        (peFlags).

             GetStockObject(Default_Palette) создает  палитру  по умолча-
        нию, состоящую из 20 цветов, которые всегда присутствуют в палит-
        ре системы.

             После выбора   палитры   в   контекст   дисплея   с  помощью
        SelectPalette,  он должен до использования "реализовать" ее.  Это
        делается с помощью функции Windows RealizePalette:

             ThePalette := CreatePalette(@ALogPalette);
             SelectPalette(TheDC, ThePalette, 0);
             RealizePalette(TheDC);

             RealizePalette помещает  цвета из вашей логической палитры в
        системную палитру устройства. Сначала Windows проверяет соответс-
        твие цветов с уже имеющимися в системной палитре,  а затем добав-
        ляет ваши новые цвета в палитру системы, если для этого есть мес-
        то.  Цветам,  которым не нашлись идентичные цвета в системной па-
        литре, подбирается наиболее соответствующий цвет из палитры  сис-
        темы.  Ваше приложение должно реализовать свою палитру до рисова-
        ния, как это делается для других инструментальных средств рисова-
        ния.

                                Рисование с палитрами
        -----------------------------------------------------------------

             После реализации палитры вашего приложения,  оно может  осу-
        ществлять  рисование  с использованием его цветов.  Цвета палитры
        можно задавать прямо или косвенно.  Для прямого задания цвета ис-
        пользуется  индекс палитры,  TColorRef.  Индекс палитры TColorRef
        есть значение типа Longint,  где старший байт установлен в  1,  а
        индекс элемента логической палитры содержится в двух младших бай-
        тах. Например, $01000009 задает девятый элемент логической палит-
        ры. Это значение можно использовать везде, где ожидается аргумент
        TColorRef. Например:

             ALogPen.lopnColor := $01000009;

             Если ваше дисплейное устройство допускает использование пол-
        ного  24-битового  цвета без системной палитры,  то использование
        индекса палитры неоправданно ограничивает вас цветами вашей логи-
        ческой палитры.  Чтобы избежать этого ограничения,  вы можете за-
        дать цвет палитры косвенно,  используя относительное значение па-
        литры TColorRef. Относительное значение TColorRef почти совпадает
        с абсолютным значением RGB TColorRef,  но байт  старшего  разряда
        установлен  в  2.  Три младших байта содержат значение цвета RGB.
        Например,  $020000FF задают значение чистого красного цвета. Если
        устройство  поддерживает  системную палитру,  то Windows подберет
        максимально соответствующий цвет  RGB  логической  палитры.  Если
        устройство  не  поддерживает системную палитру,  то TColorRed ис-
        пользуется так, как если бы он задавал явное значение RGB.

                                    Запрос палитры
        -----------------------------------------------------------------

             Windows определяет  функцию,  которая позволяет вам получать
        информацию относительно палитры.  GetPaletteEntries  воспринимает
        индекс,  диапазон  и указатель на TPaletteEntry и заполняет буфер
        заданными элементами палитры.

                                 Модификация палитры
        -----------------------------------------------------------------

             Есть два  способа  изменения  элементов  логической палитры.
        Функция SetPaletteEntries берет те  же  самые  аргументы,  что  и
        GetPaletteEntries  и  меняет заданные элементы на те,  на которые
        указывает третий аргумент.  Обратите внимание на то, что произве-
        денные  изменения  не  отражаются  в  системной палитре до вызова
        RealizePalette, и их не  видно до  перерисовки  области  клиента.
        Функция AnimatePalette   воспринимает  те  же  аргументы,  что  и
        SetPaletteEntries,  но используется для быстрых изменений палитры
        приложения,  и  они  немедленно  становятся видимыми.  При вызове
        AnimatePalette элементы палитры с полем peFlags  установленным  в
        константу  pc_Reserved  будут  заменены  на соответствующие новые
        элементы, и это найдет немедленное отражение в системной палитре.
        На другие элементы это никак не повлияет.

             Например, вам  нужно  взять первые десять элементов палитры,
        сменить их значение, добавив на единицу содержание красного цвета
        и уменьшив содержимое синего и зеленого. Все эти изменения должны
        сразу же стать видимыми (Предполагается, что некоторые из элемен-
        тов имеют установленное значение pc_Reserved):

             GetObject(ThePalette, SizeOf(NumEntries), @NumEntries);
             if NumEntries >= 10 then
             begin
                GetPaletteEntries(ThePalette, 0, 10, @PaletteEntries);
                for i:=0 to 9 do
              begin
                 PaletteEntries[i].peRed:=PaletteEntries[i].peRed+40;
                 PaletteEntries[i].peGreen:=PaletteEntries[i].peGreen-40;
                 PaletteEntries[i].peBlue:=PaletteEntries[i].peBlue-40;
              end;
                AnimatePalette(ThePalette, 0, 10, @PaletteEntries);
             end;

             Вместо AnimatePalette мы могли бы использовать:

             SetPaletteEntries(ThePalette, 0, 10, @PaletteEntries);
             RealizePalette(ThePalette);

        и затем перерисовать окно, чтобы увидеть изменения цветов.

                             Реакция на изменения палитры
        -----------------------------------------------------------------

             Когда окно принимает сообщение wm_PaletteChanged, это свиде-
        тельствует о том, что активное окно сменило системную палитру пу-
        тем реализации ее логической  палитры.  Окно,  принявшее  сообще-
        ние, может отреагировать на него тремя способами: оно может ниче-
        го не делать (очень быстрый способ,  но может привести  к  некор-
        ректным цветам),  оно может реализовать свою логическую палитру и
        перерисовать себя (медленнее, но цвета будут максимально коррект-
        ными), либо оно может реализовать свою логическую палитру и затем
        использовать функцию UpdateColors для быстрого изменения  области
        клиента в соответствии с системной палитрой. UpdateColors в общем
        случае работает быстрее,  чем перерисовка области клиента, но при
        ее  использовании могут быть некоторая потеря точности в цветопе-
        редаче.  Поле WParam  записи  TMessage,  переданной  в  сообщении
        wm_PaletteChanged,  содержит описатель окна,  которое реализовало
        свою палитру. Если в ответ вы решили реализовать свою собственную
        палитру,  сначала убедитесь в том, что этот описатель не является
        описателем вашего окна, чтобы не создать бесконечного цикла.

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

             Полный текст программы содержится в файле PALTEST.PAS на ва-
        ших дистрибутивных дискетах.  
                              Назад | Содержание | Вперед