Как определить позицию текстового курсора в поле ввода 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Платформа 1С предоставляет встроенный механизм для работы с позицией текстового курсора и границами выделения в элементах управления типа «Поле ввода» (ПолеВвода) и «Поле текстового документа» (ТекстовыйДокумент). Основным инструментом для этого является метод ПолучитьГраницыВыделения.

Основы работы с методом ПолучитьГраницыВыделения

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

Синтаксис метода:

ЭлементФормы.ПолучитьГраницыВыделения(НачалоСтроки, НачалоКолонки, КонецСтроки, КонецКолонки)

Где:

  1. НачалоСтроки: Выходной параметр (передается по ссылке), возвращает номер строки, где начинается выделение или находится курсор. Нумерация строк начинается с 1.
  2. НачалоКолонки: Выходной параметр (передается по ссылке), возвращает номер колонки (позиции символа) в строке, где начинается выделение или находится курсор. Нумерация колонок также начинается с 1.
  3. КонецСтроки: Выходной параметр (передается по ссылке), возвращает номер строки, где заканчивается выделение.
  4. КонецКолонки: Выходной параметр (передается по ссылке), возвращает номер колонки (позиции символа) в строке, где заканчивается выделение.

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

Рассмотрим, как мы можем использовать этот метод для получения координат:

Пример 1: Определение координат курсора или выделения

Для начала нам понадобится элемент формы типа «Поле ввода». Предположим, у нас есть поле ввода, которое связано с реквизитом формы типа «Строка» или «ТекстовыйДокумент». Мы создадим структуру для удобного хранения полученных координат, хотя можно использовать и отдельные переменные.

Предположим, у нас есть элемент формы с именем Элементы.МоеПолеВвода.


// Создаем структуру для хранения границ выделения
ГраницыВыделения = Новый Структура("НачалоСтроки, НачалоКолонки, КонецСтроки, КонецКолонки");

// Вызываем метод ПолучитьГраницыВыделения для нашего элемента
Элементы.МоеПолеВвода.ПолучитьГраницыВыделения(
    ГраницыВыделения.НачалоСтроки,
    ГраницыВыделения.НачалоКолонки,
    ГраницыВыделения.КонецСтроки,
    ГраницыВыделения.КонецКолонки
);

// Теперь в полях структуры ГраницыВыделения будут содержаться значения.
// Например, если курсор находится в 6-й позиции 1-й строки, значения будут: 1, 6, 1, 6.
// Если выделен текст с 1-й позиции 1-й строки по 5-ю позицию 2-й строки, значения будут: 1, 1, 2, 5.

Сообщить("Начало строки: " + ГраницыВыделения.НачалоСтроки);
Сообщить("Начало колонки: " + ГраницыВыделения.НачалоКолонки);
Сообщить("Конец строки: " + ГраницыВыделения.КонецСтроки);
Сообщить("Конец колонки: " + ГраницыВыделения.КонецКолонки);

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

Работа с многострочными полями и элементом "ТекстовыйДокумент"

Когда мы работаем с многострочными полями ввода или с элементом ТекстовыйДокумент, который специально предназначен для редактирования больших объемов текста, координатная система (Строка, Колонка) становится особенно полезной. Например, в текстовом редакторе или редакторе запросов 1С, такая информация позволяет точно позиционировать курсор в любой точке большого текста.

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

Синтаксис метода УстановитьГраницыВыделения:

ЭлементФормы.УстановитьГраницыВыделения(НачалоСтроки, НачалоКолонки, КонецСтроки, КонецКолонки)

Этот метод принимает те же четыре параметра, что и ПолучитьГраницыВыделения, и позволяет программно установить позицию курсора или создать выделение. Если требуется установить только курсор, то значения НачалоСтроки и КонецСтроки, а также НачалоКолонки и КонецКолонки должны быть одинаковыми.

Пример 2: Определение типа выделения (курсор или текст) и восстановление позиции

Предположим, у нас на форме есть реквизит с именем "ДокументРедактирование" типа "ТекстовыйДокумент", который перетащен на форму и имеет то же имя. Мы хотим определить, находится ли в нем просто курсор или выделен какой-либо текст, а также восстановить позицию курсора после возможных изменений.


// Объявляем переменные для хранения границ выделения
СтрокаНачало = 0;
КолонкаНачало = 0;
СтрокаОкончание = 0;
КолонкаОкончание = 0;

// Получаем ссылку на элемент формы "ДокументРедактирование"
Элемент = Элементы.ДокументРедактирование;

// Получаем текущие границы выделения
Элемент.ПолучитьГраницыВыделения(СтрокаНачало, КолонкаНачало, СтрокаОкончание, КолонкаОкончание);

// Определяем, что является текущим состоянием: курсор или выделение
Результат = "";
Если СтрокаНачало = СтрокаОкончание И КолонкаНачало = КолонкаОкончание Тогда
    Результат = "Это курсор";
Иначе
    Результат = "Это выделение";
КонецЕсли;

Сообщить(Результат); // Выводим результат определения

// Здесь может быть ваш код для манипуляций с текстом,
// например, добавление или удаление части текста.
// После таких операций курсор часто сбрасывается в начало поля.
// Для демонстрации, можем изменить текст:
// Элемент.Текст = "Новый текст для проверки.";

// Для обновления отображения данных на форме (если текст был изменен программно)
ЭтаФорма.ОбновитьОтображениеДанных();

// Восстанавливаем позицию курсора или выделения.
// Это критически важно для сохранения пользовательского опыта.
Элемент.УстановитьГраницыВыделения(СтрокаНачало, КолонкаНачало, СтрокаОкончание, КолонкаОкончание);

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

