Глобальный контекст.КлиентскоеПриложение

Свойства · ClientApplication

Тип: КлиентскоеПриложение. Предоставляет доступ к клиентским настройкам приложения.

Полное описание, параметры и ограничения

Глобальный контекст.КлиентскоеПриложение (Global context.ClientApplication)

Глобальный контекст (Global context)

КлиентскоеПриложение (ClientApplication)

Доступен, начиная с версии 8.3.10.

Использование:
Только чтение.
Описание:
Тип: КлиентскоеПриложение.
Предоставляет доступ к клиентским настройкам приложения.
Доступность:

Тонкий клиент, веб-клиент, мобильный клиент, сервер, толстый клиент, мобильное приложение (клиент), мобильное приложение (сервер), мобильный автономный сервер.

Использование в версии:

Доступен, начиная с версии 8.3.10.

Методическая информация

Практические примеры

Свое клиентское приложение: учебное окно750 и возврат исходного оформления за два настоящих запуска

Настоящий readonly global КлиентскоеПриложение, не неизвестный исходный объект. Window/OS setters работают только внутри настоящего BeforeStart, заголовки — после открытия своего окна. Реальный baseline сохраняется в одном собственном user-scoped ключе и проверенно возвращается при втором ручном старте.

Где и как запускать

Главный APPLICATION целиком в реальный модуль управляемого приложения own УчебноеОкно85. Window/OS setters прямо в ПередНачаломРаботыСистемы(Отказ), title setters после появления окна. SERVER отдельно server-call общий модуль, FORM отдельно actual общая управляемая форма. Два ручных own WindowsThinTaxi/FileIB запуска.

Подготовка

  1. Подготовьте отдельную собственную Windows VM с платформой8.5.1.1343, тонким клиентом и управляемым интерфейсом Такси. Не используйте интерфейс Версия8_5 для этого опыта: native OS-caption setter там игнорируется. Это собственный клиент, не перебор/подключение чужих процессов или COM.

  2. Вручную создайте новый canonical nonzero UUID-marker и собственную пустую FileIB C:\1c-labs\Уч85Окно_<UUID>\. Имя конфигурации УчебноеОкно85. В списке баз зарегистрируйте строго File="C:\1c-labs\Уч85Окно_<UUID>\";. Path-marker не является UUID самой информационной базы; реальный UUID базы в коде не измеряется. Состояние.База содержит только эту метку пути. Другие пути/параметры отвергаются, строка соединения не печатается.

  3. Создайте ровно одного настоящего пользователя IB Уч85Окно_<UUID> с правами чтения списка пользователей и СохранениеДанныхПользователя в этой учебной базе. Список и UUID реального текущего пользователя ИБ проверяются; Состояние.Пользователь сохраняет actualIBUserUUID из ТекущийПользователь().УникальныйИдентификатор, не UUID базы. Это важно, поскольку native settings связаны с именем пользователя и имя может повторно использовать другой IBUser.

  4. Конфигурация пустая: справочников/документов/регистров/общих реквизитов/разделителей/подписок/регламентных заданий/ботов/констант/расширений нет. Не меняйте типовую конфигурацию. Добавьте только указанные ниже свой общий модуль и свою одну общую управляемую форму; другие стартовые модули/обработчики отсутствуют.

  5. Конфигуратор → свойства конфигурации: управляемое приложение, интерфейс Такси. Первый baseline должен иметь Обычный режим окна и настоящий Boolean отображения заголовкаОС: принимаются и True, и False. Учебное значение — противоположное реально полученному, а не guessed default. Код не принимает kiosk/fullscreen baseline. Два исходных текста берутся реальными getters.

  6. Конфигуратор → Общие → Общие модули → УчебноеОкно85: Сервер/Вызов сервера=Да, Клиент/Привилегированный/Глобальный=Нет. Вставьте полный SERVER. ХранилищеСистемныхНастроек доступно серверу, не тонкому клиенту. Работа только с собственным объектным ключом Уч85Окно85_<marker> и ключом настройки СвойЦиклОкна85; ИмяПользователя не передается, поэтому native использует текущего пользователя.

  7. Конфигуратор → Общие → Общие формы → УчебноеОкно85: управляемая форма. Создайте параметры формы МеткаБазы/Nonce (Строка36), реквизиты с теми же именами (Строка36) и Подтверждение (Строка100). Создайте команды ПроверитьОкно/ВернутьСвоиЗаголовки, разместите кнопки и поле подтверждения. Вставьте FORM целиком; событие ПриСозданииНаСервере имеет2параметра и переносит собственные startup parameters в реквизиты.

  8. Конфигуратор → Конфигурация → Открыть модуль управляемого приложения: вставьте APPLICATION целиком. Native ПередНачаломРаботыСистемы(Отказ) настраивает окно до его появления; ПриНачалеРаботыСистемы() после открытия проверяет оформление, задает свои заголовки и открывает только свою общую форму. Не вызывайте эти процедуры вручную и не переносите window/OS setters в форму или обычный helper.

  9. Первый ручной запуск выполните тонким клиентом этой своей базы, задав дополнительный параметр запуска /C"Уч85Окно|<ваш UUID>|ОПЫТ85". ПараметрЗапуска native получает именно /C. Без точных трех частей старт отклоняется; это осознанная учебная фаза, не автоизменение при любом открытии произвольной базы.

  10. Первый BeforeStart сохраняет реально полученные Normal/Boolean OS/two captions в собственном ключе для actual IBUser, затем ставит РабочееМесто и противоположное отображение заголовкаОС. При существующем ключе опыт не повторяется и baseline не перезаписывается. Main-window mode и OS-caption setters оба разрешены только в этом событии.

  11. В РабочемМесте скрываются системное меню и многие панели/горячие клавиши; поэтому ПриНачалеРаботыСистемы открывает заранее подготовленную общую форму, а не требует открыть внешнюю обработку через скрытое меню. Закрытие главного окна остается доступным. Это не киоск/forcefullscreen и не запрет на работу ОС.

  12. После открытия окна native getters проверяют РабочееМесто/свое противоположное значение OS и исходные тексты. Затем задаются собственные заголовок Уч85Окно|Книга750|nonce и краткий Книга750|nonce, оба отдельно читаются. Краткий заголовок вставляется перед системным и отделяется точкой: getter возвращает свое значение, не весь нарисованный ОС-заголовок.

  13. Откройте автоматически показанную свою форму, нажмите ПроверитьОкно и осмотрите настоящее окно вручную. Введите ВОЗВРАТ МОИХ ЗАГОЛОВКОВ85 и нажмите ВернутьСвоиЗаголовки один раз. Возврат разрешен лишь при exact own caption/short/mode/OS/nonce. Два текста возвращаются к real baseline и читаются; если кто-то изменил оформление, код не перезаписывает его.

  14. После подтвержденной фазы ЗаголовкиВозвращены вручную закройте только собственное приложение. Не называйте это полным возвратом окна: Mode/OS нельзя изменить из формы. Сохраненная запись не удаляется. Не запускайте параллельные сеансы и не меняйте конфигурацию/пользователя/интерфейс между двумя стартами.

  15. Второй ручной запуск той же базы/пользователя задайте с /C"Уч85Окно|<тот же UUID-marker пути>|ВОЗВРАТ85". Native BeforeStart проверяет сохраненный actualIBUserUUID реального текущего пользователя ИБ и nonce, фазу и исходные тексты. Режим окна может уже быть исходным из нового запуска либо оставаться нашим РабочимМестом; иные режимы отвергаются. Возвращаются сохраненные Normal/исходный Boolean OS, не guessed defaults.

  16. Второй native OnStart после открытия проверяет фактические mode/OS/caption/short и только затем сохраняет Завершен. Пользователь отдельно осматривает окно. Font getter дает вариант шрифта, не пиксельный размер/имя установленного шрифта; ТипПриложения — настоящий тонкий клиент.

  17. КлиентСИспользованиемАвтономногоСервера по точной native справке проверяет способность данного типа клиента работать с автономным сервером, не факт подключения. В этом fixture явно FileIB; значениеBoolean не объявляется живым соединением с автономным сервером, и сервер не запускается.

  18. Любая ошибка/cancel может оставить собственный state/оформление частично измененными. Ключи/phase не являются общей транзакцией или доказательством скриншота; автоматического blindrestore/retry/deleteall нет. При неизвестном/частичном результате остановитесь и вручную проверьте только свой стенд. При авторстве реальные1С/настройкиБД/UI/процессы/сеть/файлы не изменялись, backup0.

Перем СвояМеткаОкна85;
Перем СвойСтартОкна85;
Перем СвойСнимокОкна85;

Процедура ПередНачаломРаботыСистемы(Отказ)
#Если ТонкийКлиент Тогда
    Части = СтрРазделить(ПараметрЗапуска, "|", Ложь);
    Если Части.Количество() <> 3 Или Части[0] <> "Уч85Окно"
        Или (Части[2] <> "ОПЫТ85" И Части[2] <> "ВОЗВРАТ85") Тогда
        Отказ = Истина;
        Возврат;
    КонецЕсли;
    СвояМеткаОкна85 = Части[1];
    СвойСтартОкна85 = Части[2];
    Если ТипЗнч(КлиентскоеПриложение) <> Тип("КлиентскоеПриложение")
        Или КлиентскоеПриложение.ТипПриложения() <> ТипКлиентскогоПриложения.ТонкийКлиент
        Или КлиентскоеПриложение.ТекущийВариантИнтерфейса() <> ВариантИнтерфейсаКлиентскогоПриложения.Такси
        Или ТипЗнч(КлиентскоеПриложение.ПолучитьОтображениеЗаголовкаОС()) <> Тип("Булево") Тогда
        Отказ = Истина;
        Возврат;
    КонецЕсли;
    Если СвойСтартОкна85 = "ОПЫТ85" Тогда
        СвойСнимокОкна85 = УчебноеОкно85.СохранитьПервоеСостояниеОкна85(СвояМеткаОкна85,
            КлиентскоеПриложение.ПолучитьРежимОсновногоОкна(), КлиентскоеПриложение.ПолучитьОтображениеЗаголовкаОС(),
            КлиентскоеПриложение.ПолучитьЗаголовок(), КлиентскоеПриложение.ПолучитьКраткийЗаголовок());
        ТребуемоеОкно = РежимОсновногоОкнаКлиентскогоПриложения.РабочееМесто;
        ТребуемыйОС = СвойСнимокОкна85.СвойЗаголовокОС;
    Иначе
        СвойСнимокОкна85 = УчебноеОкно85.ПолучитьСвоеСостояниеОкна85(СвояМеткаОкна85);
        Если СвойСнимокОкна85.Фаза <> "ЗаголовкиВозвращены"
            Или КлиентскоеПриложение.ПолучитьЗаголовок() <> СвойСнимокОкна85.Заголовок
            Или КлиентскоеПриложение.ПолучитьКраткийЗаголовок() <> СвойСнимокОкна85.КраткийЗаголовок Тогда
            Отказ = Истина;
            Возврат;
        КонецЕсли;
        ТекущееОкно = КлиентскоеПриложение.ПолучитьРежимОсновногоОкна();
        Если ТекущееОкно <> СвойСнимокОкна85.РежимОкна
            И ТекущееОкно <> РежимОсновногоОкнаКлиентскогоПриложения.РабочееМесто Тогда
            Отказ = Истина;
            Возврат;
        КонецЕсли;
        СвойСнимокОкна85 = УчебноеОкно85.ПеревестиСвоюФазуОкна85(СвояМеткаОкна85, СвойСнимокОкна85.Nonce, "ЗаголовкиВозвращены", "ВозвратНачат");
        ТребуемоеОкно = СвойСнимокОкна85.РежимОкна;
        ТребуемыйОС = СвойСнимокОкна85.ЗаголовокОС;
    КонецЕсли;
    КлиентскоеПриложение.УстановитьРежимОсновногоОкна(ТребуемоеОкно);
    КлиентскоеПриложение.УстановитьОтображениеЗаголовкаОС(ТребуемыйОС);
    Если КлиентскоеПриложение.ПолучитьРежимОсновногоОкна() <> ТребуемоеОкно
        Или КлиентскоеПриложение.ПолучитьОтображениеЗаголовкаОС() <> ТребуемыйОС Тогда
        Отказ = Истина;
    КонецЕсли;
