Глава 12. Объекты управляющих элементов


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

    Примечание: Об интерфейсных объектах рассказывается в Главе 9.

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

Где можно использовать объекты управляющих элементов?


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

    Примечание: Диалоговые блоки и их управляющие элементы описываются в Главе 11 "Объекты диалоговых блоков".

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

Управляющие элементы Windows, поддерживаемые в ObjectWindows Таблица 12.1
Управляющий элементТип объектаИспользование
блок списка TListBox Прокручиваемый список элементов, из которых можно сделать выбор.
полоса прокрутки TScrollBar Полоса прокрутки, аналогичная тем, которые выводятся в прокручиваемых окнах и блоках списка.
"нажимаемая" кнопка TButton Кнопка для "нажатия" со связанным с ней текстом.
кнопка с независимой фиксацией TCheckBox Состоящая из блока кнопка, которая может выбираться или нет, со связанным текстом.
кнопка с зависимой фиксацией TRadioButtonКнопка, которая может выбираться или нет. Обычно используется во взаимоисключающих группах.
блок группы TGroupBox Статический прямоугольник с текстом в левом верхнем углу.
управляющий элемент редактированияTEdit Поле для ввода текста пользователем.
статический управляющий элемент TStatic Фрагмент отображаемого текста который не может быть изменен пользователем.
Комбинированный блок TComboBox Комбинация блока списка и управляющего элемента редактирования.


Рис. 12.1 Стандартные управляющие элементы Windows.

Что такое объекты управляющих элементов?


    Для Windows управляющие элементы - это просто специализированные виды окон. В ObjectWindows тип TControl является потомком типа TWindow, так что большинство объектов управляющих элементов можно использовать как все другие оконные объекты. Объекты управляющих элементов по способу их создания и уничтожения и способу их поведения (как дочерние окна) аналогичны оконным объектам. Однако они отличаются от других окон способом реакции на сообщения. Например, методы Paint объектов управляющих элементов запрещены. Windows берет на себя функции по отображению своих стандартных управляющих элементов.

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

    Тип TControl, как и TWindowsObject, является абстрактным объектным типом. Вы можете создать экземпляры его потомков TListBox, TButton и другие - но не можете создать экземпляр TControl.

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

Построение и уничтожение объектов управляющих элементов


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

Построение объекта управляющего элемента


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

    Примечание: Уведомления описываются в Главе 16 "Сообщения Windows".

    Чтобы построить и инициализировать объект управляющего элемента, нужно сделать следующее:

Вызов конструкторов объектов управляющих элементов


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

    TListBox.Init описывается следующим образом:

     constructor TListBox.Init(AParent: PWindowsObject;
                             AnID: Integer; X, Y, W, H: Integer);

    Все объекты управляющих элементов ObjectWindows (кроме TMDIClient) требуют не менее 6 параметров. Большинство из них воспринимают также параметр, задающий текст управляющего элемента.

Присваивание полям объекта


    Часто при построении управляющего элемента в окне желательно сохранять указатель на управляющий элемент в поле оконного объекта. Например, чтобы добавить в окно, определенное типом 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;

Изменение атрибутов объекта управляющего элемента


    Все управляющие объекты, кроме TMDIClient, получает от вызова TControl.Init используемые по умолчанию стили ws_Child и ws_Visible. Если вы хотите изменить стиль управляющего элемента, то можно изменить поле Attr.Style (как это описывается для окон в Главе 10). Каждый тип управляющего элемента имеет также другие стили, определяющие его конкретные характеристики.

Инициализация управляющего элемента


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

    При необходимости методом SetupWindow порождающего окна также устанавливаются и заполняются управляющие элементы. Приведем пример типичного метода SetupWindow:

     procedure TSampleWindows.SetupWindow;
     begin

inherited SetupWindow;  { создает дочерние управляющие элементы }
    { добавляет элементы в список }
       TheList^.AddString('Элемент 1');
       TheList^.AddString('Элемент 2');
     end;

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

Сохранение управляющих элементов


    Для вывода на экран управляющих элементов нет необходимости вызывать метод Show. Как дочерние окна, они автоматически выводятся на экран и повторно отображаются вместе с порождающим окном. Однако, вы можете использовать Show для сокрытия или вывода управляющих элементов по запросу.

