Учись программированию на C++ Builder бесплатно!
  • Главная
  • 5 последовательностей фокусировки элементов
5 последовательностей фокусировки элементов

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

Свойство формы ActiveControl, установленное в процессе проектирования, определяет, какой из размещенных на форме компонентов будет в фокусе в первый момент при выполнении приложения. В процессе выполнения это свойство изменяется и показывает тот компонент, который в данный момент находится в фокусе.

Последовательность табуляции задается свойствами TabOrder компонентов. Первоначальная последовательность табуляции определяется просто той последовательностью, в которой размещались управляющие элементы на форме. Первому элементу присваивается значение TabOrder, равное 0, второму 1 и т.д. Значение TabOrder, равное нулю, означает, что при первом появлении формы на экране в фокусе будет именно этот компонент (если не задано свойство формы ActiveControl). Если на форме имеются панели, фреймы и иные контейнеры, включающие в себя другие компоненты, то последовательность табуляции составляется независимо для каждого компонента-контейнера. Например, для формы будет последовательность, включающая некоторую панель как один компонент. А уже внутри этой панели будет своя последовательность табуляции, определяющая последовательность получения фокуса ее дочерними оконными компонентами.

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

Из-за того, что при изменении TabOrder одного компонента могут меняться TabOrder других компонентов, устанавливать эти свойства поочередно в отдельных компонентах трудно. Поэтому в среде проектирования C++Builder имеется специальная команда Edit | Tab Order, позволяющая в режиме диалога задать последовательность табуляции всех элементов.

Значение свойства TabOrder играет роль только, если другое свойство компонента TabStop установлено в true и если компонент имеет родителя. Например, для формы свойство TabOrder имеет смысл только в случае, если для формы задан родитель в виде другой формы. Установка TabStop в false приводит к тому, что компонент выпадает из последовательности табуляции и ему невозможно передать фокус клавишей Tab (однако предать фокус мышью, конечно, можно).

Имеется и программная возможность переключения фокуса это метод SetFocus. Например, если нужно переключить в какой-то момент фокус на окно Edit2, можно сделать это оператором:

Edit2->SetFocus();

Выше говорилось, что в приложении с несколькими окнами редактирования, в которые пользователь должен поочередно вводить какие-то данные, ему удобно переключаться между окнами клавишей табуляции. Но еще удобнее пользователю, закончившему ввод в одном окне, нажать клавишу Enter и автоматически перейти к другому окну. Это можно сделать, обрабатывая событие нажатия клавиши OnKeyDown. Например, если после ввода данных в окно Edit1 пользователю надо переключаться в окно Edit2, то обработчик события OnKeyDown окна Edit1 можно сделать следующим:

void __fastcall TForm1::Edit1KeyDown(TObject *Sender, WORD $Key, TShiftState Shift)
{
if(Key == VK_RETURN) Edit2->SetFocus();
}

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

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

TWinControl* __fastcall FindNextControl(TWinControl* CurControl, bool GoForward, bool CheckTabStop, bool CheckParent);

Он находит и возвращает следующий за указанным в параметре CurControl дочерний оконный компонент в соответствии с последовательностью табуляции.

Параметр GoForward определяет направление поиска. Если он равен true, то поиск проводится вперед и возвращается компонент, следующий за CurControl. Если же параметр GoForward равен false, то возвращается предшествующий компонент.

Параметры CheckTabStop и CheckParent определяют условия поиска. Если CheckTabStop равен true, то просматриваются только компоненты, в которых свойство TabStop установлено в true. При CheckTabStop равном false значение TabStop не принимается во внимание. Если параметр CheckParent равен true, то просматриваются только компоненты, в свойстве Parent которых указан данный оконный элемент, т.е. просматриваются только прямые потомки. Если CheckParent равен false, то просматриваются все, даже косвенные потомки данного элемента.

Таким образом, для решения поставленной задачи автоматической передачи фокуса при нажатии клавиши Enter, можно написать единый обработчик событий OnKeyDown всех интересующих оконных компонентов, содержащий оператор:

if(Key == VK_RETURN) FindNextControl((TWinControl *)Sender, true, true, false)->SetFocus();

Этот оператор обеспечивает передачу фокуса очередному компоненту. Для кнопок аналогичный оператор можно вставить в обработчик события OnClick:

FindNextControl((TWinControl *)Sender, true, true, false)->SetFocus();

В приведенных кодах используется параметр Sender, передаваемый во все обработчики событий и соответствующий тому компоненту, в котором произошло событие. Этот параметр имеет тип TObject. А поскольку функция FindNextControl требует параметр объекта типа TWinControl, необходимо явным образом привести тип TObject к производному от него типу TWinControl с помощью операции (TWinControl *)Sender.

Поделиться