Как определить позицию курсора в многострочной строке на форме 1С 7.7 и реализовать программную вставку текста?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В платформе 1С:Предприятие 7.7 работа с текстовыми полями на формах сильно ограничена. Стандартный элемент управления "Текст" или "Поле ввода" с признаком Многострочный не предоставляет штатных методов для определения текущей позиции курсора (номера строки и колонки). Это создает сложности, если нам требуется реализовать функционал «умной» вставки текста, автозамены или верстки документа непосредственно внутри формы. Рассмотрим несколько подходов к решению этой задачи: от использования внешних компонентов и ActiveX до имитации действий пользователя.

Вариант 1. Использование специализированного ActiveX-элемента

Одним из наиболее эффективных способов получить контроль над курсором является замена стандартного поля ввода 1С на ActiveX-объект, например, Microsoft Forms 2.0 TextBox. В отличие от штатного поля 1С, этот объект обладает свойствами SelStart и SelLength, которые позволяют точно узнать, где находится фокус ввода.

Проанализируем алгоритм реализации этого метода:

  1. Разместим на форме элемент ActiveX (класс Forms.TextBox.1).
  2. Настроим его свойства для поддержки многострочности. Установим MultiLine = -1 и EnterKeyBehavior = -1.
  3. Для получения текущей позиции курсора обратимся к свойству SelStart. Оно возвращает порядковый номер символа от начала текста.

Рассмотрим пример кода, который позволяет программно вставить заготовленный текст в то место, где находится курсор пользователя:


// Предположим, что ЭлементТекст — это наш ActiveX объект на форме
ТекстДляВставки = " [Тут наш спецсимвол] ";
ПозицияКурсора = Форма.ЭлементТекст.SelStart;
ТекущийТекст = Форма.ЭлементТекст.Value;

// Разбиваем текст на две части и вставляем новую строку
ЛеваяЧасть = Лев(ТекущийТекст, ПозицияКурсора);
ПраваяЧасть = Сред(ТекущийТекст, ПозицияКурсора + 1);

Форма.ЭлементТекст.Value = ЛеваяЧасть + ТекстДляВставки + ПраваяЧасть;

// Возвращаем курсор в позицию после вставленного текста
Форма.ЭлементТекст.SelStart = ПозицияКурсора + СтрДлина(ТекстДляВставки);

Важное примечание: При использовании этого метода на современных версиях Windows (10 и 11) может потребоваться регистрация библиотеки FM20.DLL. Также стоит учитывать, что события клавиатуры могут перехватываться самой оболочкой 1С, поэтому иногда требуется создавать объект не просто на форме, а внутри контейнера, поддерживающего события.

Вариант 2. Интеграция внешнего HTML-редактора (TinyMCE)

Если задача заключается не просто во вставке текста, а в полноценной верстке (выделение жирным, таблицы, спецсимволы), рационально использовать механизм Internet Explorer внутри формы 1С, загрузив в него редактор TinyMCE. Это решение позволяет работать с текстом как с объектом DOM.

Для корректной передачи данных между 1С и HTML-редактором нам потребуются функции очистки и подготовки строк. Проанализируем набор вспомогательных функций для работы с HTML-содержимым:


// Функция проверки, является ли строка HTML-текстом
Функция IsHTML(стр) Экспорт
    Если Найти(стр, "<br />") > 0 Тогда
        Возврат 1;
    ИначеЕсли Найти(стр, "<table") > 0 Тогда
        Возврат 1;
    КонецЕсли;
    Возврат 0;
КонецФункции

// Преобразование обычных разрывов строк 1С в теги HTML
Функция HTML_LineBreaks(стр) Экспорт
    Возврат СтрЗаменить(стр, РазделительСтрок, "<br />");
КонецФункции

// Обратное преобразование HTML в простой текст
Функция ToPlainText(Знач стр) Экспорт
    стр = СтрЗаменить(стр, "<br />", РазделительСтрок);
    стр = СтрЗаменить(стр, "&nbsp;", " ");
    стр = СтрЗаменить(стр, "<p>", "");
    стр = СтрЗаменить(стр, "</p>", РазделительСтрок);
    Возврат стр;