Уничтожение управляющих элементов


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

Связь с управляющими элементами


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

Работа с управляющими элементами окна


    Диалоговые окна работают с их управляющими элементами путем передачи им сообщений с помощью метода SendDlgItemMsg с константой управляющего сообщения (такой как lb_AddString) в качестве параметра (см. Главу 11). Объекты управляющих элементов сильно упрощают этот процесс путем использования методов (таких как TListBox.AddString) для непосредственной работы с управляющими элементами на экране.

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

     TheListBox^.AddString('Scotts Valley');

Реакция на управляющие элементы


    Реакция на взаимодействие с пользователем с помощью управляющих элементов несколько более сложна, чем просто вызов методов объектов управляющих элементов. Чтобы узнать, как отвечать на сообщения управляющих элементов, см. раздел "Команды, уведомления и идентификаторы управляющих элементов" в Главе 16.

Действие, аналогичное диалоговому блоку


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

Использование конкретных управляющих элементов


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

Использование блока списка


    Использование блока списка - это простейший способ запросить пользователя программы Windows выбрать что-либо из списка. Блоки списка инкапсулируются объектным типом TListBox. TListBox определяет методы для создания блоков списка, модификации списка элементов, запроса состояния списка элементов и поиска выбранного пользователем элемента.

Построение объектов блока списка


    Конструктор 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;

Модификация блоков списка


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

Методы модификации блоков списка. Таблица 12.2
Выполняемое действиеМетод
Добавление элемента AddString
Вставка нового элемента InsertString
Добавление элемента InsertString
Удаление элемента DeleteString
Удаление каждого элемента ClearList
Выбор элемента SetSellIndex или SetSelString

Запрос в блоках списка


    Существует пять методов, которые вы можете вызвать для получения информации о списке, содержащейся в объекте блока списка. Эти методы перечислены в следующей таблице:

Методы запроса блока списка. Таблица 12.3
Получаемая информацияВызываемый метод
Число элементов в списке GetCount
Элемент с конкретным индексом GetString
Длина конкретного элемента GetStringLen
Выбранный элемент GetSelString
Индекс выбранного элемента SEgSelIndex

Реакция на блок списка


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

    Пользователь может выполнять с блоком списка только следующие действия: прокрутку списка, щелчок кнопкой "мыши" на элементе списка, двойной щелчок кнопкой "мыши" на элементе. Когда выполняется одно из этих действий, 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 символов, и выбранная строка показывается в блоке сообщения.

Пример программы: LBoxTest


    Программа LBoxTest - это полная программа, которая создает окно с блоком списка. После запуска приложения появляется основное окно с блоком списка. Когда пользователь выбирает элемент блока списка, появляется диалог с выбранным элементом. Обратите внимание на взаимоотношения между объектом окна и объектом блока списка. Блок списка - это не просто дочернее окно основного окна, основное окно владеет им как полем объекта. LB1 - это одно из полей объекта основного окна, и оно содержит объект блока списка. Полный текст программы содержится в файле LBOXTEST.PAS на ваших дистрибутивный дискетах.

Использование статических управляющих элементов


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


Рис. 12.2 Стили статических управляющих элементов.

Построение статических управляющих элементов


    Пользователь никогда не взаимодействует непосредственно со статическими управляющими элементами, поэтому приложение будет очень редко, если вообще будет, принимать уведомляющие сообщения управляющих элементов относительно статического управляющего элемента. Следовательно, большин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.

Пример программы StatTest


    Программа StatTest создает статическое тестовое приложение, показанное на Рис.12.2. Обратите внимание на то, что метки ('Default Static' и 'ss_Simple') представляют собой статистические управляющие элементы, также как и 'Sample Text', черные и серые прямоугольники. Полный текст программы содержится в файле STATTEST.PAS на ваших дистрибутивных дискетах.

