Sign in Join
Wiki copytemporary

How To Write Lazarus Component/ru: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-Это руководство по созданию компонентов.
2-
3-## Contents
4-
5- * 1 Шаг 1: Создание пакета
6- * 2 Шаг 2: Создание модуля
7- * 2.1 Создание нового модуля
8- * 2.2 Добавление существующего модуля
9- * 3 Шаг 3: Создание значков для пакета
10- * 3.1 Использование редактора изображений Lazarus
11- * 3.2 Использование lazres
12- * 3.2.1 Создание lrs-файла
13- * 3.2.2 Создание res-файла
14- * 3.3 Использование glazres
15- * 4 Перекомпиляция пакетов
16- * 5 Удаление пакетов
17- * 6 Усовершенствование mycom.pas
18- * 7 Использование встроенных (визуальных) компонентов
19- * 8 Использование пользовательской процедуры рисования
20- * 9 Интеграция компонента с IDE
21- * 9.1 Редакторы свойств
22- * 9.2 Редакторы компонентов
23- * 10 Отладка компонента в Design-time
24- * 11 См. также
1+Это руководство по созданию компонентов.
252
263## Шаг 1: Создание пакета
274
28- * В меню IDE Lazarus нажмите "Package" > "New package" для запуска диспетчера пакетов.
5+- В меню IDE Lazarus нажмите "Package" \> "New package" для запуска диспетчера пакетов.
296
30-[![package menu.png](/wiki-images/f/fb/package_menu.png)](</File:package_menu.png>)
7+![](/wiki-images/7/7c/Package_menu.png)
318
32- * Появится диалоговое окно "Save". Выберите папку и имя файла и нажмите "Save". Если программа IDE предложит использовать строчные имена файлов, нажмите "да".
9+- Появится диалоговое окно "Save". Выберите папку и имя файла и нажмите "Save". Если программа IDE предложит использовать строчные имена файлов, нажмите "да".
3310
34- * Поздравляем: вы только что создали свой первый пакет!
11+- Поздравляем: вы только что создали свой первый пакет!
3512
36-[![Package Maker](/wiki-images/3/37/How_to_write_lazarus_component_package_maker.png)](</File:How_to_write_lazarus_component_package_maker.png> "Package Maker")
13+![](/wiki-images/3/37/How_to_write_lazarus_component_package_maker.png)
3714
3815## Шаг 2: Создание модуля
3916
40-Вы можете создать новый модуль или использовать существующий файл. Оба варианта описаны ниже.
17+Вы можете создать новый модуль или использовать существующий файл. Оба варианта описаны ниже.
4118
4219### Создание нового модуля
4320
44- * Используйте кнопку **Add > New component**.
21+- Используйте кнопку **Add \> New component**.\
4522
46-[![package new component.png](/wiki-images/6/60/package_new_component.png)](</File:package_new_component.png>)
23+![](/wiki-images/5/56/Package_new_component.png)\
4724
48- * Выберите компонент, [например такой] как TComboBox.
49- * Выберите _customcontrol1.pas_ в качестве **Unit File Name** и _CustomControl1_ в качестве **Unit Name**.
50- * Теперь вы можете задать иконку компоненту и определить, на какой палитре компонент должен появиться позже в Lazarus-IDE.
51- * Нажмите **OK**[, чтобы создать новый компонент].
25+- Выберите компонент, \[например такой\] как TComboBox.
26+- Выберите *customcontrol1.pas* в качестве **Unit File Name** и *CustomControl1* в качестве **Unit Name**.
27+- Теперь вы можете задать иконку компоненту и определить, на какой палитре компонент должен появиться позже в Lazarus-IDE.
28+- Нажмите **OK**\[, чтобы создать новый компонент\].\
5229
53-```
30+``` pascal
5431unit CustomControl1;
55-
56- {$mode objfpc}{$H+}
57-
58- interface
59-
60- uses
61- Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
62-
63- type
64- TCustomControl1 = class(TComboBox)
65- private
66- { Private declarations }
67- protected
68- { Protected declarations }
69- public
70- { Public declarations }
71- published
72- { Published declarations }
73- end;
74-
75- procedure Register;
76-
77- implementation
78-
79- procedure Register;
80- begin
81- RegisterComponents('Standard', [TCustomControl1]);
82- end;
83-
84- end.
85-```
8632
87- * Установите пакет, кликнув кнопку **Use - > Install** вверху редактора пакетов.
33+{$mode objfpc}{$H+}
8834
89-[![package install.png](/wiki-images/2/2a/package_install.png)](</File:package_install.png>)
35+interface
9036
91- * Теперь IDE спросит вас, должна ли она быть пересобрана. Ответьте "Да".
37+uses
38+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
9239
93-[![package rebuild.png](/wiki-images/6/67/package_rebuild.png)](</File:package_rebuild.png>)
40+type
41+ TCustomControl1 = class(TComboBox)
42+ private
43+ { Private declarations }
44+ protected
45+ { Protected declarations }
46+ public
47+ { Public declarations }
48+ published
49+ { Published declarations }
50+ end;
9451
95- * Перезапустите Lazarus[, если он не сделал этого сам,] и посмотрите на свой новый компонент в палитре компонентов. Поздравляем: вы только что установили свой первый пакет с вашим первым компонентом.
52+procedure Register;
9653
97-[![package installed.png](/wiki-images/7/79/package_installed.png)](</File:package_installed.png>)
54+implementation
9855
99-![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Примечание:** Если вы не видите свой новый компонент в палитре компонентов, скорее всего, вы используете не пересобранную версию Lazarus. Вы можете установить, где Lazarus пересобирается, используя [пункт меню] Tools -> Options -> Files -> Lazarus directory.
56+procedure Register;
57+begin
58+ RegisterComponents('Standard', [TCustomControl1]);
59+end;
10060
101-Вместо прямого вызова Lazarus вы также можете использовать startlazarus, который запускает недавно созданный Lazarus, например исполняемый файл Lazarus в каталоге ~ / .lazarus, если у вас нет доступа на запись в каталог, в который был установлен Lazarus.
61+end.
62+```
10263
103-* * *
64+- Установите пакет, кликнув кнопку **Use -\> Install** вверху редактора пакетов.\
10465
105-[Прим.перев.](</User:Zoltanleo> "User:Zoltanleo") 23:36, 1 December 2018 (CET): В корневом каталоге Lazarus'а после пересборки обычно содержится три исполняемых файла: lazarus (текущий запускаемый файл), startlazarus (лаучер для lazarus) и lazarus.old (старая версия исполняемого файла, существующая после последней удачной пересборки среды). В примечании, вероятнее всего, речь идет о них.
66+![](/wiki-images/3/36/Package_install.png)\
10667
107-* * *
68+- Теперь IDE спросит вас, должна ли она быть пересобрана. Ответьте "Да".\
10869
109-### Добавление существующего модуля
70+![](/wiki-images/9/9b/Package_rebuild.png)\
11071
111-Если у вас уже есть модуль, вы можете добавить его в пакет:
72+- Перезапустите Lazarus\[, если он не сделал этого сам,\] и посмотрите на свой новый компонент в палитре компонентов. Поздравляем: вы только что установили свой первый пакет с вашим первым компонентом.\
11273
113-[![package existing unit.png](/wiki-images/a/a4/package_existing_unit.png)](</File:package_existing_unit.png>)
74+![](/wiki-images/3/35/Package_installed.png)\
11475
115- * Нажмите кнопку **Add** , перейдите к вкладке **Add Files**. В [колонке] file name модуля добавьте ваш существующий файл. Нажмите **Add files to package**. Если диспетчер пакетов жалуется, что модуль находится вне заданных к модулям путей, нажмите "Да", чтобы добавить каталог в пути к модулям.
116- * Нажмите кнопку **Add** снова, перейдите на вкладку **Add Files** , найдите файл _.lrs_ и нажмите "OK" (см. Шаг 3 о создании файла иконки).
117- * Снова нажмите кнопку **Add** , перейдите к вкладке **New Requirement** [(новая зависимость)]. В имени пакета выберите **LCL** и нажмите OK.
76+> **Note:** Если вы не видите свой новый компонент в палитре компонентов, скорее всего, вы используете не пересобранную версию Lazarus. Вы можете установить, где Lazarus пересобирается, используя \[пункт меню\] Tools -\> Options -\> Files -\> Lazarus directory.
77+>
78+> Вместо прямого вызова Lazarus вы также можете использовать startlazarus, который запускает недавно созданный Lazarus, например исполняемый файл Lazarus в каталоге ~ / .lazarus, если у вас нет доступа на запись в каталог, в который был установлен Lazarus.
11879
119-Конечный результат должен выглядеть следующим образом:
80+------------------------------------------------------------------------
12081
121-[![Package Maker](/wiki-images/d/d9/How_to_write_lazarus_component_package_maker_done.png)](</File:How_to_write_lazarus_component_package_maker_done.png> "Package Maker")
82+Прим.перев. 23:36, 1 December 2018 (CET): В корневом каталоге Lazarus'а после пересборки обычно содержится три исполняемых файла: lazarus (текущий запускаемый файл), startlazarus (лаучер для lazarus) и lazarus.old (старая версия исполняемого файла, существующая после последней удачной пересборки среды). В примечании, вероятнее всего, речь идет о них.
12283
123- * Щелкните по дереву файлов в диспетчере пакетов. В свойствах файла убедитесь, что установлен флажок _Register unit_.
124- * Нажмите кнопку Options. Перейдите на вкладку IDE Integration. В опции Package Type убедитесь, что выбраны [режимы] Designtime и Runtime.
125- * Нажмите кнопку Compile, чтобы проверить, файлы компилируются без ошибок.
126- * Нажмите кнопку Install. Lazarus автоматически пересоберется и перезагрузится.
84+------------------------------------------------------------------------
12785
128-Компонент создан и готов к использованию:
86+### Добавление существующего модуля
12987
130-[![Component Created](/wiki-images/3/3c/How_to_write_lazarus_component_created.png)](</File:How_to_write_lazarus_component_created.png> "Component Created")
88+Если у вас уже есть модуль, вы можете добавить его в пакет:
13189
90+![](/wiki-images/1/11/Package_existing_unit.png)\
91+
92+- Нажмите кнопку **Add**, перейдите к вкладке **Add Files**. В \[колонке\] file name модуля добавьте ваш существующий файл. Нажмите **Add files to package**. Если диспетчер пакетов жалуется, что модуль находится вне заданных к модулям путей, нажмите "Да", чтобы добавить каталог в пути к модулям.
93+- Нажмите кнопку **Add** снова, перейдите на вкладку **Add Files**, найдите файл *.lrs* и нажмите "OK" (см. Шаг 3 о создании файла иконки).
94+- Снова нажмите кнопку **Add**, перейдите к вкладке **New Requirement** \[(новая зависимость)\]. В имени пакета выберите **LCL** и нажмите OK.
95+
96+Конечный результат должен выглядеть следующим образом:\
97+![Package Maker](/wiki-images/d/d9/How_to_write_lazarus_component_package_maker_done.png)\
98+
99+- Щелкните по дереву файлов в диспетчере пакетов. В свойствах файла убедитесь, что установлен флажок *Register unit*.
100+- Нажмите кнопку Options. Перейдите на вкладку IDE Integration. В опции Package Type убедитесь, что выбраны \[режимы\] Designtime и Runtime.
101+- Нажмите кнопку Compile, чтобы проверить, файлы компилируются без ошибок.
102+- Нажмите кнопку Install. Lazarus автоматически пересоберется и перезагрузится.
103+
104+Компонент создан и готов к использованию:\
105+![Component Created](/wiki-images/3/3c/How_to_write_lazarus_component_created.png)\
106+
132107## Шаг 3: Создание значков для пакета
133108
134-Вы должны создать PNG-файлы размером 24x24 пикселя в виде значков. Если для Lazarus 1.8+ вы хотите, чтобы значки палитры масштабировались при более высоких разрешениях экрана, вы также должны предоставлять значки 36x36 и 48x48 пикселей. Имена более крупных значков требуют добавления [суффиксов] "_150" и "_200" к имени файла, соответственно [увеличению разрешения] ("_150" для 150%, "_200" для 200%).
109+Вы должны создать PNG-файлы размером 24x24 пикселя в виде значков. Если для Lazarus 1.8+ вы хотите, чтобы значки палитры масштабировались при более высоких разрешениях экрана, вы также должны предоставлять значки 36x36 и 48x48 пикселей. Имена более крупных значков требуют добавления \[суффиксов\] "_150" и "_200" к имени файла, соответственно \[увеличению разрешения\] ("_150" для 150%, "_200" для 200%).
135110
136-FPC способен использовать стандартные файлы ресурсов `.rc` или скомпилированные ресурсы `.res`, [начиная] с версии fpc 2.6. См. [[Lazarus Resources/ru|FPC ресурсы]]. [О файлах] `.lrs`: см.ниже.
111+FPC способен использовать стандартные файлы ресурсов `.rc` или скомпилированные ресурсы `.res`, \[начиная\] с версии fpc 2.6. См. [[Lazarus Resources/ru|FPC ресурсы]]. \[О файлах\] `.lrs`: см.ниже.
137112
138113### Использование редактора изображений Lazarus
139114
140-Вы можете использовать [[Lazarus Image Editor]] для создания изображений в .lrs формате.
141-
142-
115+Вы можете использовать [[Lazarus Image Editor]] для создания изображений в .lrs формате.
143116
144-* * *
117+------------------------------------------------------------------------
145118
146-[Прим.перев.](</User:Zoltanleo> "User:Zoltanleo") 17:13, 3 December 2018 (CET): Поскольку старшие версии Лазаруса (насколько я помню, после v.1.6.х точно) позволяют задавать иконку изображения в png-формате, то удобнее всего для их создания использовать бесплатный векторный редактор [InkScape](<https://inkscape.org/ru>), "родным" для которого является формат SVG. Среди его преимуществ:
119+Прим.перев. 17:13, 3 December 2018 (CET): Поскольку старшие версии Лазаруса (насколько я помню, после v.1.6.х точно) позволяют задавать иконку изображения в png-формате, то удобнее всего для их создания использовать бесплатный векторный редактор [InkScape](https://inkscape.org/ru), "родным" для которого является формат SVG. Среди его преимуществ:
147120
148- * работа со слоями
149- * поддержка альфа-канала
150- * предосмотр иконок в разных разрешениях (в файле настроек можно задать даже нестандартные значения)
151- * вменяемый и оперативный саппорт (можно напрямую пообщаться с разработчиками в [чате](<https://inkscape.org/ru/community/discussion>))
152- * экспорт изображений в png-формат
121+- работа со слоями
122+- поддержка альфа-канала
123+- предосмотр иконок в разных разрешениях (в файле настроек можно задать даже нестандартные значения)
124+- вменяемый и оперативный саппорт (можно напрямую пообщаться с разработчиками в [чате](https://inkscape.org/ru/community/discussion))
125+- экспорт изображений в png-формат
153126
154-* * *
127+------------------------------------------------------------------------
155128
156129### Использование lazres
157130
158-`lazres` обычно находится в каталоге инструментов Lazarus.
131+`lazres` обычно находится в каталоге инструментов Lazarus.
159132
160-Вам может понадобиться скомпилировать [[lazres]] при первом использовании. Просто откройте _lazres.lpi_ в среде IDE и нажмите **run > build** в меню.
133+Вам может понадобиться скомпилировать [[lazres]] при первом использовании. Просто откройте *lazres.lpi* в среде IDE и нажмите **run \> build** в меню.
161134
162135#### Создание lrs-файла
163136
164-Для создания lrs-файла запустите:
165-```
137+Для создания lrs-файла запустите:
138+
139+``` pascal
166140~/lazarus/tools/lazres samplepackage.lrs TMyCom.png
167141```
168142
169-или, если доступны изображения с высоким разрешением
170-```
143+или, если доступны изображения с высоким разрешением
144+
145+``` pascal
171146~/lazarus/tools/lazres samplepackage.lrs TMyCom.png TMyCom_150.pgn TMyCom_200.png
172147```
173148
174-где
149+где
175150
176- * _samplepackage_ \- имя вашего пакета
177- * _TMyCom_ \- имя вашего компонента. Имя изображения должно совпадать с именем вашего компонента!
151+- *samplepackage* - имя вашего пакета
152+- *TMyCom* - имя вашего компонента. Имя изображения должно совпадать с именем вашего компонента!
178153
179-Вы можете добавить несколько изображений в файл lrs, добавив имя файла изображения в конец [команды]. Например:
180-```
154+Вы можете добавить несколько изображений в файл lrs, добавив имя файла изображения в конец \[команды\]. Например:
155+
156+``` pascal
181157~/lazarus/tools/lazres samplepackage.lrs TMyCom.png TMyOtherCom.png ...
182158```
183159
184-
185160**Пример**
186161
187-Ниже приведен образец полученного файла _samplepackage.lrs_.
188-```
162+Ниже приведен образец полученного файла *samplepackage.lrs*.
163+
164+``` pascal
189165LazarusResources.Add('TMyCom','PNG',[
190- #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#2#0#0#0'o'#21#170#175
191- +#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0'|IDAT8O'#237#212#209#10#192' '#8
192- +#5'P'#247#231#251's'#215#138#133#164#166'\'#220#195'`'#209'c'#157'L'#173#131
193- +#153#169'd4'#168'dP'#137'r_'#235'5'#136'@Zmk'#16'd9'#144#176#232#164'1'#247
194- +'I'#8#160'IL'#206'C'#179#144#12#199#140'.'#134#244#141'~'#168#247#209'S~;'#29
195- +'V+'#196#201'^'#10#15#150'?'#255#18#227#206'NZ>42'#181#159#226#144#15'@'#201
196- +#148#168'e'#224'7f<@4'#130'u_YD'#23#213#131#134'Q]'#158#188#135#0#0#0#0'IEND'
197- +#174'B`'#130
198- ]);
166+ #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#2#0#0#0'o'#21#170#175
167+ +#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0'|IDAT8O'#237#212#209#10#192' '#8
168+ +#5'P'#247#231#251's'#215#138#133#164#166'\'#220#195'`'#209'c'#157'L'#173#131
169+ +#153#169'd4'#168'dP'#137'r_'#235'5'#136'@Zmk'#16'd9'#144#176#232#164'1'#247
170+ +'I'#8#160'IL'#206'C'#179#144#12#199#140'.'#134#244#141'~'#168#247#209'S~;'#29
171+ +'V+'#196#201'^'#10#15#150'?'#255#18#227#206'NZ>42'#181#159#226#144#15'@'#201
172+ +#148#168'e'#224'7f<@4'#130'u_YD'#23#213#131#134'Q]'#158#188#135#0#0#0#0'IEND'
173+ +#174'B`'#130
174+]);
199175```
200176
201-Обязательно включите свой файл ресурсов в исходник нового компонента, добавив нижеследующее в модуль вашего компонента и включив "LResources" в раздел uses
202-```
177+Обязательно включите свой файл ресурсов в исходник нового компонента, добавив нижеследующее в модуль вашего компонента и включив "LResources" в раздел uses
178+
179+``` pascal
203180initialization
204- {$I samplepackage.lrs}
181+ {$I samplepackage.lrs}
205182```
206183
207-
208-
209184#### Создание res-файла
210185
211-lazres также может создать скомпилированный файл ресурсов, просто укажите файл с расширением .res, например:
212-```
186+lazres также может создать скомпилированный файл ресурсов, просто укажите файл с расширением .res, например:
187+
188+``` pascal
213189~/lazarus/tools/lazres samplepackage.res TMyCom.png
214190```
215191
216-или, для иконок с высоким разрешением:
217-```
192+или, для иконок с высоким разрешением:
193+
194+``` pascal
218195~/lazarus/tools/lazres samplepackage.res TMyCom.png TMyCom_150.png TMyCom_200.png
219196```
220197
221-В этом случае вместо включения файла lrs в разделе инициализации просто укажите файл ресурсов в любом месте исходного файла компонента
222-```
223-{$R samplepackage.res}
198+В этом случае вместо включения файла lrs в разделе инициализации просто укажите файл ресурсов в любом месте исходного файла компонента
199+
200+``` pascal
201+ {$R samplepackage.res}
224202```
225203
226204### Использование glazres
227205
228-**GLazRes** это графическая версия `lazres`, которая может собирать файлы в файл ресурсов Lazarus (.lrs). Его можно найти в каталоге инструментов установки Lazarus.
206+**GLazRes** это графическая версия `lazres`, которая может собирать файлы в файл ресурсов Lazarus (.lrs). Его можно найти в каталоге инструментов установки Lazarus.
229207
230208## Перекомпиляция пакетов
231209
232-Вам нужно пересобирать пакет каждый раз, когда вы вносите изменения в файл _mycom.pas_. Чтобы пересобрать пакет, откройте файл _samplepackage.lpk_ в диспетчере пакетов и нажмите кнопку Install.
210+Вам нужно пересобирать пакет каждый раз, когда вы вносите изменения в файл *mycom.pas*. Чтобы пересобрать пакет, откройте файл *samplepackage.lpk* в диспетчере пакетов и нажмите кнопку Install.
233211
234212## Удаление пакетов
235213
236- * Чтобы удалить установленные компоненты: в меню IDE выберите Package > Configure installed packages. На следующем рисунке показан инструмент Installed Packages.
214+- Чтобы удалить установленные компоненты: в меню IDE выберите Package \> Configure installed packages. На следующем рисунке показан инструмент Installed Packages.
237215
238-```
239-[![Installed Components](/wiki-images/0/0e/How_to_write_lazarus_component_installed_components.png)](</File:How_to_write_lazarus_component_installed_components.png> "Installed Components")
240-```
216+![`Installed Components`](/wiki-images/0/0e/How_to_write_lazarus_component_installed_components.png)
241217
242- * Выберите пакет, который вы хотите удалить, и нажмите Uninstall selection.
218+- Выберите пакет, который вы хотите удалить, и нажмите Uninstall selection.
243219
244-Если что-то пойдет не так с пакетом (например, каталог пакета удаляется без деинсталляции [пакета в первую очередь]), Lazarus может не разрешить вам удалять пакеты. Чтобы устранить проблему, в меню IDE выберите Tools > Build Lazarus. Lazarus пересоберет все пакеты и перезапустит их. Теперь вы можете удалить проблемные пакеты.
220+Если что-то пойдет не так с пакетом (например, каталог пакета удаляется без деинсталляции \[пакета в первую очередь\]), Lazarus может не разрешить вам удалять пакеты. Чтобы устранить проблему, в меню IDE выберите Tools \> Build Lazarus. Lazarus пересоберет все пакеты и перезапустит их. Теперь вы можете удалить проблемные пакеты.
245221
246222## Усовершенствование mycom.pas
247223
248- * Код в _mycom.pas_ выше дает вам основы того, что вам нужно для создания компонента. Далее приведена усовершенствованная версия с некоторыми советами о том, как писать процедуры и события для компонентов.
249- * _OnChange2_ показывает, как создавать события.
250- * _OnSample_ показывает, как создавать пользовательские события.
251- * _MyText_ и _MyText2_ показывает различные способы записи свойств.
252- * Вы можете использовать TComboBox вместо TCustomComboBox в качестве базового класса, который [объявляет] публичными все свойства как TComboBox.
253- * Если TCustomComboBox используется в качестве базового класса, вы заметите, что в Инспекторе объектов IDE будет отсутствовать множество свойств и событий. Чтобы добавить эти свойства и события, просто скопируйте и вставьте свойства, перечисленные ниже [комментария] _// properties from TComboBox_. Этот список свойств можно получить из объявления TComboBox в модуле StdCtrls. Исключите [из списка] любое свойство, которое вы хотите [определить] самостоятельно.
224+- Код в *mycom.pas* выше дает вам основы того, что вам нужно для создания компонента. Далее приведена усовершенствованная версия с некоторыми советами о том, как писать процедуры и события для компонентов.
225+- *OnChange2* показывает, как создавать события.
226+- *OnSample* показывает, как создавать пользовательские события.
227+- *MyText* и *MyText2* показывает различные способы записи свойств.
228+- Вы можете использовать TComboBox вместо TCustomComboBox в качестве базового класса, который \[объявляет\] публичными все свойства как TComboBox.
229+- Если TCustomComboBox используется в качестве базового класса, вы заметите, что в Инспекторе объектов IDE будет отсутствовать множество свойств и событий. Чтобы добавить эти свойства и события, просто скопируйте и вставьте свойства, перечисленные ниже \[комментария\] *// properties from TComboBox*. Этот список свойств можно получить из объявления TComboBox в модуле StdCtrls. Исключите \[из списка\] любое свойство, которое вы хотите \[определить\] самостоятельно.
254230
255-```
231+``` pascal
256232unit mycom;
257-
258- {$mode objfpc}{$H+}
259-
260- interface
261-
262- uses
263- Classes, SysUtils, StdCtrls, Forms, Dialogs,
264- LCLType,LCLIntf,lresources,LCLProc;
265-
266- type
267-
268- TSampleEvent = procedure(MyText: String) of Object;
269-
270- TMyCom = class (TCustomComboBox)
271- private
272- FMyText: String;
273- FOnChange2: TNotifyEvent;
274- FOnSample: TSampleEvent;
275- public
276- constructor Create(TheOwner: TComponent); override;
277- procedure CreateWnd; override;
278- procedure Change; override;
279- protected
280- function GetMyText2: String;
281- procedure SetMyText2(MyText: String);
282- published
283- property MyText: String read FMyText write FMyText;
284- property MyText2: String read GetMyText2 write SetMyText2;
285- property OnChange2: TNotifyEvent read FOnChange2 write FOnChange2;
286- property OnSample: TSampleEvent read FOnSample write FOnSample;
287-
288- // properties from TComboBox
289- property Align;
290- property Anchors;
291- property ArrowKeysTraverseList;
292- property AutoComplete;
293- property AutoCompleteText;
294- property AutoDropDown;
295- property AutoSelect;
296- property AutoSize;
297- property BidiMode;
298- property BorderSpacing;
299- property CharCase;
300- property Color;
301- property Ctl3D;
302- property Constraints;
303- property DragCursor;
304- property DragMode;
305- property DropDownCount;
306- property Enabled;
307- property Font;
308- property ItemHeight;
309- property ItemIndex;
310- property Items;
311- property ItemWidth;
312- property MaxLength;
313- property OnChange;
314- property OnChangeBounds;
315- property OnClick;
316- property OnCloseUp;
317- property OnContextPopup;
318- property OnDblClick;
319- property OnDragDrop;
320- property OnDragOver;
321- property OnDrawItem;
322- property OnEndDrag;
323- property OnDropDown;
324- property OnEditingDone;
325- property OnEnter;
326- property OnExit;
327- property OnGetItems;
328- property OnKeyDown;
329- property OnKeyPress;
330- property OnKeyUp;
331- property OnMeasureItem;
332- property OnMouseDown;
333- property OnMouseMove;
334- property OnMouseUp;
335- property OnStartDrag;
336- property OnSelect;
337- property OnUTF8KeyPress;
338- property ParentBidiMode;
339- property ParentColor;
340- property ParentCtl3D;
341- property ParentFont;
342- property ParentShowHint;
343- property PopupMenu;
344- property ReadOnly;
345- property ShowHint;
346- property Sorted;
347- property Style;
348- property TabOrder;
349- property TabStop;
350- property Text;
351- property Visible;
352- end;
353-
354- procedure Register;
355-
356- implementation
357-
358- procedure Register;
359- begin
360- RegisterComponents('Sample',[TMyCom]);
361- end;
362-
363- constructor TMyCom.Create(TheOwner: TComponent);
364- begin
365- inherited Create(TheOwner);
366- Self.Style := csDropDownList;
367- end;
368-
369- procedure TMyCom.CreateWnd;
370- begin
371- inherited CreateWnd;
372- Items.Assign(Screen.Fonts);
373- end;
374-
375- procedure TMyCom.Change;
376- begin
377- inherited;
378- if Assigned(FOnChange2) then FOnChange2(Self);
379- if Assigned(FOnSample) then FOnSample(FMyText);
380- end;
381-
382- function TMyCom.GetMyText2: String;
383- begin
384- Result:=FMyText;
385- end;
386-
387- procedure TMyCom.SetMyText2(MyText: String);
388- begin
389- FMyText:=MyText;
390- end;
391-
392- initialization
393- {$I samplepackage.lrs}
233+
234+{$mode objfpc}{$H+}
235+
236+interface
237+
238+uses
239+ Classes, SysUtils, StdCtrls, Forms, Dialogs,
240+ LCLType,LCLIntf,lresources,LCLProc;
241+
242+type
243+
244+ TSampleEvent = procedure(MyText: String) of Object;
245+
246+ TMyCom = class (TCustomComboBox)
247+ private
248+ FMyText: String;
249+ FOnChange2: TNotifyEvent;
250+ FOnSample: TSampleEvent;
251+ public
252+ constructor Create(TheOwner: TComponent); override;
253+ procedure CreateWnd; override;
254+ procedure Change; override;
255+ protected
256+ function GetMyText2: String;
257+ procedure SetMyText2(MyText: String);
258+ published
259+ property MyText: String read FMyText write FMyText;
260+ property MyText2: String read GetMyText2 write SetMyText2;
261+ property OnChange2: TNotifyEvent read FOnChange2 write FOnChange2;
262+ property OnSample: TSampleEvent read FOnSample write FOnSample;
394263
395- end.
396-```
264+ // properties from TComboBox
265+ property Align;
266+ property Anchors;
267+ property ArrowKeysTraverseList;
268+ property AutoComplete;
269+ property AutoCompleteText;
270+ property AutoDropDown;
271+ property AutoSelect;
272+ property AutoSize;
273+ property BidiMode;
274+ property BorderSpacing;
275+ property CharCase;
276+ property Color;
277+ property Ctl3D;
278+ property Constraints;
279+ property DragCursor;
280+ property DragMode;
281+ property DropDownCount;
282+ property Enabled;
283+ property Font;
284+ property ItemHeight;
285+ property ItemIndex;
286+ property Items;
287+ property ItemWidth;
288+ property MaxLength;
289+ property OnChange;
290+ property OnChangeBounds;
291+ property OnClick;
292+ property OnCloseUp;
293+ property OnContextPopup;
294+ property OnDblClick;
295+ property OnDragDrop;
296+ property OnDragOver;
297+ property OnDrawItem;
298+ property OnEndDrag;
299+ property OnDropDown;
300+ property OnEditingDone;
301+ property OnEnter;
302+ property OnExit;
303+ property OnGetItems;
304+ property OnKeyDown;
305+ property OnKeyPress;
306+ property OnKeyUp;
307+ property OnMeasureItem;
308+ property OnMouseDown;
309+ property OnMouseMove;
310+ property OnMouseUp;
311+ property OnStartDrag;
312+ property OnSelect;
313+ property OnUTF8KeyPress;
314+ property ParentBidiMode;
315+ property ParentColor;
316+ property ParentCtl3D;
317+ property ParentFont;
318+ property ParentShowHint;
319+ property PopupMenu;
320+ property ReadOnly;
321+ property ShowHint;
322+ property Sorted;
323+ property Style;
324+ property TabOrder;
325+ property TabStop;
326+ property Text;
327+ property Visible;
328+ end;
397329
398-Также вы заметите, что в Инспекторе объектов IDE существуют некоторые необъявленные и, возможно, нежелательные элементы. Чтобы удалить те из них, которые вам не нужны, вы можете переобъявить их в разделе _Published_ как простые переменные. Например:
330+procedure Register;
331+
332+implementation
333+
334+procedure Register;
335+begin
336+ RegisterComponents('Sample',[TMyCom]);
337+end;
338+
339+constructor TMyCom.Create(TheOwner: TComponent);
340+begin
341+ inherited Create(TheOwner);
342+ Self.Style := csDropDownList;
343+end;
344+
345+procedure TMyCom.CreateWnd;
346+begin
347+ inherited CreateWnd;
348+ Items.Assign(Screen.Fonts);
349+end;
350+
351+procedure TMyCom.Change;
352+begin
353+ inherited;
354+ if Assigned(FOnChange2) then FOnChange2(Self);
355+ if Assigned(FOnSample) then FOnSample(FMyText);
356+end;
357+
358+function TMyCom.GetMyText2: String;
359+begin
360+ Result:=FMyText;
361+end;
362+
363+procedure TMyCom.SetMyText2(MyText: String);
364+begin
365+ FMyText:=MyText;
366+end;
367+
368+initialization
369+ {$I samplepackage.lrs}
370+
371+end.
399372```
373+
374+Также вы заметите, что в Инспекторе объектов IDE существуют некоторые необъявленные и, возможно, нежелательные элементы. Чтобы удалить те из них, которые вам не нужны, вы можете переобъявить их в разделе *Published* как простые переменные. Например:
375+
376+``` pascal
400377Published
401- ...
402- property Height: Integer;
403- property Width: Integer;
404- ...
378+...
379+ property Height: Integer;
380+ property Width: Integer;
381+...
405382```
406383
407384## Использование встроенных (визуальных) компонентов
408385
409-Можно использовать стандартные компоненты, встроенные в ваши собственные компоненты (посмотрите для примера на TLabeledEdit или TButtonPanel).
386+Можно использовать стандартные компоненты, встроенные в ваши собственные компоненты (посмотрите для примера на TLabeledEdit или TButtonPanel).
410387
411-Предположим, вы хотите создать пользовательскую панель с TLabel на ней. С помощью описанных выше шагов можно создать базовый пакет и исходные файлы. Теперь сделайте следующее для добавления TLabel в компонент:
388+Предположим, вы хотите создать пользовательскую панель с TLabel на ней. С помощью описанных выше шагов можно создать базовый пакет и исходные файлы. Теперь сделайте следующее для добавления TLabel в компонент:
412389
413- * Добавьте приватный атрибут (поле) для компонента label (`FEmbeddedLabel: TLabel;`).
414- * Добавьте published-свойство только для чтения для компонента label (`property EmbeddedLabel: TLabel read FEmbeddedLabel;`)
415- * Создайте label в конструкторе (переопределенном) компонента (`FEmbeddedLabel: = TLabel.Create(self);`)
416- * Задайте родительский элемент компонента (`FEmbeddedLabel.Parent: = self;`)
417- * Если встроенный компонент не является 'субкомпонентом' по умолчанию (например, TBoundLabel, TPanelBitBtn и т.д.), то добавьте вызов в SetSubComponent. Это необходимо для IDE, чтобы она знала, что она также должна хранить свойства встроенного компонента. По умолчанию TLabel не является субкомпонентом, поэтому необходимо добавить вызов метода (`FEmbeddedLabel.SetSubComponent(true);`).
390+- Добавьте приватный атрибут (поле) для компонента label (`FEmbeddedLabel: TLabel;`).
391+- Добавьте published-свойство только для чтения для компонента label (`property EmbeddedLabel: TLabel read FEmbeddedLabel;`)
392+- Создайте label в конструкторе (переопределенном) компонента (`FEmbeddedLabel: = TLabel.Create(self);`)
393+- Задайте родительский элемент компонента (`FEmbeddedLabel.Parent: = self;`)
394+- Если встроенный компонент не является 'субкомпонентом' по умолчанию (например, TBoundLabel, TPanelBitBtn и т.д.), то добавьте вызов в SetSubComponent. Это необходимо для IDE, чтобы она знала, что она также должна хранить свойства встроенного компонента. По умолчанию TLabel не является субкомпонентом, поэтому необходимо добавить вызов метода (`FEmbeddedLabel.SetSubComponent(true);`).
418395
419-В итоге вы получите что-то вроде этого (показаны только основные части):
420-```
396+В итоге вы получите что-то вроде этого (показаны только основные части):
397+
398+``` pascal
421399TEnhancedPanel = class(TCustomControl)
422- private
423- { Новые аттрибуты для встроенного label }
424- FEmbeddedLabel: TLabel;
425-
426- public
427- { Конструктор должен быть переопределен, чтобы label могла быть создана}
428- constructor Create(AOwner: TComponent); override;
429-
430- published
431- { Сделаем label видимым в IDE }
432- property EmbeddedLabel: TLabel read FEmbeddedLabel;
433- end;
434-
435- implementation
436-
437- constructor TEnhancedPanel.Create(AOwner: TComponent);
438- begin
439- inherited Create(AOwner);
440-
441- // Устанавливаем дефолтовые width и height
442- with GetControlClassDefaultSize do
443- SetInitialBounds(0, 0, CX, CY);
444-
445- // Добавляем встроенный label
446- FEmbeddedLabel := TLabel.Create(Self); // Добавляем встроенный label
447- FEmbeddedLabel.Parent := self; // Показываем label на panel
448- FEmbeddedLabel.SetSubComponent(true); // Говорим IDE сохранять измененные свойства
449- FLabel.Name := 'EmbeddedLabel';
450- FLabel.Caption := 'Howdy World!';
451-
452- // Убеждаемся, что встроенная label не может быть выделена/удалена средствами IDE
453- FLabel.ControlStyle := FLabel.ControlStyle - [csNoDesignSelectable];
454-
455- // Задаем другие свойства, если необходимо
456- //...
457-
458- end;
400+private
401+ { Новые аттрибуты для встроенного label }
402+ FEmbeddedLabel: TLabel;
403+
404+public
405+ { Конструктор должен быть переопределен, чтобы label могла быть создана}
406+ constructor Create(AOwner: TComponent); override;
407+
408+published
409+ { Сделаем label видимым в IDE }
410+ property EmbeddedLabel: TLabel read FEmbeddedLabel;
411+end;
412+
413+implementation
414+
415+constructor TEnhancedPanel.Create(AOwner: TComponent);
416+begin
417+ inherited Create(AOwner);
418+
419+ // Устанавливаем дефолтовые width и height
420+ with GetControlClassDefaultSize do
421+ SetInitialBounds(0, 0, CX, CY);
422+
423+ // Добавляем встроенный label
424+ FEmbeddedLabel := TLabel.Create(Self); // Добавляем встроенный label
425+ FEmbeddedLabel.Parent := self; // Показываем label на panel
426+ FEmbeddedLabel.SetSubComponent(true); // Говорим IDE сохранять измененные свойства
427+ FLabel.Name := 'EmbeddedLabel';
428+ FLabel.Caption := 'Howdy World!';
429+
430+ // Убеждаемся, что встроенная label не может быть выделена/удалена средствами IDE
431+ FLabel.ControlStyle := FLabel.ControlStyle - [csNoDesignSelectable];
432+
433+ // Задаем другие свойства, если необходимо
434+ //...
435+
436+end;
459437```
460438
461439## Использование пользовательской процедуры рисования
462440
463-Вы всегда можете переопределить компонент внутри вашей программы. Например, это реализует пользовательскую процедуру Paint для TLabel:
464-```
441+Вы всегда можете переопределить компонент внутри вашей программы. Например, это реализует пользовательскую процедуру Paint для TLabel:
442+
443+``` pascal
465444type
466- TMyLabel = class(TLabel)
467- protected
468- procedure Paint; override;
469- end;
470- {...}
471- implementation
472- {...}
473- procedure TMyLabel.Paint;
474- begin
475- // ваш код для реализации Paint, например
476- Canvas.TextOut(0,0,Caption);
477- end;
445+ TMyLabel = class(TLabel)
446+ protected
447+ procedure Paint; override;
448+ end;
449+{...}
450+implementation
451+{...}
452+procedure TMyLabel.Paint;
453+begin
454+ // ваш код для реализации Paint, например
455+ Canvas.TextOut(0,0,Caption);
456+end;
478457```
479458
480-Теперь вы можете создать MyLabel внутри вашей программы во время выполнения с этой переопределенной процедурой Paint вместо стандартной.
459+Теперь вы можете создать MyLabel внутри вашей программы во время выполнения с этой переопределенной процедурой Paint вместо стандартной.
481460
482-Для большинства компонентов и для большинства методов было бы полезно вызвать унаследованную процедуру внутри него:
483-```
461+Для большинства компонентов и для большинства методов было бы полезно вызвать унаследованную процедуру внутри него:
462+
463+``` pascal
484464procedure TMyLabel.Paint;
485- begin
486-
487- inherited Paint; /////////////////////
488-
489- // ваш код для реализации Paint, например
490- Canvas.TextOut(0,0,Caption);
491- end;
465+begin
466+
467+ inherited Paint; /////////////////////
468+
469+ // ваш код для реализации Paint, например
470+ Canvas.TextOut(0,0,Caption);
471+end;
492472```
493473
494-Однако унаследованное поведение нежелательно в этом случае, поскольку второе действие записи будет перекрывать первый (унаследованный).
474+Однако унаследованное поведение нежелательно в этом случае, поскольку второе действие записи будет перекрывать первый (унаследованный).
495475
496476## Интеграция компонента с IDE
497477
498478### Редакторы свойств
499479
500-Редакторы свойств предоставляют настраиваемые диалоги для редактирования свойств в инспекторе объектов. Для большинства свойств, таких как строки, строковые списки, изображения, перечисленные типы и другие, уже есть редакторы свойств по умолчанию, но если у пользовательского компонента есть особый вид свойства, для изменения свойства может потребоваться настраиваемый диалог.
480+Редакторы свойств предоставляют настраиваемые диалоги для редактирования свойств в инспекторе объектов. Для большинства свойств, таких как строки, строковые списки, изображения, перечисленные типы и другие, уже есть редакторы свойств по умолчанию, но если у пользовательского компонента есть особый вид свойства, для изменения свойства может потребоваться настраиваемый диалог.
501481
502-Каждый редактор свойств - это класс, который должен происходить из TPropertyEditor или одного из его потомков и реализовывать методы этого базового класса. Они должны быть зарегистрированы в процедуре 'Register', используя функцию RegisterPropertyEditor из модуля PropEdits. Это стандарт для имен редакторов свойств с именем свойства, за которым следует [слово] 'Property', например [имя] TFieldProperty для редактора свойств свойства TField.
503-```
504-TPropertyEditor = class
505- public
506- function AllEqual: Boolean; Virtual;
507- function AutoFill: Boolean; Virtual;
508- procedure Edit; Virtual; // Активируется двойным щелчком по значению свойства
509- procedure ShowValue; Virtual; // Активируется щелчком по элементу управления значения свойства
510- function GetAttributes: TPropertyAttributes; Virtual;
511- function GetEditLimit: Integer; Virtual;
512- function GetName: ShortString; Virtual;
513- procedure GetProperties(Proc: TGetPropEditProc); Virtual;
514- function GetHint(HintType: TPropEditHint; x, y: integer): String; Virtual;
515- function GetDefaultValue: AnsiString; Virtual;
516- procedure GetValues(Proc: TGetStrProc); Virtual;
517- procedure SetValue(const NewValue: AnsiString); Virtual;
518- procedure UpdateSubProperties; Virtual;
519- function SubPropertiesNeedsUpdate: Boolean; Virtual;
520- function IsDefaultValue: Boolean; Virtual;
521- function IsNotDefaultValue: Boolean; Virtual;
522- // ... укорочено
523- end;
482+Каждый редактор свойств - это класс, который должен происходить из TPropertyEditor или одного из его потомков и реализовывать методы этого базового класса. Они должны быть зарегистрированы в процедуре 'Register', используя функцию RegisterPropertyEditor из модуля PropEdits. Это стандарт для имен редакторов свойств с именем свойства, за которым следует \[слово\] 'Property', например \[имя\] TFieldProperty для редактора свойств свойства TField.
483+
484+``` pascal
485+ TPropertyEditor = class
486+ public
487+ function AllEqual: Boolean; Virtual;
488+ function AutoFill: Boolean; Virtual;
489+ procedure Edit; Virtual; // Активируется двойным щелчком по значению свойства
490+ procedure ShowValue; Virtual; // Активируется щелчком по элементу управления значения свойства
491+ function GetAttributes: TPropertyAttributes; Virtual;
492+ function GetEditLimit: Integer; Virtual;
493+ function GetName: ShortString; Virtual;
494+ procedure GetProperties(Proc: TGetPropEditProc); Virtual;
495+ function GetHint(HintType: TPropEditHint; x, y: integer): String; Virtual;
496+ function GetDefaultValue: AnsiString; Virtual;
497+ procedure GetValues(Proc: TGetStrProc); Virtual;
498+ procedure SetValue(const NewValue: AnsiString); Virtual;
499+ procedure UpdateSubProperties; Virtual;
500+ function SubPropertiesNeedsUpdate: Boolean; Virtual;
501+ function IsDefaultValue: Boolean; Virtual;
502+ function IsNotDefaultValue: Boolean; Virtual;
503+ // ... укорочено
504+ end;
524505```
525506
526-Хорошим примером для редактора свойств является редактор свойств TFont.
507+Хорошим примером для редактора свойств является редактор свойств TFont.
527508
528-Один из наиболее распространенных случаев для редакторов свойств - это свойства, которые являются классами. Поскольку классы имеют много полей и могут иметь различные форматы, Lazarus не может иметь [универсальное] поле редактирования в инспекторе объектов, способное их редактировать, [как это сделано,] например, для строк и числовых типов.
509+Один из наиболее распространенных случаев для редакторов свойств - это свойства, которые являются классами. Поскольку классы имеют много полей и могут иметь различные форматы, Lazarus не может иметь \[универсальное\] поле редактирования в инспекторе объектов, способное их редактировать, \[как это сделано,\] например, для строк и числовых типов.
529510
530-Для классов соглашение состоит в том, чтобы в поле значений постоянно отображалось имя класса в круглых скобках, например "(TFont)", а кнопка "..." показывала диалог для редактирования этого класса. Это поведение, за исключением диалога, реализуется стандартным редактором свойств для классов, называемых TClassPropertyEditor, который может быть унаследован при создании редакторов свойств для классов:
531-```
511+Для классов соглашение состоит в том, чтобы в поле значений постоянно отображалось имя класса в круглых скобках, например "(TFont)", а кнопка "..." показывала диалог для редактирования этого класса. Это поведение, за исключением диалога, реализуется стандартным редактором свойств для классов, называемых TClassPropertyEditor, который может быть унаследован при создании редакторов свойств для классов:
512+
513+``` pascal
532514TClassPropertyEditor = class(TPropertyEditor)
533- public
534- constructor Create(Hook: TPropertyEditorHook; APropCount: Integer); Override;
535- function GetAttributes: TPropertyAttributes; Override;
536- procedure GetProperties(Proc: TGetPropEditProc); Override;
537- function GetValue: AnsiString; Override;
538- property SubPropsTypeFilter: TTypeKinds Read FSubPropsTypeFilter
539- Write SetSubPropsTypeFilter
540- Default tkAny;
541- end;
515+public
516+ constructor Create(Hook: TPropertyEditorHook; APropCount: Integer); Override;
517+ function GetAttributes: TPropertyAttributes; Override;
518+ procedure GetProperties(Proc: TGetPropEditProc); Override;
519+ function GetValue: AnsiString; Override;
520+ property SubPropsTypeFilter: TTypeKinds Read FSubPropsTypeFilter
521+ Write SetSubPropsTypeFilter
522+ Default tkAny;
523+end;
542524```
543525
544-Возвращаясь к примеру TFont, наследование от TClassPropertyEditor уже предлагает часть желаемого поведения, а затем классу TFontPropertyEditor необходимо реализовать отображение диалога в методе Edit и установить атрибуты для редактора:
545-```
546-TFontPropertyEditor = class(TClassPropertyEditor)
547- public
548- procedure Edit; Override;
549- function GetAttributes: TPropertyAttributes; Override;
550- end;
551-
552- procedure TFontPropertyEditor.Edit;
553- var
554- FontDialog: TFontDialog;
555- begin
556- FontDialog := TFontDialog.Create(NIL);
557- try
558- FontDialog.Font := TFont(GetObjectValue(TFont));
559- FontDialog.Options := FontDialog.Options + [fdShowHelp, fdForceFontExist];
560- if FontDialog.Execute then SetPtrValue(FontDialog.Font);
561- finally
562- FontDialog.Free;
563- end;
564- end;
565-
566- function TFontPropertyEditor.GetAttributes: TPropertyAttributes;
567- begin
568- Result := [paMultiSelect, paSubProperties, paDialog, paReadOnly];
569- end;
526+Возвращаясь к примеру TFont, наследование от TClassPropertyEditor уже предлагает часть желаемого поведения, а затем классу TFontPropertyEditor необходимо реализовать отображение диалога в методе Edit и установить атрибуты для редактора:
527+
528+``` pascal
529+ TFontPropertyEditor = class(TClassPropertyEditor)
530+ public
531+ procedure Edit; Override;
532+ function GetAttributes: TPropertyAttributes; Override;
533+ end;
534+
535+procedure TFontPropertyEditor.Edit;
536+var
537+ FontDialog: TFontDialog;
538+begin
539+ FontDialog := TFontDialog.Create(NIL);
540+ try
541+ FontDialog.Font := TFont(GetObjectValue(TFont));
542+ FontDialog.Options := FontDialog.Options + [fdShowHelp, fdForceFontExist];
543+ if FontDialog.Execute then SetPtrValue(FontDialog.Font);
544+ finally
545+ FontDialog.Free;
546+ end;
547+end;
548+
549+function TFontPropertyEditor.GetAttributes: TPropertyAttributes;
550+begin
551+ Result := [paMultiSelect, paSubProperties, paDialog, paReadOnly];
552+end;
570553```
571554
572555### Редакторы компонентов
573556
574-Редакторы компонентов управляют поведением компонентов по щелчку правой кнопкой мыши и двойному щелчку в дизайнере форм.
557+Редакторы компонентов управляют поведением компонентов по щелчку правой кнопкой мыши и двойному щелчку в дизайнере форм.
575558
576-Каждый редактор компонентов - это класс, который должен происходить от TComponentEditor или одного из его потомков и реализовывать методы из этого базового класса. Он должен быть зарегистрирован в процедуре 'Register', использущей функцию RegisterComponentEditor из модуля ComponentEditors. Это стандарт для именования редакторов компонентов с именем компонента, за которым следует [слово] 'Editor', например TStringGridComponentEditor для редактора свойств компонента TStringGrid. Хотя редакторы пользовательских компонентов должны быть основаны на TComponentEditor, большинство его методов на самом деле [берут начало] от предка, поэтому необходимо также знать TBaseComponentEditor:
577-```
578-TBaseComponentEditor = class
579- protected
580- public
581- constructor Create(AComponent: TComponent;
582- ADesigner: TComponentEditorDesigner); Virtual;
583- procedure Edit; Virtual; Abstract;
584- procedure ExecuteVerb(Index: Integer); Virtual; Abstract;
585- function GetVerb(Index: Integer): String; Virtual; Abstract;
586- function GetVerbCount: Integer; Virtual; Abstract;
587- procedure PrepareItem(Index: Integer; const AnItem: TMenuItem); Virtual; Abstract;
588- procedure Copy; Virtual; Abstract;
589- function IsInInlined: Boolean; Virtual; Abstract;
590- function GetComponent: TComponent; Virtual; Abstract;
591- function GetDesigner: TComponentEditorDesigner; Virtual; Abstract;
592- function GetHook(out Hook: TPropertyEditorHook): Boolean; Virtual; Abstract;
593- procedure Modified; Virtual; Abstract;
594- end;
559+Каждый редактор компонентов - это класс, который должен происходить от TComponentEditor или одного из его потомков и реализовывать методы из этого базового класса. Он должен быть зарегистрирован в процедуре 'Register', использущей функцию RegisterComponentEditor из модуля ComponentEditors. Это стандарт для именования редакторов компонентов с именем компонента, за которым следует \[слово\] 'Editor', например TStringGridComponentEditor для редактора свойств компонента TStringGrid. Хотя редакторы пользовательских компонентов должны быть основаны на TComponentEditor, большинство его методов на самом деле \[берут начало\] от предка, поэтому необходимо также знать TBaseComponentEditor:
560+
561+``` pascal
562+ TBaseComponentEditor = class
563+ protected
564+ public
565+ constructor Create(AComponent: TComponent;
566+ ADesigner: TComponentEditorDesigner); Virtual;
567+ procedure Edit; Virtual; Abstract;
568+ procedure ExecuteVerb(Index: Integer); Virtual; Abstract;
569+ function GetVerb(Index: Integer): String; Virtual; Abstract;
570+ function GetVerbCount: Integer; Virtual; Abstract;
571+ procedure PrepareItem(Index: Integer; const AnItem: TMenuItem); Virtual; Abstract;
572+ procedure Copy; Virtual; Abstract;
573+ function IsInInlined: Boolean; Virtual; Abstract;
574+ function GetComponent: TComponent; Virtual; Abstract;
575+ function GetDesigner: TComponentEditorDesigner; Virtual; Abstract;
576+ function GetHook(out Hook: TPropertyEditorHook): Boolean; Virtual; Abstract;
577+ procedure Modified; Virtual; Abstract;
578+ end;
595579```
596580
597-Наиболее важным методом редактора компонентов является [метод] Edit, который вызывается по двойному щелчку на компоненте. Когда вызывается контекстное меню для компонента, запрашивается метод GetVerbCount и GetVerb для создания меню. Если выбран один из глаголов (что означает пункты меню в этом случае), вызывается ExecuteVerb. Существует редактор компонентов по умолчанию (TDefaultEditor), который реализует Edit для поиска свойств компонента для наиболее подходящего для редактирования. Обычно он выбирает событие, которое будет редактироваться, путем добавления скелета кода в редактор кода и установки курсора в это место.
581+Наиболее важным методом редактора компонентов является \[метод\] Edit, который вызывается по двойному щелчку на компоненте. Когда вызывается контекстное меню для компонента, запрашивается метод GetVerbCount и GetVerb для создания меню. Если выбран один из глаголов (что означает пункты меню в этом случае), вызывается ExecuteVerb. Существует редактор компонентов по умолчанию (TDefaultEditor), который реализует Edit для поиска свойств компонента для наиболее подходящего для редактирования. Обычно он выбирает событие, которое будет редактироваться, путем добавления скелета кода в редактор кода и установки курсора в это место.
598582
599-Другими важными методами из TBaseComponentEditor являются:
583+Другими важными методами из TBaseComponentEditor являются:
600584
601- * **ExecuteVerb(Index)** \- Выполняет один из дополнительных пунктов меню, расположенных во всплывающем меню правой кнопки мыши;
602- * **GetVerb** – Возвращает имя каждого дополнительного пункта всплывающего меню. Обратите внимание, что редактор компонентов должен размещать специальные символы заголовка элемента, такие как &, для создания ускорителя клавиатуры и "-" для создания разделителя;
603- * **GetVerbCount** – Возвращает количество элементов, которые будут добавлены во всплывающее меню. Индекс для подпрограмм GetVerb и ExecuteVerb равен нулю, начиная от 0 до GetVerbCount - 1;
604- * **PrepareItem** – Вызывается для каждого глагола [(GetVerbCount и GetVerb)] после создания пункта меню. Позволяет настраивать элемент меню, например, добавляя подэлементы, добавляя флажок или даже скрывая его, устанавливая Visible в false;
605- * **Copy** \- Вызывается, когда компонент копируется в буфер обмена. Данные компонента при использовании Lazarus'ом всегда будут [только] добавляться и не могут быть изменены. Этот метод предназначен для добавления различных типов из буфера обмена при вставке компонента в другие приложения, но не будет влиять на вставку в Lazarus'е.
585+- **ExecuteVerb(Index)** - Выполняет один из дополнительных пунктов меню, расположенных во всплывающем меню правой кнопки мыши;
586+- **GetVerb** – Возвращает имя каждого дополнительного пункта всплывающего меню. Обратите внимание, что редактор компонентов должен размещать специальные символы заголовка элемента, такие как &, для создания ускорителя клавиатуры и "-" для создания разделителя;
587+- **GetVerbCount** – Возвращает количество элементов, которые будут добавлены во всплывающее меню. Индекс для подпрограмм GetVerb и ExecuteVerb равен нулю, начиная от 0 до GetVerbCount - 1;
588+- **PrepareItem** – Вызывается для каждого глагола \[(GetVerbCount и GetVerb)\] после создания пункта меню. Позволяет настраивать элемент меню, например, добавляя подэлементы, добавляя флажок или даже скрывая его, устанавливая Visible в false;
589+- **Copy** - Вызывается, когда компонент копируется в буфер обмена. Данные компонента при использовании Lazarus'ом всегда будут \[только\] добавляться и не могут быть изменены. Этот метод предназначен для добавления различных типов из буфера обмена при вставке компонента в другие приложения, но не будет влиять на вставку в Lazarus'е.
606590
607-Простым и интересным примером является редактор компонентов TCheckListBox, который создает диалоговое окно для редактирования. Более удобный, чем реализация всех методов из TBaseComponentEditor, [он] наследуется от TComponentEditor, и это то, что делает TCheckListBoxEditor. Этот базовый класс добавляет пустые реализации для большинства методов и некоторые умолчательные для других. Для [метода] Edit он вызывает ExecuteVerb(0), поэтому, если первый пункт [popup menu] будет сопоставлен действию двойного щелчка мыши, что является условным обозначением для редактора, то нет необходимости в [ручной] реализации [кода метода] Edit. Это основное действие для двойного щелчка и первого элемента меню часто является диалогом, и для TCheckListBox это также реализуется [так]:
608-```
609-TCheckListBoxComponentEditor = class(TComponentEditor)
610- protected
611- procedure DoShowEditor;
612- public
613- procedure ExecuteVerb(Index: Integer); override;
614- function GetVerb(Index: Integer): String; override;
615- function GetVerbCount: Integer; override;
616- end;
617-
618- procedure TCheckGroupComponentEditor.DoShowEditor;
619- var
620- Dlg: TCheckGroupEditorDlg;
621- begin
622- Dlg := TCheckGroupEditorDlg.Create(NIL);
623- try
624- // .. укорочено
625- Dlg.ShowModal;
626- // .. укорочено
627- finally
628- Dlg.Free;
629- end;
630- end;
631-
632- procedure TCheckGroupComponentEditor.ExecuteVerb(Index: Integer);
633- begin
634- case Index of
635- 0: DoShowEditor;
636- end;
637- end;
638-
639- function TCheckGroupComponentEditor.GetVerb(Index: Integer): String;
640- begin
641- Result := 'CheckBox Editor...';
642- end;
643-
644- function TCheckGroupComponentEditor.GetVerbCount: Integer;
645- begin
646- Result := 1;
647- end;
591+Простым и интересным примером является редактор компонентов TCheckListBox, который создает диалоговое окно для редактирования. Более удобный, чем реализация всех методов из TBaseComponentEditor, \[он\] наследуется от TComponentEditor, и это то, что делает TCheckListBoxEditor. Этот базовый класс добавляет пустые реализации для большинства методов и некоторые умолчательные для других. Для \[метода\] Edit он вызывает ExecuteVerb(0), поэтому, если первый пункт \[popup menu\] будет сопоставлен действию двойного щелчка мыши, что является условным обозначением для редактора, то нет необходимости в \[ручной\] реализации \[кода метода\] Edit. Это основное действие для двойного щелчка и первого элемента меню часто является диалогом, и для TCheckListBox это также реализуется \[так\]:
592+
593+``` pascal
594+ TCheckListBoxComponentEditor = class(TComponentEditor)
595+ protected
596+ procedure DoShowEditor;
597+ public
598+ procedure ExecuteVerb(Index: Integer); override;
599+ function GetVerb(Index: Integer): String; override;
600+ function GetVerbCount: Integer; override;
601+ end;
602+
603+procedure TCheckGroupComponentEditor.DoShowEditor;
604+var
605+ Dlg: TCheckGroupEditorDlg;
606+begin
607+ Dlg := TCheckGroupEditorDlg.Create(NIL);
608+ try
609+ // .. укорочено
610+ Dlg.ShowModal;
611+ // .. укорочено
612+ finally
613+ Dlg.Free;
614+ end;
615+end;
616+
617+procedure TCheckGroupComponentEditor.ExecuteVerb(Index: Integer);
618+begin
619+ case Index of
620+ 0: DoShowEditor;
621+ end;
622+end;
623+
624+function TCheckGroupComponentEditor.GetVerb(Index: Integer): String;
625+begin
626+ Result := 'CheckBox Editor...';
627+end;
628+
629+function TCheckGroupComponentEditor.GetVerbCount: Integer;
630+begin
631+ Result := 1;
632+end;
648633```
649634
650635## Отладка компонента в Design-time
651636
652-Чтобы отловить ошибки времени разработки во (вновь созданном) _dbgcomponent_ :
637+Чтобы отловить ошибки времени разработки во (вновь созданном) *dbgcomponent*:
653638
654- * откройте проект `C:\lazarus\ide\lazarus.lpi`;
655- * запустите проект;
656- * установите точку останова в _dbgcomponent_ в главном (1-ом) приложении;
657- * используйте паскалевский код _dbgcomponent_ во втором приложении;
658- * выполнить пошагово код компонента времени разработки в режиме отладки; делайте все, что необходимо;
639+- откройте проект `C:\lazarus\ide\lazarus.lpi`;
640+- запустите проект;
641+- установите точку останова в *dbgcomponent* в главном (1-ом) приложении;
642+- используйте паскалевский код *dbgcomponent* во втором приложении;
643+- выполнить пошагово код компонента времени разработки в режиме отладки; делайте все, что необходимо;
659644
660645## См. также
661646
662- * [[Extending the IDE/ru|Extending the IDE]]
663- * [[Lazarus Packages/ru|Lazarus Packages]] \- A guide for creating a package under Lazarus
664- * [[Components and Code examples/ru|Components and Code examples]]
665- * [[Lazarus Components]]
666- * [IDE Window: Add to Package](</index.php?title=IDE_Window:_Add_to_Package&action=edit&redlink=1> "IDE Window: Add to Package \(page does not exist\)")
667- * [[IDE Window: Create new package component]]
668- * [Создание визуальных компонент для Lazarus](<http://freepascal.ru/article/lazarus/20050530152619>) \- статья Сергея Смирнова с русскоязычного ресурса
647+- [[Extending the IDE/ru|Extending the IDE]]
648+- [[Lazarus Packages/ru|Lazarus Packages]] - A guide for creating a package under Lazarus
649+- [[Components and Code examples/ru|Components and Code examples]]
650+- [[Lazarus Components]]
651+- [[IDE Window: Add to Package]]
652+- [[IDE Window: Create new package component]]
653+- [Создание визуальных компонент для Lazarus](http://freepascal.ru/article/lazarus/20050530152619) - статья Сергея Смирнова с русскоязычного ресурса
669654
670-Все вопросы вы можете оставлять также [на этой](<http://forum.lazarus.freepascal.org/index.php/topic,5789.0.html>) странице
655+Все вопросы вы можете оставлять также [на этой](http://forum.lazarus.freepascal.org/index.php/topic,5789.0.html) странице
671656
672657---
673-*From the Free Pascal wiki, page "How To Write Lazarus Component/ru", as the Internet Archive kept it on 2024-01-21. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
658+*From the Free Pascal wiki, page "How To Write Lazarus Component/ru", as it stood on 2020-02-17 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history