Как использовать элементы ActiveX в 1С 7.7 и управлять прогресс-баром (ProgressBar) без ошибок?

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

При разработке интерфейсов на платформе 1С 7.7 стандартных элементов управления часто бывает недостаточно. Для реализации красивых закладок, деревьев (TreeView), списков (ListView) или индикаторов процесса (ProgressBar) программисты часто прибегают к использованию внешних ActiveX-компонентов из стандартной библиотеки Windows — MSComCtlLib. Однако при работе с ними разработчики сталкиваются с двумя главными проблемами: отсутствием встроенной документации по методам объектов в 1С и ошибками при попытке принудительного обновления элементов на форме.

В этой статье мы подробно разберем, как быстро находить доступные свойства и методы любых ActiveX-компонентов, рассмотрим правильный способ создания элементов управления на форме 1С 7.7, решим проблему зависания и ошибок метода Refresh(), а также проанализируем стабильные альтернативные варианты реализации интерфейса.

Как найти методы и свойства ActiveX-компонентов?

Поскольку среда разработки 1С 7.7 не имеет встроенного автодополнения (IntelliSense) для внешних OLE- и ActiveX-объектов, информацию об их структуре приходится искать во внешних источниках. Самый простой, быстрый и надежный способ узнать состав свойств, методов и событий любого установленного в системе ActiveX-контрола — это использование обозревателя объектов (Object Browser) в пакете Microsoft Office.

Разберем этот процесс по шагам:

  1. Запустите текстовый процессор Microsoft Word или табличный редактор Microsoft Excel.
  2. Перейдите в редактор макросов VBA, нажав комбинацию клавиш Alt + F11.
  3. Откройте встроенный обозреватель объектов, нажав клавишу F2 (или выбрав в верхнем меню View -> Object Browser).
  4. В выпадающем списке библиотек (в левом верхнем углу, где по умолчанию выбрано <All Libraries>) найдите нужную библиотеку, например MSComCtlLib.
  5. Если нужной библиотеки в списке нет, ее необходимо подключить вручную. Для этого перейдите в меню Tools -> References, найдите в списке нужный компонент (например, Microsoft Windows Common Controls) и отметьте его галочкой. Если файла нет в списке, нажмите кнопку Browse и укажите прямой путь к файлу библиотеки (например, к файлу MSCOMCTL.OCX в системной директории).
  6. После подключения выберите библиотеку в Object Browser. В левом списке вы увидите доступные классы (например, ProgressBar, TreeView, ImageList), а в правом — все их методы, свойства и события с указанием типов передаваемых параметров.

Создание ActiveX-контрола на форме 1С 7.7

Для того чтобы внедрить ActiveX-элемент на форму в 1С 7.7, обычно используется внешняя компонента 1С++ или Йоксель, предоставляющая класс АктивИкс. Рассмотрим пример функции, которая инициализирует элемент управления и связывает его с атрибутом формы:


Функция СоздатьКонтрол(ИмяКонтрола, ИмяАтрибутаФормы)
    АктивХ = СоздатьОбъект("АктивИкс");
    АктивХ.УстановитьАтрибут(Форма, ИмяАтрибутаФормы);
    АктивХ.СоздатьЭУ(ИмяКонтрола);
    Возврат АктивХ.Объект;
КонецФункции

В этом коде мы создаем объект класса АктивИкс, позиционируем его на форме поверх заранее подготовленного пустого текстового атрибута с идентификатором ИмяАтрибутаФормы и инициализируем сам элемент управления по его программному идентификатору (ProgID). Функция возвращает непосредственный OLE-объект, с методами и свойствами которого мы и будем работать в кодовой базе 1С.

Проблема с методом Refresh() в ProgressBar и её решение

Рассмотрим типичный сценарий использования прогресс-бара из библиотеки MSComCtlLib.ProgCtrl.2. Разработчики часто пытаются обновлять состояние индикатора в цикле следующим образом:


Прог = СоздатьКонтрол("MSComCtlLib.ProgCtrl.2", "Prog");
Прог.Min = 1;
Прог.Max = 100000;
Для ы = 1 По 100000 Цикл
    Прог.Value = ы;
    // Попытка принудительно обновить элемент
    Прог.Refresh(); // Вызывает ошибку IDispatch!
КонецЦикла;

При запуске такого кода система выдает ошибку на строке Прог.Refresh(). Выясним причину этого поведения. Дело в том, что стандартный контейнер 1С 7.7 не всегда корректно транслирует вызовы интерфейса IDispatch для некоторых системных методов элементов ActiveX. Прямой вызов Refresh() отвергается OLE-контейнером.

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

Как правильно решить проблему отрисовки?

Во-первых, в операционных системах Windows изменение свойства Value у элемента ProgressBar автоматически отправляет системе сигнал на перерисовку (событие WM_PAINT) конкретно для этого элемента. Дополнительный вызов Refresh() или Форма.Обновить() просто не требуется. Код работает корректно и без них:


Для ы = 1 По 100000 Цикл
    Прог.Value = ы;
КонецЦикла;

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


ВсегоОпераций = 100000;
Прог.Min = 0;
Прог.Max = 100;
ПредыдущийПроцент = -1;

Для ы = 1 По ВсегоОпераций Цикл
    // Выполняем полезную работу...
    
    ТекущийПроцент = Цел((ы / ВсегоОпераций) * 100);
    Если ТекущийПроцент <> ПредыдущийПроцент Тогда
        Прог.Value = ТекущийПроцент;
        ПредыдущийПроцент = ТекущийПроцент;
    КонецЕсли;
КонецЦикла;

Такой подход снижает количество обращений к графической подсистеме Windows с 100 000 до 100 раз. Скорость выполнения операции при этом возрастает в разы, а индикатор заполняется плавно и красиво.

Ограничения платформы 1С 7.7 при работе с ActiveX

При использовании компонентов из библиотеки MSComCtlLib на современных операционных системах (Windows 10, Windows 11, Windows Server) важно учитывать следующие ограничения:

Альтернативные варианты реализации индикатора процесса

Если вы хотите избежать проблем с регистрацией внешних ActiveX-библиотек на компьютерах пользователей, рассмотрим более надежные и простые альтернативы.

1. Использование внешней компоненты FormEx

Популярная библиотека FormEx предоставляет собственный встроенный объект класса ПрогрессБар. Он работает стабильно, не требует регистрации сторонних OCX-файлов в реестре Windows и может быть легко размещен как в любом месте формы, так и непосредственно внутри системной строки состояния (Status Bar) внизу экрана.

2. Текстовая псевдографика в строке состояния (без внешних компонент)

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


ВсегоШагов = 500;
Для Шаг = 1 По ВсегоШагов Цикл
    // Полезный код алгоритма...
    
    Процент = Цел((Шаг / ВсегоШагов) * 100);
    Шкала = СтрЗаменить(Формат("", "С" + Цел(Процент / 5)), " ", "|");
    Состояние("Обработка данных: " + Процент + "% [" + ФиксШирина(Шкала, 20, ".") + "]");
КонецЦикла;

В данном примере функция Формат("", "С" + Число) генерирует строку из пробелов заданной длины, которая затем заменяется на символы-разделители "|". Этот способ работает мгновенно, не вызывает мерцания интерфейса и гарантированно откроется на любом компьютере без установки дополнительных библиотек.

3. Использование HTML-контейнера (Shell.Explorer.2)

Вместо нестабильных библиотек ActiveX на форму можно поместить стандартный браузерный контейнер через ProgID "Shell.Explorer.2". Сам прогресс-бар в этом случае верстается на CSS и HTML, а управление его состоянием и анимацией происходит с помощью простых скриптов на JavaScript, передаваемых из кода 1С. Это дает неограниченные возможности для стилизации интерфейса под любые современные стандарты дизайна.

← На главную