Использование командных кнопок


    Управляющие элементы типа командных кнопок (которые иногда называют "нажимаемыми" кнопками) выполняют некоторое действие при "нажатии" такой кнопки. Есть два стиля командных кнопок, и оба они имеют тип TButton. Эти два стиля - bs_PushButton и DefPushButton. Используемые по умолчанию командные кнопки аналогичны командным другим кнопкам, но имеют жирную рамку и обычно используются для указания реакции пользователя по умолчанию. На Рис. 12.3 показан пример программы Windows, в которой используются обычные кнопки нажатия и командные кнопки по умолчанию.


Рис. 12.3 Программа Windows, использующая командные кнопки.

Построение командных кнопок


    Кроме обычных 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));

Реакция на командные кнопки


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

    Для организации реакции на сообщения кнопок нужно определить основанный на дочернем идентификаторе метод для обработки каждой кнопки. Например, следующий метод 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, которую вы можете найти на дистрибутивных дисках.

Использование блоков выбора


    Тип TCheckBox наследует от TButton, а тип TRadioButton - от TCheckBox. Кнопки с зависимой и независимой фиксацией мы будем иногда кратко называть блоками выбора.

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

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

    Однако, вы можете для выполнения ими некоторых действий при нажатии создать типы, производные от TCheckBox и TRadioButton. Если ваш тип определяет метод для nf_First + bn_Clicked, то он сначала должен вызывать метод реакции BNClicked, а уже затем выполнять любые дополнительные действия.

Построение кнопок с зависимой и независимой фиксацией


    Кроме обычных 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. В соответствии с этими стилями в каждый момент времени может выбираться только одна клавиша выбора в группе. Если одна выбрана, то другие автоматически остаются невыбранными.

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

Модификация блоков выбора


    Модификация (выбор или отмена выбора) блоков выбора выглядит задачей пользователя программы, а не вашей. Но в некоторых случаях программе требуется явно управлять состоянием блоков выбора. Одним из таких случаев является вывод на экран параметров, которые были выбраны и сохранены ранее. Для модификации состояния кнопки с независимой фиксацией TCheckBox определяет 4 метода:

Методы модификации кнопок с независимой фиксацией Таблица 12.5
Выполняемое действиеВызов метода
Выбор кнопки Check или SetCheck(bf_Chacked)
Отмена выбора кнопки Uncheck или SetCheck(bf_Unchecked)
Переключение кнопки Toggle

    Когда вы используете данные методы с кнопками с зависимой фиксацией, ObjectWindows обеспечивает выбор в группе только одной кнопки с зависимой фиксацией.

Опрос блоков выбора


    Опрос блока выбора - это один из способов выяснения его состояния и организации реакции на него. Кнопки с зависимой и независимой фиксацией имеют два состояния: выбранные и невыбранные. Для получения состояния блока выбора используется метод GetCheck типа TheckBox:

     MyState:=Check1^.GetCheck;

    Для определения состояния блока возвращаемое GetCheck значение можно сравнить с заданными константами bf_Unchecked, bf_Checked и bf_Grayed.

    Примечание: Использование кнопок обоих видов показано в примере программы BtnTest на ваших дистрибутивных дисках.

Использование групповых блоков


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

Построение групповых блоков


    Конструктор 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));

Группирование управляющих элементов


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

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

     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 порождающего окна экранных элементов.

Реакция на групповые блоки


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

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

Пример программы: BtnTest


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

    Примечание: Полный текст программы содержится в файле BTNTEST.PAS на ваших дистрибутивных дискетах.


Рис. 12.4 Окно с различными видами кнопок.

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


    Полосы прокрутки являются важнейшим механизмом изменения обзора пользователем окна приложения, блока списка или комбинированного блока. Однако, может возникнуть ситуация, когда нужна отдельная полоса прокрутки для выполнения некоторой специализированной задачи (например, управление температурой в программе термостата или цветом в программе рисования). Когда нужна отдельная специализированная полоса прокрутки, используются объекты TScrollBar. Рис. 12.5 показывает типичное использование объекта TSсrollBar.


Рис. 12.5 Объект полосы прокрутки.

Построение полос прокрутки


    Кроме обычных 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.


Рис. 12.6 Окно с разнообразными полосами прокрутки.

