docs(cfe): expand section 5.4 with borrowed form structure (BaseForm, callType, IDs)

Previously section 5.4 only documented the metadata XML of borrowed forms.
Now covers: two-part Form.xml structure (result + BaseForm), callType attribute
(Before/After/Override) on events and commands, ID numbering convention (1000000+),
own forms vs borrowed forms distinction, and form module patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-02-21 14:23:33 +03:00
parent 48de4cdc2a
commit 9c1985b710
+203 -3
View File
@@ -324,9 +324,20 @@ Enums/ # Перечисления
</EnumValue>
```
### 5.4. Заимствованные формы
### 5.4. Формы в расширениях
Метаданные формы (файл `.xml` в каталоге `Forms/`):
В расширении существуют **два принципиально разных сценария** работы с формами:
| Сценарий | Описание | `<BaseForm>` | ID элементов | `callType` |
|----------|----------|:------------:|:------------:|:----------:|
| **Собственная форма** на заимствованном объекте | Новая форма, не существующая в базовой конфигурации | Нет | Обычные (1+) | Нет |
| **Заимствованная форма** | Расширение существующей формы базовой конфигурации | Есть | Базовые + 1000000+ | Есть |
> **Как отличить:** Если файл метаданных формы (`.xml`) содержит `<ObjectBelonging>Adopted</ObjectBelonging>` — это заимствованная форма. Собственные формы не имеют `ObjectBelonging`.
#### 5.4.1. Метаданные заимствованной формы
Файл `.xml` в каталоге `Forms/`:
```xml
<Form uuid="8fcebcc1-...">
@@ -341,7 +352,196 @@ Enums/ # Перечисления
</Form>
```
Содержимое формы (расширение) хранится в `Forms/ФормаСписка/Ext/Form.xml`, модуль формы — в `Forms/ФормаСписка/Ext/Form/Module.bsl`.
Содержимое формы хранится в `Forms/ФормаСписка/Ext/Form.xml`, модуль формы — в `Forms/ФормаСписка/Ext/Form/Module.bsl`.
#### 5.4.2. Структура Form.xml заимствованной формы
Form.xml заимствованной формы — **двухчастный файл**:
```xml
<Form xmlns="http://v8.1c.ru/8.3/xcf/logform" ... version="2.17">
<!-- ═══ ЧАСТЬ 1: Результирующая форма (база + изменения расширения) ═══ -->
<AutoCommandBar name="ФормаКоманднаяПанель" id="-1">
<ChildItems>
<!-- Элементы базовой формы -->
<Popup name="ГруппаПараметры" id="154">...</Popup>
<!-- Элементы, добавленные расширением -->
<Button name="ФормаНоваяКоманда" id="159">
<CommandName>Form.Command.НоваяКоманда</CommandName>
...
</Button>
</ChildItems>
</AutoCommandBar>
<Events>
<Event name="OnCreateAtServer" callType="After">Расш1_ПриСозданииПосле</Event>
</Events>
<ChildItems>
<!-- Все элементы: базовые + добавленные расширением -->
</ChildItems>
<Attributes>
<Attribute name="РеквизитФормы" id="1000001">...</Attribute>
</Attributes>
<Commands>
<Command name="НоваяКоманда" id="1000000">
<Action callType="Override">Расш1_НоваяКомандаВместо</Action>
</Command>
</Commands>
<!-- ═══ ЧАСТЬ 2: Оригинальная форма из базовой конфигурации ═══ -->
<BaseForm version="2.17">
<AutoCommandBar name="ФормаКоманднаяПанель" id="-1">...</AutoCommandBar>
<ChildItems>
<!-- Только оригинальные элементы базовой конфигурации -->
</ChildItems>
<Attributes/>
<Commands>...</Commands>
</BaseForm>
</Form>
```
**Ключевые правила:**
1. **Часть 1** (до `<BaseForm>`) — **результирующая форма**, содержит ВСЕ элементы: и базовые, и добавленные расширением. Именно эта часть определяет итоговую форму при запуске.
2. **Часть 2** (`<BaseForm>`) — **полная копия оригинальной формы** из базовой конфигурации. Используется платформой для контроля совместимости — при обновлении конфигурации платформа сравнивает `<BaseForm>` с текущей формой конфигурации и предупреждает о расхождениях.
3. Элемент `<BaseForm>` всегда идёт **последним** в `<Form>` и имеет атрибут `version`.
#### 5.4.3. Нумерация ID элементов
| Диапазон | Принадлежность |
|----------|---------------|
| `-1` | Авто-командная панель (`AutoCommandBar`) — фиксированный ID |
| `1` `999999` | Элементы базовой формы (сохраняют оригинальные ID) |
| `1000000`+ | Реквизиты (`Attributes`) и команды (`Commands`), добавленные расширением |
> **Важно:** Визуальные элементы форм (элементы в `ChildItems`), добавленные расширением в тело базовой формы, могут использовать ID из обычного диапазона (продолжая нумерацию базовой формы). Диапазон 1000000+ гарантирован для `Attributes` и `Commands`.
#### 5.4.4. Атрибут callType — перехват событий и команд
В заимствованных формах события и действия команд используют атрибут `callType` для определения момента перехвата:
| Значение | Описание |
|----------|----------|
| `Before` | Обработчик расширения вызывается **до** оригинального обработчика |
| `After` | Обработчик расширения вызывается **после** оригинального обработчика |
| `Override` | Обработчик расширения **заменяет** оригинальный обработчик |
##### События формы (form-level)
```xml
<Events>
<Event name="OnCreateAtServer" callType="After">Расш1_ПриСозданииНаСервереПосле</Event>
<Event name="OnOpen" callType="Before">Расш1_ПриОткрытииПеред</Event>
<Event name="BeforeWriteAtServer" callType="After">Расш1_ПередЗаписьюНаСервереПосле</Event>
<Event name="NotificationProcessing" callType="After">Расш1_ОбработкаОповещенияПосле</Event>
</Events>
```
##### События элементов формы (element-level)
```xml
<InputField name="Банк" id="37">
<Events>
<Event name="OnChange" callType="Before">Расш1_БанкПриИзменении</Event>
<Event name="Clearing" callType="Before">Расш1_БанкОчистка</Event>
</Events>
...
</InputField>
<Table name="СписокСпецификаций" id="102">
<Events>
<Event name="Selection" callType="Before">Расш1_СписокВыборПеред</Event>
</Events>
...
</Table>
```
##### Действия команд (Command Action)
Команда может иметь **несколько элементов `<Action>`** с разными `callType`:
```xml
<!-- Перехват существующей команды базовой формы: до + после -->
<Command name="ПодборИзКлассификатора" id="1000002">
<Action callType="Before">Расш1_ПодборИзКлассификатораПеред</Action>
<Action callType="After">Расш1_ПодборИзКлассификатораПосле</Action>
</Command>
<!-- Полная замена обработчика команды -->
<Command name="НоваяКоманда" id="1000000">
<Action callType="Override">Расш1_НоваяКомандаВместо</Action>
</Command>
<!-- Один перехват (только после) -->
<Command name="ЗапросКорректировки" id="1000005">
<Action callType="After">Расш1_ЗапросКорректировкиПосле</Action>
</Command>
```
> **Отличие от обычной формы:** В обычной форме (конфигурации или собственной форме расширения) у `<Event>` и `<Action>` **нет** атрибута `callType` — обработчик вызывается напрямую.
#### 5.4.5. Собственная форма на заимствованном объекте
Расширение может добавить к заимствованному объекту **собственную форму**, не существующую в базовой конфигурации. Такая форма:
- **Не имеет** `ObjectBelonging` и `ExtendedConfigurationObject` в метаданных формы
- **Не содержит** `<BaseForm>` в Form.xml
- **Не использует** атрибут `callType`
- Использует обычную нумерацию ID (1+)
- Формат полностью совпадает с форматом форм конфигурации (см. [1c-form-spec.md](1c-form-spec.md))
```xml
<!-- Метаданные: Forms/МояФорма.xml — без ObjectBelonging -->
<Form uuid="...">
<Properties>
<Name>Расш1_МояФорма</Name>
<Synonym>...</Synonym>
<Comment/>
<FormType>Managed</FormType>
<UsePurposes>...</UsePurposes>
</Properties>
</Form>
```
```xml
<!-- Содержимое: Forms/МояФорма/Ext/Form.xml — обычная форма без BaseForm -->
<Form ... version="2.17">
<Events>
<Event name="OnCreateAtServer">ПриСозданииНаСервере</Event>
</Events>
<ChildItems>...</ChildItems>
<Attributes>...</Attributes>
</Form>
```
#### 5.4.6. Модуль заимствованной формы
Модуль формы (`Forms/Имя/Ext/Form/Module.bsl`) в заимствованной форме использует те же декораторы перехвата, что и другие модули расширений (см. раздел 7.2):
```bsl
&НаСервере
&Вместо("ЗаполнитьПодменюПараметры")
Процедура Расш1_ЗаполнитьПодменюПараметры()
ПродолжитьВызов();
КонецПроцедуры
&НаКлиенте
&ИзменениеИКонтроль("ПараметрыНаЯзыке")
Функция Расш1_ПараметрыНаЯзыке(КодЯзыка)
// ... тело с #Вставка / #Удаление маркерами ...
КонецФункции
// Обработчик собственной команды расширения (без декоратора)
&НаКлиенте
Процедура Расш1_НоваяКомандаВместо(Команда)
// ...
КонецПроцедуры
```
> **Обработчики событий с `callType`** (определённые в Form.xml секции Events/Action) реализуются в модуле как обычные процедуры **без** аннотаций-декораторов — привязка к событию уже задана в XML через `callType`.
---