Глава 2. Заполнение окна

             Пока ваша программа не делает ничего интересного.  В  данной
        главе мы возьмем программу Step,  которая пока представляет собой
        просто оболочку программы,  и преобразуем ее в полезное  интерак-
        тивное графическое приложение. Сначала мы выведем в основном окне
        текст. Затем преобразуем Step в  полное  графическое  приложение,
        позволяющее вам отображать в основном окне линии различной толщи-
        ны.

                           Шаг 2: Отображение текста в окне
        -----------------------------------------------------------------

                              +-----------------------+
                              | Step 1: Basic App     |
                              |XStepX2:XTextXXXXXXXXXX|
                              | Step 3: Lines         |
                              | Step 4: Menu          |
                              | Step 5: About Box     |
                              | Step 6: Pens          |
                              | Step 7: Painting      |
                              | Step 8: Streams       |
                              | Step 9: Printing      |
                              | Step 10: Palette      |
                              | Step 11: BWCC         |
                              | Step 12: Custom ctrls |
                              +-----------------------+

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

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

                              Вывод в контексте дисплея
        -----------------------------------------------------------------

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

                   Примечание: Подробно о контексте дисплея рассказывает-
              ся в Главе 17 "Интерфейс с графическими устройствами".

                             Что такое контекст дисплея?
        -----------------------------------------------------------------

             Контекст дисплея имеет три основных функции отображения:

             * Он обеспечивает,  что текст и графика не выводятся вне по-
               верхности окна.

             * Он управляет выбором и  отменой  инструментальных  средств
               отображения:  перьев,  кистей и шрифтов.  В шаге 3 показан
               пример выбора нового пера,  но мы начнем сначала с  вывода
               текста.

             * Он обеспечивает независимость от устройства.  Для вывода в
               контексте дисплея ваша  программа  использует  стандартные
               функции API Windows. В шаге 9 мы покажем как можно исполь-
               зовать одни и те же команды для отображения в  окне  и  на
               принтере.

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

             Поскольку, чтобы рисовать в окне при буксировке "мыши",  вам
        необходим контекст дисплея, создайте в объекте основного окна но-
        вое поле с именем DragDC,  которое будет содержать описатель кон-
        текста дисплея.  DragDC имеет тип HDC,  который эквивалентен типу
        Word.

             Чтобы использовать контекст дисплея, ваша программа должна:

             * получить контекст дисплея;

             * нарисовать в нем;

             * освободить контекст дисплея.

                             Получение контекста дисплея
        -----------------------------------------------------------------

             Чтобы отобразить что-то в окне,  вы должны сначала  получить
        контекст дисплея.  Это  можно сделать,  вызвав в одном из методов
        типа непосредственно перед отображением на экране функцию Windows
        GetDC:

             DragDC := GetDC(HWindow);
                           Использование контекста дисплея
        -----------------------------------------------------------------

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

             TextOut(DragDC, 20, 20, 'Пример текста', 11);
             LineTo(DragDC, 30, 45);

                            Освобождение контекста дисплея
        -----------------------------------------------------------------

             После отображения текста или графики  вы  должны  освободить
        контекст дисплея (как только закончите отображение).

             ReleaseDC(HWindow, DragDC);

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

             Windows выделяет по пять контекстов дисплея  на  приложение,
        которые можно совместно использовать через GetDC.  Пока в Windows
        зарезервировано достаточно памяти,  вы можете с помощью GetDC по-
        лучить другие контексты.

                   Примечание: GDI и вопросы использования памяти освеща-
              ются в Главе 17 "Интерфейс с графическим устройством".


                                  Координаты Windows
        -----------------------------------------------------------------

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

             При отображении  вас  касаются только координаты в контексте
        дисплея. Windows обеспечивает,  чтобы контекст дисплея попадал  в
        область клиента окна.

                   Примечание: Область  клиента  -  это часть окна внутри
              рамки.

             На этом  шаге Step отобразит текст,  показывающий координаты
        той точки в окне, где вы щелкнули кнопкой "мыши". Например, '(20,
        30)' - это точка,  отстоящая на 20 элементов изображения вправо и
        на  30 элементов изображения вниз от верхнего левого угла поверх-
        ности отображения.  Вы можете отображать прямо в той  точке,  где
        щелкнули "мышью". Это показано на Рис. 2.1.

        +-----------------------------------------------------------+-+-+
        |#=#XXXXXXXXXXXXXXXXXXXXStepsXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|^|v|
        +-----------------------------------------------------------+-+-|
        |(3,7)                                                (483,7)   |
        |                                    (385,31)                   |
        |                                                               |
        |          (60,42)                                              |
        |                          (217,52)                             |
        |                                                               |
        |                                 (302,110)      (444,110)      |
        |                                                               |
        |                                                               |
        |                (109,141)                                      |
        |                                                               |
        |    (52,182)                                                   |
        |                            (239,187)       (385,181)          |
        |                                                               |
        |(4,288)                                               (474,220)|
        +---------------------------------------------------------------+

             Рис. 2.1 Отображение текста в точке нажатия кнопки "мыши".

                                 Параметры сообщений
        -----------------------------------------------------------------

             Щелчок левой    кнопкой    "мыши"    генерирует    сообщение
        wm_LButtonDown, который  вы перехватываете с помощью метода реак-
        ции на сообщение WMLButtonDown.

             Параметр Msg метода реакции на сообщение несет информацию  о
        породившем сообщение  событии  (такую  как координаты точки,  где
        пользователь щелкнул кнопкой "мыши").  Msg - это запись TMessage,
        поля которой  содержат  параметр  lParam  типа Longint и параметр
        wParam типа Word.  Идентификаторы lParam и  wParam  соответствуют
        полям в структуре сообщения Windows TMsg.

             TMessage определяют также вариантные поля, содержащие подпо-
        ля lParam и wParam. Например, Msg.lParamLo содержит младшее слово
        lParam, а  Msg.lParamHi - старшее слово.  Чаще всего используются
        поля wParam, lParamLo и lParamHi.

             В случае WMLButtonDown  Msg.lParamLo  содержит  x-координату
        точки нажатия  кнопки "мыши",  а Msg.lParamHi - y-координату этой
        точки. Таким образом,  чтобы переписать WMLButtonDown для отобра-
        жения координат   точки   нажатия   кнопки,  нужно  преобразовать
        Msg.lParamLo и Msg.lParamHi в строки и,  чтобы  они  приняли  вид
        '(25,21)', конкатенировать их с запятой. В примере для форматиро-
        вания строки используется функция Windows WVSPrintF.

                   Примечание: Слияние параметров зависит  от  сообщения.
              Подробности  о  каждом  сообщении и его параметре вы можете
              узнать, воспользовавшись оперативным справочником Help.

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

             procedure TStepWindow.WMLButtonDown(var Msg: TMessage);

             var S: array[09] of Char;
             begin
               WVSPrint(S, '(%d,%d)', Msg.LParam);
               DragDC := GetDC(HWindow);
               TextOut(DragDc, Msg.LParamLo, Msg.LParamHi, S, StrLen(S));
               ReleaseDC(HWindow, DragDC);
             end;

                   Примечание: Windows ожидает получения строк с заверша-
              ющим нулем (конечным нулевым байтом).  Подробнее эти строки
              описываются в Главе 18 "Руководства по языку".

                                     Очистка окна
        -----------------------------------------------------------------

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

             Чтобы очистить окно в ответ на щелчок правой кнопкой "мыши",
        переопределите метод WMRButtonDown и  вызовите  в  нем  процедуру
        InvalidateRect, которая  приводит  к повторному отображению всего
        окна. Так как ваша программа пока не знает,  как повторно вывести
        изображение, она просто очистит область клиента:

             Procedure TStepWindow.WMRButtonDown(var Msg: TMessage);
             begin
                InvelidateRect(HWindow, nil, Trut);
             end;

             Текущий исходный код вы можете найти в файле STEP02.PAS.