Управление диапазоном полосы прокрутки


    Один из атрибутов полосы прокрутки, инициализируемый при ее конструировании, это диапазон. Диапазон полосы прокрутки - это набор всевозможных положений указателя (маркера полосы прокрутки). Маркер полосы прокрутки - это подвижный прямоугольник, который пользователь может перемещать по ней. Каждой позиции соответствует целое число. Порождающее окно использует эту целую величину, позицию, для установки и запроса по полосе прокрутки. После конструирования объекта полосы прокрутки его диапазон устанавливается от 1 до 100.

    Положению маркера в "самой верхней" позиции (вершина вертикальной полосы прокрутки или крайнее левое положение горизонтальной полосы прокрутки) соответствует позиция 1. "Самой нижней" позиции маркера соответствует позиция 100. Для установки иного диапазона нужно использовать метод SetRange, описанный в разделе "Модификация полосы прокрутки".

Управление параметрами полосы прокрутки


    Два других атрибута объекта полосы прокрутки - это его приращение по строкам и страницам. Приращение по строкам, установленное в 1, это расстояние в единицах диапазона, на которое переместится указатель при нажатии пользователем стрелок на полосе прокрутки. Приращение по страницам, установленное в 10, это расстояние в единицах диапазона, на которое переместится указатель при нажатии пользователем в области прокрутки. Эти значения можно изменить непосредственной модификацией полей объекта TScrollBar, LineSize и PageSize.

Опрос полосы прокрутки


    TScrollBar определяет два метода опроса полосы прокрутки: GetRange и GetPosition. Метод GetRange - это процедура, использующая два целочисленных переменных аргумента. Процедура заносит в эти целые значения верхнюю и нижнюю позиции из диапазона полосы прокрутки. Этот метод очень удобен, когда нужно, чтобы ваша программа переместила указатель в его верхнюю или нижнюю позицию.

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

Модификация полос прокрутки


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

Методы модификации полос прокрутки. Таблица 12.6
Выполняемое действиеВызываемый метод
Задание диапазона прокрутки SetRange
Установка позиции маркера SetPosition
Перемещение позиции маркера DeltaPos

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

     ThermScroll^.SetRange(32, 120);

    SetPosition - это процедура, которая воспринимает один целочисленый аргумент - позицию, в которую нужно переместить указатель полосы прокрутки. В рассмотренном ранее приложении для термостата, ваша программа может непосредственно установить температуру 78 градусов:

     ThermScroll^.SetPosition(78);

    Третий метод DeltaPos передвигает позицию указателя полосы прокрутки вверх (налево) или вниз (направо) на величину, заданную целым аргументом. Положительная целая величина перемещает указатель вниз (направо). Отрицательная целая величина перемещает его вверх (налево). Например, для уменьшения температуры термостата на 5 градусов используется:

     ThermScroll^.DeltaPos(-5);

Реакция на полосы прокрутки


    При работе пользователя с полосой прокрутки ее порождающее окно получает от нее уведомляющие сообщения 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.

Пример программы: SBarTest


    Программа SBarTest создает приложение для термостата, показанное на Рис. 12.5. Полный текст программы содержится в файле SBARTEST.PAS на ваших дистрибутивных дискетах.

Использование управляющих элементов редактирования


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

    На Рис. 12.7 показано окно с двумя управляющими элементами редактирования.


Рис. 12.7 Окно с управляющими элементами редактирования.

Построение управляющих элементов редактирования


    Конструктор 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));

Использование буфера вырезанного изображения и меню 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, который определяет, можно ли отменить последнюю операцию редактирования.

Опрос управляющих элементов редактирования


    Иногда нужно организовать опрос управляющих элементов редактирования для проверки допустимости введенного текста, записи ввода для его последующего использования или копирования ввода в другой управляющий элемент. 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[0..20] of Char;
    begin
     if EC1^.GetText(@TheText, 20) then
      RetText:=@TheText
     else RetText:=nil;
    end;

    procedure TTestWindow.ReturnText(RetText: PChar);
    var TheText: array[0..20] 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[0..20] of Char;
     begin
       with EC1^ do
       begin
         GetSelection(SelStart, SelEnd);
         GetSubText(TheText, SelStart, SelEnd);
       end;
         RetText := TheText;
     end;

Модификация управляющих элементов редактирования


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