#Иначе
    Отказ = Истина;
#КонецЕсли
КонецПроцедуры

Процедура ПриНачалеРаботыСистемы()
    Если СвойСнимокОкна85 = Неопределено Тогда
        ВызватьИсключение "Own native BeforeStart не подготовил настоящий сохраненный baseline";
    КонецЕсли;
    Свежий = УчебноеОкно85.ПолучитьСвоеСостояниеОкна85(СвояМеткаОкна85);
    Если Свежий.Nonce <> СвойСнимокОкна85.Nonce Тогда
        ВызватьИсключение "Собственный старт получил чужой nonce";
    КонецЕсли;
    Если СвойСтартОкна85 = "ОПЫТ85" Тогда
        Если Свежий.Фаза <> "Подготовлен" Или КлиентскоеПриложение.ПолучитьРежимОсновногоОкна() <> РежимОсновногоОкнаКлиентскогоПриложения.РабочееМесто
            Или КлиентскоеПриложение.ПолучитьОтображениеЗаголовкаОС() <> Свежий.СвойЗаголовокОС
            Или КлиентскоеПриложение.ПолучитьЗаголовок() <> Свежий.Заголовок
            Или КлиентскоеПриложение.ПолучитьКраткийЗаголовок() <> Свежий.КраткийЗаголовок Тогда
            ВызватьИсключение "Actual own first main-window/baseline не подтвержден; не перезаписываем заголовки";
        КонецЕсли;
        КлиентскоеПриложение.УстановитьЗаголовок(Свежий.СвойЗаголовок);
        КлиентскоеПриложение.УстановитьКраткийЗаголовок(Свежий.СвойКраткий);
        Если КлиентскоеПриложение.ПолучитьЗаголовок() <> Свежий.СвойЗаголовок
            Или КлиентскоеПриложение.ПолучитьКраткийЗаголовок() <> Свежий.СвойКраткий Тогда
            ВызватьИсключение "Own заголовки могли измениться частично, но отдельно не подтверждены. Повтора/автоrestore нет";
        КонецЕсли;
        СвойСнимокОкна85 = УчебноеОкно85.ПеревестиСвоюФазуОкна85(СвояМеткаОкна85, Свежий.Nonce, "Подготовлен", "Показан");
    Иначе
        Если Свежий.Фаза <> "ВозвратНачат" Или КлиентскоеПриложение.ПолучитьРежимОсновногоОкна() <> Свежий.РежимОкна
            Или КлиентскоеПриложение.ПолучитьОтображениеЗаголовкаОС() <> Свежий.ЗаголовокОС
            Или КлиентскоеПриложение.ПолучитьЗаголовок() <> Свежий.Заголовок
            Или КлиентскоеПриложение.ПолучитьКраткийЗаголовок() <> Свежий.КраткийЗаголовок Тогда
            ВызватьИсключение "Исходный real saved own UI baseline после второго старта не подтвержден";
        КонецЕсли;
        СвойСнимокОкна85 = УчебноеОкно85.ПеревестиСвоюФазуОкна85(СвояМеткаОкна85, Свежий.Nonce, "ВозвратНачат", "Завершен");
    КонецЕсли;
    Шрифт = КлиентскоеПриложение.ТекущийВариантОсновногоШрифта();
    ВозможенАвтономный = КлиентскоеПриложение.КлиентСИспользованиемАвтономногоСервера();
    Если ТипЗнч(Шрифт) <> Тип("ВариантОсновногоШрифтаКлиентскогоПриложения") Или ТипЗнч(ВозможенАвтономный) <> Тип("Булево") Тогда
        ВызватьИсключение "Native font/capability types не совпали";
    КонецЕсли;
    Сообщить("Свой thin-client: " + Строка(КлиентскоеПриложение.ТипПриложения()) + "; основной шрифт: " + Строка(Шрифт));
    Сообщить("Способность этого типа клиента работать с автономным сервером: " + Строка(ВозможенАвтономный) + ". Это НЕ факт подключения: наш fixture использует FileIB");
    Сообщить("Own phase: " + СвойСнимокОкна85.Фаза + "; nonce: " + СвойСнимокОкна85.Nonce);
    ОткрытьФорму("ОбщаяФорма.УчебноеОкно85", Новый Структура("МеткаБазы,Nonce", СвояМеткаОкна85, СвойСнимокОкна85.Nonce));
КонецПроцедуры
Полный серверный модуль собственного baseline/phase в одном current-user system-settings ключе

Конфигуратор → Общие → Общие модули → УчебноеОкно85 → Модуль.

Серверный server-call общий модуль; exact ownIB/current realuser и только own scoped native settings. Window/OS client setters здесь отсутствуют.

Функция СохранитьПервоеСостояниеОкна85(МеткаБазы, ИсходноеОкно, ИсходныйОС, ИсходныйЗаголовок, ИсходныйКраткий) Экспорт
    Паспорт = ПроверитьСвоюБазуОкна85(МеткаБазы);
    Если ХранилищеСистемныхНастроек.Загрузить(Паспорт.КлючОбъекта, "СвойЦиклОкна85") <> Неопределено Тогда
        ВызватьИсключение "Own namespace уже содержит состояние; первый запуск не повторяется";
    КонецЕсли;
    Если ТипЗнч(ИсходноеОкно) <> Тип("РежимОсновногоОкнаКлиентскогоПриложения")
        Или ИсходноеОкно <> РежимОсновногоОкнаКлиентскогоПриложения.Обычный
        Или ТипЗнч(ИсходныйОС) <> Тип("Булево")
        Или ТипЗнч(ИсходныйЗаголовок) <> Тип("Строка") Или СтрДлина(ИсходныйЗаголовок) > 512
        Или ТипЗнч(ИсходныйКраткий) <> Тип("Строка") Или СтрДлина(ИсходныйКраткий) > 512 Тогда
        ВызватьИсключение "Нужен реальный Normal/Boolean OScaption собственный baseline и две исходные строки";
    КонецЕсли;
    Nonce = Строка(Новый УникальныйИдентификатор);
    Состояние = Новый Структура("База,Пользователь,Nonce,РежимОкна,ЗаголовокОС,СвойЗаголовокОС,Заголовок,КраткийЗаголовок,СвойЗаголовок,СвойКраткий,Фаза",
        МеткаБазы, Паспорт.Пользователь, Nonce, ИсходноеОкно, ИсходныйОС, Не ИсходныйОС, ИсходныйЗаголовок, ИсходныйКраткий,
        "Уч85Окно | Книга3×250=750 | " + Nonce, "Книга750 | " + Nonce, "Подготовлен");
    ХранилищеСистемныхНастроек.Сохранить(Паспорт.КлючОбъекта, "СвойЦиклОкна85", Состояние);
    Свежий = ПолучитьСвоеСостояниеОкна85(МеткаБазы);
    Если Свежий.Nonce <> Nonce Или Свежий.Фаза <> "Подготовлен" Тогда
        ВызватьИсключение "Запись своего baseline могла произойти, но отдельно не подтверждена; не повторяйте";
    КонецЕсли;
    Возврат Свежий;
КонецФункции

Функция ПолучитьСвоеСостояниеОкна85(МеткаБазы) Экспорт
    Паспорт = ПроверитьСвоюБазуОкна85(МеткаБазы);
    Состояние = ХранилищеСистемныхНастроек.Загрузить(Паспорт.КлючОбъекта, "СвойЦиклОкна85");
    Если ТипЗнч(Состояние) <> Тип("Структура") Тогда
        ВызватьИсключение "Собственный real saved baseline не найден";
    КонецЕсли;
    Если Состояние.База <> МеткаБазы Или Состояние.Пользователь <> Паспорт.Пользователь
        Или ТипЗнч(Состояние.Nonce) <> Тип("Строка") Или СтрДлина(Состояние.Nonce) <> 36
        Или Состояние.РежимОкна <> РежимОсновногоОкнаКлиентскогоПриложения.Обычный
        Или ТипЗнч(Состояние.ЗаголовокОС) <> Тип("Булево") Или ТипЗнч(Состояние.СвойЗаголовокОС) <> Тип("Булево")
        Или Состояние.СвойЗаголовокОС <> (Не Состояние.ЗаголовокОС) Или ТипЗнч(Состояние.Заголовок) <> Тип("Строка")
        Или ТипЗнч(Состояние.КраткийЗаголовок) <> Тип("Строка") Или СтрДлина(Состояние.Заголовок) > 512
        Или СтрДлина(Состояние.КраткийЗаголовок) > 512 Тогда
        ВызватьИсключение "Own namespace/current actualIBUserUUID/baseline passport изменен";
    КонецЕсли;
    UUIDNonce = Новый УникальныйИдентификатор(Состояние.Nonce);
    Если Состояние.Nonce <> Строка(UUIDNonce) Или UUIDNonce = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000")
        Или Состояние.СвойЗаголовок <> "Уч85Окно | Книга3×250=750 | " + Состояние.Nonce
        Или Состояние.СвойКраткий <> "Книга750 | " + Состояние.Nonce Тогда
        ВызватьИсключение "Собственная учебная строка/nonce не подтвердились";
    КонецЕсли;
    Возврат Состояние;
КонецФункции

Функция ПеревестиСвоюФазуОкна85(МеткаБазы, Nonce, ИзФазы, ВФазу) Экспорт
    Паспорт = ПроверитьСвоюБазуОкна85(МеткаБазы);
    Состояние = ПолучитьСвоеСостояниеОкна85(МеткаБазы);
    Если Состояние.Nonce <> Nonce Или Состояние.Фаза <> ИзФазы Тогда
        ВызватьИсключение "Чужой/старый nonce или повтор own phase не принимается";
    КонецЕсли;
    Допустимо = (ИзФазы = "Подготовлен" И ВФазу = "Показан")
        Или (ИзФазы = "Показан" И ВФазу = "ЗаголовкиВозвращены")
        Или (ИзФазы = "ЗаголовкиВозвращены" И ВФазу = "ВозвратНачат")
        Или (ИзФазы = "ВозвратНачат" И ВФазу = "Завершен");
    Если Не Допустимо Тогда
        ВызватьИсключение "Переход не входит в собственный цикл двух ручных запусков";
    КонецЕсли;
    Состояние.Фаза = ВФазу;
    ХранилищеСистемныхНастроек.Сохранить(Паспорт.КлючОбъекта, "СвойЦиклОкна85", Состояние);
    Свежий = ПолучитьСвоеСостояниеОкна85(МеткаБазы);
    Если Свежий.Фаза <> ВФазу Или Свежий.Nonce <> Nonce Тогда
        ВызватьИсключение "Переход own phase мог сохраниться, но отдельно не подтвержден; автоматического повтора нет";
    КонецЕсли;
    Возврат Свежий;
