Что такое объекты управляющих элементов?
-----------------------------------------------------------------
Для Windows управляющие элементы - это просто специализиро- ванные виды окон. В ObjectWindows тип TControl является потомком типа TWindow, так что большинство объектов управляющих элементов можно использовать как все другие оконные объекты. Объекты управ- ляющих элементов по способу их создания и уничтожения и способу их поведения (как дочерние окна) аналогичны оконным объектам. Од- нако они отличаются от других окон способом реакции на сообщения. Например, методы Paint объектов управляющих элементов запрещены. Windows берет на себя функции по отображению своих стандартных управляющих элементов.
Может оказаться, что перечисленные в приведенной выше табли- це управляющие элементы отвечают всем потребностям вашего прило- жения. Однако могут возникать случаи, когда требуется определить наследующие типы управляющих элементов. Например, вы можете соз- дать специализированный блок списка TFontListBox, производный от TListBox, содержащий имена всех доступных вашему приложению шриф- тов и автоматически выводящих их при создании нового экземпляра объекта.
Тип TControl, как и TWindowsObject, является абстрактным объектным типом. Вы можете создать экземпляры его потомков - TListBox, TButton и другие - но не можете создать экземпляр TControl.
Заметим, что вам, возможно, никогда не потребуется создавать новый объектный тип, наследующий непосредственно из TControl. TControl инкапсулирует свойства и стандартные управляющие элемен- ты, о которых уже знает Windows. Создание специализированных уп- равляющих элементов описывается в данной главе ниже.
Действие, аналогичное диалоговому блоку
-----------------------------------------------------------------
Диалоговый блок с управляющими элементами позволяет пользо- вателю с помощью клавиши Tab циклически перемещаться по всем эле- ментам диалогового блока. Он может также использовать клавиши стрелок для выбора в групповом блоке кнопок с зависимой фиксаци- ей. Чтобы эмулировать этот клавиатурный интерфейс для окон с уп- равляющими элементами, вызовите для оконного объекта в его конс- трукторе метод EnableKBHandler объекта TWindowsObject.
Для чего используется буфер передачи?
-----------------------------------------------------------------
В качестве альтернативы вы можете не определять производный объект, а определить соответствующую запись, представляющую сос- тояние управляющих элементов окна или диалога. Эта запись называ- ется буфером передачи, поскольку легко передает информацию о сос- тоянии между буфером и набором управляющих элементов.
Например, ваша программа может иметь режимный блок диалога и после его закрытия, выделить информацию из буфера передачи от- носительно состояния каждого из его управляющих элементов. Следо- вательно, при повторном вызове пользователем блока диалога, его управляющие элементы будут выведены в соответствии с их состояни- ем перед последним закрытием диалога. Кроме того, вы можете уста- новить начальное состояние каждого из управляющих элементов и на основании данных буфера передачи. Вы можете явно передавать дан- ные в любом направлении в любой момент времени, например, устано- вить значения управлений равными их предыдущим значениям. Окно или безрежимный блок диалога с управляющими элементами также мо- гут использовать механизм передачи для установки или выяснения информации о состоянии в любой момент времени.
Механизм передачи требует для представления управляющих элементов, для которых вы будете передавать данные, использования объектов ObjectWindows. Это означает, что вы должны использовать InitResource для связывания объектов с управляющими элементами в блоках и окнах диалога.
Примечания: Связь управляющих элементов с управляющими объектами описывается в Главе 11 "Объекты диалоговых бло- ков".
Чтобы использовать механизм передачи, вы можете сделать сле- дующее:
* Определить буфер передачи. * Определить соответствующее окно. * Передать данные.
Где можно использовать объекты управляющих элементов?
-----------------------------------------------------------------
Управляющие элементы - это специализированные окна, которые позволяют пользователю предопределенным образом задавать или вы- бирать данные. Чаще всего управляющие элементы содержатся в диа- логовом блоке. Диалоговый блок управляет их определением с по- мощью ресурса диалогового блока, так что вам не потребуется часто использовать в них объекты. Режимные диалоговые блоки не распола- гают способами взаимодействия с управляющим объектом, поэтому в диалоговых блоках объекты управляющих элементов используются обычно для установки и считывания значений управляющих элементов с помощью передачи. Передача для объектов управляющих элементов в диалоговых блоках и в окнах выполняется одинаково (как описывает- ся ниже в этой главе).
Примечание: Диалоговые блоки и их управляющие элементы описываются в Главе 11 "Объекты диалоговых блоков".
Возможно вы захотите использовать управляющие элементы в ок- нах, поэтому в данной главе описывается использование управляющих элементов вне диалоговых блоков. Следующая таблица описывает уп- равляющие элементы Windows, поддерживаемые типами объектов ObjectWindows:
Управляющие элементы Windows, поддерживаемые в ObjectWindows Таблица 12.1 +---------------+------------+----------------------------------+ | Управляющий | Тип объекта| Использование | | элемент | | | +---------------+------------+----------------------------------| | блок списка |TListBox |Прокручиваемый список элементов,| | | |из которых можно сделать выбор. | +---------------+------------+----------------------------------| | полоса |TScrollBar |Полоса прокрутки, аналогичная| | прокрутки | |тем, которые выводятся в прокру-| | | |чиваемых окнах и блоках списка. | +---------------+------------+----------------------------------| | "нажимаемая" |TButton |Кнопка для "нажатия" со связанным| | кнопка | |с ней текстом. | +---------------+------------+----------------------------------| | кнопка с |TCheckBox |Состоящая из блока кнопка, которая| | независимой | |может выбираться или нет, со свя-| | фиксацией | |занным текстом. | +---------------+------------+----------------------------------| | кнопка с |TRadioButton|Кнопка, которая может выбираться| | зависимой | |или нет. Обычно используется| | фиксацией | |во взаимоисключающих группах. | +---------------+------------+----------------------------------| | блок группы |TGroupBox |Статический прямоугольник с текс-| | | |том в левом верхнем углу. | +---------------+------------+----------------------------------| | управляющий |TEdit |Поле для ввода текста пользовате-| | элемент | |лем. | | редактирования| | | +---------------+------------+----------------------------------| | статический |TStatic |Фрагмент отображаемого текста | | управляющий | |который не может быть изменен | | элемент | |пользователем. | +---------------+------------+----------------------------------| | Комбиниро- |TComboBox |Комбинация блока списка и управля-| | ванный блок | |ющего элемента редактирования. | +---------------+------------+----------------------------------+
+----------------------------------+ Командная строка: | | +----------------------------------+ ^ + редактируемый упрвляющий элемент
+----------+ +----------+ |###OK#####| |##Cancel##| <- командные кнопки +----------+ +----------+
+---+-----------------------------------------------+---+ | < |########################X######################| > | +---+-----------------------------------------------+---+ ^ полоса прокрутки -+
+--------------+-+ |collect3.pas |^| <- блок списка |collect4.pas +-| |diatest.pas |#| |edittest.pas |X| +----------------+ |ewndtest.pas |#| | *.txt | |helpwind.pas |#| +-+--------------+-+ |lboxtest.pas |#| |netlect3.txt |^| |mditest.pas +-| |netlect4.txt +-| |paltest.pas |v| |diatext.txt |#| +--------------+-+ |readtxt.txt |X| |vwndtext.txt |#| комбинированный блок -> |whelpwnd.txt |#| |wboxtext.txt |#| |ydrtest.txt +-| |xaltesx.txt |v| +--------------+-+
Рис. 12. 1 Стандартные управляющие элементы Windows.
Объекты управляющих элементов
Windows предусматривает ряд стандартных интерфейсных элемен- тов, называемых управляющими элементами. Управляющие элементы - это специальные окна с некоторым предопределенным поведением. ObjectWindows обеспечивает интерфейсные объекты для стандартных управляющих элементов Windows, так что вы можете использовать эти интерфейсные элементы в своих приложениях. Интерфейсные объекты для управляющих элементов называются объектами управляющих эле- ментов или просто управляющими объектами.
Примечание: Об интерфейсных объектах рассказывается в Главе 9.
Данная глава охватывает следующие темы:
* Задачи, общие для всех управляющих объектов:
- построение и уничтожение объектов управляющих элементов;
- взаимодействие с другими управляющими объектами.
* Установка и чтение значений управляющих элементов.
* Использование специализированных управляющих элементов.
Кроме того, в данной главе подробно описывается использова- ние каждого интерфейсного объекта для стандартных управляющих элементов Windows.
Группирование управляющих элементов
-----------------------------------------------------------------
Поскольку блок группы визуально связывает группу других уп- равляющих элементов, он может логически связывать группу блоков выбора (кнопок с зависимой и независимой фиксацией). Логическая группа автоматически отменяет выбор характеристик блоков выбора "автоматического" стиля.
Для добавления в группу, нужно при конструировании блока вы- бора указать указатель на блок группы. Например, чтобы добавить в окно группу кнопок с независимой фиксацией, в оконный объект и его конструктор можно включить следующее:
type TSomeWindow = object(TWindow) Group: PGroupBox; FirstCheck, SecondCheck: PCheckBox: constructor Init(AParent: PWindowsObject, ATitle: PChar); end;
constructor TSomeWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin inherited Init(AParent, ATitle); Group := New(PCheckBox, Init(@Self, id_TheGroup, 'Various boxes', 10, 01, 100, 50)); FirstCheck := New(PCheckBox, Init(@Self, id_FirstCheck, 'One', 15, 20, 90, 10, Group)); SecondCheck := New(PCheckBox, Init(@Self, id_SecondCheck, 'Two', 15, 20, 90, 10, Group)); end;
Заметим, что передаваемый блоку выбора параметр группы - это указатель на объект блока группы, а не идентификатор группового управляющего элемента (как в API Windows). Использование указате- ля позволяет вам строить объекты перед созданием методом SetupWindows порождающего окна экранных элементов.
Инициализация управляющего элемента
-----------------------------------------------------------------
Экранный элемент управляющего объекта автоматически создает- ся методом SetupWindow, наследуемым объектом порождающего окна. Убедитесь, что при создании новых производных типов окон вы вызы- ваете наследуемый метод SetupWindow перед любой другой инициали- зацией окна.
При необходимости методом SetupWindow порождающего окна так- же устанавливаются и заполняются управляющие элементы. Приведем пример типичного метода SetupWindow:
procedure TSampleWindows.SetupWindow; begin inherited SetupWindow; { создает дочерние управляющие элементы } { добавляет элементы в список } TheList^.AddString('Элемент 1'); TheList^.AddString('Элемент 2'); end;
Заметим, что инициализация управляющего элемента, такая как добавление строк в блок списка, должна выполняться в SetupWindow, а не в конструкторе. Вызов такого метода как TListBox.AddString приводит к передаче сообщений экранному управляющему элементу. Так как экранный элемент до вызова наследуемого метода SetupWindow не создается, попытки инициализации управляющих эле- ментов до этого момента завершится неудачно.
Использование блока списка
-----------------------------------------------------------------
Использование блока списка - это простейший способ запросить пользователя программы Windows выбрать что-либо из списка. Блоки списка инкапсулируются объектным типом TListBox. TListBox опреде- ляет методы для создания блоков списка, модификации списка эле- ментов, запроса состояния списка элементов и поиска выбранного пользователем элемента.
Использование блоков выбора
-----------------------------------------------------------------
Тип TCheckBox наследует от TButton, а тип TRadioButton - от TCheckBox. Кнопки с зависимой и независимой фиксацией мы будем иногда кратко называть блоками выбора.
Кнопки с независимой фиксацией обычно используются для пре- доставления пользователю выбора одного из двух возможных вариан- тов. Пользователь может установить или не установить управляющий элемент, или оставить его так, как он установлен. Если имеется группа кнопок с независимой фиксацией, то может устанавливаться не одна кнопка, а несколько. Например, вы можете использовать кнопку с независимой фиксацией для выбора трех шрифтов для их загрузки в приложение.
Кнопки с зависимой фиксацией используются для выбора одного из нескольких взаимоисключающих вариантов. Например, кнопка с за- висимой фиксацией может использоваться для выбора шрифта для конкретного символа. Когда пользователь щелкает "мышью" на кнопке с зависимой фиксацией, это событие приводит к генерации сообщения Windows. Как и в случае других управляющих элементов, порождающее окно кнопки с независимой фиксацией обычно перехватывает эти со- общения и выполняет по ним действия.
Однако, вы можете для выполнения ими некоторых действий при нажатии создать типы, производные от TCheckBox и TRadioButton. Если ваш тип определяет метод для nf_First + bn_Clicked, то он сначала должен вызывать метод реакции BNClicked, а уже затем вы- полнять любые дополнительные действия.
Использование буфера передачи с диалоговым блоком
-----------------------------------------------------------------
Для случая окон с управляющими элементами объекты управляю- щих элементов конструируются с использованием Init. Для диалогов и окон диалогов нужно использовать конструктор InitResource. Нап- ример (используется определенный ранее тип TSampleRecord):
type TSampleTransferRecord = record . . . PParentWindow = ^TParentWindow; TParentWindow = object(TWindow) TheDialog: PDialog; TheBuffer: SampleTransferRecord; . . . . constructor TParentWindow.Init(AParent: PWindowsObject; ATitle: PChar); var Stat1: PStatic; Edit1: PEdit; List1: PListBox; Combo1: PComboBox; Check1: PCheckBox; Radio1: PRadioButton; Scroll1: PScrollBar; begin TWindow.Init(AParent, ATitle); TheDialog^.Init(@Self, PChar(101)); New(Stat1, InitResource(TheDialog, id_Stat1)); New(Edit1, InitResource(TheDialog, id_Edit1)); New(List1, InitResource(TheDialog, id_List1)); New(Combo1, InitResource(TheDialog, id_Combo1)); New(Check1, InitResource(TheDialog, id_Check1)); New(Radio1, InitResource(TheDialog, id_Radio1)); New(Scroll1, InitResource(TheDialog, id_Scroll1)); TheDialog^.TranssferBuffer:=@TheBuffer; end;
Для управляющих элементов, построенных с помощью InitResource, механизм передачи разрешается автоматически.
Использование буфера передачи с окном
-----------------------------------------------------------------
Для случая окна с управляющими элементами используйте для конструирования объектов управления в надлежащей последователь- ности Init, а не InitResource. Другое отличие между диалогами и окнами состоит в том, что механизм передачи по умолчанию для уп- равляющих элементов окна запрещен. Для разрешения использования механизма вызывается EnableTransfer:
constructor TSampleWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin inherited Init(AParent, ATitle); Edit1 := New(PEdit, Init(@Self, id_Edit1, '', 10, 10, 100, 30, 40, False)); Edit1^.EnableTransfer; end;
Чтобы явно исключить управляющий элемент из механизма пере- дачи, вызовите после его создания метод DisableTransfer.
Использование буфера вырезанного изображения и меню Edit
-----------------------------------------------------------------
Вы можете передавать текст непосредственно между объектом управляющего элемента редактирования и буфером вырезанного изоб- ражения Windows, используя для этого вызовы методов. Часто вам бывает нужно предоставить пользователю доступ к этим методам че- рез меню редактирования. Объект управляющего элемента редактиро- вания автоматически отреагирует на выбор из меню таких вариантов, как Edit|Copy и Edit|Undo. TEdit определяет основанные на коман- дах методы (например, CMEditCopy и CMEditUndo), которые вызывают- ся в ответ на конкретный выбор (команду) меню в порождающем окне управляющего элемента редактирования. CMEditCopy вызывает Copy, а CMEditUndo вызывает Undo.
Следующая таблица содержит список методов, которые вызывают- ся в ответ на выбор пункта меню:
Управляющие элементы редактирования и меню Edit Таблица 12.7 +-----------------------+-------------------+-------------------+ | Операция | Метод TEdt | Команда меню | +-----------------------+-------------------+-------------------| | Копирование текста в | Cut | cm_EditCut | | буфер вырезанного | | | | изображения. | | | +-----------------------+-------------------+-------------------| | Вырезание текста в | Copy | cm_EditCopy | | буфер вырезанного | | | | изображения. | | | +-----------------------+-------------------+-------------------| | Вставка текста из | Paste | cm_EditPaste | | буфера вырезанного | | | | изображения. | | | +-----------------------+-------------------+-------------------| | Очистка всего элемента| Clear | cm_EditClear | | редактирования. | | | +-----------------------+-------------------+-------------------| | Удаление выделенного | DeleteSelection | cm_EditDelete | | текста. | | | +-----------------------+-------------------+-------------------| | Отмена последнего | Undo | cm_EditUndo | | редактирования. | | | +-----------------------+-------------------+-------------------+
Чтобы добавить в окно меню редактирования, содержащее управ- ляющий элемент редактирования, определите для окна с помощью ко- манд, перечисленных в Таблице 12.7, ресурс меню. Никаких новых методов вам писать не нужно.
Имеется также один дополнительный метод в виде булевской функции CanUndo, который определяет, можно ли отменить последнюю операцию редактирования.
Использование групповых блоков
-----------------------------------------------------------------
В своей простейшей форме блок группы представляет собой ста- тический прямоугольник с меткой, который обычно объединяет другие управляющие элементы.
Использование командных кнопок
-----------------------------------------------------------------
Управляющие элементы типа командных кнопок (которые иногда называют "нажимаемыми" кнопками) выполняют некоторое действие при "нажатии" такой кнопки. Есть два стиля командных кнопок, и оба они имеют тип TButton. Эти два стиля - bs_PushButton и DefPushButton. Используемые по умолчанию командные кнопки анало- гичны командным другим кнопкам, но имеют жирную рамку и обычно используются для указания реакции пользователя по умолчанию. На Рис. 12.3 показан пример программы Windows, в которой используют- ся обычные кнопки нажатия и командные кнопки по умолчанию.
+---------------------------------+-+ |#=#XXXXXXXXXHex CalculatorXXXXXXX|v| +---------------------------------+-| | +-----------------+ | | | 0 | | | +-----------------+ | | | | +---+ +---+ +---+ +---+ +---+ | | D | E | | F | | + | | & | | | +---+ +---+ +---+ +---+ +---+ | | +---+ +---+ +---+ +---+ +---+ | | | A | | B | | C | | - | | | | | | +---+ +---+ +---+ +---+ +---+ | | +---+ +---+ +---+ +---+ +---+ | | | 7 | | 8 | | 9 | | * | | ^ | | | +---+ +---+ +---+ +---+ +---+ | | +---+ +---+ +---+ +---+ +---+ | | | 4 | | 5 | | 6 | | / | | < | | | +---+ +---+ +---+ +---+ +---+ | | +---+ +---+ +---+ +---+ +---+ | | | 1 | | 2 | | 3 | | % | | > | | | +---+ +---+ +---+ +---+ +---+ | | +---+ +---------+ +----------+ | | | 0 | | Back | | Equals | | | +---+ +---------+ +----------+ | +-----------------------------------+
Рис. 12.3 Программа Windows, использующая командные кнопки.
Использование комбинированных блоков
-----------------------------------------------------------------
Управляющий элемент типа комбинированного блока является со- четанием двух других управляющих элементов: блока списка и управ- ляющего элемента редактирования. Он служит тем же целям, что и блок списка - позволяет пользователю выбрать один элемент списка из прокручиваемого списка элементов текста, нажимая на кнопку "мыши". Управление редактированием, вынесенное в верхнюю часть блока списка предоставляет иной механизм выбора, позволяя пользо- вателю ввести текст нужного элемента. Если отображается область списка комбинированного блока, то автоматически выбирается нужный элемент. Тип TComboBox является производным от типа TListBox и наследует его методы модификации, опроса и выбора элементов спис- ка. Кроме того, TComboBox предоставляет методы по манипулированию списком, находящемся в комбинированном блоке, который в некоторых случаях может раскрываться по запросу.
Использование конкретных управляющих элементов
-----------------------------------------------------------------
Каждый вид управляющих элементов работает в чем-то отлично от других. В данном разделе вы можете найти конкретную информацию о том, как использовать объекты для каждого из стандартных управ- ляющих элементов Windows.
Использование полос прокрутки
-----------------------------------------------------------------
Полосы прокрутки являются важнейшим механизмом изменения об- зора пользователем окна приложения, блока списка или комбиниро- ванного блока. Однако, может возникнуть ситуация, когда нужна от- дельная полоса прокрутки для выполнения некоторой специализиро- ванной задачи (например, управление температурой в программе тер- мостата или цветом в программе рисования). Когда нужна отдельная специализированная полоса прокрутки, используются объекты TScrollBar. Рис. 12.5 показывает типичное использование объекта TSсrollBar.
+-----------------------------------------------------------+-+-+ |#=#XXXXXXXXXXXXXXXXXXXXXXThermostatXXXXXXXXXXXXXXXXXXXXXXXX|^|v| +-----------------------------------------------------------+-+-| | | | 68 градусов | | | | | | | | +--+----------------------------------------------------+--+ | | |<X|#################X##################################|X>| | | +--+----------------------------------------------------+--+ | | | +---------------------------------------------------------------+
Рис. 12.5 Объект полосы прокрутки.
Использование специализированных управляющих элементов
-----------------------------------------------------------------
Windows обеспечивает механизм, позволяющий вам создавать свои собственные виды управляющих элементов, а ObjectWindows об- легчает создание объектов, использующих преимущества управляющих элементов. В данном разделе обсуждается использование специализи- рованных управляющих элементов Borland, которые придают своеоб- разный вид работающим в Windows приложениям Borland, а затем опи- сывается, как создавать свои собственные уникальные управляющие элементы.
Использование стандартных BWCC
-----------------------------------------------------------------
ObjectWindows позволяет легко добавлять BWCC в ваши приложе- ния Windows. Нужно просто добавить модуль BWCC в оператор uses программы:
uses BWCC;
Использование BWCC автоматически позволяет вам делать следу- ющее:
* использовать загружаемые из ресурсов управляющие элементы BWCC;
* создавать в вашей программе BWCC.
Например, с помощью пакета разработчика ресурсов Resource WorkShop вы можете создать ресурсы диалоговых блоков, использую- щие специализированные управляющие элементы Borland. Включение в оператор uses программы модуля BWCC обеспечивает для вашей прог- раммы информацию о том, где искать динамически компонуемую библи- отеку (BWCC.DLL), содержащую код, который обеспечивает работу BWCC.
Кроме того, после добавления модуля BWCC любые создаваемые в программе объекты управляющих элементов будут иметь вид и харак- теристики управляющих элементов Borland.
Использование статических управляющих элементов
-----------------------------------------------------------------
Статические управляющие элементы - это обычно неизменяемые модули текста или простые изображения, которые могут появляться на экране в окне или блоке диалога. Пользователь не взаимодейс- твует со статическими управляющими элементами, хотя программа и может изменять их текст. Рис. 12.2 показывает множество стилей статического управления и соответствующих констант стиля Windows.
+-----------------------------------------------------------+-+-+ |#=#XXXXXXXXXXXXXXXXXStatic Control TesterXXXXXXXXXXXXXXXXXX|^|v| +-----------------------------------------------------------+-+-| | | | Default Static Sample Text | | | | ss_Simple Sample Text | | | | ss_Left Sample Text | | | | ss_Center Sample Text | | | | ss_Right Sample Text | | +------------------------------+ | | ss_BlackFrame | | | | +------------------------------+ | | +------------------------------+ | | ss_BlackRect |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | | +------------------------------+ | | +------------------------------+ | | ss_GrayFrame | | | | +------------------------------+ | | +------------------------------+ | | ss_GrayRect |##############################| | | +------------------------------+ | | | | ss_NoPrefix Sample & Text | | | +---------------------------------------------------------------+
Рис. 12.2 Стили статических управляющих элементов.
Использование управляющих элементов редактирования
-----------------------------------------------------------------
Управляющие элементы редактирования могут быть описаны, как интерактивные статические управляющие элементы. Это прямоугольные области (с рамкой или без) на экране, которые пользователь прило- жения может заполнять текстом, изменять или удалять. Управляющий элемент редактирования наиболее удобен в качестве поля для ввода данных на экране. Они обеспечивают следующие операции:
- Ввод текста пользователем. - Динамическое отображение текста приложением. - Вырезание, копирование и вставка в буфер вырезанного изоб- ражения. - Многострочное редактирование (удобно для текстовых редак- торов).
На Рис. 12.7 показано окно с двумя управляющими элементами редактирования.
+-----------------------------------------------------------+-+-+ |#=#@@@@@@@@@@@@@@@@@Edit Control Tester@@@@@@@@@@@@@@@@@@@@|^|v| +-----------------------------------------------------------+-+-| | | | Оригинал: Копия: | | +----------------------+ +---+ +----------------------+ | | |Default Text | |#>#| |DEFAULT.TEXT | | | +----------------------+ +---+ +----------------------+ | | | | | +---------------------------------------------------------------+
Рис. 12.7 Окно с управляющими элементами редактирования.
Изменение атрибутов объекта управляющего элемента
-----------------------------------------------------------------
Все управляющие объекты, кроме TMDIClient, получает от вызо- ва TControl.Init используемые по умолчанию стили ws_Child и ws_Visible. Если вы хотите изменить стиль управляющего элемента, то можно изменить поле Attr.Style (как это описывается для окон в Главе 10). Каждый тип управляющего элемента имеет также другие стили, определяющие его конкретные характеристики.
Модификация блоков списка
-----------------------------------------------------------------
После создания блока списка вам нужно заполнить его элемен- тами списка, который должны представлять собой строки. Позднее вы можете добавить, вставить или удалить элементы, либо полностью очистить список. Указанные действия вы можете выполнить с помощью методов, приведенный в следующей таблице:
Методы модификации блоков списка Таблица 12.2 +--------------------------------+------------------------------+ | Выполняемое действие | Метод | +--------------------------------+------------------------------| | Добавление элемента | AddString | | Вставка нового элемента | InsertString | | Добавление элемента | InsertString | | Удаление элемента | DeleteString | | Удаление каждого элемента | ClearList | | Выбор элемента | SetSellIndex или SetSelString| +--------------------------------+------------------------------+
Существует пять методов, которые вы можете вызвать для полу- чения информации о списке, содержащейся в объекте блока списка. Эти методы перечислены в следующей таблице:
Методы запроса блока списка Таблица 12.3 +-------------------------------------------+-------------------+ | Получаемая информация | Вызываемый метод | +-------------------------------------------+-------------------| | Число элементов в списке | GetCount | | Элемент с конкретным индексом | GetString | | Длина конкретного элемента | GetStringLen | | Выбранный элемент | GetSelString | | Индекс выбранного элемента | SEgSelIndex | +-------------------------------------------+-------------------+
Модификация блоков выбора
-----------------------------------------------------------------
Модификация (выбор или отмена выбора) блоков выбора выглядит задачей пользователя программы, а не вашей. Но в некоторых случа- ях программе требуется явно управлять состоянием блоков выбора. Одним из таких случаев является вывод на экран параметров, кото- рые были выбраны и сохранены ранее. Для модификации состояния кнопки с независимой фиксацией TCheckBox определяет 4 метода:
Методы модификации кнопок с независимой фиксацией Таблица 12.5 +---------------------------+-----------------------------------+ | Выполняемое действие | Вызов метода | +---------------------------+-----------------------------------| | Выбор кнопки | Check или SetCheck(bf_Chacked) | | Отмена выбора кнопки | Uncheck или SetCheck(bf_Unchecked)| | Переключение кнопки | Toggle | +---------------------------+-----------------------------------+
Когда вы используете данные методы с кнопками с зависимой фиксацией, ObjectWindows обеспечивает выбор в группе только одной кнопки с зависимой фиксацией.
Модификация комбинированных блоков
-----------------------------------------------------------------
TComboBox определяет два метода для демонстрации и сокрытия области списка в раскрывающихся комбинированных блоках и раскры- вающихся комбинированных блоках списка: ShowList и HideList. Обе эти процедуры не нуждаются в аргументах. Вызывать эти методы для демонстрации или сокрытия списка, когда пользователь нажимает стрелку вниз справа от области редактирования, не нужно. В этом случае работает автоматический механизм комбинированных блоков. Эти методы полезны только для принудительного вывода или сокрытия списка.
Модификация полос прокрутки
-----------------------------------------------------------------
Модификация полос прокрутки - это скорее работа для пользо- вателя вашей программы, и часто это действительно так. Однако, ваша программа также может модифицировать полосу прокрутки. Ис- пользуемые для этого методы перечислены в следующей таблице.
Методы модификации полос прокрутки Таблица 12.6 +--------------------------------------+------------------------+ | Выполняемое действие | Вызываемый метод | +--------------------------------------+------------------------| | Задание диапазона прокрутки | SetRange | | Установка позиции маркера | SetPosition | | Перемещение позиции маркера | DeltaPos | +--------------------------------------+------------------------+
SetRange - это процедура, которая воспринимает два целочис- ленных аргумента, наименьшую и наибольшую позицию диапазона. По умолчанию новая полоса прокрутки имеет диапазон от 1 до 100. Вы можете изменить этот диапазон для наилучшего расположения управ- ляющих элементов полос прокрутки. Например, полоса прокрутки в приложении для термостата может иметь диапазон от 32 до 120 гра- дусов Фаренгейта:
ThermScroll^.SetRange(32, 120);
SetPosition - это процедура, которая воспринимает один цело- численый аргумент - позицию, в которую нужно переместить указа- тель полосы прокрутки. В рассмотренном ранее приложении для тер- мостата, ваша программа может непосредственно установить темпера- туру 78 градусов:
ThermScroll^.SetPosition(78);
Третий метод DeltaPos передвигает позицию указателя полосы прокрутки вверх (налево) или вниз (направо) на величину, заданную целым аргументом. Положительная целая величина перемещает указа- тель вниз (направо). Отрицательная целая величина перемещает его вверх (налево). Например, для уменьшения температуры термостата на 5 градусов используется:
ThermScroll^.DeltaPos(-5);
Модификация управляющих элементов редактирования
-----------------------------------------------------------------
Для традиционной программы ввода текста вам может не потре- боваться непосредственно модифицировать управляющий элемент ре- дактирования. Пользователь модифицирует текст, а программа считы- вает этот текст методом опроса. Однако, во многих других случаях использование управляющего элемента редактирования требует, чтобы ваше приложение явно заменяло, вставляло, удаляло и выбирало текст. ObjectWindows обеспечивает подобное поведение и кроме того предоставляет возможность использовать прокрутку управляющего элемента редактирования.
Методы модификации управляющих элементов редактирования Таблица 12.9 +----------------------------------------+----------------------+ | Выполняемое действие | Вызываемый метод | +----------------------------------------+----------------------| | Удаление всего текста | Clear | | Удаление выделенного текста | DeleteSelection | | Удаление диапазона символов | DeleteSubText | | Удаление строки текста | DeleteLine | | Вставка текста | Insert | | Вставка текста из буфера | Paste | | вырезанного изображения | | | Замена всего текста | SetText | | Выделение диапазона текста | SelectRange | | Прокрутка текста | Scroll | +----------------------------------------+----------------------+
Определение буфера передачи
-----------------------------------------------------------------
Буфер передачи - это запись с одним полем для каждого управ- ляющего элемента, участвующего в передаче. Окно или диалог могут также иметь управляющие элементы, значения которых не устанавли- ваются механизмом передачи. Например, командные кнопки, у которых нет состояния, не участвуют в передаче. Это же справедливо для групповых блоков.
Для определения буфера передачи нужно определить поле для каждого участвующего управляющего элемента диалога или окна. Оп- ределять поля для каждого управления диалога или окна не требует- ся - нужно лишь определить поля для тех из них, которые будут по- лучать и принимать значения по вашему желанию. Этот буфер переда- чи хранит один из каждых типов управляющих элементов, кроме ко- мандной кнопки и блока группы:
type TSampleTransferRecord = record Stat1: array[0TextLen-1] of Char; { статический текст } Edit1: array[0TextLen-1] of Char; { текст управляющего элемента редактирования } List1Strings: PStrCollection; { строки блока списка } List1Selection: Integer; { индекс выбранных строк } ComboStrings: PStrCollection; { строки комбинированного блока } ComboSelection: array[0TextLen-1] of Char; { выбранные строки } Check1: Word; { проверка состояния блока} Radio1: Word; { состояние кнопки с независимой фиксацией } Scroll1: ScrollBarTransferRec; { диапазон полосы прокрутки и т.д. } end;
В каждом типе управляющего элемента хранится различная ин- формация. Буфер передачи для каждого стандартного управляющего элемента поясняется в следующей таблице:
Поля буфера передачи для каждого типа управляющего элемента Таблица 12.11 +-----------------------+---------------------------------------+ | Тип управляющего | Буфер передачи | | элемента | | +-----------------------+---------------------------------------| | Статический | Символьный массив размером до макси-| | | мальной длины текста, плюс завершающий| | | нулевой символ. | | | | +-----------------------+---------------------------------------| | Редактирование | Текстовый буфер управляющего элемента| | | редактирования размером до длины, оп-| | | ределенной в текстовом поле TextLen. | | | | +-----------------------+---------------------------------------| | Блок списка | | | одиночный выбор | Набор строк в списке, плюс целочислен-| | | ный индекс выделенной строки. | | | | | множественный выбор | Набор строк в списке, плюс запись, со-| | | держащая индексы всех выделенных эле-| | | ментов. | | | | +-----------------------+---------------------------------------| | Комбинированный блок | Набор строк в списке, плюс выбранная| | | строка. | | | | +-----------------------+---------------------------------------| | Кнопка с независимой | Значения Word с указывающими состояния| | фиксацией | bf_Unchecked, bf_Checked и bf_Grayed. | | | | +-----------------------+---------------------------------------| | Кнопка с зависимой | Значения Word с указывающими состояния| | фиксацией | bf_Unchecked, bf_Checked и bf_Grayed. | | | | +-----------------------+---------------------------------------| | Полоса прокрутки | Запись типа TScrollBarTransferRec, со-| | | храняющая диапазон полосы прокрутки и| | | позицию в ней. | | | | +-----------------------+---------------------------------------+
Тип TScrollBarTransferRec имеет вид:
TScrollBarTransferRec := record LowValue : Integer; HighValue: Integer; Position : Integer; end;
Определение окна
-----------------------------------------------------------------
Окно или диалоговый блок, которые используют буфер передачи, должны создавать объекты участвующих управляющих элементов в той последовательности, в которой определяются их соответствующие по- ля буфера передачи. Для подключения механизма передачи к объекту окна или диалога нужно просто установить значение его поля TransferBuffer в указатель на определенный вами буфер передачи.
Опрос блоков выбора
-----------------------------------------------------------------
Опрос блока выбора - это один из способов выяснения его сос- тояния и организации реакции на него. Кнопки с зависимой и неза- висимой фиксацией имеют два состояния: выбранные и невыбранные. Для получения состояния блока выбора используется метод GetCheck типа TheckBox:
MyState:=Check1^.GetCheck;
Для определения состояния блока возвращаемое GetCheck значе- ние можно сравнить с заданными константами bf_Unchecked, bf_Checked и bf_Grayed.
Примечание: Использование кнопок обоих видов показано в примере программы BtnTest на ваших дистрибутивных дисках.
Опрос полосы прокрутки
-----------------------------------------------------------------
TScrollBar определяет два метода опроса полосы прокрутки: GetRange и GetPosition. Метод GetRange - это процедура, использу- ющая два целочисленных переменных аргумента. Процедура заносит в эти целые значения верхнюю и нижнюю позиции из диапазона полосы прокрутки. Этот метод очень удобен, когда нужно, чтобы ваша прог- рамма переместила указатель в его верхнюю или нижнюю позицию.
GetPosition - это функция, которая возвращает в виде целой величины позицию указателя. Ваша программа очень часто будет зап- рашивать диапазон и позицию и сравнивать их.
Опрос управляющих элементов редактирования
-----------------------------------------------------------------
Иногда нужно организовать опрос управляющих элементов редак- тирования для проверки допустимости введенного текста, записи ввода для его последующего использования или копирования ввода в другой управляющий элемент. TEdit поддерживает несколько методов опроса. Многие из опросов управляющих элементов редактирования и методов модификации возвращают или требуют от вас указать номер строки или позицию символа в строке. Все эти индексы начинаются с нуля. Другими словами, первая строка - это нулевая строка, а пер- вый символ в любой строке это нулевой символ. Самыми важными ме- тодами запроса являются GetText, GetLine, NumLines и LineLength.
Методы опроса управляющих элементов редактирования Таблица12.8 +------------------------------------------+--------------------+ | Выполняемое действие | Вызываемый метод | +------------------------------------------+--------------------| | Определение изменения текста | IsModified | | Считывание всего текста | GetText | | Считывание строки | GetLine | | Получение числа строк | GetNumLines | | Получение длины данной строки | GetLineLength | | Получение индекса выделенного текста | GetSelection | | Получение диапазона символов | GetSubText | | Подсчет символов перед строкой | LineIndex | | Поиск строки, содержащей индекс | GetLineFromProc | +------------------------------------------+--------------------+
Вы можете заметить, что методы запросов TEdit, которые возв- ращают текст из управляющего элемента редактирования, сохраняют форматирование текста. Это важно только для многострочных управ- ляющих элементов редактирования, которые допускают появление нес- кольких строк текста. В этом случае возвращаемый текст, который занимает несколько строк в управляющем элемента редактирования содержит в конце каждой строки два дополнительных символа: возв- рат каретки (#13) и смена строки (#10). Если этот текст снова по- мещается в управляющий элемент редактирования, вставляется из бу- фера вырезанного изображения, записывается в файл или выводится на принтер, то строки разбиваются так, как это было в управляющем элемента редактирования.
Следовательно, при использовании метода запроса для получе- ния определенного числа символов, нужно учитывать эти два симво- ла, которые заканчивают строку. GetText ищет текст в управляющем элементе редактирования. Он заполняет строку, на которую указыва- ет переданный аргумент PChar, содержимым управляющего элемента редактирования, включая перевод строки. Общее число символов за- дается вторым параметром. Он возвращает значение False, если уп- равляющий элемент редактирования пуст, или содержит текста боль- ше, чем помещается в предоставленную строку. Следующая процедура считывает из управляющего элемента редактирования строку и выде- ленный текст:
procedure TTestWindow.ReturnText(RetText: PChar); var TheText: array[020] of Char; begin if EC1^.GetText(@TheText, 20) then RetText:=@TheText else RetText:=nil; end;
procedure TTestWindow.ReturnText(RetText: PChar); var TheText: array[020] of Char; begin RetText:=nil; with EC^ do if NumLines >= LineNum then if LineLength(LineNum) < 11 then if GetLine(@TheText, 20, LineNum) then RetText := @TheText; end;
procedure TestWindow.ReturnLineText(RetText: PChar; LineNum: Integer); var TheText: array[020] of Char; begin with EC1^ do begin GetSelection(SelStart, SelEnd); GetSubText(TheText, SelStart, SelEnd); end; RetText := TheText; end;
Передача данных
-----------------------------------------------------------------
В большинстве случаев передача данных в окно выполняется автоматически, но в любой момент вы можете явно передать данные.
Передача данных из диалогового окна
-----------------------------------------------------------------
Когда режимное диалоговое окно получает командной сообщение с идентификатором управляющего элемента id_OK, оно автоматически передает данные из управляющего элемента в буфер передачи. Обычно ляет свой буфер передачи. Затем, если вы снова выполняете диалог, диалоговый блок передает текущие данные в управляющие элементы.
Передача данных из окна
-----------------------------------------------------------------
Однако, вы можете явно передавать данные в любом направлении в любой момент времени. Например, вы можете передать данные из управляющих элементов окна или безрежимного диалога. Вы также мо- жете сбросить состояния управляющих элементов, используя данные буфера передачи, в ответ на щелчок "мышью" на кнопке Reset (сброс). В обоих случаях используется метод TransferData. Конс- танта tf_SetData обозначает передачу данных из буфера в управляю- щий элемент, а константа tf_GetData - передачу в другом направле- нии. Например, вы можете вызвать TransferData в методе Destroy объекта окна:
procedure TSampleWindow.Destroy; begin TransferData(tf_GetData); TWindow.Destroy; end;
Передача данных в окно
-----------------------------------------------------------------
После создания окна или диалогового блока данные автомати- чески. Для создания экранного элемента, представляющего оконный объект, конструктор вызывает SetupWindow. Затем для загрузки дан- ных из буфера передачи вызывается TransferData. Окно SetupWindow интерактивно вызывает SetupWindow для каждого из дочерних окон, так что дочерние окна имеют возможность передать свои данные. Поскольку порождающее окно устанавливает свои дочерние окна в по- рядке их построения, данные в буфере передачи должны следовать в том же порядке.
Если объект управляющего элемента был построен с помощью InitResource или если порождающее окно явным образом разрешило межанизм передачи путем вызова для управляющего элемента EnableTransfer, то методы управляющего объекта SetupWindow вызы- вают TransferData.
Поддержка передачи для специализированных управляющих элементов
-----------------------------------------------------------------
Вы можете изменить способ передачи данных для конкретного управляющего элемента или включить новый управляющий элемент, оп- ределенный вами в механизме передачи. В обоих случаях вам просто нужно написать метод Transfer для вашего управляющего объекта, который если установлен флаг tf_GetData копирует данные из управ- ляющего элемента в место, задаваемое указателем. Если установлен флаг tf_SetData, то просто скопируйте данные по заданному указа- телю в управляющий элемент. Рассмотрим в качестве примера TStatic.Transfer:
function TStatic.Transfer(DataPrt: Pointer; TransferFlag: Word): Word; begin if TransferFlag = tf_GetData then GetText(DataPrt, TextLen) else if TransferFlag = tf_SetData then SetText(DataPtr); Transfer:=TextLen; end;
Метод Transfer должен всегда возвращать число переданных байт информации.
Построение групповых блоков
-----------------------------------------------------------------
Конструктор Init группового блока кроме обычных 6 параметров воспринимает текстовую строку метки группы.
constructor TGroupBoxInit(AParent: PWindowsObject; AnID: Integer; AText: PChar; X, Y, W, H: Integer);
Типичное использование конструктора группового блока может быть следующим:
GroupBox1 := New(PGroupBox, Init(@Self, id_GB1, 'A Group Box', 38, 102, 176, 108));
Построение и уничтожение объектов управляющих элементов
-----------------------------------------------------------------
Обычно в объекта порождающего окна для каждого из дочерних окон определяется поле данных. Независимо от того, какой вид объ- ектов вы используете, для каждого из них вы можете выполнить нес- колько задач:
* Построение объекта управляющего элемента.
* Вывод управляющего элемента.
* Уничтожение управляющего элемента.
Построение кнопок с зависимой и независимой фиксацией
-----------------------------------------------------------------
Кроме обычных 6 параметров, конструктор Init для кнопок с зависимой и независимой фиксацией воспринимает текстовую строку и указатель на объект группового блока (см. "Групповые блоки"), ко- торый логически и визуально выделяет кнопки. AGroup - это указа- тель на объект группового блока. Если AGroup имеет значение nil, то блок выбора не является частью какой-либо логической группы. Конструкторы описываются следующим образом:
constructor Init(AParent: PWindowsObject; AnID: Integer; ATitle: PChar; X, Y, W, H: Integer; AGroup: PGroupBox);
Для обоих видов блоков выбора синтаксис идентичен. Конструк- торы различаются только присваиваемым стилем, используемым по умолчанию. Типичное использование конструкторов блока выбора име- ет вид:
GroupBox1 := New(PGroupBox, Init(@Self, id_GB1, 'A Group Box', 38, 102, 176, 108)); ChBox1 := New(PCheckBox, Init(@Self, id_Check1, 'Check Box Text', 235, 12, 150, 26, GroupBox1));
Кнопки с независимой фиксацией по умолчанию инициализируются со стилем bs_AutoCheckBox, а кнопки с независимой фиксацией име- ют стиль bs_AutoRadioButton. В соответствии с этими стилями в каждый момент времени может выбираться только одна клавиша выбора в группе. Если одна выбрана, то другие автоматически остаются не- выбранными.
Если вы переопределяете стили объектов кнопок с зависимой или независимой фиксацией как "неавтоматические", то тогда уже вы отвечаете за их выбор или не выбор в ответ на произведенные поль- зователем нажатия.
Построение командных кнопок
-----------------------------------------------------------------
Кроме обычных 6 параметров, конструктор Init объекта TButton воспринимает текстовую строку типа PChar, AText и флаг типа Boolean IsDefaultButton, указывающий, должна ли кнопка быть ис- пользуемой по умолчанию или обычной командной кнопкой. Конструк- тор Init объекта TButton описывается следующим образом:
constructor TButton.Init(AParent: PWindowsObject; AnID: Integer; AText: PChar; X, Y, W, H: Integer; IsDefault: Boolean);
Типичный конструктор для обычной кнопки выглядит так:
Push1 := New(PButton, Init(@Self, id_Push1, 'Test Button', 38, 48, 316, 24, False));
Построение комбинированных блоков
-----------------------------------------------------------------
Кроме обычных 6 параметров объектов управляющих элементов конструктор Init для TComboBox воспринимает в качестве аргументов стиль и максимальную длину текста. Конструктор TComboBox описыва- ется следующим образом:
constructor TComboBox.Init(AParent: PWindowsObject; AnID: Integer: X, Y, W, H: Integer; AStyle, ATextLen: Word);
Все комбинированные блоки, построенные с помощью Init, име- ют стили ws_Child, ws_Visible, cbs_AutoHScroll, cbs_Sort (отсор- тированный список), и VScroll (вертикальная полоса прокрутки). Параметр стиля - это один из стандартных стилей комбинированных блоков Windows: cbs_Simple, cbs_DropDown или cbs_DropDownList. Параметр длины текста работает подобно соответствующему параметру управляющего элемента редактирования, ограничивая число символов, которые можно ввести в область редактирования комбинированного блока.
Следующие строки приведут к созданию спускающегося комбини- рованного блока списка с неотсортированным списком:
CB3: = New(PComboBox, Init(@Self, id_CB3, 190, 160, 150, 100, cbs_DropDownList, 40)); CB3^.Attr.Style:=CB3^.Attr.Style and (not cbs_Sort);
Построение объекта управляющего элемента
-----------------------------------------------------------------
Построение управляющих элементов отличается от построения любых других дочерних окон. Обычно конструктор порождающего окна вызывает конструкторы всех его дочерних окон. Однако в случае уп- равляющих элементов не просто создается связь "родитель - пото- мок", но устанавливается также связь "окно - управляющий эле- мент". Это очень важно, поскольку кроме обычных связей между предком и потомком управляющие элементы взаимодействуют с порож- дающими окнами особыми способами (через уведомления).
Примечание: Уведомления описываются в Главе 16 "Сооб- щения Windows". Чтобы построить и инициализировать объект управляющего эле- мента, нужно сделать следующее:
* добавить в объект порождающего окна поле (не обязательно); * вызвать конструктор объекта управляющего элемента; * изменить атрибуты управляющего элемента; * инициализировать управляющий элемент в SetupWindows.
Построение объектов блока списка
-----------------------------------------------------------------
Конструктор Init в TListBox воспринимает только шесть пара- метров, которые необходимы всем объектам управляющих элементов. Этими параметрами являются порождающее окно, идентификатор и раз- меры управляющего элемента X, Y, W и H:
LB1 := New(PListBox, Init(@Self, id_LB1, 20, 20, 340, 100));
TListBox получает используемый по умолчанию стиль управляю- щего элемента ws_Child or ws_Visible, затем прибавляется lbs_Standard. lbs_Standard - это комбинация lbs_Notify (для полу- чения уведомляющих сообщений), ws_VScroll (для получения верти- кально полосы прокрутки), lbs_Sort (для сортировки списка элемен- тов в алфавитном порядке) и ws_Border (для вывода рамки). Если вы хотите получить другой стиль блока списка, то можете модифициро- вать поле Attr.Style в TListBox. Например, для блока списка, не сортирующего свои элементы, можно использовать следующее:
LB1 := New(PListBox, Init(@Self, id_LB1, 20, 20, 340, 100)); LB1^.Attr.Style := LB1^.Attr.Style and not lbs_Sort;
Построение полос прокрутки
-----------------------------------------------------------------
Кроме обычных 6 параметров управляющего объекта, конструктор Init полосы прокрутки воспринимает флаг типа Boolean, указываю- щий, является ли полоса прокрутки горизонтальной. Приведем описа- ние конструктора полосы прокрутки:
constructor TScrollBarInit(AParent: PWindowsObject; AnID: Integer; X, Y, W, H: Integer; IsHScrollBar: Boolean);
Если вы зададите нулевую ширину вертикальной полосы прокрут- ки, Windows присвоит ей стандартную ширину (аналогичную полосе прокрутки блока списка). То же самое касается задания нулевой вы- соты горизонтальной полосы прокрутки. Вызов:
ThermScroll := New(PScrollBar, Init(@Self, id_ThermScroll, 20, 170, 340, 0, True));
создает горизонтальную полосу прокрутки стандартной высоты, как это показано на Рис. 12.5. Init конструирует полосы прокрутки со стилями ws_Child, ws_Visible и sbs_Horz или sbs_Vert для горизон- тальной или вертикальной полосы прокрутки соответственно. Разно- образные полосы прокрутки показаны на Рис. 12.6.
+-----------------------------------------------------------+-+-+ |#=#XXXXXXXXXXXXXXXXXXXScroll Bar TesterXXXXXXXXXXXXXXXXXXXX|^|v| +-----------------------------------------------------------+-+-| | +--+ +-+ | | +--+--|/\|---------------------------+--+ |^| | | |/X|##+--|###########X###############|X\| +-| | | |\X|##|##|###########X###############|X/| |#| | | +--+--|XX|---------------------------+--+ |X| | | |##| |#| | | |##| |#| | | |##| +-| | | +--| |v| | | |\/| +-+ | | +--+ | | +--+----------------------------------------------------+--+ | | |<X|#################X##################################|X>| | | +--+----------------------------------------------------+--+ | | | | | +---------------------------------------------------------------+
Рис. 12.6 Окно с разнообразными полосами прокрутки.
Построение статических управляющих элементов
-----------------------------------------------------------------
Пользователь никогда не взаимодействует непосредственно со статическими управляющими элементами, поэтому приложение будет очень редко, если вообще будет, принимать уведомляющие сообщения управляющих элементов относительно статического управляющего эле- мента. Следовательно, большинcтво статических управляющих элемен- тов можно сконструировать с идентификатором ресурса -1 или неко- торым другим неиспользуемым числом.
Конструктор Init в TStatic конструирует новый объект стати- ческого управления и описывается следующим образом:
constructor TStatic.Init(AParent: PWindowsObject; AnID: Integer; ATitle: PChar; X, Y, W, H: Integer; ATextLen: Word);
Кроме обычных параметров Init управляющего объекта, TStatic.Init имеет два дополнительных параметра - текстовую стро- ку ATitle и максимальную длину текста ATextLen. Текст должен за- канчиваться нулевым символом, поэтому в действительности число отображаемых символов на единицу меньше заданной в конструкторе длины текста. Типичный вызов для построения статического управля- ющего элемента может выглядеть так:
Stat1 := New(Static, Init(@Self, id_ST1, '&Text', 20, 50, 200, 24, 6));
После его создания обращаться к статическому управляющему объекту или манипулировать им требуется редко, поэтому поле, со- держащее статический управляющий объект, в общем случае присваи- вать не нужно.
Используемым по умолчанию стилем статического управляющего элемента является назначенный по умолчанию стиль управляющего элемента, то есть ws_Child or ws_Visible (выравнивание влево). Чтобы изменить стиль, модифицируйте поле Attr.Style. Например, чтобы центрировать текст управляющего элемента, сделайте следую- щее:
Stat1^.Attr.Style := Stat1^.Attr.Style and (not ss_Left) or ss_Center;
В статическом управляющем элементе есть возможность подчер- кивания одного или нескольких символов в строке текста. Реализа- ция и действие этого эффекта аналогичны подчеркиванию первого символа в выборе меню: Insert и & должны непосредственно пред- шествовать символу в строке, который будет подчеркиваться. Напри- мер, для подчеркивания T в слове 'Text' нужно в вызове Init стро- ку '&Text'. Если в строке вам нужно использовать &, применяйте статический стиль Windows ss_NoPrefix (см. Рис. 12.2). Для уточ- нения текущего текста, который хранится в статическом управляющем элементе, используется метод GetText.
Модификация статического управляющего элемента
Для изменения текста статического управляющего элемента TStatic имеет два метода. SetText устанавливает статический текст, передаваемый аргументом PChar. Clear удаляет статический текст. Однако, вы не можете сменить текст статического управляю- щего элемента, созданный со стилем ss_Simple.
Опрос статических управляющих элементов
Чтобы считать текст, содержащийся в статическом управляющем элементе, используйте метод GetText.
Построение управляющих элементов редактирования
-----------------------------------------------------------------
Конструктор Init управляющего элемента редактирования анало- гичен конструктору статического управляющего элемента и восприни- мает 6 обычных параметров, плюс начальная текстовая строка, мак- симальная длина строки и флаг Multiline типа Boolean. Конструктор TEdit описывается следующим образом:
constructor TEdit.Init(AParent: PWindowsObject; AnID: Integer; ATitle: PChar; X, Y, W, H, ATextLen: Integer; Multiline: Boolean);
По умолчанию управляющий элемент редактирования имеет стили ws_Child, ws_Visible, es_TabStop, es_Left и es_AutoHScroll. Так как управляющий элемент должен включать в себя завершающий нуле- вой символ, параметр длины текста на самом деле на 1 превышает максимальное число символов, допустимых в строке редактирования.
Если Multiline имеет значение True, то управление редактиро- ванием имеет стиль es_MultiLine, es_AutoVScroll, ws_VScroll и ws_HScroll. Приведем типичные конструкторы управляющих элементов редактирования (один для однострочного элемента, другой - для многострочного):
EC1 := New(PEdit, Init(@Self, id_EC1, 'Default Text', 20, 50, 150, 30, 40, False)); EC2 := New(PEdit, Init(@Self, id_EC2, '', 20, 20, 200, 150, 40, True));
Пример программы: BtnTest
-----------------------------------------------------------------
BtnTest - это полная программа, которая создает окно с ко- мандной кнопкой, кнопками с зависимой и независимой фиксацией и блоком группы управляющих элементов. После запуска приложения по- является основное окно с управляющими элементами. Когда пользова- тель "нажимает" на управляющий элемент, приложение реагирует на это различными способами. См. Рис. 12.4.
Примечание: Полный текст программы содержится в файле BTNTEST.PAS на ваших дистрибутивных дискетах.
+-----------------------------------------------------------+-+-+ |#=#XXXXXXXXXXXXXXXXXXXButton TesterXXXXXXXXXXXXXXXXXXXXXXXX|^|v| +-----------------------------------------------------------+-+-| | | | +---+ | | | X | Текст кнопки с независимой фиксацией | | +---+ | | +----------------------------------------------------------+ | | |###########Состояние кнопки с независимой фиксацией#######| | | +----------------------------------------------------------+ | | | | +-Групповой блок-------------------------------+ | | | ( ) Кнопка с зависимой фиксацией 1 | | | | (*) Кнопка с зависимой фиксацией 2 | | | +----------------------------------------------+ | +---------------------------------------------------------------+
Рис. 12.4 Окно с различными видами кнопок.
Пример программы: CBoxTest
-----------------------------------------------------------------
Программа CBoxTest реализует приложение, показанное на Рис. 12.8. В нем использованы все три типа комбинированных блоков. CB1 - это простой комбинированный блок, CB2 это раскрывающийся комби- нированный блок, а CB3 - это раскрывающийся комбинированный блок списка. Нажатие кнопок Show и Hide выполняет принудительный вывод и сокрытие правого верхнего комбинированного блока, CB3, путем вызова методов ShowList и HideList.
Примечание: Полный текст файла CBOXTEST.PAS содержится на ваших дистрибутивных дискетах.
Пример программы: EditTest
-----------------------------------------------------------------
EditTest - это программа, которая помещает на экран основное окно, которое будет порождающим для двух управляющих элементов редактирования, двух статических управляющих элементов и кнопки. Данное окно показано на Рис. 12.7.
Когда пользователь щелкает на командной кнопке кнопкой "мы- ши", текст из левого управляющего элемента редактирования (EC1) копируется в правый управляющий элемент редактирования (EC2). В EC2 текст преобразуется в буквы верхнего регистра, поскольку оно было построено со стилем es_UpperCase. Если в C1 никакой текст не выбран, то в EC2 копируется весь текст. Если в EC1 выбран некото- рый текст, то будет скопирован именно он. Меню редактирования обеспечивает функции редактирования независимо от того, с каким управляющим элементов редактирования идет работа. Полный файл EDITTEST.PAS и файл ресурса EDITTEST содержатся на ваших дистри- бутивных дискетах.
Пример программы: LBoxTest
-----------------------------------------------------------------
Программа LBoxTest - это полная программа, которая создает окно с блоком списка. После запуска приложения появляется основ- ное окно с блоком списка. Когда пользователь выбирает элемент блока списка, появляется диалог с выбранным элементом. Обратите внимание на взаимоотношения между объектом окна и объектом блока списка. Блок списка - это не просто дочернее окно основного окна, основное окно владеет им как полем объекта. LB1 - это одно из по- лей объекта основного окна, и оно содержит объект блока списка. Полный текст программы содержится в файле LBOXTEST.PAS на ваших дистрибутивный дискетах.
Пример программы: SBarTest
-----------------------------------------------------------------
Программа SBarTest создает приложение для термостата, пока- занное на Рис. 12.5. Полный текст программы содержится в файле SBARTEST.PAS на ваших дистрибутивных дискетах.
Пример программы StatTest
-----------------------------------------------------------------
Программа StatTest создает статическое тестовое приложение, показанное на Рис.12.2. Обратите внимание на то, что метки ('Default Static' и 'ss_Simple') представляют собой статистичес- кие управляющие элементы, также как и 'Sample Text', черные и се- рые прямоугольники. Полный текст программы содержится в файле STATTEST.PAS на ваших дистрибутивных дискетах.
Пример программы: TranTest
-----------------------------------------------------------------
Основное окно программы TranTest воспроизводит режимный диа- лог с полями, в которые пользователь вводит данные об имени и ад- ресе. Буфер передачи используется для хранения этой информации и отображения ее в управляющих элементах диалога при повторном его выполнении. Обратите внимание на то, что нам не нужно определять новый тип объекта диалога для установки и поиска данных диалога. Также обратите ваше внимание на то, что мы непосредственно мани- пулируем данными буфера передачи, поэтому статическое управление при первом выводе диалога гласит "First Mailing Label" (первая почтовая этикетка), а при всех остальных появлениях "Subsequent Mailing Label" (следующая почтовая этикетка).
Примечание: Полный текст программы содержится в файле TRANTEST.PAS на ваших дистрибутивных дискетах.
Присваивание полям объекта
----------------------------------------------------------------- Часто при построении управляющего элемента в окне желательно сохранять указатель на управляющий элемент в поле оконного объек- та. Например, чтобы добавить в окно, определенное типом TSampleWindow блок списка, вы можете задать в поле TSampleWindow поле TheList и присвоить ему блок списка:
constructor SampleWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin inherited Init(AParent, ATitle); TheList := New(PListBox, Init(@Self, id_LB1, 20, 20, 100, 80)); end;
Порождающие окна автоматически поддерживают список своих до- черних окон, включая управляющие элементы. Однако удобнее манипу- лировать управляющими объектами, когда имеются соответствующие поля объекта. Управляющие элементы, с которыми часто работать не требуется (такие как статический текст или групповые блоки) могут не иметь соответствующих полей.
При наличии поля объекта построение объекта управляющего элемента не представляет труда. Например, чтобы добавить в TSampleWindow групповой блок, нужно сделать следующее:
constructor SampleWindow.Init(AParent: PWindowsObject; ATitle: PChar); begin inherited Init(AParent, ATitle); TempGroupBox := New(PListBox, Init(@Self, id_LB1, 'Group name', 140, 20, 100, 80)); end;
Работа с управляющими элементами окна
-----------------------------------------------------------------
Диалоговые окна работают с их управляющими элементами путем передачи им сообщений с помощью метода SendDlgItemMsg с констан- той управляющего сообщения (такой как lb_AddString) в качестве параметра (см. Главу 11). Объекты управляющих элементов сильно упрощают этот процесс путем использования методов (таких как TListBox.AddString) для непосредственной работы с управляющими элементами на экране.
Когда объекты управляющих элементов окна имеют соответствую- щие поля объекта, то вызвать управляющие методы достаточно прос- то:
TheListBox^.AddString('Scotts Valley');
Расширение BWCC
-----------------------------------------------------------------
BWCC обеспечивает кнопки с графическими изображениями для всех стандартных командных кнопок Windows. То есть, имеются гра- фические изображения, предусмотренные для командных кнопок, для которых Windows обеспечивает стандартный идентификатор: id_Abort, id_Cancel, id_Ignore, id_No, id_Ok, id_Retry и id_Yes.
Создание кнопок с графическими изображениями
В своих приложениях вы можете обеспечить для командных кно- пок собственные графические образы. Все что нужно предусмотреть - это шесть ресурсов графических изображений (битовых массивов), пронумерованных относительно идентификатора управляющего элемента вашей командной кнопки. Например, если вы хотите создать графи- ческую командную кнопку с идентификатором id_MyButton, то создае- те ресурсы битовых массивов с идентификаторами ресурса 1000 + id_MyButton, 2000 + id_MyButton, 3000 + id_MyButton, 4000 + id_MyButton, 5000 + id_MyButton и 6000 + id_MyButton. Каждый представляемый битовый массив показан в следующей таблице:
Ресурсы битовых массивов для командных кнопок BWCC Таблица 12.12 +------------------------+-----------------+--------------------+ | Образ | Идентификатор | Идентификатор | | | ресурса VGA | ресурса VGA | +------------------------+-----------------+--------------------| | Командная кнопка | 1000 + идент. | 2000 + идент. | | в фокусе | | | | | | | +------------------------+-----------------+--------------------| | Нажатая командная | 3000 + идент. | 4000 + идент. | | кнопка | | | | | | | +------------------------+-----------------+--------------------| | Командная кнопка | 5000 + идент. | 6000 + идент. | | не в фокусе | | | | | | | +------------------------+-----------------+--------------------+
Графические образы командных кнопок VGA должны иметь ширину 63 и высоту 39 элементов изображения. Графические образы команд- ных кнопок EGA должны иметь ширину 63 и высоту 39 элементов изображения.
Для текста следует использовать шрифт Helvetica размером 8 пунктов, а вокруг образа кнопки, находящейся в фокусе, следует выводить рамку из точек. Набор графических изображений для ко- мандных кнопок с идентификатором 201 показан на следующем рисун- ке:
+------------------+ +------------------+ +------------------+ |##################| |##################| |##################| |###@@######Add####| |###@@######Add####| |###@@######Add####| |#@@@@@@####Pen####| |#@@@@@@####Pen####| |#@@@@@@####Pen####| |###@@#############| |###@@#############| |###@@#############| |##################| |##################| |##################| +------------------+ +------------------+ +------------------+ 1201 3201 5201
+------------------+ +------------------+ +------------------+ | |# | . | | . #| | @@ Add |# | @@ : Add : | | @@ : Add : #| | @@@@@@ Pen |# | @@@@@@ : Pen : | | @@@@@@ : Pen : #| | @@ |# | @@ . | | @@ . #| | |# | | | #################| +------------------+# +------------------+ +------------------+ ################### 2201 4201 6201
Рис. 12. 9 Графические ресурсы для командной кнопки BWCC с идентификатором 201.
Реакция на блок списка
-----------------------------------------------------------------
Методы модификации и запроса блока списка позволяют вам ус- тановить значения или определять в каждый конкретный момент сос- тояние блока списка. Однако, чтобы знать, что делает пользователь в данный момент с блоком списка, вам нужно реагировать на уведом- ляющие сообщения управляющего элемента.
Пользователь может выполнять с блоком списка только следую- щие действия: прокрутку списка, щелчок кнопкой "мыши" на элементе списка, двойной щелчок кнопкой "мыши" на элементе. Когда выполня- ется одно из этих действий, Windows посылает порождающему окну блока списка уведомляющее сообщение блока списка. Обычно метод реакции на уведомление для обработки сообщений для каждого управ- ляющего элемента порождающего объекта определяется в порождающем оконном объекте.
Каждое уведомляющее сообщение блока списка содержит в поле lParamHi параметра Msg код уведомления (константу lbn_), который специфицирует характер действия. Наиболее общие коды lbn перечис- лены в следующей таблице:
Информационные сообщения блока списка Таблица 12.2 +-------------+-------------------------------------------------+ | wParam | Действие | +-------------+-------------------------------------------------| |lbn_SelChange|Отдельным нажатием кнопки "мыши" был выбран| | |элемент. | +-------------+-------------------------------------------------| |lbn_DblClk |Элемент был выбран двойным щелчком кнопки "мыши".| +-------------+-------------------------------------------------| |lbn_SetFocus |Пользователь переместил фокус на блок списка| | |простым или двойным нажатием кнопки "мыши", либо| | |клавишей Tab. Предшествует lbn_SelChange. | +-------------+-------------------------------------------------+
Приведем пример метода порождающего окна по обработке сооб- щений блока списка:
procedure TLBoxWindow.HandleLB1Msg(var Msg: TMessage); var Idx: Integer; ItemText: string[10] begin if Msg.lParamHi=lbn_SelChange then begin Idx:=LB1^.GetSelIndex; if LB1^.GetStringLenIdx)<11 then begin LB1^.GetSelString(@ItemText, 10); MessageBox(HWindow, @ItemText, 'Вы выбрали:', mb_OK); end; end; else DefWndProc(Msg); end;
Пользователь делает выбор, если Msg.lParamHi совпадает с константой lbn_SelChange. Если это так, то берется длина выбран- ной строки, проверяется, что она помещается в строку из 10 симво- лов, и выбранная строка показывается в блоке сообщения.
Реакция на групповые блоки
-----------------------------------------------------------------
Когда происходит событие, которое может изменить выбор блока группы (например, "нажатие" пользователем кнопки или вызов прог- раммой метода Check), порождающее окно блока группы принимает со- общение, основанное на дочернем идентификаторе. Порождающий объ- ект воспринимает сообщение, используя сумму id_First и идентифи- катора группового блока. Это позволяет вам определить методы для каждой группы вместо их задания для каждого блока выбора в груп- пе.
Для определения управляющего элемента в группе, на который было оказано воздействие, вы можете прочитать текущее состояние каждого управляющего элемента.
Реакция на командные кнопки
-----------------------------------------------------------------
Когда пользователь щелкает на командной кнопке "мышью", по- рождающее окно кнопки принимает уведомляющее сообщение. Если объ- ект порождающего окна перехватывает сообщение, он может отреаги- ровать на эти события выводом блока диалога, записью файла или другим контролируемым программой действием.
Для организации реакции на сообщения кнопок нужно определить основанный на дочернем идентификаторе метод для обработки каждой кнопки. Например, следующий метод IDBut1 обрабатывает реакцию на "нажатие" пользователем кнопки. Единственный код уведомления, оп- ределенный в Windows для командных кнопок - это bn_Clicked, поэ- тому код уведомления не нужно проверять.
type TTestWindow = object(TWindow) But1: PButton; procedure IDBut1(var Msg: TMessage); virtual id_First + idBut1; . . . end;
procedure TestWindow.IDBut1(var Msg: TMessage); begin MessageBox(HWindow, 'Clicked', 'The Button was:' mb_OK) end;
Примечание: Пример использования командных кнопок по- казывает программа BtnTest, которую вы можете найти на дистрибутивных дисках.
Реакция на полосы прокрутки
-----------------------------------------------------------------
При работе пользователя с полосой прокрутки ее порождающее окно получает от нее уведомляющие сообщения Windows. Если нужно, чтобы ваше окно реагировало на сообщения прокрутки, реакция на информационные сообщения должна быть обычной, путем определения методов реакции, основанных на дочерних идентификаторах.
Однако, уведомляющие сообщения полосы прокрутки несколько отличаются от других уведомляющих сообщений элемента управления. Они основаны на сообщениях Windows wm_HScroll и wm_VScroll, а не wm_Command. Единственное отличие, на которое нужно обратить вни- мание состоит в том, что уведомляющие коды полосы прокрутки запи- саны в Msg.wParam, а не в Msg.lParamHi.
Чаще всего встречаются коды sb_LineUp, sb_LineDown, sb_PageUp, sb_PageDown, sb_ThumbPosition и sb_ThumbTrack. Наибо- лее часто вы будете реагировать на каждое событие проверкой новой позиции полосы прокрутки и организацией соответствующего дейс- твия. В данном случае вы можете игнорировать уведомляющий код. Например:
procedure TestWindow.HandleThermScrollMsg(var Msg: TMessage); var NewPos: Integer; begin NewPos:=ThermScroll^.GetPosition; { обработка с помощью NewPos } end;
Часто альтернатива состоит в том, чтобы не реагировать на перемещение указателя до тех пор, пока пользователь не выберет его нового местоположения. В этом случае нужно реагировать на со- общение с кодом sb_ThumbTrack.
procedure TestWindow.HandleThermScrollMsg(var Msg: TMessage); var NewPos: Integer; begin if Msg.wParam <> sb_ThumbTrack then begin NewPos:=ThermScroll^.GetPosition; { некоторая обработка на основе NewPos. } end; end;
Иногда может потребоваться, чтобы объекты полосы прокрутки сами реагировали на уведомляющие сообщения полосы прокрутки. При этом конкретная реакция поведения должна быть встроена в объект полосы прокрутки. Для программирования объекта полосы прокрутки, который непосредственно реагировал бы на его информационные сооб- щения, нужно определить для его типа метод реакции, основанный на информации. В качестве идентификатора заголовка метода нужно ис- пользовать сумму nf_First и информационного кода полосы прокрут- ки. Этот процесс описан в разделе "Уведомляющие сообщения управ- ляющих элементов" Главы 16.
Реакция на управляющие элементы
-----------------------------------------------------------------
Реакция на взаимодействие с пользователем с помощью управля- ющих элементов несколько более сложна, чем просто вызов методов объектов управляющих элементов. Чтобы узнать, как отвечать на со- общения управляющих элементов, см. раздел "Команды, уведомления и идентификаторы управляющих элементов" в Главе 16.
Сохранение управляющих элементов
-----------------------------------------------------------------
Для вывода на экран управляющих элементов нет необходимости вызывать метод Show. Как дочерние окна, они автоматически выво- дятся на экран и повторно отображаются вместе с порождающим ок- ном. Однако, вы можете использовать Show для сокрытия или вывода управляющих элементов по запросу.
Создание ваших собственных специализированных управляющих элементов
-----------------------------------------------------------------
Простейший способ создания специализированного управляющего элемента состоит в фактическом создании окна, которое действует как управляющий элемент, но вовсе не является окном. Этот подход используется в программе Steps в Части 1 данного руководства. Тот же используемый в программе Steps метод применяется для ее объек- та палитры, который можно использовать, например, для создания объекта инструментальной полосы. Таким "управляющие элементы" яв- ляются наследниками TWindow, а не TControl, поскольку TControl имеет дело только со стандартными управляющими элементами Windows.
Другим стандартным способом создания специализированного уп- равляющего элемента является построение в динамически компонуемой библиотеке нового класса окон. После этого вы можете создавать объекты ObjectWindows, использующие этот новый класс. Пакет раз- работчика ресурсов также может использовать специализированные управляющие элементы, созданные в DLL. Информацию об использова- нии специализированных управляющих элементов в ресурсах диалого- вых блоках вы можете найти в "Руководстве пользователя по пакету разработчика ресурсов".
Примечание: О классах окон рассказывается в Главе 10.
Специализированные управляющие элементы Borland для Windows
-----------------------------------------------------------------
Специализированные управляющие элементы Borland для Windows (BWCC) обеспечивают выразительный внешний вид приложений Borland для Windows. Основными средствами BWCC являются:
* командные кнопки с графическими изображениями;
* серый "рельефный" фон диалоговый блоков;
* трехмерные кнопки с зависимой и независимой фиксацией.
ObjectWindows дает вам возможность простого доступа к BWCC, так что вы можете придать своим приложениями стандартный для Borland вид.
Средства BWCC
-----------------------------------------------------------------
BWCC добавляет к стандартным управляющим элементам в стиле Windows некоторые новые стили, но подчиняется также новым согла- шения и предположениям. Если вы создаете все свои новые управляю- щие элементы из ресурсов, то беспокоиться об этом вам не нужно. Однако при построении управляющих элементов в программном коде вам может потребоваться использовать некоторые новые стили и сле- довать соглашениям.
Связь с управляющими элементами
-----------------------------------------------------------------
Связь между оконным объектом и его управляющими объектами в некотором смысле аналогичны взаимодействию между объектом диало- гового блока и его управляющими элементами. Как и диалоговому блоку, окну требуется механизм для работы с его управляющими эле- ментами и для ответа на управляющие события, такие как выбор в блоке списка.
Три типа комбинированных блоков
-----------------------------------------------------------------
Имеются три типа комбинированных блоков: простые, раскрываю- щиеся и раскрывающиеся со списком. На Рис. 12.8 показан вывод трех типов комбинированных блоков с блоком списка.
+-----------------------------------------------------------+-+-+ |#=#XXXXXXXXXXXXXXXXXStatic Control TesterXXXXXXXXXXXXXXXXXX|^|v| +-----------------------------------------------------------+-+-| | | | Блок списка Простой комбинированный блок | | +----------------+ +--------------------------+ | | |a | | | | | |b | ++-------------------------| | | |c | |a | | | |d | |b | | | |e | |c | | | |f | |d | | | +----------------+ +-------------------------+ | | | | Раскрывающийся комбинированный Комбинированный блок с | | блок раскрывающимся списком | | +-----------------------++---+ +----------------------+---+ | | | v | |c#####################| v | | | +-----------------------++---+ +----------------------+---+ | | | | | | | +---------------------------------------------------------------+
Рис. 12.8 Три типа комбинированных блоков и блок списка.
Перечень стилей комбинированного блока Таблица 12.10 +---------------------+---------------------+-------------------+ | Стиль |Возможность скрытого |Соответствие текста| | | списка | списку | +---------------------+---------------------+-------------------| | Простой | нет | нет | | Раскрывающийся | есть | нет | | Раскрывающийся со | есть | да | | списком | | | +---------------------+---------------------+-------------------+
С точки зрения пользователя между различными стилями комби- нированных блоков существуют следующие различия:
* Простые комбинированные блоки.
Простой комбинированный блок не может делать область спис- ка скрытой. Его область редактирования ведет себя анало- гично управляющему элементу редактирования. Пользователь может вводить и редактировать текст, и текст не обязан совпадать ни с одним из элементов в списке. При совпадении выбирается соответствующий элемент списка.
* Раскрывающиеся комбинированные блоки.
Раскрывающиеся комбинированные блоки ведут себя аналогично простым комбинированным блокам, но с одним исключением. В начальной стадии работы их область списка не отображается. Она появляется, когда пользователь нажимает стрелку вниз, расположенную справа от области редактирования. Раскрываю- щиеся комбинированные блоки и раскрывающиеся комбинирован- ные блоки списков очень удобны, когда нужно поместить большое число управляющих элементов в маленькую область. Когда они не используются, то занимают значительно меньшую площадь, чем простой комбинированный блок или блок списка.
* Раскрывающиеся комбинированные блоки списка.
Область списка в раскрывающемся комбинированном блоке списка ведет себя подобно области списка в спускающемся комбинированном блоке - появляется при необходимости и ис- чезает, когда не нужна. Эти два типа комбинированных бло- ков отличаются поведением их областей редактирования. Раскрывающиеся области редактирования ведут себя подобно обычным управляющим элементам редактирования. Раскрывающи- еся области редактирования списка ограничиваются только отображением одного элемента списка. Если редактируемый текст соответcтвует элементу списка, то никаких дополни- тельных символов ввести нельзя.
Уничтожение управляющих элементов
-----------------------------------------------------------------
Порождающее окно отвечает за уничтожение управляющих элемен- тов. Экранный управляющий элемент автоматически уничтожается вместе с элементом порожденного окна, когда пользователь закрыва- ет окно или приложение. Деструктор порождающего окна автоматичес- ки уничтожает все дочерние объекты.
Управление диапазоном полосы прокрутки
-----------------------------------------------------------------
Один из атрибутов полосы прокрутки, инициализируемый при ее конструировании, это диапазон. Диапазон полосы прокрутки - это набор всевозможных положений указателя (маркера полосы прокрут- ки). Маркер полосы прокрутки - это подвижный прямоугольник, кото- рый пользователь может перемещать по ней. Каждой позиции соот- ветствует целое число. Порождающее окно использует эту целую ве- личину, позицию, для установки и запроса по полосе прокрутки. После конструирования объекта полосы прокрутки его диапазон уста- навливается от 1 до 100.
Положению маркера в "самой верхней" позиции (вершина верти- кальной полосы прокрутки или крайнее левое положение горизонталь- ной полосы прокрутки) соответствует позиция 1. "Самой нижней" по- зиции маркера соответствует позиция 100. Для установки иного диа- пазона нужно использовать метод SetRange, описанный в разделе "Модификация полосы прокрутки".
Управление параметрами полосы прокрутки
-----------------------------------------------------------------
Два других атрибута объекта полосы прокрутки - это его при- ращение по строкам и страницам. Приращение по строкам, установ- ленное в 1, это расстояние в единицах диапазона, на которое пере- местится указатель при нажатии пользователем стрелок на полосе прокрутки. Приращение по страницам, установленное в 10, это расс- тояние в единицах диапазона, на которое переместится указатель при нажатии пользователем в области прокрутки. Эти значения можно изменить непосредственной модификацией полей объекта TScrollBar, LineSize и PageSize.
Установка значений управляющих элементов
-----------------------------------------------------------------
Для управления сложными блоками диалога или окнами с мно- жеством дочерних окон управляющих элементов вы обычно можете для хранения и выяснения состояния его управляющих элементов создать производный тип объекта. Состояние управляющего элемента включает в себя текст управляющего элемента редактирования, положение по- лосы прокрутки и установку кнопки с зависимой фиксацией.
Выбор типа комбинированного блока
-----------------------------------------------------------------
Раскрывающиеся комбинированные блоки списка удобно использо- вать тогда, когда не допускаются никакие другие варианты, кроме перечисленных в области списка. Например, при выборе принтера для печати можно выбрать только принтер, к которому есть доступ в ва- шей системе.
С другой стороны, раскрывающиеся комбинированные блоки могут воспринимать выбор, который отличается от приведенных в списке элементов. Раскрывающийся комбинированный блок можно использовать для выбора файлов на диске при их открытии или записи. Пользова- тель может либо просматривать каталоги в поисках нужного файла, либо ввести полный маршрут и имя файла в области редактирования, независимо от того, присутствует ли это имя файла в области спис- ка.
Вызов конструкторов объектов управляющих элементов
-----------------------------------------------------------------
В то время как обычный конструктор объекта дочернего окна имеет только два параметра (порождающее окно и строку заголовка), конструктор управляющего объекта имеет их не менее шести. Объект блока списка имеет наиболее простой из всех управляющих элементов конструктор, который требует задания только шести параметров:
- объекта порождающего окна; - идентификатора управляющего элемента; - координату x верхнего левого угла; - координату y верхнего левого угла; - ширину; - высоту.
TListBox.Init описывается следующим образом:
constructor TListBox.Init(AParent: PWindowsObject; AnID: Integer; X, Y, W, H: Integer);
Все объекты управляющих элементов ObjectWindows (кроме TMDIClient) требуют не менее 6 параметров. Большинство из них воспринимают также параметр, задающий текст управляющего элемен- та.
Абстрактный объект проверки допустимости
-----------------------------------------------------------------
Абстрактный тип TValidator служит базовым типом для всех объектов проверки допустимости, но сам по себе он не делает ниче- го полезного. По существу, TValidator - это объект проверки до- пустимости, для которого всегда допустим любой ввод: IsValid и IsValidInput возвращают True, а Error не выполняет никаких функ- ций. Наследующие типы переопределяют IsValid и/или IsValidInput для фактического определения того, какие значения являются допус- тимыми.
Если никакие из других объектных типов проверки допустимости не годятся в качестве исходных, вы можете использовать TValidator в качестве отправной точки собственных объектов проверки допусти- мости.
Добавление к управляющим элементам редактирования средств проверки допустимости
-----------------------------------------------------------------
Каждый управляющий элемент редактирования имеет поле с име- нем Validator, установленное по умолчанию в nil, которое может указывать на объект проверки допустимости. Если вы не присваивае- те объекта полю Validator, то управляющий элемент редактирования ведет себя так, как описано в Главе 12. После присваивания с по- мощью вызова SetValidator объекта проверки допустимости управляю- щий элемент редактирования автоматически проверяется им при обра- ботке основных событий и при самом вызове для проверки допусти- мости.
Обычно, как показано ниже, объект проверки допустимости строится и присваивается в одном операторе:
. . { создание трехсимвольного управляющего элемента редакти- . рования } Ed := New(PEdit, Init(@Self, id_Me, '', 10, 10, 50, 30, 3, False)); Ed^.SetValidator(New(PRangeValidator, Init(100, 999))); . . .
Фильтрация
-----------------------------------------------------------------
Фильтрующие объекты проверки допустимости - это простая реа- лизация средств проверки допустимости, при которой проверяется только набираемый пользователем ввод. Конструктор фильтрующего объекта проверки допустимости воспринимает один параметр - набор допустимых символов:
constructor TFilterValidator.Init(AValidChars: TCharSet);
TFilterValidator переопределяет IsValidInput для возврата True только в том случае, если все символы в текущей строке ввода содержатся в наборе символов, переданных конструктору. Управляю- щие элементы редактирования включают символы только в том случае, если IsValidInput возвращает True, так что нет необходимости пе- реопределять IsValid. Поскольку символы проходят через фильтр ввода, полная строка допустима по определению.
Потомки TFilterValidator, такие как TRAngeValidator, могут сочетать фильтрацию ввода с другими проверками завершенной стро- ки.
Фильтрация ввода
-----------------------------------------------------------------
Простейший способ обеспечения включения в поле только допус- тимых данных состоит в обеспечении ввода пользователем только до- пустимых данных. Например, числовое поле ввода может быть ограни- чено вводом пользователем только цифровых данных.
Объект фильтра проверки допустимости ObjectWindows представ- ляет общий механизм, ограничивающий вид символов, которые пользо- ватель может вводить в данном управляющем элементе редактирова- ния. Объекты проверки допустимости рисунков могут также контроли- ровать форматирование и типы символов, которые может набирать пользователь.
Проверка допустимости данных
ObjectWindows представляет вам несколько гибких способов проверки допустимости информации, набираемой пользователем в уп- равляющем элементе редактирования, путем связи объектов проверки допустимости с объектами управляющих элементов редактирования. Использование объектов проверки допустимости облегчает добавление механизма проверки допустимости к существующим приложениям ObjectWindows или для изменения способа проверки в поле его дан- ных.
Данная глава охватывает следующие темы, относящиеся к про- верке допустимости:
* Три вид проверки допустимости данных.
* Использование объектов проверки допустимости.
* Как работает проверка допустимости.
Проверка допустимости обрабатывается методом CanClose интер- фейсных объектов. В любой момент вы можете проверить содержимое любого конкретного управляющего элемента редактирования или экра- на данных, вызвав метод CanClose объекта, но ObjectWindows пре- дусматривает также механизм автоматизации проверки допустимости данных. В большинстве случаев проверка допустимости данных прак- тически не требует от программиста никаких усилий.
Использование механизма проверки допустимости данных
-----------------------------------------------------------------
Использование объекта проверки допустимости данных с управ- ляющим элементом редактирования требует двух шагов:
* Построение объекта проверки допустимости. * Присваивание объекта проверки допустимости управляющему элементу редактирования.
После того, как вы построите объект проверки допустимости и свяжите его с управляющим элементом редактирования, вам не потре- буется взаимодействовать с ним непосредственно. Управляющий эле- мент редактирования знает, когда вызывать методы проверки допус- тимости и в какие моменты.
Как работает проверка допустимости
-----------------------------------------------------------------
В ObjectWindows предусмотрено несколько видов объектов про- верки допустимости, которые должны охватывать большинство ваших потребностей по проверке данных. Из абстрактных типов проверки допустимости вы можете также построить свои собственные произ- водные типы.
В данном разделе освещаются следующие темы:
* Виртуальные методы объекта проверки допустимости. * Стандартные типы объекта проверки допустимости.
Методы объекта проверки допустимости
-----------------------------------------------------------------
Каждый объект проверки допустимости наследует от абстрактно- го объектного типа TValidator четыре важных метода. Различным образом переопределяя эти методы, наследующие объекты проверки допустимости выполняют свои конкретные задачи по проверке. Если вы собираетесь модифицировать стандартные объекты проверки допус- тимости или написать собственные объекты проверки допустимости, то нужно понимать, что делает каждый из этих методов и как их ис- пользуют управляющие элементы редактирования.
Этими четырьмя методами являются следующие:
* Valid
* IsValid
* IsValidInput
* Error
Единственными методами, вызываемыми вне объекта, являются Valid и IsValidInput. Error и IsValid - единственные методы, вы- зываемые другими методами объекта проверки допустимости.
Построение объектов проверки допустимости
-----------------------------------------------------------------
Так как объекты проверки допустимости не являются интерфейс- ными объектами, их конструкторам требуется только информация, достаточная для установки критерия проверки допустимости. Напри- мер, объект проверки допустимости числового диапазона воспринима- ет два параметра - минимальное и максимальное значения в допусти- мом диапазоне:
constructor TRangeValidator.Init(AMin, AMax: Integer);
Просмотр строк
-----------------------------------------------------------------
Рабочий пример объекта проверки допустимости с преобразова- нием представляет TStringLookupValidator, сравнивающий переданную из управляющего элемента редактирования строку с элементами в списке строк. Если переданная строка содержится в списке, метод объекта проверки допустимости с просмотром строки возвращает True. Конструктор воспринимает только один параметр - список до- пустимых строк:
constructor TStringLookupValidator.Init(AString: PStringCollection);
Чтобы после построения объекта проверки допустимости с прос- мотром использовать другой список строк, передайте новый список методу NewStringList объекта проверки допустимости (который унич- тожает старый список и задает новый).
TStringLookupValidator переопределяет методы Lookup и Error, так что Lookup возвращает True, если переданная строка содержится в наборе строк, а Error выводит на экран блок сообщения, указыва- ющий, что строка отсутствует в списке.
Проверка диапазона
-----------------------------------------------------------------
Объект проверки допустимости диапазона TRangeVaidator - это потомок TFilterValidator, которые воспринимают только числа и до- бавляют к итоговым результатам проверку диапазона. Конструктор воспринимает два параметра, определяющим минимальное и максималь- ное допустимое значение:
constructor TRangeValidator.Init(AMin, AMax: Integer);
Объект проверки допустимости диапазона сам строит числовое средство проверки-фильтрации, воспринимающее только цифры '0''9' и символы плюса и минуса. Таким образом, наследуемый IsValidInput обеспечивает отфильтрацию только цифр. Затем TRangeValidator переопределяет IsValid, чтобы он возвращал True только если введенные числа находятся в допустимом диапазоне, оп- ределяемом в конструкторе. Метод Error выводит блок сообщения, указывающий, что введенное значение находится вне диапазона.
Проверка допустимости данных
-----------------------------------------------------------------
Основным внешним интерфейсом с объектами проверки допусти- мости данных является метод Valid. Аналогично методу CanClose ин- терфейсных объектов, Valid представляет собой булевскую функцию, которая возвращает значение True, если переданная ей строка со- держит допустимые данные. Один из компонентов метода CanClose уп- равляющего элемента редактирования является вызов метода Valid с переданным ему текущим текстом управляющего элемента редактирова- ния.
При использовании средств проверки допустимости с управляю- щими элементами редактирования вам никогда не требуется вызывать или переопределять метод Valid объекта проверки допустимости. По умолчанию Valid возвращает True, если возвращает True метод IsValid. В противном случае для уведомления пользователя об ошиб- ке и возврата значения False вызывается Error.
Проверка допустимости каждого поля
-----------------------------------------------------------------
Иногда удобно гарантировать, чтобы пользователь обеспечивал для конкретного поля допустимый ввод перед переходом к следующему полю. Этот подход часто называют "проверкой допустимости по табу- ляции", поскольку переход в новое поле обычно выполняется по кла- више Tab.
В качестве примера можно привести приложение, которое выпол- няет поиск в базе данных, где пользователь вводит в поле некото- рые виды ключевой информации, а приложение отвечает на это считы- ванием соответствующей записи и фильтрацией остальных полей. В таком случае вашему приложению перед действием по клавише требу- ется проверка, что пользователь набрал в этом ключевом поле пра- вильную информацию.
Проверка допустимости нажатий клавиш
-----------------------------------------------------------------
Когда объект управляющего элемента редактирования получает имеющее для него значение событие нажатия клавиши, он вызывает метод IsValidInput объекта проверки допустимости. По умолчанию методы IsValid всегда возвращают True. Это означает, что воспри- нимаются все нажатия клавиш. Однако, наследующие объекты проверки допустимости могут переопределять метод IsValidInput, чтобы от- фильтровывать нежелательные нажатия клавиш.
Например, средства проверки допустимости диапазона, которые используются для числового ввода, возвращают из IsValidInput True только для цифр и символов '+' и '-'.
IsValidInput воспринимает два параметра. Первый параметр - это параметр-переменная, содержащая текущий текст ввода. Второй параметр - это булевское значение, указывающее, следует ли перед попыткой проверки допустимости применять к строке ввода дополне- ние или заполнение. TPictureValidator - это единственный из стан- дартных объектов проверки допустимости, использующий второй пара- метр.
Проверка допустимости по шаблону
-----------------------------------------------------------------
Объекты проверки допустимости с шаблоном сравнивают строки, набранные пользователем, с шаблоном, описывающим формат допусти- мого ввода. Применяемые шаблоны совместимы с теми, которые ис- пользуются для контроля ввода в реляционной базе данных Paradox фирмы Borland. При построении объекта проверки допустимости по шаблону используется два параметра: строка, содержащая образ шаб- лона, и булевское значение, указывающее, нужно ли заполнять по шаблону литеральные строки.
Примечание: Синтаксис шаблонов описывается в справоч- нике. См. TPXPictureValidator.Picture.
constuctor TPictureValidator.Init(const APic: String; AAutoFill: Boolean);
TPictureValidator переопределяет Error, IsValidInput и IsValid и добавляет новый метод Picture. Изменения в Error и IsValid просты: Error выводит на экран блок сообщения, указываю- щий, какой формат должна иметь строка, а IsValid возвращает True только если True возвращается функцией Picture, позволяя получать новые производные типы проверки допустимости по шаблону путем пе- реопределения только метода Picture. IsValidInput проверяет сим- волы по мере набора их пользователем, допуская только те символы, которые разрешены в шаблоне формата, и возможно дополняя лите- ральные символы из шаблона.
Метод Picture пытается сформатировать заданную строку ввода в соответствии с шаблоном формата и возвращает значение, указы- вающее степень успеха: полный, неполный или ошибка.
Проверка допустимости полных экранов
-----------------------------------------------------------------
Проверить допустимость полных экранов вы можете тремя раз- личными способами:
* Проверкой допустимости режимных окон. * Проверкой допустимости при изменении фокуса. * Проверкой допустимости по запросу.
Проверка допустимости режимных окон
Когда пользователь закрывает режимное окно, оно перед закры- тием автоматически проверяет допустимость всех своих подобластей просмотра (если закрывающей командой не была cmCancel). Для про- верки допустимости всех подобластей окно вызывает метод CanClose каждой подобласти, и если каждый из них возвращает True, то окно можно закрыть. Если любая из подобластей возвращает значение False, то окно закрыть нельзя.
Пока пользователь не обеспечит допустимые данные, режимное окно с недопустимыми данными можно только отменить.
Проверка допустимости по запросу
В любой момент вы можете указать окну на необходимость про- верки всех его подокон путем вызова метода CanClose. CanClose по существу спрашивает окно "Если сейчас будет дана команда закры- тия, являются ли все поля допустимыми?" Окно вызывает методы CanClose всех своих дочерних окон в порядке включения и возвраща- ет True, если все они возвращают значение True.
Вызов CanClose не обязывает вас фактически закрывать окно. Например, вы можете вызвать CanClose, когда пользователь "нажима- ет" командную кнопку Save (Сохранение), обеспечивая проверку до- пустимости данных перед их сохранением.
Вы можете проверить любое окно (режимное или безрежимное) и в любое время. Однако автоматическую проверку допустимости при закрытии имеют только режимные окна. Если вы используете безре- жимные окна ввода данных, то нужно обеспечить, чтобы приложение перед выполнением действий с введенными данными вызывало метод CanClose окна.
Проверка допустимости с просмотром
-----------------------------------------------------------------
Абстрактный объект проверки допустимости с просмотром TLookupValidator обеспечивает основу для общего типа объекта про- верки допустимости, который для определения допустимости сравни- вает введенное значение со списком воспринимаемый элементов.
TLookupValidator - это абстрактный тип, который никогда не используется сам по себе, но служит важным изменением и дополне- нием к стандартному объекту проверки допустимости.
Примечание: Пример работы такого объектного типа вы можете найти в разделе по преобразованию строк.
Новый метод, вводимый объектом TLookupValidator называется Lookup. По умолчанию Lookup возвращает значение False, но при об- разовании производного абстрактного объекта проверки допустимости c просмотром вы можете переопределить Lookup для сравнения пере- данной строки со списком и возвращать True, если строка содержит допустимую запись.
TLookupValidator переопределяет IsValid для возврата True только если Lookup также возвращает True. В наследующих типах проверки допустимости с просмотром вам следует переопределять не IsValid, а Lookup.
Проверка полной строки
-----------------------------------------------------------------
Объекты проверки допустимости содержат виртуальный метод IsValid, который воспринимает в качестве единственного аргумента строку и возвращает True, если строка представляет допустимые данные. IsValid - это метод, который выполняет фактическую про- верку допустимости, так что если вы создаете собственные объекты проверки допустимости, то почти всегда переопределяете IsValid.
Заметим, что метод IsValid не вызывается вами явно. Исполь- зуйте для вызова IsValid метод Valid, так как для уведомления пользователя в случае возврата методом IsValid значения False Valid вызывает метод Error. Не путайте также проверку допустимос- ти сообщением об ошибке.
Сообщение о недопустимых данных
-----------------------------------------------------------------
Виртуальный метод Error уведомляет пользователя, что содер- жимое управляющего элемента редактирования не прошло проверку до- пустимости. Стандартные объекты проверки допустимости в общем случае представляет простой блок сообщения, уведомляющий пользо- вателя, что содержимое ввода недопустимо, и описывающее, каким должен быть правильный ввод.
Например, метод Error для проверки допустимости диапазона создает блок сообщения, указывающий, что значение в управляющем элементе редактирования не находится между указанными минимальным и максимальным значениями.
Хотя большинство объектов проверки допустимости переопреде- ляют Error, вам не следует вызывать его непосредственно. Метод Error вызывается методом Valid, если IsValid возвращает False (что является единственным моментом, когда необходимо вызывать Error).
Стандартные средства проверки допустимости
-----------------------------------------------------------------
ObjectWindows включает в себя шесть стандартных типов объек- тов проверки допустимости, включая абстрактный объект проверки допустимости и следующие пять специальных типов таких объектов:
* Фильтрация. * Проверка диапазона. * Проверка допустимости с просмотром. * Проверка допустимости с просмотром строк. * Проверка допустимости с просмотром шаблонов.
Три вида проверки допустимости данных
-----------------------------------------------------------------
Существует три различных типа проверки допустимости данных, и ObjectWindows поддерживает их по-разному. Этими тремя видами являются:
* Фильтрация ввода.
* Проверка допустимости каждого элемента.
* Проверка допустимости полных экранов.
Заметим, что эти методы не являются взаимно-исключающими. Ряд стандартных средств проверки допустимости могут комбинировать в одном механизме проверки допустимости различные методы.
Важно запомнить, что проверка допустимости выполняется объ- ектом проверки допустимости, а не объектом управляющего элемента редактирования. Если вы уже создали для особого назначения специ- ализированный управляющий элемент редактирования, то возможно сдублировали возможность, встроенную в управляющие элементы ре- дактирования и их средства проверки допустимости.
В разделе данной главы "Как работают средства проверки до- пустимости" описываются различные способы, с помощью которых объ- екты управляющего элемента редактирования автоматически вызывают объекты проверки допустимости.