Методы модификации управляющих элементов редактирования. Таблица 12.9
Выполняемое действиеВызываемый метод
Удаление всего текста Clear
Удаление выделенного текста DeleteSelection
Удаление диапазона символов DeleteSubText
Удаление строки текста DeleteLine
Вставка текста Insert
Вставка текста из буфера вырезанного изображения Paste
Замена всего текста SetText
Выделение диапазона текста SelectRange
Прокрутка текста Scroll

Пример программы: EditTest


    EditTest - это программа, которая помещает на экран основное окно, которое будет порождающим для двух управляющих элементов редактирования, двух статических управляющих элементов и кнопки. Данное окно показано на Рис. 12.7.

    Когда пользователь щелкает на командной кнопке кнопкой "мыши", текст из левого управляющего элемента редактирования (EC1) копируется в правый управляющий элемент редактирования (EC2). В EC2 текст преобразуется в буквы верхнего регистра, поскольку оно было построено со стилем es_UpperCase. Если в C1 никакой текст не выбран, то в EC2 копируется весь текст. Если в EC1 выбран некоторый текст, то будет скопирован именно он. Меню редактирования обеспечивает функции редактирования независимо от того, с каким управляющим элементов редактирования идет работа. Полный файл EDITTEST.PAS и файл ресурса EDITTEST содержатся на ваших дистрибутивных дискетах.

Использование комбинированных блоков


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

Три типа комбинированных блоков


    Имеются три типа комбинированных блоков: простые, раскрывающиеся и раскрывающиеся со списком. На Рис. 12.8 показан вывод трех типов комбинированных блоков с блоком списка.


Рис. 12.8 Три типа комбинированных блоков и блок списка.

Перечень стилей комбинированного блока. Таблица 12.10
СтильВозможность скрытого спискаСоответствие текста списку
Простой нет нет
Раскрывающийся есть нет
Раскрывающийся со списком есть да

    С точки зрения пользователя между различными стилями комбинированных блоков существуют следующие различия:

Выбор типа комбинированного блока


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

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

Построение комбинированных блоков


    Кроме обычных 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);

Модификация комбинированных блоков


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

Пример программы: CBoxTest


    Программа CBoxTest реализует приложение, показанное на Рис. 12.8. В нем использованы все три типа комбинированных блоков. CB1 - это простой комбинированный блок, CB2 это раскрывающийся комбинированный блок, а CB3 - это раскрывающийся комбинированный блок списка. Нажатие кнопок Show и Hide выполняет принудительный вывод и сокрытие правого верхнего комбинированного блока, CB3, путем вызова методов ShowList и HideList.

    Примечание: Полный текст файла CBOXTEST.PAS содержится на ваших дистрибутивных дискетах.

Установка значений управляющих элементов


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

Для чего используется буфер передачи?


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

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

    Механизм передачи требует для представления управляющих элементов, для которых вы будете передавать данные, использования объектов ObjectWindows. Это означает, что вы должны использовать InitResource для связывания объектов с управляющими элементами в блоках и окнах диалога.

    Примечания: Связь управляющих элементов с управляющими объектами описывается в Главе 11 "Объекты диалоговых блоков".

    Чтобы использовать механизм передачи, вы можете сделать следующее:

