Как вывести информацию на второй монитор (дисплей покупателя) из 1С 7.7?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

В современной розничной торговле вывод информации для покупателя на второй монитор (чека, текущих позиций, скидок, рекламных баннеров и видеороликов) стал стандартом де-факто. Но как реализовать этот функционал на «классической» платформе 1С:Предприятие 7.7, интерфейс которой изначально не проектировался под многомониторные конфигурации? В этой статье мы подробно разберем пять проверенных практических методов решения этой задачи: от самых простых и легковесных до профессиональных отказоустойчивых решений.

Вариант 1. Генерация HTML-файла с автообновлением

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

Рассмотрим пошагово, как это реализовать. В заголовке генерируемого HTML-документа мы используем специальный мета-тег, который заставляет браузер обновлять страницу каждые 1-2 секунды.

Пример кода на стороне 1С 7.7 для выгрузки файла чека:


Процедура ОбновитьМониторПокупателя(ТаблицаТоваров)
    ТекстHTML = СоздатьОбъект("Текст");
    ТекстHTML.ДобавитьСтроку("<html>");
    ТекстHTML.ДобавитьСтроку("<head>");
    // Указываем автообновление страницы каждую секунду
    ТекстHTML.ДобавитьСтроку("<meta http-equiv=""refresh"" content=""1"" />");
    ТекстHTML.ДобавитьСтроку("<style>");
    ТекстHTML.ДобавитьСтроку("body { font-family: Arial; background-color: #f0f0f0; margin: 20px; }");
    ТекстHTML.ДобавитьСтроку(".title { font-size: 24px; color: #333; text-align: center; }");
    ТекстHTML.ДобавитьСтроку(".item-table { width: 100%; border-collapse: collapse; margin-top: 20px; }");
    ТекстHTML.ДобавитьСтроку(".item-table th { background-color: #ff9900; color: white; padding: 10px; }");
    ТекстHTML.ДобавитьСтроку(".item-table td { padding: 10px; border-bottom: 1px solid #ccc; font-size: 18px; }");
    ТекстHTML.ДобавитьСтроку(".total { font-size: 32px; font-weight: bold; color: red; text-align: right; margin-top: 20px; }");
    ТекстHTML.ДобавитьСтроку("</style>");
    ТекстHTML.ДобавитьСтроку("</head>");
    ТекстHTML.ДобавитьСтроку("<body>");
    
    ТекстHTML.ДобавитьСтроку("<div class=""title"">Ваша покупка</div>");
    ТекстHTML.ДобавитьСтроку("<table class=""item-table"">");
    ТекстHTML.ДобавитьСтроку("<tr><th>Наименование</th><th>Кол-во</th><th>Сумма</th></tr>");
    
    ИтогСумма = 0;
    ТаблицаТоваров.ВыбратьСтроки();
    Пока ТаблицаТоваров.ПолучитьСтроку() = 1 Цикл
        ТекстHTML.ДобавитьСтроку("<tr>");
        ТекстHTML.ДобавитьСтроку("<td>" + СокрЛП(ТаблицаТоваров.Товар) + "</td>");
        ТекстHTML.ДобавитьСтроку("<td>" + ТаблицаТоваров.Количество + "</td>");
        ТекстHTML.ДобавитьСтроку("<td>" + Формат(ТаблицаТоваров.Сумма, "Ч015.2") + "</td>");
        ТекстHTML.ДобавитьСтроку("</tr>");
        ИтогСумма = ИтогСумма + ТаблицаТоваров.Сумма;
    КонецЦикла;
    
    ТекстHTML.ДобавитьСтроку("</table>");
    ТекстHTML.ДобавитьСтроку("<div class=""total"">ИТОГО: " + Формат(ИтогСумма, "Ч015.2") + " руб.</div>");
    ТекстHTML.ДобавитьСтроку("</body></html>");
    
    // Записываем во временную папку
    ТекстHTML.Записать(КаталогИБ() + "ExtFiles\customer_display.html");
КонецПроцедуры

Преимущества: предельная простота реализации, отсутствие внешних DLL-библиотек.

Недостатки: неприятное мерцание экрана в момент перезагрузки страницы браузером, повышенный износ твердотельного накопителя (SSD) из-за постоянной перезаписи файлов при быстром сканировании товаров на кассе.

Вариант 2. Прямое управление DOM-моделью браузера через OLE/COM

Чтобы избавиться от мерцания экрана и постоянных дисковых операций записи/чтения, проанализируем профессиональный подход — управление запущенным экземпляром Internet Explorer непосредственно из памяти 1С через COM-соединение.

При этом методе мы один раз создаем OLE-объект браузера, позиционируем его окно на координаты второго монитора и далее точечно обновляем HTML-код в памяти процесса, не используя жесткий диск.

Рассмотрим пример реализации:


Перем мБраузер;