Продвинутый сценарий: Вставка текста по позиции курсора

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

Рассмотрим функцию, которая вставляет переданную строку по текущей позиции курсора в элемент типа ТекстовыйДокумент.

Пример 3: Функция вставки текста по позиции курсора

Предположим, у нас есть реквизит формы ТекстЗапроса, к которому привязан элемент формы типа Поле текстового документа. Данная процедура будет выполняться на клиенте, поэтому мы используем директиву &НаКлиенте.


&НаКлиенте
Процедура ВставитьТекстПоПозицииКурсора(ДобавляемаяСтрока)

    // 1. Получаем текущие границы выделения или позицию курсора
    // Эти переменные будут содержать координаты до изменения текста
    СтрокаНачало = 0;
    КолонкаНачало = 0;
    СтрокаОкончание = 0;
    КолонкаОкончание = 0;
    Элементы.ТекстЗапроса.ПолучитьГраницыВыделения(СтрокаНачало, КолонкаНачало, СтрокаОкончание, КолонкаОкончание);

    // Получаем текущий текст из реквизита формы
    ТекущийТекст = ТекстЗапроса;

    // 2. Создаем массив для хранения модифицированных строк.
    // Мы будем перестраивать текст по строкам.
    МассивСтрок = Новый Массив;

    // 3. Проходим по всем строкам текущего текста.
    // Используем СтрЧислоСтрок для определения общего количества строк.
    Для СчетчикСтрок = 1 по СтрЧислоСтрок(ТекущийТекст) цикл

        // Получаем текущую строку для обработки
        ТекущаяСтрока = СтрПолучитьСтроку(ТекущийТекст, СчетчикСтрок);

        // 4. Если это не строка, в которую нужно вставить текст, просто добавляем ее в массив без изменений
        Если СчетчикСтрок <> СтрокаНачало Тогда
            МассивСтрок.Добавить(ТекущаяСтрока);
        Иначе // Мы нашли строку, в которую нужно произвести вставку
            МассивТекущейСтрокиЧасти = Новый Массив;
            // Добавляем часть строки до курсора.
            // КолонкаНачало - 1, потому что КолонкаНачало - это позиция символа,
            // а Лев извлекает N символов СЛЕВА. Если курсор на 1-м символе,
            // то часть "до" курсора пустая.
            МассивТекущейСтрокиЧасти.Добавить(Лев(ТекущаяСтрока, КолонкаНачало - 1));
            // Добавляем вставляемую строку целиком
            МассивТекущейСтрокиЧасти.Добавить(ДобавляемаяСтрока);
            // Добавляем часть строки после курсора.
            // Сред извлекает подстроку, начиная с указанной позиции.
            // Если курсор на 1-м символе, то Сред(ТекущаяСтрока, 1) вернет всю строку.
            МассивТекущейСтрокиЧасти.Добавить(Сред(ТекущаяСтрока, КолонкаНачало));
            // Соединяем части текущей строки (до + вставляемая + после) и добавляем в общий массив строк
            МассивСтрок.Добавить(СтрСоединить(МассивТекущейСтрокиЧасти));
        КонецЕсли;

    КонецЦикла;

    // 5. Соединяем все строки массива обратно в единый текст.
    // Используем Символы.ПС (перенос строки) как разделитель, чтобы восстановить многострочный формат.
    ТекстЗапроса = СтрСоединить(МассивСтрок, Символы.ПС);

    // 6. Обновляем отображение данных на форме, чтобы изменения были видны пользователю
    ЭтаФорма.ОбновитьОтображениеДанных();

    // 7. Восстанавливаем позицию курсора.
    // Курсор должен встать после вставленного текста.
    // Поэтому мы корректируем КолонкаНачало, прибавляя к ней длину ДобавляемаяСтрока.
    // Если изначально было выделение, оно будет сброшено, и курсор встанет в новую позицию.
    НовоеНачалоКолонки = КолонкаНачало + СтрДлина(ДобавляемаяСтрока);
    Элементы.ТекстЗапроса.УстановитьГраницыВыделения(СтрокаНачало, НовоеНачалоКолонки, СтрокаНачало, НовоеНачалоКолонки);

КонецПроцедуры

Пояснения к примеру:

  1. Мы сначала получаем текущие координаты курсора или выделения с помощью ПолучитьГраницыВыделения. Это позволяет нам точно знать, куда вставлять текст.
  2. Далее мы итерируем по строкам исходного текста. Функции СтрЧислоСтрок и СтрПолучитьСтроку помогают нам работать с многострочным текстом как с набором отдельных строк, что является эффективным способом манипуляции.
  3. Когда мы находим строку, в которой находится курсор (или начинается выделение), мы разбиваем эту строку на две части: до курсора и после курсора.
  4. Между этими двумя частями мы вставляем ДобавляемаяСтрока. Функции Лев и Сред используются для извлечения частей строки. Важно помнить, что нумерация колонок начинается с 1. Поэтому для извлечения части до курсора мы используем КолонкаНачало - 1, а для части после курсора — КолонкаНачало, так как Сред включает символ, находящийся по указанной позиции.
  5. После модификации текущей строки, мы собираем весь текст обратно с помощью СтрСоединить, используя Символы.ПС для восстановления переносов строк, и обновляем реквизит формы ТекстЗапроса.
  6. Наконец, мы восстанавливаем позицию курсора. В данном случае, если текст был вставлен, курсор должен переместиться в конец вставленного текста. Поэтому мы корректируем КолонкаНачало, прибавляя к ней длину вставленной строки с помощью СтрДлина(). Метод УстановитьГраницыВыделения используется для установки новой позиции курсора.

Общие рекомендации и особенности

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

← На главную