Определение буфера передачи


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

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

     type
     TSampleTransferRecord = record
       Stat1: array[0..TextLen-1] of Char; { статический текст }
       Edit1: array[0..TextLen-1] of Char; { текст управляющего
                                        элемента редактирования }
       List1Strings: PStrCollection;      { строки блока списка }
       List1Selection: Integer; { индекс выбранных строк }
       ComboStrings: PStrCollection; { строки комбинированного
                                        блока }
       ComboSelection: array[0..TextLen-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 в указатель на определенный вами буфер передачи.

Использование буфера передачи с диалоговым блоком


    Для случая окон с управляющими элементами объекты управляющих элементов конструируются с использованием 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.

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


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

Передача данных в окно


    После создания окна или диалогового блока данные автоматически. Для создания экранного элемента, представляющего оконный объект, конструктор вызывает SetupWindow. Затем для загрузки данных из буфера передачи вызывается TransferData. Окно SetupWindow интерактивно вызывает SetupWindow для каждого из дочерних окон, так что дочерние окна имеют возможность передать свои данные. Поскольку порождающее окно устанавливает свои дочерние окна в порядке их построения, данные в буфере передачи должны следовать в том же порядке.

    Если объект управляющего элемента был построен с помощью InitResource или если порождающее окно явным образом разрешило межанизм передачи путем вызова для управляющего элемента EnableTransfer, то методы управляющего объекта SetupWindow вызывают TransferData.

Передача данных из диалогового окна


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

Передача данных из окна


    Однако, вы можете явно передавать данные в любом направлении в любой момент времени. Например, вы можете передать данные из управляющих элементов окна или безрежимного диалога. Вы также можете сбросить состояния управляющих элементов, используя данные буфера передачи, в ответ на щелчок "мышью" на кнопке Reset (сброс). В обоих случаях используется метод TransferData. Константа tf_SetData обозначает передачу данных из буфера в управляющий элемент, а константа tf_GetData - передачу в другом направлении. Например, вы можете вызвать TransferData в методе Destroy объекта окна:

     procedure TSampleWindow.Destroy;
     begin
      TransferData(tf_GetData);
      TWindow.Destroy;
     end;

Поддержка передачи для специализированных управляющих элементов


    Вы можете изменить способ передачи данных для конкретного управляющего элемента или включить новый управляющий элемент, определенный вами в механизме передачи. В обоих случаях вам просто нужно написать метод 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 должен всегда возвращать число переданных байт информации.

Пример программы: TranTest


    Основное окно программы TranTest воспроизводит режимный диалог с полями, в которые пользователь вводит данные об имени и адресе. Буфер передачи используется для хранения этой информации и отображения ее в управляющих элементах диалога при повторном его выполнении. Обратите внимание на то, что нам не нужно определять новый тип объекта диалога для установки и поиска данных диалога. Также обратите ваше внимание на то, что мы непосредственно манипулируем данными буфера передачи, поэтому статическое управление при первом выводе диалога гласит "First Mailing Label" (первая почтовая этикетка), а при всех остальных появлениях "Subsequent Mailing Label" (следующая почтовая этикетка).

    Примечание: Полный текст программы содержится в файле TRANTEST.PAS на ваших дистрибутивных дискетах.

Использование специализированных управляющих элементов


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

Специализированные управляющие элементы Borland для Windows


    Специализированные управляющие элементы Borland для Windows (BWCC) обеспечивают выразительный внешний вид приложений Borland для Windows. Основными средствами BWCC являются:

    ObjectWindows дает вам возможность простого доступа к BWCC, так что вы можете придать своим приложениями стандартный для Borland вид.

Использование стандартных BWCC


    ObjectWindows позволяет легко добавлять BWCC в ваши приложения Windows. Нужно просто добавить модуль BWCC в оператор uses программы:

     uses BWCC;

    Использование BWCC автоматически позволяет вам делать следующее:

    Например, с помощью пакета разработчика ресурсов Resource WorkShop вы можете создать ресурсы диалоговых блоков, использующие специализированные управляющие элементы Borland. Включение в оператор uses программы модуля BWCC обеспечивает для вашей программы информацию о том, где искать динамически компонуемую библиотеку (BWCC.DLL), содержащую код, который обеспечивает работу BWCC.

    Кроме того, после добавления модуля BWCC любые создаваемые в программе объекты управляющих элементов будут иметь вид и характеристики управляющих элементов Borland.

Средства BWCC


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

Расширение 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 показан на следующем рисунке:


Рис. 12.9 Графические ресурсы для командной кнопки BWCC с идентификатором 201.

Создание ваших собственных специализированных управляющих элементов


    Простейший способ создания специализированного управляющего элемента состоит в фактическом создании окна, которое действует как управляющий элемент, но вовсе не является окном. Этот подход используется в программе Steps в Части 1 данного руководства. Тот же используемый в программе Steps метод применяется для ее объекта палитры, который можно использовать, например, для создания объекта инструментальной полосы. Таким "управляющие элементы" являются наследниками TWindow, а не TControl, поскольку TControl имеет дело только со стандартными управляющими элементами Windows.

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

    Примечание: О классах окон рассказывается в Главе 10.