Процедура ИнициализироватьВторойМонитор()
    Попытка
        мБраузер = СоздатьОбъект("InternetExplorer.Application");
        // Позиционируем окно на второй монитор (координата X начинается за пределами первого)
        мБраузер.Left = 1920; // Предположим, разрешение первого монитора 1920x1080
        мБраузер.Top = 0;
        мБраузер.Width = 1024;
        мБраузер.Height = 768;
        мБраузер.MenuBar = 0;
        мБраузер.ToolBar = 0;
        мБраузер.StatusBar = 0;
        мБраузер.AddressBar = 0;
        мБраузер.Visible = 1;
        
        // Открываем пустую страницу
        мБраузер.Navigate("about:blank");
        
        // Ожидаем завершения инициализации документа
        Пока мБраузер.ReadyState <> 4 Цикл
            // В 1С 7.7 нет штатной функции сна, используем пустой цикл или внешнюю компоненту
        КонецЦикла;
    Исключение
        Предупреждение("Не удалось запустить дисплей покупателя: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Процедура ОбновитьДанныеНаМониторе(ТекстСообщения, СуммаЧека)
    Если ПустоеЗначение(мБраузер) = 1 Тогда
        Возврат;
    КонецЕсли;
    
    // Формируем чистый HTML-код для записи в DOM
    HTMLКод = "<html><body style='background:black; color:lime; font-family:monospace; font-size:24px; text-align:center;'>"
            + "<h1>" + ТекстСообщения + "</h1>"
            + "<div style='font-size:48px; font-weight:bold;'>К ОПЛАТЕ: " + СуммаЧека + " руб.</div>"
            + "</body></html>";
            
    // Пишем напрямую в открытый документ браузера в памяти
    мБраузер.Document.open();
    мБраузер.Document.write(HTMLКод);
    мБраузер.Document.close();
КонецПроцедуры

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

Вариант 3. Использование специализированного софта (утилиты CashDisplay)

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

Данные программы работают по следующей схеме:

  1. Утилита запускается на компьютере кассира и автоматически разворачивается во весь экран на втором мониторе, скрывая панель задач Windows.
  2. Она регистрирует в системе COM-объект (например, CashDisplay.Application) или отслеживает появление определенного текстового/XML/JSON файла в локальном каталоге обмена.
  3. В режиме простоя программа может проигрывать рекламные видеоролики из локальной папки или крутить слайд-шоу.
  4. При отправке команд из 1С программа мгновенно переключается в режим отображения чека, выводя товары красивым списком с картинками.

Пример интеграции через COM-объект утилиты в 1С 7.7:


Попытка
    Дисплей = СоздатьОбъект("CashDisplay.Application");
    Дисплей.Очистить();
    Дисплей.ДобавитьСтрокуТовара("Шоколад Аленка", 2, 85.50);
    Дисплей.ДобавитьСтрокуТовара("Кока-Кола 0.5л", 1, 90.00);
    Дисплей.ПоказатьИтого(261.00);
Исключение
    Сообщить("Специализированная программа дисплея покупателя не запущена!");
КонецПопытки;

Вариант 4. Отвязка родных окон 1С 7.7 через WinAPI (FormEx / 1C++)

Интерфейс 1С 7.7 построен по архитектуре MDI (Multiple Document Interface), где все открытые окна (документы, справочники, отчеты) жестко ограничены рамками главного окна программы. Просто перетащить форму «ЭкранПокупателя» за пределы главного окна на второй монитор штатными средствами невозможно.

Для преодоления этого ограничения продвинутые разработчики используют вызовы функций Windows API с помощью известных внешних компонент FormEx или 1С++. С помощью WinAPI мы можем принудительно изменить стиль любого окна 1С, сделав его «свободным» (всплывающим) окном операционной системы, а затем переместить его по координатам второго монитора.

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

  1. Создаем в конфигураторе обычную форму отчета или обработки, которая будет выступать в качестве табло покупателя. Наполняем ее крупными шрифтами и нужными реквизитами.
  2. При открытии этой формы с помощью ВК FormEx получаем дескриптор окна (HWND).
  3. С помощью функции API SetWindowLong удаляем у окна стиль WS_CHILD (дочернее окно) и устанавливаем стиль WS_POPUP (всплывающее окно).
  4. Используя функцию API SetParent, отвязываем окно от главного окна 1С (делаем его родителем рабочий стол Desktop).
  5. Вызовом функции API MoveWindow или SetWindowPos перемещаем форму на второй монитор.

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

Вариант 5. Клиент-серверная схема на базе локального веб-сервера и WebSockets

Если на кассовом узле используется высоконагруженная база данных и критически важно, чтобы процессы обновления второго экрана не тормозили работу кассира (что часто бывает при COM-соединениях или тяжелых дисковых операциях), применяется наиболее современная и стабильная схема взаимодействия.

Архитектура решения состоит из трех звеньев:

  1. Локальный веб-сервер. На компьютере кассира в фоне работает крошечный веб-сервер (написанный, например, на Go, Node.js или Python). Он не требует ресурсов и запускается как служба Windows.
  2. Браузер покупателя. На втором мониторе открыт современный браузер (Chrome, Edge), отображающий веб-страницу, загруженную с локального веб-сервера. Страница держит постоянное фоновое соединение с веб-сервером через быстрый протокол WebSockets.
  3. 1С 7.7. При сканировании товара 1С отправляет асинхронный HTTP-запрос (POST) на локальный веб-сервер с данными чека в формате JSON.

Для отправки запросов из 1С 7.7 используется системный объект Windows MSXML2.XMLHTTP или библиотека WinHttp.WinHttpRequest:


Процедура ОтправитьДанныеНаСервер(СтрокаJSON)
    Попытка
        Http = СоздатьОбъект("MSXML2.XMLHTTP");
        Http.open("POST", "http://localhost:8080/update_screen", 0); // 0 - асинхронный режим, чтобы не вешать 1С
        Http.setRequestHeader("Content-Type", "application/json");
        Http.send(СтрокаJSON);
    Исключение
        Сообщить("Ошибка отправки данных на дисплей покупателя: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Локальный сервер мгновенно принимает этот JSON и транслирует его в открытый веб-интерфейс на втором мониторе по протоколу WebSockets. Страница на втором мониторе плавно, красиво, с использованием современных CSS-анимаций отображает позиции чека и крутит рекламные баннеры без малейших задержек интерфейса самой 1С.

Выводы и рекомендации

Выбор конкретного метода зависит от технических условий проекта и квалификации разработчика:

← На главную