КонецФункции

Функция ПроверитьСвоюБазуОкна85(МеткаБазы)
    ПроверитьСвойПустойСтенд();
    UUIDМетки = Новый УникальныйИдентификатор(МеткаБазы);
    Если МеткаБазы <> Строка(UUIDМетки) Или UUIDМетки = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
        ВызватьИсключение "Own file-path marker должен быть canonical nonzero UUID; это метка пути, не UUID базы и не UUID реального пользователя ИБ";
    КонецЕсли;
    Соединение = "File=""C:\1c-labs\Уч85Окно_" + МеткаБазы + "\"";";
    Если СтрокаСоединенияИнформационнойБазы() <> Соединение Или ПривилегированныйРежим() Тогда
        ВызватьИсключение "Нужна только точная собственная новая FileIB без privileged. Connection string не выводится";
    КонецЕсли;
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если Пользователи.Количество() <> 1 Или Текущий = Неопределено Тогда
        ВызватьИсключение "Нужен единственный real ownIBUser";
    КонецЕсли;
    Если Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор
        Или Текущий.Имя <> "Уч85Окно_" + МеткаБазы Или Метаданные.ОбщиеФормы.Количество() <> 1
        Или Метаданные.ОбщиеФормы.УчебноеОкно85.Имя <> "УчебноеОкно85"
        Или Метаданные.Боты.Количество() <> 0 Или Метаданные.Константы.Количество() <> 0 Тогда
        ВызватьИсключение "Own actual user/sole common form/empty metadata не подтверждены";
    КонецЕсли;
    Возврат Новый Структура("КлючОбъекта,Пользователь", "Уч85Окно85_" + МеткаБазы, Строка(Текущий.УникальныйИдентификатор));
КонецФункции

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры
Полный модуль собственной общей управляемой формы: проверка и возврат только заголовков

Конфигуратор → Общие → Общие формы → УчебноеОкно85 → Модуль.

Клиент-серверный модуль actual общей управляемой формы. Прямые window/OS setters запрещены; settings остаются серверными.

Перем ВозвратЗаголовковНачат85;

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    МеткаБазы = Параметры.МеткаБазы;
    Nonce = Параметры.Nonce;
    Состояние = УчебноеОкно85.ПолучитьСвоеСостояниеОкна85(МеткаБазы);
    Если Состояние.Nonce <> Nonce Тогда
        Отказ = Истина;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьОкно(Команда)
    Состояние = ПолучитьСостояниеНаСервере85();
    Если КлиентскоеПриложение.ТипПриложения() <> ТипКлиентскогоПриложения.ТонкийКлиент Тогда
        ВызватьИсключение "Это не наш собственный тонкий клиент";
    КонецЕсли;
    Сообщить("Сохраненная own phase: " + Состояние.Фаза + "; actual window: " + Строка(КлиентскоеПриложение.ПолучитьРежимОсновногоОкна())
        + "; actual OS caption: " + Строка(КлиентскоеПриложение.ПолучитьОтображениеЗаголовкаОС()));
КонецПроцедуры

&НаКлиенте
Процедура ВернутьСвоиЗаголовки(Команда)
    Если ВозвратЗаголовковНачат85 = Истина Или Подтверждение <> "ВОЗВРАТ МОИХ ЗАГОЛОВКОВ85" Тогда
        ВызватьИсключение "Own возврат заголовков одноразовый и требует отдельной фразы";
    КонецЕсли;
    Состояние = ПолучитьСостояниеНаСервере85();
    Если Состояние.Фаза <> "Показан" Или КлиентскоеПриложение.ТипПриложения() <> ТипКлиентскогоПриложения.ТонкийКлиент
        Или КлиентскоеПриложение.ПолучитьЗаголовок() <> Состояние.СвойЗаголовок
        Или КлиентскоеПриложение.ПолучитьКраткийЗаголовок() <> Состояние.СвойКраткий
        Или КлиентскоеПриложение.ПолучитьРежимОсновногоОкна() <> РежимОсновногоОкнаКлиентскогоПриложения.РабочееМесто
        Или КлиентскоеПриложение.ПолучитьОтображениеЗаголовкаОС() <> Состояние.СвойЗаголовокОС Тогда
        ВызватьИсключение "Текущее оформление уже не наш checked snapshot; чужие/частичные значения не перезаписываются";
    КонецЕсли;
    ВозвратЗаголовковНачат85 = Истина;
    КлиентскоеПриложение.УстановитьЗаголовок(Состояние.Заголовок);
    КлиентскоеПриложение.УстановитьКраткийЗаголовок(Состояние.КраткийЗаголовок);
    Если КлиентскоеПриложение.ПолучитьЗаголовок() <> Состояние.Заголовок
        Или КлиентскоеПриложение.ПолучитьКраткийЗаголовок() <> Состояние.КраткийЗаголовок Тогда
        ВызватьИсключение "Own возврат мог произойти частично, но отдельно не подтвержден; не повторяйте";
    КонецЕсли;
    ПодтвердитьЗаголовкиНаСервере85();
    Сообщить("Только два own заголовка возвращены. Window-mode/OS-caption setters из формы запрещены: их восстановит следующий отдельный native BeforeStart с ВОЗВРАТ85");
КонецПроцедуры

&НаСервере
Функция ПолучитьСостояниеНаСервере85()
    Состояние = УчебноеОкно85.ПолучитьСвоеСостояниеОкна85(МеткаБазы);
    Если Состояние.Nonce <> Nonce Тогда
        ВызватьИсключение "Own form nonce не совпал с actual saved state";
    КонецЕсли;
    Возврат Состояние;
КонецФункции

&НаСервере
Процедура ПодтвердитьЗаголовкиНаСервере85()
    УчебноеОкно85.ПеревестиСвоюФазуОкна85(МеткаБазы, Nonce, "Показан", "ЗаголовкиВозвращены");
КонецПроцедуры

Разбор по шагам

  1. Native readonly globalfactory дает текущий КлиентскоеПриложение; startup guard требует Thin/Taxi и Boolean OS-caption, исключая неподдерживаемые clients/styles.

  2. ПередНачаломРаботыСистемы имеет1параметр Отказ, OnStart0. Ни формы, ни сообщений/окон не создается до готовности главного окна; оба ограниченных setters находятся прямо в BeforeStart.

  3. Первый baseline взят из реальных getters до изменения, ограничен Normal/Boolean OS и сохраняется только в собственном user-scoped ключе, который изначально отсутствует. Противоположный Boolean используется для видимого собственного опыта.

  4. Сервер проверяет exact emptyFileIB/version/oneactualuser и сохраненный actualIBUserUUID реального пользователя ИБ. UUID самой базы не измеряется; ее поле База содержит marker пути. Settings.Load/Save без имени пользователя используют текущего; чужие ключи/пользователи/настройки не затрагиваются.

  5. После реального открытия своего окна mode/OS и заголовки сверяются. Новые caption/short с own nonce устанавливаются и читаются, не заявляются нарисованными только по return setters.

  6. Форма восстанавливает только два своих текста при совпадении текущего собственного оформления. Ее one-shot flag ставится до setters; partialfailure не запускает повтор или автоматический restore.

  7. Второй настоящий запуск разрешен после возвращенных текстов и подтвержденного состояния. Перед стартом допустимы только original/own window mode; новый клиент не выдается за тот же ОС-процесс.

  8. Восстановление Window/OS происходит только в новом native BeforeStart. OnStart отдельно читает весь original baseline и завершает own saved phase; запись сохраняется для ручной проверки.

  9. Font/тип/standalone capability применяются к текущему реальному клиенту. CapabilityBoolean не доказывает actual autonomous connection или готовый запущенный сервер.

Как проверить результат

  1. После первого старта свое приложение показывает РабочееМесто, противоположное собственному baseline отображение ОС-заголовка и два текста750; главный код не управляет чужими процессами.

  2. Форма подтверждает exact own nonce/current appearance и возвращает исходные два текста; window/OS setters из нее отсутствуют.

  3. После второго старта реальные mode/OS/caption/short совпали с сохраненным исходным baseline, а собственная запись отмечена Завершен.

  4. Возврат не выполняется при другом пользователе/пути/фазе/nonce/измененном оформлении. Partial/cancel не объявляются успешным завершением.

  5. Отчет о способности автономного сервера отделен от фактического FileIB connection. Шрифт прочитан как enum, не выдуманный Windows font.

  6. Нужен ручной запуск и визуальная проверка владельца своего стенда. Здесь native/static проверки, а не runtime/UI/DB результат вашей базы.

Ожидаемый результат

При двух успешных ручных запусках своего подготовленного WindowsThinTaxi/FileIB стенда native startup события меняют и отдельно возвращают оформление текущего собственного клиента. Исходные значения действительно получены getters и сохранены только в своем ключе текущего пользователя. Здесь runtime0; реальное отображение/перезапуск/настройки вашей базы не выполнялись.

На что обратить внимание

  1. КлиентскоеПриложение получается из readonly global property, не constructor и не неизвестный переданный объект. Тот же тип доступен на сервере, но конкретные window/OS methods имеют более узкую client availability.

  2. УстановитьРежимОсновногоОкна и УстановитьОтображениеЗаголовкаОС разрешены исключительно в ПередНачаломРаботыСистемы. Нельзя восстановить их в форме/OnStart/обычном общему helper даже в thin-client.

  3. OS setter реально действует только WindowsThin/ThickTaxi; другие clients/interfaces игнорируют вызов. Getter может вернуть Undefined. Нельзя трактовать игнорирование как успешную UI-операцию.

  4. РабочееМесто скрывает меню, панели и горячие клавиши. Собственная заранее созданная общая форма открывается только после появления главного окна, поэтому опыт не зависит от скрытого пункта открытия EPF.

  5. Краткий заголовок автоматически отделяется точкой и участвует в составном системном заголовке. Getter своего значения не является OCR/скриншотом полного заголовка ОС.

  6. Settings storage scope — IB/имя пользователя. Переименование не загружает старые настройки, повторное использование имени может их наследовать; поэтому сохраненный actualIBUserUUID реального пользователя ИБ проверяется и не заменяется marker пути или UUID самой базы.

  7. Save требует СохранениеДанныхПользователя. Thin не вызывает системное settings storage напрямую; отдельный серверный модуль использует только own keys/currentuser, не стороннюю управленческую базу.

  8. Native startup отказ/exception может произойти после saved state или частичного UI изменения. Restore phase не является общей транзакцией. Не повторяйте первый старт поверх baseline и не удаляйте все system settings.

  9. Между двумя стартами новый процесс может уже иметь часть defaults. Это допустимый original snapshot, не гарантия сохранения setters между процессами. Иные modes/тексты отвергаются, а не слепо перезаписываются.

  10. Saved phase является журналом только собственного учебного цикла, не физической backup copy и не доказательством реального UI без manual inspection. No files/archives/backup APIs.

  11. Название ClientUsesStandaloneServer неоднозначно; exact native описание — способность типа клиента. True не означает actual connection, False из регламентного задания не описывает ваше интерактивное окно.

  12. В собственной VM нужны один реальный пользователь, неизмененная CF/Taxi и отсутствие параллельных сеансов. Автор не запускал1С/ОС/process/network/DB/settings/UI/files, а статические тесты не заменяют ваши runtime проверки.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Проверить настоящий поиск: редактор,750/300,chip и доступную собственную сводку1080

