Как правильно обновлять Табличное Поле в 1С 7.7 при использовании 1C++ и ПоставщикаДанныхИТ?

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

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

Анализ механизмов обновления данных

Для начала проанализируем, почему возникает мерцание. В связке ТабличноеПоле + ПоставщикДанныхИТ + ИндексированнаяТаблица (ИТ) данные хранятся в объекте ИТ, а провайдер (ПоставщикДанных) выступает мостом между таблицей в памяти и визуальным элементом управления. Когда мы добавляем строку в ИТДанные и вызываем методы обновления ТП, элемент управления Windows перерисовывает свои границы и содержимое.

В компоненте 1С++ существуют два основных метода для обновления визуального состояния:

  1. ОбновитьСтроки() (RefreshRows) — этот метод заставляет ТП полностью сбросить внутренний кэш и перечитать данные из провайдера. Это "тяжелая" операция, вызывающая полную перерисовку.
  2. ПерерисоватьСтроки() (RedrawRows) — более легкий метод. Согласно документации, он обновляет строки без обращения к провайдеру, инициируя стандартное событие перерисовки окна (Windows Invalidate).

Посмотрим на классический пример кода, который часто приводит к мерцанию:


// В цикле обработки
ИТДанные.НоваяСтрока();
ИТДанные.ТекстСообщения = "Обработка объекта " + ТекущийОбъект;
мТабличноеПоле.ТекущаяСтрока = ИТДанные.КоличествоСтрок();
мТабличноеПоле.ОбновитьСтроки();

Борьба с мерцанием: влияние вертикального скроллера

Выясним причину, по которой интерфейс "прыгает". Экспериментальным путем установлено, что основное влияние на визуальную стабильность оказывает полоса прокрутки (вертикальный скроллер). Если свойство ВертСкроллер установлено в значение 1 (всегда включен), то при добавлении каждой строки Windows пересчитывает размер "бегунка" и положение всей клиентской области окна.

Разберем ситуацию: мерцание наиболее заметно, пока таблица не заполнена полностью (то есть количество строк меньше высоты видимой части ТП). Как только данных становится много и появляется необходимость прокрутки, поведение меняется.

Рекомендация: попробуем использовать автоматический режим скроллера. Вместо жесткой установки мТабличноеПоле.ВертСкроллер = 1;, лучше оставить его в авторежиме или управлять им динамически. Это значительно снижает количество лишних перерисовок рамки окна.

Оптимизация частоты обновлений

Рассмотрим ситуацию с точки зрения производительности. Если цикл выполняется очень быстро (сотни итераций в секунду), вызывать ОбновитьСтроки() на каждом шаге — избыточно. Человеческий глаз не способен воспринять изменения с такой скоростью, а ресурсы процессора будут тратиться на отрисовку UI.

Проанализируем стратегию "пакетного обновления":

  1. Добавляем данные в ИндексированнаяТаблица.
  2. Вызываем обновление ТП не на каждой строке, а, например, каждые 10-20 итераций или по таймеру (раз в 200-500 миллисекунд).
  3. Используем метод ПерерисоватьСтроки() вместо ОбновитьСтроки(), если структура таблицы (состав колонок) не менялась.

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

Часто пользователю нужно видеть именно последнюю добавленную строку ("автоскролл"). Для этого используется свойство ТекущаяСтрока. Однако здесь есть важный нюанс, связанный с индексами. В ПоставщикеДанныхИТ визуальный индекс строки в ТП может не совпадать с физическим номером строки в ИТ (например, если включена сортировка или фильтрация).

Если мы хотим гарантированно перейти в конец списка, нужно учитывать, что ТекущаяСтрока ожидает номер строки в контексте текущего представления провайдера. Посмотрим на правильный подход:


// После добавления данных
мТабличноеПоле.ТекущаяСтрока = мПоставщикТабличногоПоля.КоличествоСтрок();
мТабличноеПоле.ПерерисоватьСтроки();

Если стандартное присвоение ТекущаяСтрока = 1 не прокручивает таблицу вверх (например, застряв на 18-й строке), это может означать, что фокус установлен, но команда "показать строку" (EnsureVisible) не отработала. В таких случаях помогает связка установки текущей строки и принудительного обновления.

Использование Windows API для "заморозки" экрана

Для продвинутых разработчиков существует метод полной блокировки отрисовки окна на время массовых изменений. Это делается через отправку сообщения WM_SETREDRAW окну Табличного Поля. Хотя 1С++ старается делать это внутренними средствами, при очень интенсивных обновлениях ручное управление может помочь.

Разберем алгоритм:

  1. Запрещаем перерисовку окна ТП через SendMessage(hWnd, WM_SETREDRAW, 0, 0).
  2. Добавляем порцию строк в таблицу.
  3. Разрешаем перерисовку SendMessage(hWnd, WM_SETREDRAW, 1, 0).
  4. Вызываем InvalidateRect для принудительного обновления всей области.

Однако в большинстве случаев для 1С 7.7 достаточно просто заменить ОбновитьСтроки() на ПерерисоватьСтроки() и грамотно настроить ВертСкроллер.

Итоги и выводы

Подводя итог, для реализации плавного и красивого обновления таблицы в 1С++ следуйте этим правилам:

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

← На главную