При проектировании интерфейсов в «классической» платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с необходимостью повысить удобство ввода данных для конечного пользователя (юзабилити). Одна из таких задач — автоматическое позиционирование курсора (фокуса ввода) на конкретной колонке многострочной части справочника при его открытии. Например, при открытии справочника «Контрагенты» логично сразу направить фокус на колонку Наименование, чтобы пользователь мог мгновенно начать поиск или редактирование, не совершая лишних кликов мышью или нажатий клавиш на клавиатуре.
В этой статье мы подробно разберем, как решить эту задачу различными методами: рассмотрим стандартные механизмы платформы, разберем обходные пути для обхода ограничений интерфейса, проанализируем альтернативный метод с эмуляцией нажатия клавиш через Windows Script Host (WSH) и в качестве полезного бонуса научимся выделять цветом всю строку под курсором с помощью внешней компоненты FormEx.
Для управления фокусом элементов диалога и колонок табличной части в платформе 1С 7.7 предназначен предопределенный метод Активизировать(). Синтаксис этого метода выглядит следующим образом:
Активизировать(ИмяРеквизита, Режим)
Где параметры принимают следующие значения:
"Наименование").1 (или если параметр опущен) переводит ячейку в режим непосредственного редактирования. Значение 0 просто устанавливает фокус на колонку (выделяет ее рамкой) без открытия режима редактирования ячейки.Казалось бы, достаточно просто прописать вызов этого метода в предопределенной процедуре ПриОткрытии() формы списка справочника. Давайте посмотрим на этот пример:
Процедура ПриОткрытии()
// Пытаемся установить фокус на наименование контрагента
Активизировать("Наименование", 0);
КонецПроцедуры
Однако на практике разработчики часто сталкиваются с тем, что этот код при открытии формы игнорируется платформой. Выясним причину такого поведения. Дело в том, что в момент выполнения процедуры ПриОткрытии() форма еще не полностью инициализирована и не отрисована на экране. После завершения этой процедуры ядро 1С 7.7 выполняет стандартный алгоритм обхода элементов интерфейса и принудительно устанавливает фокус на первый элемент в порядке обхода (как правило, это дерево групп справочника слева или самая первая колонка списка).
Чтобы обойти это платформенное ограничение, мы можем применить проверенный временем прием — использование отложенного вызова через обработку ожидания. Суть метода заключается в том, чтобы дать платформе полностью завершить открытие формы, а затем с минимальной задержкой перенаправить фокус в нужное место.
Разберем по шагам, как реализовать этот обходной путь:
ПриОткрытии() мы запускаем таймер с помощью метода ОбработкаОжидания(), передавая имя нашей будущей процедуры фокусировки и интервал в 1 секунду.УстановитьФокусНаКолонку()), в которой первым делом отключаем таймер (чтобы процедура не зациклилась), а затем вызываем метод Активизировать().Посмотрим на пример программного кода, реализующего данный алгоритм:
Процедура УстановитьФокусНаКолонку()
// Отключаем обработку ожидания, чтобы процедура выполнилась единожды
Форма.ОбработкаОжидания("", 0);
// Активизируем колонку "Наименование" без входа в режим редактирования
Активизировать("Наименование", 0);
КонецПроцедуры
Процедура ПриОткрытии()
// Запускаем отложенный вызов процедуры фокусировки
Форма.ОбработкаОжидания("УстановитьФокусНаКолонку", 1);
КонецПроцедуры
Этот простой и изящный прием гарантирует, что колонка будет успешно активизирована сразу после того, как форма появится на экране пользователя.
В процессе обсуждения подобных задач разработчики иногда путают методы Активизировать() и АктивизироватьОбъект(). Давайте четко разграничим сферы их применения, так как они управляют совершенно разными направлениями перемещения курсора:
Активизировать() управляет фокусом по горизонтали. Он указывает, в каком именно столбце таблицы (или на каком элементе управления диалога) должен находиться курсор ввода. В качестве параметра он принимает строковое имя колонки.АктивизироватьОбъект() позиционирует курсор по вертикали. Он находит нужную строку в списке справочника или журнала документов и устанавливает выделение на нее. В качестве параметра он принимает ссылку на конкретный элемент справочника или документ (объект типа Справочник.Контрагенты, Документ и т.д.).Таким образом, для решения нашей задачи — позиционирования на колонке — использовать АктивизироватьОбъект() технически не имеет смысла, однако эти два метода отлично работают в паре, если вам нужно открыть справочник, спозиционироваться на конкретном контрагенте по вертикали и сразу подсветить его наименование по горизонтали.
Существует альтернативный способ решения задачи, основанный на эмуляции нажатия клавиш клавиатуры. Для этого используется системный COM-объект операционной системы Windows — WScript.Shell и его метод SendKeys().
Проанализируем пример кода, который эмулирует нажатие клавиши Home (перевод курсора в самое начало строки списка) и последующее нажатие стрелки вправо для перехода на вторую колонку:
Процедура ПриОткрытии()
Попытка
WSHShell = СоздатьОбъект("WScript.Shell");
// Отправляем в буфер клавиатуры нажатие клавиши HOME и стрелки ВПРАВО
WSHShell.SendKeys("{HOME}{RIGHT}");
Исключение
// Обработка ситуации, когда объект WSH недоступен в системе
Предупреждение("Не удалось инициализировать WScript.Shell для эмуляции клавиатуры!");
КонецПопытки;
КонецПроцедуры
Важное предупреждение: Несмотря на то что этот метод работоспособен и часто применяется на практике, мы крайне не рекомендуем использовать его в качестве основного решения. Рассмотрим подробнее его ключевые недостатки:
{HOME}{RIGHT} сработает корректно только в том случае, если целевая колонка всегда находится на второй позиции слева. Если пользователь интерактивно перетащит колонки местами, скроет одну из них или разработчик изменит их порядок в конфигураторе, фокус гарантированно встанет на другую (ошибочную) колонку.Разберем еще один интересный юзабилити-кейс, который упоминался участниками обсуждения. По умолчанию в списках 1С 7.7 при навигации подсвечивается только одна активная ячейка таблицы. Для удобства пользователей часто требуется сделать «курсор на всю строку» — то есть подсвечивать всю строку цветом при перемещении по справочнику.
Для реализации этого поведения нам понадобится популярная внешняя компонента FormEx, которая расширяет возможности отображения интерфейса в 1С 7.7. Сделать это можно двумя способами.
Этот способ прост в реализации и не требует сложного программирования:
ЗагрузитьВнешнююКомпоненту("formex.dll") в глобальном модуле)."BRUSH_S[0xCCCCCC]"
Макрос BRUSH_S указывает компоненте FormEx, что необходимо закрасить фон текущей выбранной строки (Selected). В квадратных скобках передается шестнадцатеричный код цвета в формате RGB (в данном примере 0xCCCCCC — это светло-серый цвет). Текст при этом остается хорошо читаемым.
При быстрой прокрутке больших списков классический метод через формулы в колонках может приводить к микрофризам («тормозам») интерфейса, так как формула вычисляется для каждой отрисовываемой строки. В современных версиях FormEx реализован более производительный механизм — План раскраски.
Для его настройки выполним следующие действия:
FormEx_ПланРаскраски (регистр значения не имеет). Сделаем ширину этой колонки равной 0 или скроем ее программно.ПриОткрытии()) инициализируем план раскраски:
Процедура ПриОткрытии()
// Создаем объект Сервис из компоненты FormEx
Сервис = СоздатьОбъект("Сервис");
// Включаем использование плана раскраски для формы
Сервис.ИспользоватьПланРаскраски(1);
КонецПроцедуры
Теперь компонента автоматически считывает значения из колонки FormEx_ПланРаскраски. Чтобы подсветить строку под курсором, достаточно в формулу этой колонки поместить шаблон вида "(BRUSH_S[0xCCCCCC])". Данный метод работает непосредственно на уровне отрисовки WinAPI и обеспечивает плавный скроллинг списков любого объема.
Мы детально изучили методы позиционирования курсора на колонках справочников в 1С 7.7. Настоятельно рекомендуем использовать штатное решение на базе метода Активизировать() в сочетании с отложенным запуском через ОбработкаОжидания(), избегая нестабильной эмуляции клавиатуры через WSH.