Полный собственный managedSource и TestManager показывают отличие ввода редактора от ручного commit и полного исходного запроса от фактического GUI-показа.

Где и как запускать

Полный модуль своей managedформы ManagerПоиска25.Пульт; WindowsThin /TESTMANAGER, точная8.5.1.1343/Такси, isolatedownVM/FileIB. Actual testingcalls только будущий manualprotocol, не выполнены.

Подготовка

  1. Только будущий ручной опыт в собственной VM/собственной учётной записи Windows и новой пустой FileИБ C:\1C85_OwnSearchLab\4c7f629b-8da2-4f04-af39-847f824a2810\Base на точной8.5.1.1343. В этой работе стенд, файлыEPF, процессы, порты, БД и UI не создавались и не запускались. GUID каталога не является UUIDИБ.

  2. CF с нуля УчебныйПоискИнтерфейс85: Управляемое приложение, совместимостьНеИспользовать, РежимсовместимостиинтерфейсаТакси (неВерсия8_5 и неТаксиРазрешить...). Ровно рольУченикПоиска85 и общий модульУчебныйПоискСтенд85; остальных объектов/общихформ/расширений/регламентныхзаданий/подписок0. ОбработкиSource/Manager ниже являются собственными вручную скомпилированными внешнимиEPF и не входят вCF.

  3. РольУченикПоиска85: Администрирование для soleUser проверки и право использовать только собственные внешние обработки. Единственный настоящий пользовательУченикПоиска85 с этой ролью. Код получает настоящий UUID пользователяИБ, не выдумывает UUID базы; производственные аккаунты запрещены.

  4. Общий модульУчебныйПоискСтенд85: СерверДа, ВызовСервераДа, Клиент(обычное приложение)Нет, Клиент(управляемое приложение)Нет, ГлобальныйНет, ПривилегированныйНет. Полный supporting PASSPORT в его модуль. Это разрешённый native RPC экспортПаспорт85, не клиентская имитация сервера.

  5. Собственная SourceПоиска25.epf: создайте вручную новую внешнюю обработку по полному supportingSOURCE, основная управляемая формаИсточник. Не загружайте чужуюEPF и не считайте filename/hash/metadata универсальным доказательством доверия: внешний код может выполняться при открытии. Используйте лишь свой вручную собранный исходник в собственнойVM.

  6. Source реквизиты формы: СписокДинамическийСписок; МеткаСеанса/Пользователь85Строка36; ПаспортСтендаСтрока100; ИмяПоиска85/ИмяСостояния85/ИмяУправления85Строка150; ИтогИсточника85Строка неограниченная; ЧислоСводок85Число5.0; Ошибка85Булево. Для всех кромеСписок/Ошибка85 добавьте одноимённые readonly поля. ЧислоСводок85 полеВвода сФорматЧДЦ=0;ЧГ=0;ЧН=0.

  7. Source один реальный элементТаблицаТоваровТаблицаФормы сПутьКДаннымСписок; ручныхколонок0. Полный SOURCE создаёт6колонок только своего списка и новое banner/его собственное пустое меню. СобытияПриСозданииНаСервере иПриОткрытии назначьте одноимённым процедурам; Clickbanner назначает реальный nativeSetAction. Не создавайте расширения конструктором.

  8. Query использует прежние4 собственных literal строки:1Книга/Канцелярия/3/250/750;2Ручка/Канцелярия/1/30/30;3Чай/Продукты/2/150/300;4Вода/Продукты/0/70/0. КлючЗначениеПоляУчебныйНомер, основная таблица пустая, динамическое считывание и автосохранение настроекЛожь, группировки0. Ни каталога товаров, ни записиБД нет.

  9. ActualC sourceУправлениеПоиском проверяется типомДополнениеЭлементаФормы иВидУправлениеПоиском; строка исостояние имеют свои readonly factories/kinds. PRIMARY длинные @EnglishApiName нужны только registry карточек, это НЕ имена дляТип() илиНовый. Manager используетТестируемоеДополнениеЭлементаФормы+actualkind+realname изreadonlysource.

  10. Оформление8свойств: типизированный фактический baseline→свой24/40/цвета/Arial11→readback→restore только при полном совпадении currentOwnprofile→baselineReadback→финальныйOwnprofile. Всё в одном native serverподготовительном вызове; после частичного setterошибки автоматического restore нет. Color/Font nativeXML-сериализуются: helper пишет только эти два разрешённых значения в память черезXMLWriter.SetString/XDTO.WriteXML/Close, не в файл и неmetadata. Так различаются инеабсолютныецвета/шрифты: RGB/Size=-1 сами по себе не доказывают идентичность styleelement. Width в символах,0авто;MaxWidth0безограничения, HorizontalStretch допускаетUndefined. Серверный readback не доказывает видимые пиксели/рендеринг.

  11. Native4страницыColor/Font явно говорят «Не применяется в интерфейсе Версия8.5», НЕ «в платформе8.5». СобственнаяCF явноТакси, metadataguard проверяет это на сервере; каждый клиент дополнительно проверяет реальныйКлиентскоеПриложение.ТекущийВариантИнтерфейса(). Платформа остаётся8.5.1.1343. НаличиеArial/его фактическое изображение проверяется вручную; успехgetter не подменяет визуальную проверку.

  12. Banner выравниваниеВерх/Лево, SkipOnInputЛожь, Ctrl+Alt+F6 назначается конструкторомShortcut тольконаКлиенте. Его readonlyContextMenu используется как реальный родитель одной собственной кнопки. Header/Footer своейколонкиСумма используют толькоБиблиотекаКартинок.Информация (видИзБиблиотеки); nativeпрограммноразрешаеттолькоПустая/ИзБиблиотеки, никакихSVG/Absolute. Подвал явно «Все исходные строки:1080» и НЕ сумма отфильтрованногоGUI.

  13. ManagerПоиска25.epf: новая собственная внешняя обработка, основная управляемая формаПульт. РеквизитыСогласие85Булево/флажок, ПодтверждаюРучнойШаг85Булево/флажок, МеткаСеансаСтрока36/поле, Итог85Строка неограниченная/readonlyполе. Полный основной MANAGER в модуль; nativeПриОткрытии1 и все14команд/кнопок изmetadataSchema.manager_buttons к указанным nativecommandhandler1. Не заменять их вызовами событий вручную.

  14. Только вручную открыть два собственных тонких клиента той жеИБ: source/TESTCLIENT -TPort15383 иmanager/TESTMANAGER. Перед этим человек проверяет, что127.0.0.1:15383 свободен и принадлежит именно своим двум приложениям/этойVM; никаких автоматических launch/port/network команд в авторской проверке нет. В TestClient открыта только одна source-форма; перенесите её настоящий canonicalUUID вManager. Другие окна/чужие клиенты запрещены.

  15. Порядокконечныхкоманд: Начать85→ВвестиКнигу85 (НЕEnter)→ОтменитьКнигу85→ВвестиКнигуДляПоиска85→настоящий ручнойEnter в своейстроке поиска→флажок ручногошага→ПроверитьКнигу85→ОткрытьСвойChip85. ВвестиТекст только замещает editor; код не обещает универсального defaultcommit/auto-search. При неожиданном переходе прекращает опыт, не угадывает режим.

  16. НажатьChip0 разрешён только послеactualFixedArrayCount1 и реальныхBook3×250/750. Native может показать стандартныйdialog; осмотрите и закройте только этот собственныйdialog вручную без изменений. Не придумываем его caption/type/events/контракт или автоматическое закрытие. Затем подтвердите ручнойшаг иУдалитьСвойChip85: вновьтолькоoneSource и actualreturnedchipText; реальные4/1080/chips0/editorEmpty.

  17. ДалееВвестиЧай85→настоящий ручнойEnter→новое подтверждение→ПроверитьЧай85: realGUI2×150/300, actualchip1. ОчиститьСвойПоиск85 должен дать4/1080/chips0/editorEmpty. NativeWaitForCondition явно5секунд, callback толькоactualeditor/chips/currentownidentity, без цикла ожидания и без измененияUI; при истечении времени STOP, не обещание тайминга. СверкаGUI отдельно перебирает настоящие currentrow maps максимум5переходов с6полями/ключами/явным целочисленнымФормат, не используетQuery вместофильтрованныхстрок и не угадывает decimal locale.

  18. Послеочистки вручную в своёмTestClient Ctrl+Alt+F6 (НЕEnter), подтвердить иПроверитьКлавиши85: actualTestedForm.GetCurrentItem должен бытьТестируемаяДекорацияФормыСводка85, actualsourcecounter1 подтвержден отдельно и вНачать85. ОбычныйCurrentItem формы не используем какproofдляDecorator. Затем сноваCtrl+Alt+F6+Enter одинраз: realbannerClick; подтвердить иПроверитьНажатие85 обязана отдельно получить actual2. Только после этого егоowncontextmenu→Сверить все четыре исходные строки одинраз; подтвердить иПроверитьСводку85 обязана получить actual3. Промежуточный2 не заменяется проверкой лишь конечного3.

  19. НажатьЗавершить85 только после13фазного собственного процесса: actualcurrentlim10→originalexactlimit readback→разрыв только своего testingtransport. Приошибке sticky-stop, sourceUI могчастичноизмениться; неclear/restore/reset/retry. Закройте свои TestClient/Manager вручную после отдельной проверки, не чужиеокна. ИсходнаяEPF/CF/данные не удаляются и backups не создаются.

Перем Тест85;
Перем Лимит85;
Перем Этап85;
Перем Ошибка85;
Перем СвойПользователь85;
Перем Заголовок85;
Перем Подключался85;

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Этап85 = 0;
    Ошибка85 = Ложь;
    Подключался85 = Ложь;
    Согласие85 = Ложь;
    ПодтверждаюРучнойШаг85 = Ложь;
    МеткаСеанса = "";
    Итог85 = "Откройте только собственный Source. Перенесите реальный UUID формы. Ручные Enter/собственный dialog не заменяются вызовом события";
КонецПроцедуры

&НаКлиенте
Функция КонтрольныйТекст85(Форма, Имя)
    Поле = Форма.ПолучитьОбъект(Тип("ТестируемоеПолеФормы"), , Имя, 3);
    Если ТипЗнч(Поле) <> Тип("ТестируемоеПолеФормы") Или Поле.Имя <> Имя Тогда
        ВызватьИсключение "OWN-SEARCH-CONTROL: неверное настоящее контрольное поле";
    КонецЕсли;
    Возврат Поле.ПолучитьПредставлениеДанных();
КонецФункции