------------------------------------------------------------------------
                           Шаг 3: Изображение линий в окне
        -----------------------------------------------------------------

                              +-----------------------+
                              | Step 1: Basic App     |
                              | Step 2: Tex           |
                              |XStepX3:XLinesXXXXXXXXX|
                              | Step 4: Menu          |
                              | Step 5: About Box     |
                              | Step 6: Pens          |
                              | Step 7: Painting      |
                              | Step 8: Streams       |
                              | Step 9: Printing      |
                              | Step 10: Palette      |
                              | Step 11: BWCC         |
                              | Step 12: Custom ctrls |
                              +-----------------------+

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

             На шаге 3 мы добавим следующее поведение:

             * Щелчок левой кнопкой "мыши" и буксировка соединяют началь-
               ную и конечную точки отображая в результате линию.

             * Щелчок  правой кнопкой "мыши" выводит диалоговое окно вво-
               да, позволяющее пользователю изменить толщину линии.

             Чтобы выполнить эти шаги,  изучим сначала  схему  буксировки
        Windows, а затем реализуем простую графическую программу.


                                   Буксировка линии
        -----------------------------------------------------------------

             Мы уже видели,  что щелчок левой кнопкой "мыши" дает  в  ре-
        зультате сообщение wm_LButtonDown и вызывает метод WMLButtonDown.
        В шаге 1 ваша программа отвечала на щелчки левой кнопкой  "мыши",
        выводя окна сообщений.  Вы могли также видеть,  что щелчок правой
        кнопкой "мыши" давал в результате сообщение wm_RButtonDown и  вы-
        зывал метод WMRButtonDown.  На нажатие правой кнопки "мыши" прог-
        рамма отвечала очисткой окна.

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

                                Сообщения wm_MouseMove 
        -----------------------------------------------------------------

             Сделать это  можно путем реакции еще на несколько сообщений.
        Когда пользователь буксирует "мышь" в новую точку  окна,  Windows
        посылает сообщение  wm_MouseMove,  а когда пользователь отпускает
        левую кнопку "мыши" - сообщение wm_LButtonUp. Обычно окно получа-
        ет одно  сообщение wm_LButtonDown,  за которым следует последова-
        тельность сообщений wm_MouseMove (по одному на каждую промежуточ-
        ную точку буксировки) и одно сообщение wm_LButtonUp.

             Типичная графическая  программа Windows реагирует на сообще-
        ние wm_LButtonDown  инициализацией процесса  рисования  (получая,
        кроме всего прочего, контекст дисплея). На сообщение wm_LButtonUp
        она реагирует завершением процесса рисования (освобождая контекст
        дисплея).


                           Реакция на сообщения буксировки
        -----------------------------------------------------------------

             Нужно помнить о том, что после wm_LButtonDown всегда следует
        сообщение wm_LButtonUp      (с     промежуточными     сообщениями
        wm_MouseMove или без них).  Таким образом,  каждый раз,  когда вы
        получаете контекст дисплея, вы можете позднее освободить его.

             Для правильного  функционирования  программы  Windows  очень
        важным является освобождение каждого получаемого  вами  контекста
        дисплея. Однако вы можете добавить еще одно более надежное средс-
        тво. Определите в TStepWindow новое булевское поле - тип основно-
        го окна  с  именем  ButtonDown  и  обеспечьте его инициализацию в
        TStepWindow.Unit значением False. Затем вы можете проверять перед
        получением и освобождением контекста дисплея значение ButtonDown.

             Приведем три метода обработки буксировки "мыши":

             procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
             begin
                InvalidateRect(HWindow, nil, True);
                if not ButtonDown then
                begin
                   ButtonDown := True;
                   SetCapture(HWindow);
                   DragDC := GetDC(HWindow);
                   MoveTo(DragDC, Msg.lParamLo, Msg.lParamHi);
                end;
             end;

             procedure TStepWindow.WMMouseMove(var Msg: TMessage);
             begin
                if ButtonDown then
                      LineTo(DragDC, Msg.lParamLo, MsglParamHi);
             end;

             procedure TStepWindow.WMLButtonUp(var Msg: TMessage);
             begin
               if ButtonDown then
               begin
                  ButtonDown := False;
                  ReleaseCapture;
                  ReleaseDC(HWindow, DragDC);
               end;
             end;


                              Изображение точек и линий
        -----------------------------------------------------------------

             В API  Windows  имеются графические функции MoveTo и LineTo,
        которые, соответственно,  перемещают текущую позицию рисования  и
        рисуют линию  до  текущей позиции.  Для правильной работы функций
        требуется указание описателя контекста дисплея DragDC. Нужно пом-
        нить о  том,  что  вы рисуете не непосредственно в окне,  а в его
        контексте дисплея.

                                   Перехват "мыши"
        -----------------------------------------------------------------

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

             Нужно изменить  определение  объекта для TStepWindow с заго-
        ловками метода для WMMouseMove и WMLButtonUp:

             procedure WMLButtonUp(var Msg: TMessage); virtual wm_First +
                         wm_LButtonUp;
             procedure WMLMouseMove(var Msg: TMessage); virtual wm_First +
                         wm_LMouseMove;

             Пример полученного   исходного   кода  вы  найдете  в  файле
        STEP03A.PAS.


                                Изменение размера пера
        -----------------------------------------------------------------

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

             Для реализации  механизма  выбора пользователем размера пера
        мы используем диалоговое окно (типа TInputDialog). Это окно вида:

        +-----------------------------------------------------------+-+-+
        |#=#XXXXXXXXXXXXXXXXXXXXStepsXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|^|v|
        +-----------------------------------------------------------+-+-|
        |                                                               |
        |      Введите новую толщину линии:                             |
        |      +----------------------------------------------+         |
        |      |@1@                                           |         |
        |      +----------------------------------------------+         |
        |              +-----------+      +-----------+                 |
        |              |####OK#####|      |##Cancel###|                 |
        |              +-----------+      +-----------+                 |
        |                                                               |
        +---------------------------------------------------------------+

             Рис. 2.2 Задание новой толщины линии с  помощью  диалогового
        окна ввода.

                              Отслеживание размера пера
        -----------------------------------------------------------------

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

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

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

                   Примечание: В шаге 6 мы создадим объект, инкапсулирую-
              щий одно инструментальное средство - перо.

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

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

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

                            Получение пера нового размера
        -----------------------------------------------------------------

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

             program Steps;

             uses Strings, WinTypes, WinProcs, OWindow, OStdDlgs;
               .
               .
               .

                        Выполнение диалогового окна ввода

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

             Щелчок правой  кнопкой "мыши" дает удобный способ вывода па-
        раметра для изменения толщины пера.  Давайте переопределим  метод
        WMRButtonDown для вывода нового диалогового окна ввода.

             Так как  диалоговое окно ввода появляется только на короткое
        время, а вся обработка выполняется одним методом, вам нет необхо-
        димости определять его как поле TStepWindows. Оно может существо-
        вать в виде локальной переменной метода WMRButtonDown.  Все пост-
        роение и  отмену  объекта  диалогового окна вы можете выполнять в
        рамках метода WMRButtonDowm.

             Когда Init построит объект диалогового окна ввода, вы можете
        выполнить его как режимное диалоговое  окно,  вызвав  ExecDialog.
        ExecDialog  проверяет  успешность  выполнения конструктора Init и
        создает объект диалогового окна, соответствующий элементу экрана,
        выполняя затем диалоговое окно. Обработка для ExecDialog заверша-
        ется только после того как пользователь  закрыл  диалог,  щелкнув
        "мышью"  на командной кнопке OK (Подтверждение) или Cancel (Отме-
        на).

             Если пользователь щелкнул "мышью" на  командной  кнопке  OK,
        InputText заполняется полученным от пользователя текстом, вызывая
        метод GetText из TInputDialog. Так как вы запрашиваете номер тол-
        щины,  возвращаемый  текст нужно преобразовать в число и передать
        его в вызове SetPenSize. Таким образом, каждый раз, когда пользо-
        ватель выбирает новую толщину линии, старое перо удаляется и соз-
        дается новое.

             procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
             var
                InputText: array[09] of Char;
                NewSize, ErrorPos: Integer;
             begin
                if not ButtonDown then
                begin
                   Str(PenSize, InputText);
                   if Application^.ExecDialog(New(PInputDialog,
                       Init(@Self, 'Толщина линии',
                       'Введите новую толщину:', InputText,
                       SizeOf(InputText))) = id_Ok then
                begin
                   Val(InputText, NewSize, ErrorPos);
                   if ErrorPos = 0 then SetPenSize(NewSize);
                end;
             end;
             end.

                            Добавление полей объекта

             Далее добавим в TStepWindow новое поле для хранения описате-
        ля пера,  которое вы будете использовать для рисования графики. В
        данной программе в каждый момент времени вы можете рисовать и вы-
        водить на экран линии только одной толщины.  Соответствующее этой
        толщине  перо  хранится в новом поле TStepWindow с именем ThePen.
        Вы напишете также метод SetPenSize, создающий новое перо и удаля-
        ющий  старое.  Теперь описание объекта TStepWindow должно принять
        следующий вид:

             type
               PStepWindow = ^TStepWindow;
               TStepWindow = object(TWindow)
                 DragDC: HDC;
                 ButtonDown, HasChanged: Boolean;
                 ThePen: HPen;
                 PenSize: Integer;
                 constructor Init(AParent: PWindowsObject;
                                   ATitle: PChar);
                 destructor Done; virtual;
                 function CanClopse: Boolean: virtual;
                 procedure WMLButtonDown(var Msg: TMessage); virtual
                             wm_First + wm_LButtonDown;
                 procedure WMLButtonUp(var Msg: TMessage); virtual
                             wm_First + wm_LButtonUp;
                 procedure WMMouseMove(var Msg: TMessage); virtual
                             wm_First + wm_LMouseMove;
                 procedure WMRButtonDown(var Msg: TMessage); virtual
                             wm_First + wm_RButtonDown;
                 procedure SetPenSize(NewSize: Integer); virtual;
             end;

                               Инициализация полей

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

             constructor TStepWindow.Init(AParent: PWindowsObject;
                           ATitle: PChar);
             begin
                Inherited Init(AParent, ATitle);
                ButtonDown := False;
                HasChanged := False;
                PenSize := 1;
                ThePen := CreatePen(ps_Solid, Pensize, 0);
             end;

             destructor TStepWindow.Done;
             begin
               DeleteObject(ThePen);
               inherited Done;
             end;

                                Изображение линий

             Теперь изменим  метод WMLButtonDown для выбора текущего пера
        (ThePen) во вновь полученном контексте дисплея. Аналогично MoveTo
        и MessageBox, SelectObject является функцией API Windows.

             procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
             begin
                if not ButtonDown then
                begin
                    ButtonDown := True;
                    SetCapture"(HWindow);
                    DragDC := GetDC(HWindow);
                    SelectObject(DragDC, ThePen);
                    MoveTo(DragDC, Msg.lParamLo, Msg.lParamHi);
                end;
             end;

             Указанные методы  выбирают в контексте дисплея уже созданное
        перо. Однако для создания пера нужно написать следующий  вызывае-
        мый WMRButtonDown метод SetPenSize:

             procedure TStepWindow.SetPenSize(NewSize: Integer);
             begin
                DeleteObject(ThePen);
                ThePen := Create(ps_Solid, NewSize, 0);
                PenSize := NewSize;
             end;

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

             На шаге 5 и 6 вы создадите  собственное  диалоговое  окно  и
        объект пера  и используете их для более эффективного графического
        отображения.
                              Назад | Содержание | Вперед