КонецФункции

Для экранирования спецсимволов при передаче данных в JavaScript-движок редактора можно использовать MSScriptControl.ScriptControl. Это поможет избежать ошибок синтаксиса при наличии кавычек в тексте. Рассмотрим реализацию:


Функция стрЭкранироватьСпецСимволы(стр) Экспорт
    ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
    ScrptCtrl.Language = "jscript";
    ScrptCtrl.AddCode(
    "function quote(str)
    |{
    |    str = str.replace(/\r\n/g, '<br>');
    |    str = str.replace(/\n\r/g, '<br>');
    |    str = str.replace('\r', '<br>');
    |    str = str.replace('\n', '<br>');
    |    str = str.replace('\'', '\\\'');
    |    str = str.replace('\"', '\\\"');
    |    return str;
    |}
    |");
    Возврат ScrptCtrl.CodeObject.quote(стр);
КонецФункции

Вариант 3. Метод посимвольного сравнения («Хак»)

Если использование внешних компонентов невозможно, разберем более примитивный, но рабочий способ. Мы можем временно изменить текст и проанализировать изменения. Выясним алгоритм действий:

  1. Пользователь нажимает кнопку «Вставить».
  2. Программа запоминает текущее содержимое поля.
  3. Программа программно устанавливает фокус в поле ввода (если он был потерян).
  4. Имитируется ввод уникального символа-метки (например, редкого символа типа «~» или «¶»).
  5. Сравниваются старая и новая версии строки.
  6. Позиция, в которой появился новый символ, и есть позиция курсора.
  7. Символ-метка заменяется на нужный нам текст.

Этот метод не всегда стабилен, так как программно «нажать» клавишу в 1С 7.7 без внешних библиотек сложно, но его можно реализовать через WScript.Shell.

Вариант 4. Использование Windows API (SendMessage)

Наиболее профессиональный подход для платформы 7.7 заключается в использовании внешней компоненты FormEx, которая позволяет получить HWND (идентификатор окна) элемента управления формы. Имея HWND, мы можем отправить окну стандартное сообщение Windows EM_GETSEL.

Разберем, как это работает на низком уровне:

Посмотрим на пример логики (требуется наличие FormEx):


// Примерный алгоритм получения позиции через WinAPI
Расширение = СоздатьОбъект("РасширениеФормы");
ХендлПоля = Расширение.ПолучитьHWND("ИмяВашегоРеквизита");

// Здесь вызывается SendMessage из внешней DLL
// Результат даст нам позицию курсора в байтах/символах
Позиция = WinAPI_SendMessage(ХендлПоля, 176, 0, 0); // 176 - это константа EM_GETSEL

Вариант 5. Эмуляция вставки через буфер обмена

Если нам не нужно знать точные координаты (строку/символ), а нужно просто вставить текст «здесь и сейчас», можно воспользоваться объектом WScript.Shell. Рассмотрим этот простой метод:

  1. Копируем необходимый текст в буфер обмена (например, через объект htmlfile).
  2. Активируем поле ввода на форме.
  3. Вызываем метод SendKeys для имитации нажатия Ctrl+V.

Проанализируем код:


// Вставляем текст в буфер обмена
ОбъектШелл = СоздатьОбъект("WScript.Shell");
// Код для записи в Clipboard (можно использовать стороннюю компоненту)
// ...
// Имитируем вставку
ОбъектШелл.SendKeys("^{v}"); 

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

Резюме

Мы рассмотрели несколько подходов к определению позиции курсора в 1С 7.7. Для простых задач идеально подойдет имитация нажатия клавиш или использование буфера обмена. Если же вы разрабатываете сложный интерфейс для редактирования текстов, стоит посмотреть в сторону ActiveX MS Forms 2.0 или интеграции TinyMCE через HTML-поле. Для максимально глубокой интеграции в ОС Windows оптимальным выбором будет использование WinAPI совместно с компонентой FormEx.

← На главную