&НаКлиенте
Функция СвояФорма85()
    Если Ошибка85 Или Тест85 = Неопределено Или СвойПользователь85 <> УчебныйПоискСтенд85.Паспорт85()
        Или КлиентскоеПриложение.ТекущийВариантИнтерфейса() <> ВариантИнтерфейсаКлиентскогоПриложения.Такси Тогда
        ВызватьИсключение "OWN-SEARCH-STOP: чужая ИБ/пользователь/интерфейс или предыдущая ошибка";
    КонецЕсли;
    Формы = Тест85.НайтиОбъекты(Тип("ТестируемаяФорма"), , , 3);
    Если ТипЗнч(Формы) <> Тип("ФиксированныйМассив") Или Формы.Количество() <> 1 Тогда
        ВызватьИсключение "OWN-SEARCH-FORMS: нужен только один собственный Source, никаких чужих/диалоговых форм";
    КонецЕсли;
    Форма = Формы[0];
    Если ТипЗнч(Форма) <> Тип("ТестируемаяФорма") Или Форма.ТекстЗаголовка <> Заголовок85
        Или КонтрольныйТекст85(Форма, "МеткаСеанса") <> МеткаСеанса
        Или КонтрольныйТекст85(Форма, "Пользователь85") <> СвойПользователь85
        Или КонтрольныйТекст85(Форма, "ПаспортСтенда") <> "own-search-ui25-four-literals-1080-taxi"
        Или КонтрольныйТекст85(Форма, "ИтогИсточника85") <> "4/1080; полный запрос, не строки текущего поискового показа" Тогда
        ВызватьИсключение "OWN-SEARCH-IDENTITY: источник и весь его исходный набор не подтверждены";
    КонецЕсли;
    Возврат Форма;
КонецФункции

&НаКлиенте
Функция Дополнение85(Форма, ПолеИмени, Вид)
    Имя = КонтрольныйТекст85(Форма, ПолеИмени);
    Если Имя = "" Или СтрНайти(Имя, "*") > 0 Или СтрНайти(Имя, "?") > 0 Тогда
        ВызватьИсключение "OWN-SEARCH-ADDITION: нужно настоящее точное имя из собственной source-формы";
    КонецЕсли;
    Найденные = Форма.НайтиОбъекты(Тип("ТестируемоеДополнениеЭлементаФормы"), , Имя, 3);
    Если ТипЗнч(Найденные) <> Тип("ФиксированныйМассив") Или Найденные.Количество() <> 1 Тогда
        ВызватьИсключение "OWN-SEARCH-ADDITION: нужно ровно одно собственное дополнение";
    КонецЕсли;
    Дополнение = Найденные[0];
    Если ТипЗнч(Дополнение) <> Тип("ТестируемоеДополнениеЭлементаФормы") Или Дополнение.Имя <> Имя Или Дополнение.Вид <> Вид
        Или Не Дополнение.ТекущаяВидимость() Или Не Дополнение.ТекущаяДоступность() Тогда
        ВызватьИсключение "OWN-SEARCH-ADDITION: неверный вид/имя/фактическая доступность";
    КонецЕсли;
    Возврат Дополнение;
КонецФункции

&НаКлиенте
Процедура СверитьРедактор85(Поиск, Текст)
    Факт = Поиск.ПолучитьТекстРедактирования();
    Если ТипЗнч(Факт) <> Тип("Строка") Или Факт <> Текст Тогда
        ВызватьИсключение "OWN-SEARCH-EDIT: фактический редактор не совпал; ввод не объявляется принятым поиском";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Функция СверитьСостояние85(Состояние, Количество)
    Тексты = Состояние.ПолучитьТекстыЭлементовСостоянияПросмотра();
    Если ТипЗнч(Тексты) <> Тип("ФиксированныйМассив") Или Тексты.Количество() <> Количество Тогда
        ВызватьИсключение "OWN-SEARCH-CHIPS: фактические состояния просмотра не совпали с этапом";
    КонецЕсли;
    Для Каждого Текст Из Тексты Цикл
        Если ТипЗнч(Текст) <> Тип("Строка") Или Текст = "" Тогда
            ВызватьИсключение "OWN-SEARCH-CHIPS: нужен реальный непустой текст, не угаданный заголовок";
        КонецЕсли;
    КонецЦикла;
    Возврат Тексты;
КонецФункции

&НаКлиенте
Функция СвоёСостояниеГотово85(Контроль) Экспорт
    Форма = СвояФорма85();
    Поиск = Дополнение85(Форма, "ИмяПоиска85", ВидДополненияЭлементаФормы.ОтображениеСтрокиПоиска);
    Состояние = Дополнение85(Форма, "ИмяСостояния85", ВидДополненияЭлементаФормы.ОтображениеСостоянияПросмотра);
    Тексты = Состояние.ПолучитьТекстыЭлементовСостоянияПросмотра();
    Если ТипЗнч(Тексты) <> Тип("ФиксированныйМассив") Тогда
        ВызватьИсключение "OWN-SEARCH-WAIT: неверный native тип, а не ожидаемая задержка";
    КонецЕсли;
    Возврат (Контроль.Редактор = Неопределено Или Поиск.ПолучитьТекстРедактирования() = Контроль.Редактор)
        И (Контроль.Чипов = Неопределено Или Тексты.Количество() = Контроль.Чипов);
КонецФункции

&НаКлиенте
Процедура ДождатьсяСвоегоСостояния85(Редактор, Чипов)
    Условие = Новый ОписаниеОповещения("СвоёСостояниеГотово85", ЭтотОбъект, Новый Структура("Редактор,Чипов", Редактор, Чипов));
    Если Не Тест85.ОжидатьСостояния(Условие, 5) Тогда
        ВызватьИсключение "OWN-SEARCH-WAIT: фактический editor/chips не достигнуты за5секунд; не обещаем тайминга или auto-commit";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура СверитьСтроки85(Форма, НомерТовара)
    Таблица = Форма.ПолучитьОбъект(Тип("ТестируемаяТаблицаФормы"), , "ТаблицаТоваров", 3);
    Если ТипЗнч(Таблица) <> Тип("ТестируемаяТаблицаФормы") Или Таблица.Имя <> "ТаблицаТоваров" Тогда
        ВызватьИсключение "OWN-SEARCH-GUI: нужна реальная собственная таблица, не исходный запрос";
    КонецЕсли;
    Таблица.ПерейтиКПервойСтроке(Ложь);
    Ключи = Новый Массив;
    Сумма = 0;
    Для Индекс = 0 По 4 Цикл
        Данные = Таблица.ПолучитьТекущуюСтроку();
        Если Данные = Неопределено Тогда
            Прервать;
        КонецЕсли;
        Если ТипЗнч(Данные) <> Тип("Соответствие") Или Данные.Количество() <> 6 Тогда
            ВызватьИсключение "OWN-SEARCH-GUI: неизвестный фактический состав колонок текущей строки";
        КонецЕсли;
        НомерТекст = Данные.Получить("УчебныйНомер");
        Если НомерТекст <> "1" И НомерТекст <> "2" И НомерТекст <> "3" И НомерТекст <> "4" Тогда
            ВызватьИсключение "OWN-SEARCH-GUI: неизвестный фактический целочисленный ключ";
        КонецЕсли;
        Номер = Число(НомерТекст);
        Если Ключи.Найти(Номер) <> Неопределено Тогда
            Прервать;
        КонецЕсли;
        Если НомерТовара <> 0 И Номер <> НомерТовара Тогда
            ВызватьИсключение "OWN-SEARCH-GUI: поисковый показ содержит не свой ожидаемый товар";
        КонецЕсли;
        Имя = ?(Номер = 1, "Книга", ?(Номер = 2, "Ручка", ?(Номер = 3, "Чай", "Вода")));
        Категория = ?(Номер <= 2, "Канцелярия", "Продукты");
        Количество = ?(Номер = 1, 3, ?(Номер = 2, 1, ?(Номер = 3, 2, 0)));
        Цена = ?(Номер = 1, 250, ?(Номер = 2, 30, ?(Номер = 3, 150, 70)));
        Если Данные.Получить("Наименование") <> Имя Или Данные.Получить("Категория") <> Категория
            Или Данные.Получить("Количество") <> Формат(Количество, "ЧДЦ=0;ЧГ=0;ЧН=0")
            Или Данные.Получить("Цена") <> Формат(Цена, "ЧДЦ=0;ЧГ=0;ЧН=0")
            Или Данные.Получить("Сумма") <> Формат(Количество * Цена, "ЧДЦ=0;ЧГ=0;ЧН=0") Тогда
            ВызватьИсключение "OWN-SEARCH-GUI: реальные тексты всех колонок не совпали с собственной арифметикой";
        КонецЕсли;
        Ключи.Добавить(Номер);
        Сумма = Сумма + Число(Данные.Получить("Сумма"));
        Таблица.ПерейтиКСледующейСтроке(Ложь);
    КонецЦикла;
    ОжидаемоеКоличество = ?(НомерТовара = 0, 4, 1);
    ОжидаемаяСумма = ?(НомерТовара = 0, 1080, ?(НомерТовара = 1, 750, 300));
    Если Ключи.Количество() <> ОжидаемоеКоличество Или Сумма <> ОжидаемаяСумма Тогда
        ВызватьИсключение "OWN-SEARCH-GUI: не все реальные строки доставлены или показ не совпал; повтор автоматически не выполняется";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура Начать85(Команда)
    Если Этап85 <> 0 Или Подключался85 Или Ошибка85 Или Не Согласие85 Тогда
        ВызватьИсключение "OWN-SEARCH-BEGIN: нужно одно отдельное согласие на собственный TestClient";
    КонецЕсли;
    Согласие85 = Ложь;
    Подключался85 = Истина;
    Попытка
        СвойПользователь85 = УчебныйПоискСтенд85.Паспорт85();
        UUID = Новый УникальныйИдентификатор(МеткаСеанса);
        Если Строка(UUID) <> МеткаСеанса Тогда
            ВызватьИсключение "OWN-SEARCH-UUID: нужен точный реальный UUID Source, не новый придуманный UUID";
        КонецЕсли;
        Заголовок85 = "Уч85Поиск25 " + МеткаСеанса;
        Тест85 = Новый ТестируемоеПриложение("127.0.0.1", 15383);
        Тест85.УстановитьСоединение();
        Лимит85 = Тест85.ПолучитьМаксимальноеВремяВыполненияДействия();
        Если ТипЗнч(Лимит85) <> Тип("Число") Или Лимит85 < 0 Тогда
            ВызватьИсключение "OWN-SEARCH-LIMIT: фактический исходный лимит не подтвержден";
        КонецЕсли;
        Тест85.УстановитьМаксимальноеВремяВыполненияДействия(10);
        Форма = СвояФорма85();
        Поиск = Дополнение85(Форма, "ИмяПоиска85", ВидДополненияЭлементаФормы.ОтображениеСтрокиПоиска);
        Состояние = Дополнение85(Форма, "ИмяСостояния85", ВидДополненияЭлементаФормы.ОтображениеСостоянияПросмотра);
        СверитьРедактор85(Поиск, "");
        СверитьСостояние85(Состояние, 0);
        СверитьСтроки85(Форма, 0);
        Если КонтрольныйТекст85(Форма, "ЧислоСводок85") <> "1" Тогда
            ВызватьИсключение "OWN-SEARCH-SUMMARY: свежий Source должен подтвердить ровно один собственный подготовительный вызов";
        КонецЕсли;
        Этап85 = 1;
        Итог85 = "Исходный настоящий GUI4/1080, editorEmpty/chips0 подтверждены. Далее ВвестиКнигу85 без Enter";
    Исключение
        Ошибка85 = Истина;
        Итог85 = "Остановлено: " + ОписаниеОшибки();
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура ВвестиКнигу85(Команда)
    ИсполнитьШаг85(1);
КонецПроцедуры

&НаКлиенте
Процедура ОтменитьКнигу85(Команда)
    ИсполнитьШаг85(2);
