Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

Глава 4. Работа с диалоговым блоком

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

             В данной главе описаны следующие шаги:

             * Определение объекта пера.

             * Создание сложного диалогового блока.

             * Добавление управляющих объектов.

             * Создание буфера передачи.

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

             * Чтение результатов.

                           Шаг 6: Изменение атрибутов пера
        -----------------------------------------------------------------

                            +-----------------------+
                            | Step 1: Basic App     |
                            | Step 2: Text          |
                            | Step 3: Lines         |
                            | Step 4: Menu          |
                            | Step 5: About Box     |
                            |XStepX6:XPensXXXXXXXXXX|
                            | Step 7: Painting      |
                            | Step 8: Streams       |
                            | Step 9: Printing      |
                            | Step 10: Palette      |
                            | Step 11: BWCC         |
                            | Step 12: Custom ctrls |
                            +-----------------------+

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

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

                                Создание объекта пера
        -----------------------------------------------------------------

             Хотя Windows  ссылается на свои изобразительные средства как
        на "объекты" (отсюда и имена типа SelectObject  и  DeleteObject),
        они не  являются  объектами  в  истинном объектно-ориентированном
        смысле, так как не используют наследование и полиморфизм. Перо на
        самом деле представляет собой просто группу из трех характеристик
        отображения, на которые Windows ссылается при изображении  линии.
        Эти характеристики  являются просто свойствами контекста дисплея,
        но полезно рассматривать их, как встроенные в перо.

                               Характеристики пера

             Три характеристики пера - это его стиль,  размер и  цвет.  В
        шаге 3  вы изменяли размер пера и отслеживали текущий размер пера
        в поле объекта окна.  Вместо реализации трех отдельных полей  для
        отслеживания характеристик  пера  вы  можете инкапсулировать их в
        единый объект TPen. Описание TPen имеет следующий вид:

             type
               PPen = ^TPen;
               TPen = object(TObject)
                  Width, Style: Integer;
                  Color: Longint;
                  constructor Init(AStyle, AWidth: Integer;
                                   AColor: Longint);
                  constructor Load(var S: TStream);
                  procedure ChangePen;
                  procedure Delete;
                  procedure Select(ADC: HDC);
                  procedure SetAttributes(AStyle, AWidth: Integer;
                                   AColor: Longint);
                  procedure Store(var S: TStream);
             private
                PenHandle, OldPen: HPen;
                TheDC: HDC;
                PenData: TPenData;
             end;

                   Примечание: Большую часть  исходного  кода  из  данной
              главы  вы  можете найти в файле PEN.PAS.  Для использования
              модуля Pen в STEP06A.PAS и STEP06B.PAS нужно  внести  мини-
              мальные изменения.

                   Примечание: Тип TPen определен в модуле Pen.

             Конструктор Init создает новый объект пера с  заданным  сти-
        лем, размером и цветом.  SetAttributes изменяет атрибуты уже соз-
        данного объекта пера. ChangePen выводит диалоговое окно, позволя-
        ющее пользователю  задать  атрибуты пера.  Load и Store позволяют
        сохранять объекты пера в потоке.

                         Выбор и удаление объектов пера

             Наиболее интересную  работу  выполняют  процедуры  Select  и
        Delete. Select создает изобразительное средство Windows на основе
        характеристик, записанных в полях атрибутов.  Вместо того,  чтобы
        вызывать в графической программе для создания пера, получения его
        описателя, выбора пера в контексте дисплея,  использования пера и
        его удаления функцию API Windows, вы строите объект пера, а затем
        можете его использовать, выделять и удалять.

             Метод Delete отменяет описатель пера,  освобождая ресурс для
        Windows.  Select проверяет, имеется ли уже выделенное перо, и пе-
        ред  созданием  и выбором нового отменяет существующее перо.  Это
        полезно использовать,  если это же перо предполагается  применять
        повторно,  так что вам не понадобиться вызывать Delete при каждом
        использовании пера.  С другой стороны,  в шаге 7 вы увидите,  как
        можно  сохранять  нарисованные линии,  и каждая линия будет иметь
        свой собственный объект пера.  Если бы каждый объект пера  созда-
        вался и сохранялся в пере Windows, Windows скоро исчерпала бы ре-
        сурсы. Поэтому важно непосредственно после использования пера вы-
        зывать для его отмены метод Delete.

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

             Файл STEP06A.PAS  содержит код программы Steps,  модифициро-
        ванный для использования объекта TPen в модуле  Pen.  В  основном
        изменения невелики (например,  поле ThePen изменяет тип с HPen на
        PPen, а    метод    SetPenSize    заменяется    вызовом    метода
        SetPenAttributes объекта пера, поскольку объект пера может управ-
        лять цветом и стилем наряду с размером).


                         Создание сложного диалогового блока
        -----------------------------------------------------------------

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

             В модуле Pen определяется более сложный  ресурс  диалогового
        блока  с именем 'PenDlg',  который дает вам возможность изменения
        атрибутов только что определенного объекта пера.  Этот диалоговый
        блок показан на Рис. 4.1.

              +---------------------------------------------------+
              |#=#XXXXXXXXXXSet Pen AttributesXXXXXXXXXXXXXXXXXXXX|
              +---------------------------------------------------|
              |   +-Color----------+ +-Style-----------+          |
              |   | (*) Black      | | (*) Solid       |          |
              |   | ( ) Purple     | | ( ) Dash        |          |
              |   | ( ) Blue       | | ( ) Dot         |          |
              |   | ( ) Cyan       | | ( ) DashDot     |          |
              |   | ( ) Green      | | ( ) DasDotDot   |          |
              |   | ( ) Yellow     | | ( ) Null        |          |
              |   | ( ) Red        | +-----------------|          |
              |   | ( ) White      | | Width: #1#      |          |
              |   +----------------+ +-----------------+          |
              +---------------------------------------------------|
              |                                                   |
              |                     +------------+ +------------+ |
              |                     |####OK######| |##Cancel####| |
              |                     +------------+ +------------+ |
              |                                                   |
              +---------------------------------------------------+

             Рис. 4.1 Диалоговый блок с изменением атрибутов пера.

             Set Pen Attributes - установка атрибутов пера; Color - цвет;
        Black - черный; Purple - фиолетовый; Blue - голубой; Cyan - бирю-
        зовый; Green - зеленый;  Yellow - желтый;  Red - красный; White -
        белый; Style - стиль;  Solid - непрерывная линия; Dash - пунктир;
        Dot - точки;  DashDot - точки и тире; DasDotDot - тире и две точ-
        ки; Null - пусто;  Width - ширина;  OK - подтверждение;  Cancel -
        отмена.

             Построение объекта из ресурса  'PenDlg'  выполняется  также,
        как это  делается для окна About Box (за исключением порождающего
        окна). Поскольку диалоговый блок  атрибута  пера  выполняется  из
        объекта TPen,  а не из оконного объекта,  вы не можете в качестве
        порождающего окна использовать @Self. Вместо этого TPen присоеди-
        няет диалоговый блок к одному из окон,  о присутствии которых из-
        вестно заранее - основному окну приложения:

             procedure TPent.ChangePen;
             var PenDlg: PPenDialog;
             begin
               .
               .
               .
               PenDlg := New(PPenDialog, Init(Application^.MainWindow,
                             'PenDlg'));
                  .
                  .
                  .
             end;

             Другим важным отличием является то, что на этот раз вы имее-
        те новый производный объектный тип TPenDialog. Так как окно About
        box не использует ничего, кроме назначенного по умолчанию поведе-
        ния диалогового окна, инкапсулированного в TDialog, вам не требу-
        ется создавать для него новый объектный тип.  Однако диалог атри-
        бутов пера отличается более сложным поведением и требует настрой-
        ки объекта.

             Приведем определение TPenDialog из модуля Pen:

             type
               PPenDialog = ^TPenDialog;
               TPenDialog = object(TDialog);
                  constructor Init(AParent: PWindowsObject; AName;
                                   PChar);
             end;

             constructor TPenDialog.Init(AParent: PWindowsObject;
                                   AName: PChar;
             var
               AControl: PRadioButton;
               i: Integer;
             begin
               inherited Init(AParent, AName);
               AControl := New(PRadioButton, InitResource(@Self,
                               1100 + i));
               for i := 0 to 5 do
               AControl := New(PRadioButton, InitResource(@Self,
                               1200 + i));
             end;

             Построенные в TPenDialog управляющие  объекты  поясняются  в
        следующем разделе.

                                 Управляющие объекты
        -----------------------------------------------------------------

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

                         Использование интерфейсных объектов
        -----------------------------------------------------------------

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

                   Примечание: Интерфейсные объекты описываются  в  Главе
              9,  а управляющие объекты описываются, в частности, в Главе
              12.

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

             Связь объекта  с созданными из ресурса управляющим элементом
        достаточно проста:  внутри конструктора объекта диалогового блока
        вы строите объекты для любых управляющих элементов,  которыми хо-
        тите манипулировать.  Однако вместо использования для  построения
        управляющих объектов конструктора Init применяется InitResource.


                               Конструктор InitResource
        -----------------------------------------------------------------

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

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

             Как показано в приведенном выше примере,  диалог пера модуля
        Pen связывает объекты с их управляющими элементами редактирования
        (для задания размера пера) и обоими наборами кнопок  с  зависимой
        фиксацией (для задания цвета и стиля).

             Заметим, что все управляющие объекты строятся и присваивают-
        ся одной и той же локальной переменной AControl.  Вашей программе
        не придется взаимодействовать ни с одним из этих управляющих эле-
        ментов непосредственно,  так как пока выполняется режимный диало-
        говый блок,  остальная  часть программы не активна.  InitResource
        к списку дочерних окон диалогового блока, чтобы обеспечить очист-
        ку и уничтожение элементов экрана вместе с диалоговым окном.

             В общем  случае нет необходимости присваивать дочерним окнам
        в режимных диалоговых блоках поля объекта.  Однако в шаге  11  вы
        увидите,  как  можно  сохранять указатели на управляющие элементы
        объектов безрежимного окна, что облегчает работу с ними.

                               Создание буфера передачи
        -----------------------------------------------------------------

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

             Например, диалоговый блок,  созданный в шаге 6,  имеет  поле
        редактирования и четырнадцать кнопок с зависимой фиксацией. В уп-
        равляющий элемент редактирования требуется передавать  строку,  а
        каждая кнопка с зависимой фиксацией получает значение Word,  ука-
        зывающее на его выбор.  Модуль Pen определяет тип записи, переда-
        ваемый TPenDialogs и из него:

             type
               TPenData = record
                 XWidth: array[06] of Char;
                 ColorArray: arra[07] of Word;
                 StyleArray: array[05] of Word;
             end;

             Вы можете также управлять кнопками с независимой  фиксацией,
        используя 14  отдельных полей или один массив из 14 значений типа
        Word; передаваемые данные будут теми же.  Однако,  так  как  ваша
        прикладная программа  будет интерпретировать их как две группы из
        8 и 6 кнопок соответственно,  удобно задать поле для каждой груп-
        пы.

                               Присваивание буфера

             Каждый потомок  TWindowsObject  имеет  поле  TransferBuffer.
        Когда вы хотите передать данные в диалоговое  окно,  нужно задать
        объект TransferBuffer  диалогового  блока,  указывающий на запись
        передачи:

             PenDlg := New(PPenDialog, Init(Application^.MainWindow,
                                            'PenDlg'));
             PenDlg^.TransferBuffer := @PenData;

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

                                Заполнение буфера

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

             procedure TPen.ChangePen;
             var
               PenDlg: PPenDialog;
               TempWidth, ErrorPos: Integer;
             begin
               SetColorAttr(PenDate, Color);
               SetStyle(PenDate, Style);
               wvsprintf(PenDialog, Init(Application^.MainWindows,
                         'PenDlg'));
               PenDlg^.TransferBuffer := @PenData;
               if Application^.ExecDialog(PenDlg) <> id_Cancel then
               begin
                  Val(PenData.XWidth, TempWidth, ErrorPos);
                  if ErrorPos = 0 then
                      SetAttributes(SetStyle(PenData), TempWidth,
                           GetColorAttr(PenData));
               end;
             end;

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

             procedure SetStyle(var ARec: TPenData; AStyle: Integer);
             var i: Integer;
             begin
               for i := 0 to 5 do
                   if = AStyle then ARec.StyleArray[i] := bf_Checked
                   else ARec.StyleArray[i] := bf_Unchecked;
             end;

                   Примечание: SetColorAttr выполняет то  же  назначение,
              что и ColorArray. bf_Checked и bf_Unchecled - это константы
              ObjectWindows.

                          Передача данных
        -----------------------------------------------------------------

             После того  как  вы создадите буфер передачи и заполняет его
        значениями, получение  этой  информации  в  диалоговом  блоке  не
        представляет  труда,  поскольку  все за вас делает ObjectWindows.
        Когда для выполнения диалогового блока вызывается  ExecDialog, он
        вызывает TransferDatа для копирования значений из буфера передачи
        в отдельные объекты управляющих элементов.

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

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

                             Чтение возвращаемых значений
        -----------------------------------------------------------------

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

             function GetStyle(ARec: TPenDate): Longint;
             var i: Integer;
             begin
               for i := 0 to 5 do
                  if ARec.StyleArray[i] = bf_Cheched then GetStyle := i;
             end;

             Если пользователь отменяет диалоговый блок, то вас, конечно,
        не должно беспокоить считывание значений:  они совпадают с  пере-
        данными значениями.  Обычно когда вы выполняете диалоговый блок с
        помощью ExecDialog,  то чтобы определить, возвратил ли диалоговый
        блок какие-либо полезные данные,  проверяется возвращаемое значе-
        ние (id_Ok, если пользователь щелкнул "мышью" на командной кнопке
        OK, в противном случае id_Cancel).

             if Application^.ExecDialog(PenDlg) <> id_Cancel then
             begin
               Val(PenDate.XWith, TempWith, ErrorPos);
               SetAttributes(GetStyle(PenData), TempWidth,
                             GetColorAttr(PenData));
             end;

                             Вызов диалогового блока пера 
        -----------------------------------------------------------------

             Чтобы вывести  диалоговый  блок  пера,  вызовите  его  метод
        ChangePen.  Программа STEP06B.PAS делает это в ответ  на  команду
        cm_Pen,  генерируемую  выбором  пункта меню Options|Pen и щелчком
        правой кнопкой "мыши".

             procedure TStepWindow.CMPen(var Msg: TMessage);
             begin
               CurrentPen^.ChangePen;           { CurrentPen - это объект
                                                  блока пера }
             end;

             procedure TStepWindow.WMRButtonDown(var Msg: TMessage);
             begin
               if not ButtonDown then CurrentPen^.ChangePen;
             end;

                   Примечание: Данные   методы   можно   найти   в  файле
              STEP06B.PAS.
                              Назад | Содержание | Вперед
VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...