КонецПроцедуры

&НаКлиенте
Процедура ВвестиКнигуДляПоиска85(Команда)
    ИсполнитьШаг85(3);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьКнигу85(Команда)
    ИсполнитьШаг85(4);
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьСвойChip85(Команда)
    ИсполнитьШаг85(5);
КонецПроцедуры

&НаКлиенте
Процедура УдалитьСвойChip85(Команда)
    ИсполнитьШаг85(6);
КонецПроцедуры

&НаКлиенте
Процедура ВвестиЧай85(Команда)
    ИсполнитьШаг85(7);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьЧай85(Команда)
    ИсполнитьШаг85(8);
КонецПроцедуры

&НаКлиенте
Процедура ОчиститьСвойПоиск85(Команда)
    ИсполнитьШаг85(9);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьКлавиши85(Команда)
    ИсполнитьШаг85(10);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСводку85(Команда)
    ИсполнитьШаг85(12);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьНажатие85(Команда)
    ИсполнитьШаг85(11);
КонецПроцедуры

&НаКлиенте
Процедура Завершить85(Команда)
    ИсполнитьШаг85(13);
КонецПроцедуры

&НаКлиенте
Процедура ИсполнитьШаг85(НомерШага)
    Если Ошибка85 Или Этап85 <> НомерШага Тогда
        ВызватьИсключение "OWN-SEARCH-PHASE: предыдущая ошибка или неверный конечный этап; не сбрасывать и не повторять";
    КонецЕсли;
    Попытка
        Если НомерШага = 4 Или НомерШага = 6 Или НомерШага = 8 Или НомерШага = 10 Или НомерШага = 11 Или НомерШага = 12 Тогда
            Если Не ПодтверждаюРучнойШаг85 Тогда
                ВызватьИсключение "OWN-SEARCH-MANUAL: сначала настоящий ручной Enter/закрытие своего диалога/shortcut/menu, затем отдельное подтверждение";
            КонецЕсли;
        КонецЕсли;
        ПодтверждаюРучнойШаг85 = Ложь;
        Форма = СвояФорма85();
        Поиск = Дополнение85(Форма, "ИмяПоиска85", ВидДополненияЭлементаФормы.ОтображениеСтрокиПоиска);
        Состояние = Дополнение85(Форма, "ИмяСостояния85", ВидДополненияЭлементаФормы.ОтображениеСостоянияПросмотра);
        Если НомерШага = 1 Или НомерШага = 3 Или НомерШага = 7 Тогда
            СверитьРедактор85(Поиск, "");
            СверитьСостояние85(Состояние, 0);
            СверитьСтроки85(Форма, 0);
            Поиск.Активизировать();
            Поиск.ВвестиТекст(?(НомерШага = 7, "Чай", "Книга"));
            ДождатьсяСвоегоСостояния85(?(НомерШага = 7, "Чай", "Книга"), Неопределено);
            СверитьРедактор85(Поиск, ?(НомерШага = 7, "Чай", "Книга"));
            Итог85 = "Введен лишь фактический редактор. Не выдаём это за принятый поиск. Для этапа3/7 вручную нажмите Enter именно в своей строке поиска";
        ИначеЕсли НомерШага = 2 Тогда
            СверитьРедактор85(Поиск, "Книга");
            Поиск.ОтменитьРедактирование();
            ДождатьсяСвоегоСостояния85("", 0);
            СверитьРедактор85(Поиск, "");
            СверитьСостояние85(Состояние, 0);
            СверитьСтроки85(Форма, 0);
            Итог85 = "Отмена настоящего редактора подтверждена. При неожиданном auto-search остановиться, не объяснять его выдуманным default";
        ИначеЕсли НомерШага = 4 Или НомерШага = 8 Тогда
            ДождатьсяСвоегоСостояния85(Неопределено, 1);
            Тексты = СверитьСостояние85(Состояние, 1);
            СверитьСтроки85(Форма, ?(НомерШага = 4, 1, 3));
            Итог85 = "После настоящего ручного Enter проверен GUI: " + ?(НомерШага = 4, "Книга3×250=750", "Чай2×150=300") + "; фактический chip: " + Тексты[0];
        ИначеЕсли НомерШага = 5 Тогда
            СверитьСостояние85(Состояние, 1);
            СверитьСтроки85(Форма, 1);
            Состояние.НажатьНаЭлементСостоянияПросмотра(0);
            Итог85 = "Нажат настоящий единственный chip по подтвержденному индексу0. Возможный стандартный dialog осмотрите и закройте вручную только у своего TestClient; ничего не меняйте. Следующий этап проверяет вновь одну source-форму";
        ИначеЕсли НомерШага = 6 Тогда
            Тексты = СверитьСостояние85(Состояние, 1);
            СверитьСтроки85(Форма, 1);
            Состояние.УдалитьЭлементСостоянияПросмотра(Тексты[0]);
            ДождатьсяСвоегоСостояния85("", 0);
            СверитьСостояние85(Состояние, 0);
            СверитьСтроки85(Форма, 0);
            СверитьРедактор85(Поиск, "");
            Итог85 = "Удалён реальный chip по фактически полученному тексту. GUI4/1080 восстановлен, исходный query всё время4/1080";
        ИначеЕсли НомерШага = 9 Тогда
            СверитьСостояние85(Состояние, 1);
            СверитьСтроки85(Форма, 3);
            Поиск.Очистить();
            ДождатьсяСвоегоСостояния85("", 0);
            СверитьРедактор85(Поиск, "");
            СверитьСостояние85(Состояние, 0);
            СверитьСтроки85(Форма, 0);
            Итог85 = "Очистить вернул реальный GUI4/1080/chips0. Вручную Ctrl+Alt+F6 фокусирует ownbanner; НЕ нажимайте Enter до ПроверитьКлавиши85";
        ИначеЕсли НомерШага = 10 Тогда
            Если КонтрольныйТекст85(Форма, "ЧислоСводок85") <> "1" Тогда
                ВызватьИсключение "OWN-SEARCH-SUMMARY: до своего nativeClick нужен исходный фактический счетчик1";
            КонецЕсли;
            Текущий = Форма.ПолучитьТекущийЭлемент();
            Если ТипЗнч(Текущий) <> Тип("ТестируемаяДекорацияФормы") Или Текущий.Имя <> "Сводка85" Тогда
                ВызватьИсключение "OWN-SEARCH-SHORTCUT: настоящий Ctrl+Alt+F6 не привёл к своей декорации; setter-readback не доказательство UI";
            КонецЕсли;
            СверитьСтроки85(Форма, 0);
            Итог85 = "Реальный фокус banner и исходный счетчик1 подтверждены. Вручную нажмите Ctrl+Alt+F6 и Enter один раз, затем подтвердите ручной шаг и ПроверитьНажатие85. Собственное меню пока НЕ нажимать";
        ИначеЕсли НомерШага = 11 Тогда
            Если КонтрольныйТекст85(Форма, "ЧислоСводок85") <> "2" Тогда
                ВызватьИсключение "OWN-SEARCH-SUMMARY: один настоящий nativeClick не дал независимый фактический переход1до2";
            КонецЕсли;
            СверитьСтроки85(Форма, 0);
            СверитьСостояние85(Состояние, 0);
            Итог85 = "NativeClick отдельно подтвержден actual2. Теперь только собственное контекстное меню banner → Сверить все четыре исходные строки один раз; подтвердите ручной шаг и ПроверитьСводку85";
        ИначеЕсли НомерШага = 12 Тогда
            Если КонтрольныйТекст85(Форма, "ЧислоСводок85") <> "3" Тогда
                ВызватьИсключение "OWN-SEARCH-SUMMARY: настоящий callback+ownmenu не дали ожидаемые два независимых срабатывания";
            КонецЕсли;
            СверитьСтроки85(Форма, 0);
            СверитьСостояние85(Состояние, 0);
            Итог85 = "Два ручных ownUI вызова полной исходной сводки подтверждены. Header/Footer картинка из библиотеки и geometry/color/font readback не выдаются за доказанный renderer";
        ИначеЕсли НомерШага = 13 Тогда
            СверитьРедактор85(Поиск, "");
            СверитьСостояние85(Состояние, 0);
            СверитьСтроки85(Форма, 0);
            Если Тест85.ПолучитьМаксимальноеВремяВыполненияДействия() <> 10 Тогда
                ВызватьИсключение "OWN-SEARCH-LIMIT: текущий лимит не наш, слепое восстановление запрещено";
            КонецЕсли;
            Тест85.УстановитьМаксимальноеВремяВыполненияДействия(Лимит85);
            Если Тест85.ПолучитьМаксимальноеВремяВыполненияДействия() <> Лимит85 Тогда
                ВызватьИсключение "OWN-SEARCH-LIMIT: исходный фактический лимит не восстановлен";
            КонецЕсли;
            Тест85.РазорватьСоединение();
            Итог85 = "Конечный собственный процесс подтверждён ручным пользователем: GUI4/1080, Book750, Tea300, actualeditor/chips/focus/menu. Закрытия чужих окон и данных нет. Это сообщение возникает только при будущем реальном исполнении, не при статической сборке справочника";
        КонецЕсли;
        Этап85 = НомерШага + 1;
    Исключение
        Ошибка85 = Истина;
        Итог85 = "Опыт остановлен без повторного изменения/слепой очистки/восстановления: " + ОписаниеОшибки();
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры
Полный реальный источник собственного поиска и доступной fullsourceсводки

Своя внешняя обработка SourceПоиска25 → Управляемая форма Источник → Модуль

WindowsThin Taxi, managedserver/client directives; literalDynamicList nativefactories, реальные nativeevents. Не выполнен.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Попытка
    Список.ПроизвольныйЗапрос = Истина;
    Список.ОсновнаяТаблица = "";
    Список.ДинамическоеСчитываниеДанных = Ложь;
    Список.АвтоЗаполнениеДоступныхПолей = Истина;
    Список.АвтоматическоеСохранениеПользовательскихНастроек = Ложь;
    Список.ВидКлюча = ВидКлючаДинамическогоСписка.ЗначениеПоля;
    КлючевыеПоля = Новый Массив;
    КлючевыеПоля.Добавить("УчебныйНомер");

    Список.ПоляКлюча = Новый ФиксированныйМассив(КлючевыеПоля);
    Список.ТекстЗапроса = "ВЫБРАТЬ Д.УчебныйНомер, Д.Наименование, Д.Категория, Д.Количество, Д.Цена, Д.Количество * Д.Цена КАК Сумма ИЗ (ВЫБРАТЬ
|    1 КАК УчебныйНомер,
|    ""Книга"" КАК Наименование,
|    ""Канцелярия"" КАК Категория,
|    3 КАК Количество,
|    250 КАК Цена
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 2, ""Ручка"", ""Канцелярия"", 1, 30
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 3, ""Чай"", ""Продукты"", 2, 150
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 4, ""Вода"", ""Продукты"", 0, 70) КАК Д";
    Элементы.ТаблицаТоваров.ТолькоПросмотр = Истина;
    Пользователь85 = УчебныйПоискСтенд85.Паспорт85();
    МеткаСеанса = Строка(Новый УникальныйИдентификатор);
    ПаспортСтенда = "own-search-ui25-four-literals-1080-taxi";
    Ошибка85 = Ложь;
    ЧислоСводок85 = 0;
    ИтогИсточника85 = "";
    ЭтаФорма.АвтоЗаголовок = Ложь;
    ЭтаФорма.Заголовок = "Уч85Поиск25 " + МеткаСеанса;
    Элементы.ТаблицаТоваров.ПоложениеСтрокиПоиска = ПоложениеСтрокиПоиска.Верх;
    Элементы.ТаблицаТоваров.ПоложениеСостоянияПросмотра = ПоложениеСостоянияПросмотра.Верх;
    Элементы.ТаблицаТоваров.ПоложениеУправленияПоиском = ПоложениеУправленияПоиском.КоманднаяПанель;
    Группа = Элементы.Добавить("СводкаГруппа85", Тип("ГруппаФормы"));
    Группа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
    Сводка = Элементы.Добавить("Сводка85", Тип("ДекорацияФормы"), Группа);
    Сводка.Вид = ВидДекорацииФормы.Надпись;
    Сводка.Заголовок = "Все исходные строки:4; сумма1080. Сводка не является суммой отобранных строк";
    Сводка.Гиперссылка = Истина;
    Сводка.ВертикальноеПоложениеВГруппе = ВертикальноеПоложениеЭлемента.Верх;
    Сводка.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Лево;
    Сводка.ПропускатьПриВводе = Ложь;
    Сводка.УстановитьДействие("Нажатие", "Сводка85Нажатие");
    Меню = Сводка.КонтекстноеМеню;
    Если ТипЗнч(Меню) <> Тип("ГруппаФормы") Или Меню.ПодчиненныеЭлементы.Количество() <> 0 Тогда
        ВызватьИсключение "OWN-SEARCH-MENU: нужен только собственный пустой контейнер нового banner";
    КонецЕсли;
    Команда = Команды.Добавить("СводкаМеню85");
    Команда.Действие = "СводкаМеню85";
    Команда.Заголовок = "Сверить все четыре исходные строки";
    КнопкаМеню = Элементы.Добавить("КнопкаСводкаМеню85", Тип("КнопкаФормы"), Меню);
    КнопкаМеню.ИмяКоманды = "СводкаМеню85";

    Для Каждого ИмяПоля Из СтрРазделить("УчебныйНомер,Наименование,Категория,Количество,Цена,Сумма", ",") Цикл
        Колонка = Элементы.Добавить("Товары" + ИмяПоля, Тип("ПолеФормы"), Элементы.ТаблицаТоваров);
        Колонка.Вид = ВидПоляФормы.ПолеВвода;
        Колонка.ПутьКДанным = "Список." + ИмяПоля;
        Колонка.Заголовок = ИмяПоля;
    КонецЦикла;
    ЗавершитьПодготовку85();
    Исключение
        Ошибка85 = Истина;
        Отказ = Истина;
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры

&НаСервере
Функция СнимокОформления85(Управление)
    Если ТипЗнч(Управление) <> Тип("ДополнениеЭлементаФормы") Или Управление.Вид <> ВидДополненияЭлементаФормы.УправлениеПоиском Тогда
        ВызватьИсключение "OWN-SEARCH-STYLE: источник только настоящее управление поиском своей таблицы";
    КонецЕсли;
    Снимок = Новый Структура("Авто,Максимум,Растяжение,Ширина,Рамка,Текст,Фон,Шрифт",
        Управление.АвтоМаксимальнаяШирина, Управление.МаксимальнаяШирина, Управление.РастягиватьПоГоризонтали,
        Управление.Ширина, Управление.ЦветРамки, Управление.ЦветТекста, Управление.ЦветФона, Управление.Шрифт);
    Если ТипЗнч(Снимок.Авто) <> Тип("Булево") Или ТипЗнч(Снимок.Максимум) <> Тип("Число") Или ТипЗнч(Снимок.Ширина) <> Тип("Число")
        Или (ТипЗнч(Снимок.Растяжение) <> Тип("Булево") И Снимок.Растяжение <> Неопределено)
        Или ТипЗнч(Снимок.Рамка) <> Тип("Цвет") Или ТипЗнч(Снимок.Текст) <> Тип("Цвет") Или ТипЗнч(Снимок.Фон) <> Тип("Цвет") Или ТипЗнч(Снимок.Шрифт) <> Тип("Шрифт") Тогда
        ВызватьИсключение "OWN-SEARCH-STYLE: типизированный исходный профиль не подтвержден";
    КонецЕсли;
    Снимок.Вставить("XMLРамка", XMLОформления85(Снимок.Рамка));
    Снимок.Вставить("XMLТекст", XMLОформления85(Снимок.Текст));
    Снимок.Вставить("XMLФон", XMLОформления85(Снимок.Фон));
    Снимок.Вставить("XMLШрифт", XMLОформления85(Снимок.Шрифт));
    Возврат Снимок;
КонецФункции

&НаСервере
Функция XMLОформления85(Значение)
    Если ТипЗнч(Значение) <> Тип("Цвет") И ТипЗнч(Значение) <> Тип("Шрифт") Тогда
        ВызватьИсключение "OWN-SEARCH-STYLE: XML только своего serializableColor/Font, никаких данных/metadata";
    КонецЕсли;
    Писатель = Новый ЗаписьXML;
    Писатель.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(Писатель, Значение);
    Возврат Писатель.Закрыть();
КонецФункции

&НаСервере
Процедура СверитьОформление85(Управление, Ожидание)
    Факт = СнимокОформления85(Управление);
    Если Факт.Авто <> Ожидание.Авто Или Факт.Максимум <> Ожидание.Максимум Или Факт.Растяжение <> Ожидание.Растяжение Или Факт.Ширина <> Ожидание.Ширина
        Или Факт.XMLРамка <> XMLОформления85(Ожидание.Рамка) Или Факт.XMLТекст <> XMLОформления85(Ожидание.Текст)
        Или Факт.XMLФон <> XMLОформления85(Ожидание.Фон) Или Факт.XMLШрифт <> XMLОформления85(Ожидание.Шрифт) Тогда
        ВызватьИсключение "OWN-SEARCH-STYLE: фактический профиль не совпал, слепое восстановление запрещено";
    КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ПрименитьОформление85(Управление, ОжиданиеДо, Новое)
    СверитьОформление85(Управление, ОжиданиеДо);
    Управление.АвтоМаксимальнаяШирина = Новое.Авто;
    Управление.МаксимальнаяШирина = Новое.Максимум;
    Управление.РастягиватьПоГоризонтали = Новое.Растяжение;
    Управление.Ширина = Новое.Ширина;
    Управление.ЦветРамки = Новое.Рамка;
    Управление.ЦветТекста = Новое.Текст;
    Управление.ЦветФона = Новое.Фон;
    Управление.Шрифт = Новое.Шрифт;
    СверитьОформление85(Элементы.ТаблицаТоваров.УправлениеПоиском, Новое);
КонецПроцедуры

&НаСервере
Функция СвойПрофиль85()
    Возврат Новый Структура("Авто,Максимум,Растяжение,Ширина,Рамка,Текст,Фон,Шрифт", Ложь, 40, Истина, 24,
        Новый Цвет(0, 72, 96), Новый Цвет(0, 40, 60), Новый Цвет(235, 249, 250), Новый Шрифт("Arial", 11, Истина, Ложь, Ложь, Ложь, 100));
КонецФункции

&НаСервере
Процедура ЗавершитьПодготовку85()
    УчебныйПоискСтенд85.Паспорт85();
    Поиск = Элементы.ТаблицаТоваров.ОтображениеСтрокиПоиска;
    Состояние = Элементы.ТаблицаТоваров.ОтображениеСостоянияПросмотра;
    Управление = Элементы.ТаблицаТоваров.УправлениеПоиском;
    Если ТипЗнч(Поиск) <> Тип("ДополнениеЭлементаФормы") Или Поиск.Вид <> ВидДополненияЭлементаФормы.ОтображениеСтрокиПоиска
        Или ТипЗнч(Состояние) <> Тип("ДополнениеЭлементаФормы") Или Состояние.Вид <> ВидДополненияЭлементаФормы.ОтображениеСостоянияПросмотра
        Или ТипЗнч(Управление) <> Тип("ДополнениеЭлементаФормы") Или Управление.Вид <> ВидДополненияЭлементаФормы.УправлениеПоиском Тогда
        ВызватьИсключение "OWN-SEARCH-FACTORY: нужны три настоящих автоматически сформированных дополнения своей таблицы";
    КонецЕсли;
    ИмяПоиска85 = Поиск.Имя;
    ИмяСостояния85 = Состояние.Имя;
    ИмяУправления85 = Управление.Имя;
    Если ИмяПоиска85 = "" Или ИмяСостояния85 = "" Или ИмяУправления85 = "" Или ИмяПоиска85 = ИмяСостояния85 Или ИмяПоиска85 = ИмяУправления85 Или ИмяСостояния85 = ИмяУправления85 Тогда
        ВызватьИсключение "OWN-SEARCH-FACTORY: нужны три разных реальных имени без подмены";
    КонецЕсли;
    Поиск.Доступность = Истина;
    Состояние.Доступность = Истина;
    Управление.Доступность = Истина;
    База = СнимокОформления85(Управление);
    Новое = СвойПрофиль85();
    ПрименитьОформление85(Управление, База, Новое);
    ПрименитьОформление85(Управление, Новое, База);
    ПрименитьОформление85(Управление, База, Новое);
    Для Каждого Имя Из СтрРазделить("УчебныйНомер,Количество,Цена,Сумма", ",") Цикл
        Элементы["Товары" + Имя].Формат = "ЧДЦ=0;ЧГ=0;ЧН=0";
    КонецЦикла;
    КолонкаСуммы = Элементы.ТоварыСумма;
    Если КолонкаСуммы.Родитель <> Элементы.ТаблицаТоваров Или КолонкаСуммы.ПутьКДанным <> "Список.Сумма" Тогда
        ВызватьИсключение "OWN-SEARCH-PICTURE: картинки разрешены только своей реальной колонке суммы";
    КонецЕсли;
    КолонкаСуммы.ОтображатьВШапке = Истина;
    КолонкаСуммы.ОтображатьВПодвале = Истина;
    КолонкаСуммы.ТекстПодвала = "Все исходные строки:1080";
    КолонкаСуммы.КартинкаШапки = БиблиотекаКартинок.Информация;
    КолонкаСуммы.КартинкаПодвала = БиблиотекаКартинок.Информация;
    Если КолонкаСуммы.КартинкаШапки.Вид <> ВидКартинки.ИзБиблиотеки Или КолонкаСуммы.КартинкаПодвала.Вид <> ВидКартинки.ИзБиблиотеки Тогда
        ВызватьИсключение "OWN-SEARCH-PICTURE: native позволяет только Пустая/ИзБиблиотеки, не абсолютную или произвольный SVG";
    КонецЕсли;
    СверитьИсточникНаСервере85();
КонецПроцедуры

&НаСервере
Процедура СверитьИсточникНаСервере85()
    Если Ошибка85 Или Пользователь85 <> УчебныйПоискСтенд85.Паспорт85() Или ПаспортСтенда <> "own-search-ui25-four-literals-1080-taxi" Тогда
        ВызватьИсключение "OWN-SEARCH-STOP: собственный исходник изменен или ранее завершился ошибкой";
    КонецЕсли;
    СверитьОформление85(Элементы.ТаблицаТоваров.УправлениеПоиском, СвойПрофиль85());
    Если Не Элементы.ТаблицаТоваров.ТолькоПросмотр Или Элементы.ТаблицаТоваров.ПутьКДанным <> "Список"
        Или Список.ОсновнаяТаблица <> "" Или Список.ДинамическоеСчитываниеДанных
        Или Список.АвтоматическоеСохранениеПользовательскихНастроек Или Список.Группировка.Элементы.Количество() <> 0
        Или Список.ВидКлюча <> ВидКлючаДинамическогоСписка.ЗначениеПоля
        Или Список.ПоляКлюча.Количество() <> 1 Или Список.ПоляКлюча.Получить(0) <> "УчебныйНомер" Тогда
        ВызватьИсключение "OWN-SEARCH-SOURCE: изменена собственная политика буквального списка";
    КонецЕсли;
    Если Список.ТекстЗапроса <> "ВЫБРАТЬ Д.УчебныйНомер, Д.Наименование, Д.Категория, Д.Количество, Д.Цена, Д.Количество * Д.Цена КАК Сумма ИЗ (ВЫБРАТЬ
|    1 КАК УчебныйНомер,
|    ""Книга"" КАК Наименование,
|    ""Канцелярия"" КАК Категория,
|    3 КАК Количество,
|    250 КАК Цена
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 2, ""Ручка"", ""Канцелярия"", 1, 30
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 3, ""Чай"", ""Продукты"", 2, 150
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ 4, ""Вода"", ""Продукты"", 0, 70) КАК Д" Тогда
        ВызватьИсключение "OWN-SEARCH-SOURCE: неизвестный текст запроса не исполняем даже ради проверки итога";
    КонецЕсли;
    Данные = Новый Запрос(Список.ТекстЗапроса);
    Таблица = Данные.Выполнить().Выгрузить();
    Если Таблица.Количество() <> 4 Или Таблица.Колонки.Количество() <> 6 Или Таблица.Итог("Сумма") <> 1080 Тогда
        ВызватьИсключение "OWN-SEARCH-MATH: полный исходный запрос не дал свои4/1080";
    КонецЕсли;
    Для Номер = 1 По 4 Цикл
        Строки = Таблица.НайтиСтроки(Новый Структура("УчебныйНомер", Номер));
        Если Строки.Количество() <> 1 Тогда
            ВызватьИсключение "OWN-SEARCH-MATH: неизвестный ключ или дубль";
        КонецЕсли;
        Товар = Строки[0];
        ОжидаемоеИмя = ?(Номер = 1, "Книга", ?(Номер = 2, "Ручка", ?(Номер = 3, "Чай", "Вода")));
        ОжидаемаяКатегория = ?(Номер <= 2, "Канцелярия", "Продукты");
        ОжидаемоеКоличество = ?(Номер = 1, 3, ?(Номер = 2, 1, ?(Номер = 3, 2, 0)));
        ОжидаемаяЦена = ?(Номер = 1, 250, ?(Номер = 2, 30, ?(Номер = 3, 150, 70)));
        Если ТипЗнч(Товар.УчебныйНомер) <> Тип("Число") Или ТипЗнч(Товар.Количество) <> Тип("Число") Или ТипЗнч(Товар.Цена) <> Тип("Число") Или ТипЗнч(Товар.Сумма) <> Тип("Число")
            Или Товар.Наименование <> ОжидаемоеИмя Или Товар.Категория <> ОжидаемаяКатегория Или Товар.Количество <> ОжидаемоеКоличество
            Или Товар.Цена <> ОжидаемаяЦена Или Товар.Сумма <> ОжидаемоеКоличество * ОжидаемаяЦена Тогда
            ВызватьИсключение "OWN-SEARCH-MATH: все фактические поля должны совпасть, один итог недостаточен";
        КонецЕсли;
    КонецЦикла;
    ЧислоСводок85 = ЧислоСводок85 + 1;
    ИтогИсточника85 = "4/1080; полный запрос, не строки текущего поискового показа";
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Попытка
        Если КлиентскоеПриложение.ТекущийВариантИнтерфейса() <> ВариантИнтерфейсаКлиентскогоПриложения.Такси Тогда
            ВызватьИсключение "OWN-SEARCH-INTERFACE: требуется фактический Такси, а не интерфейс Версия8_5";
        КонецЕсли;
        Элементы.Сводка85.СочетаниеКлавиш = Новый СочетаниеКлавиш(Клавиша.F6, Истина, Истина, Ложь);
        Сочетание = Элементы.Сводка85.СочетаниеКлавиш;
        Если Сочетание.Клавиша <> Клавиша.F6 Или Не Сочетание.Alt Или Не Сочетание.Ctrl Или Сочетание.Shift Тогда
            ВызватьИсключение "OWN-SEARCH-SHORTCUT: собственное Ctrl+Alt+F6 не подтверждено";
        КонецЕсли;
    Исключение
        Ошибка85 = Истина;
        Отказ = Истина;
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура Сводка85Нажатие(Элемент)
    Если Элемент <> Элементы.Сводка85 Или ТипЗнч(Элемент) <> Тип("ДекорацияФормы") Тогда
        ВызватьИсключение "OWN-SEARCH-BANNER: неизвестная декорация";
    КонецЕсли;
    ПоказатьСводку85();
КонецПроцедуры

&НаКлиенте
Процедура СводкаМеню85(Команда)
    Если Команда <> Команды.СводкаМеню85 Тогда
        ВызватьИсключение "OWN-SEARCH-MENU: неизвестная команда";
    КонецЕсли;
    ПоказатьСводку85();
КонецПроцедуры

&НаКлиенте
Процедура ПоказатьСводку85()
    Если Ошибка85 Тогда
        ВызватьИсключение "OWN-SEARCH-STOP: после ошибки повтор и слепое восстановление запрещены";
    КонецЕсли;
    Попытка
        Если КлиентскоеПриложение.ТекущийВариантИнтерфейса() <> ВариантИнтерфейсаКлиентскогоПриложения.Такси Тогда
            ВызватьИсключение "OWN-SEARCH-INTERFACE: текущий интерфейс изменен";
        КонецЕсли;
        СверитьИсточникНаСервере85();
    Исключение
        Ошибка85 = Истина;
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры
Полный собственный serverpassport soleuser/File/metadata/Taxi

Собственная CF → Общие модули → УчебныйПоискСтенд85

ServerДа/CallServerДа, managedclient/ordinaryclient/global/privilegedНет; native readonly metadata/currentuser proof.

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры

Функция Паспорт85() Экспорт
    ПроверитьСвойПустойСтенд();
    Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1C85_OwnSearchLab\4c7f629b-8da2-4f04-af39-847f824a2810\Base"";"
        Или Метаданные.РежимСовместимостиИнтерфейса <> РежимСовместимостиИнтерфейса.Такси
        Или Метаданные.Обработки.Количество() <> 0 Или Метаданные.Отчеты.Количество() <> 0
        Или Метаданные.ОбщиеФормы.Количество() <> 0 Или Метаданные.ОбщиеМодули.Количество() <> 1
        Или Метаданные.ОбщиеМодули.Найти("УчебныйПоискСтенд85") = Неопределено
        Или Метаданные.Роли.Количество() <> 1 Или Не РольДоступна("УченикПоиска85") Тогда
        ВызватьИсключение "OWN-SEARCH-PASSPORT: разрешены только собственная новая FileИБ и явно настроенный Такси";
    КонецЕсли;
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если ТипЗнч(Пользователи) <> Тип("Массив") Или Пользователи.Количество() <> 1 Или Текущий = Неопределено Тогда
        ВызватьИсключение "OWN-SEARCH-USER: нужен единственный настоящий пользователь своей ИБ";
    КонецЕсли;
    Если Пользователи[0].Имя <> "УченикПоиска85" Или Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор Тогда
        ВызватьИсключение "OWN-SEARCH-USER: currentUUID не совпал с единственным собственным пользователем";
    КонецЕсли;
    Возврат Строка(Текущий.УникальныйИдентификатор);
КонецФункции

Разбор по шагам

  1. Подготовить только свой emptyCF/soleuser/Такси/две manually compiledEPF. Source создаёт реальный буквальныйDynamicList,3автоматическихaddon,6колонок,ownbanner/одноownmenu; фабрики/context не подменяются.

  2. Подтвердить typed nativebaseline8props→knownownprofile→restoreonlyownexpected→baseline→finalprofile; фактическиеTaxiguards иlibraryonlycolumnpictures. Getterпрофиль не являетсяrendererproof.

  3. Реально подключиться к только своему TestClient, проверитьcanonicalUUID/user/stamp/exactoneform/editorEmpty/chips0 и все4GUIстроки1080. Limitbaseline измерен, явно10.

  4. InputBook безcommit→CancelEdit→InputBook/manualEnter→actualBook750/chip1. Нажатьconfirmedindex0, самостоятельно осмотреть/закрыть толькоownsystemdialog; delete пореальномучipText, GUI4/1080.

  5. InputTea/manualEnter→actualTea300/chip1→Clear→actualGUI4/1080/chips0. Все6фактическихполей проверяются поnativeCurrentRow, суммы складываются изреальныхtextvalues, не изQuery.

  6. Ручнойownshortcut→реальнаяtestedDecorationfocus иactual1; отдельноownnativeClick→ПроверитьНажатие85 actual2; только затемownmenu→ПроверитьСводку85 actual3. ПоследнееЗавершить13 guardedexactlimitrestore/disconnect, никакихUIcleanup послеfailure.

Как проверить результат

  1. Future manual: все4GUIстроки1/750,2/30,3/300,4/0; сумма1080. Booksearch ровно1/750,Teasearch ровно1/300; исходныйзапрос независимо всегда4/1080.

  2. ActualeditorInput/Cancel/Clear,FixedArraychip0/1/0,returnedchiptext/index0 послеCount1. Неизвестнаяформа/type/kind/identity/profile/field/phase останавливают процесс.

  3. Счётчикownfullsourcesummary actual1 вStart/focus, actual2 вПроверитьНажатие85 и actual3 вПроверитьСводку85 подтверждает отдельно настоящиеклавиатурныйClick/menu, но не UIрендеринг/тайминг/атомарность. Статическивэтойработе realcalls0, все runtimeпроверки только будущие.

Ожидаемый результат

Ожидаемый результат будущего ручного выполнения: настоящий editor/search/chip/shortcut/menu cycle с проверенными750/300/1080. Здесь только авторский исходник и статические проверки, не выполненный результат1С.

На что обратить внимание

  1. NativeInputText не гарантируетпринятиепоиска. ManualEnter и actualGUI/chipreadback обязателен; unexpectedauto-search не маскируется фальшивымdefault.

  2. Запрос собственногоисточника не учитывает пользовательскийsearchfilter. Banner/Footer1080 прямообозначаютвсеисходныестроки, не поисковуювыборку.

  3. Color/Fontнеприменимы именно кinterfaceVersion8_5; рабочийcontext данногоownlesson явноTaxi наplatform8.5.1343. Width всимволах, font/colorbaseline не гарантияpixelrenderer.

  4. Readonlycontextmenu и3sourceaddon не присваиваются/не конструируются. Тольконативныеownfactories+basekind. Captionchips иstandarddialog не угадываются; чужие формы не закрываются.

  5. UIдействия неатомарны. Sticky-stop послеpartialfailure, неrestorefonts/search/defaultblind. Нет реальных1С/GUI/DB/network/process/files/backups действий при подготовке справочника.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.