Sign in Join
Wiki copytemporary

How To Write Lazarus Component/ru: what changed

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

OldNewLine
1-Это руководство по созданию компонентов.
1+Это руководство по созданию компонентов.
22
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 См. также
25+
326## Шаг 1: Создание пакета
427
5-- В меню IDE Lazarus нажмите "Package" \> "New package" для запуска диспетчера пакетов.
28+ * В меню IDE Lazarus нажмите "Package" > "New package" для запуска диспетчера пакетов.
629
7-<figure>
8-<img src="package_menu.png" title="package_menu.png" />
9-<figcaption>package_menu.png</figcaption>
10-</figure>
30+[![package menu.png](/wiki-images/f/fb/package_menu.png)](</File:package_menu.png>)
1131
12-- Появится диалоговое окно "Save". Выберите папку и имя файла и нажмите "Save". Если программа IDE предложит использовать строчные имена файлов, нажмите "да".
32+ * Появится диалоговое окно "Save". Выберите папку и имя файла и нажмите "Save". Если программа IDE предложит использовать строчные имена файлов, нажмите "да".
1333
14-- Поздравляем: вы только что создали свой первый пакет!
34+ * Поздравляем: вы только что создали свой первый пакет!
1535
16-<figure>
17-<img src="How_to_write_lazarus_component_package_maker.png" title="Package Maker" />
18-<figcaption>Package Maker</figcaption>
19-</figure>
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")
2037
2138## Шаг 2: Создание модуля
2239
23-Вы можете создать новый модуль или использовать существующий файл. Оба варианта описаны ниже.
40+Вы можете создать новый модуль или использовать существующий файл. Оба варианта описаны ниже.
2441
2542### Создание нового модуля
2643
27-- Используйте кнопку **Add \> New component**.\
44+ * Используйте кнопку **Add > New component**.
2845
29-![](/wiki-images/5/56/Package_new_component.png)\
46+[![package new component.png](/wiki-images/6/60/package_new_component.png)](</File:package_new_component.png>)
3047
31-- Выберите компонент, \[например такой\] как TComboBox.
32-- Выберите *customcontrol1.pas* в качестве **Unit File Name** и *CustomControl1* в качестве **Unit Name**.
33-- Теперь вы можете задать иконку компоненту и определить, на какой палитре компонент должен появиться позже в Lazarus-IDE.
34-- Нажмите **OK**\[, чтобы создать новый компонент\].\
48+ * Выберите компонент, [например такой] как TComboBox.
49+ * Выберите _customcontrol1.pas_ в качестве **Unit File Name** и _CustomControl1_ в качестве **Unit Name**.
50+ * Теперь вы можете задать иконку компоненту и определить, на какой палитре компонент должен появиться позже в Lazarus-IDE.
51+ * Нажмите **OK**[, чтобы создать новый компонент].
3552
36-``` pascal
53+```
3754unit CustomControl1;
38-
39-{$mode objfpc}{$H+}
40-
41-interface
42-
43-uses
44- Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
45-
46-type
47- TCustomControl1 = class(TComboBox)
48- private
49- { Private declarations }
50- protected
51- { Protected declarations }
52- public
53- { Public declarations }
54- published
55- { Published declarations }
56- end;
57-
58-procedure Register;
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+```
5986
60-implementation
87+ * Установите пакет, кликнув кнопку **Use - > Install** вверху редактора пакетов.
6188
62-procedure Register;
63-begin
64- RegisterComponents('Standard', [TCustomControl1]);
65-end;
89+[![package install.png](/wiki-images/2/2a/package_install.png)](</File:package_install.png>)
6690
67-end.
68-```
91+ * Теперь IDE спросит вас, должна ли она быть пересобрана. Ответьте "Да".
6992
70-- Установите пакет, кликнув кнопку **Use -\> Install** вверху редактора пакетов.\
93+[![package rebuild.png](/wiki-images/6/67/package_rebuild.png)](</File:package_rebuild.png>)
7194
72-![](/wiki-images/3/36/Package_install.png)\
95+ * Перезапустите Lazarus[, если он не сделал этого сам,] и посмотрите на свой новый компонент в палитре компонентов. Поздравляем: вы только что установили свой первый пакет с вашим первым компонентом.
7396
74-- Теперь IDE спросит вас, должна ли она быть пересобрана. Ответьте "Да".\
97+[![package installed.png](/wiki-images/7/79/package_installed.png)](</File:package_installed.png>)
7598
76-![](/wiki-images/9/9b/Package_rebuild.png)\
99+![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Примечание:** Если вы не видите свой новый компонент в палитре компонентов, скорее всего, вы используете не пересобранную версию Lazarus. Вы можете установить, где Lazarus пересобирается, используя [пункт меню] Tools -> Options -> Files -> Lazarus directory.
77100
78-- Перезапустите Lazarus\[, если он не сделал этого сам,\] и посмотрите на свой новый компонент в палитре компонентов. Поздравляем: вы только что установили свой первый пакет с вашим первым компонентом.\
101+Вместо прямого вызова Lazarus вы также можете использовать startlazarus, который запускает недавно созданный Lazarus, например исполняемый файл Lazarus в каталоге ~ / .lazarus, если у вас нет доступа на запись в каталог, в который был установлен Lazarus.
79102
80-![](/wiki-images/3/35/Package_installed.png)\
103+* * *
81104
82-> **Note:** Если вы не видите свой новый компонент в палитре компонентов, скорее всего, вы используете не пересобранную версию Lazarus. Вы можете установить, где Lazarus пересобирается, используя \[пункт меню\] Tools -\> Options -\> Files -\> Lazarus directory.
83->
84-> Вместо прямого вызова Lazarus вы также можете использовать startlazarus, который запускает недавно созданный Lazarus, например исполняемый файл Lazarus в каталоге ~ / .lazarus, если у вас нет доступа на запись в каталог, в который был установлен Lazarus.
105+[Прим.перев.](</User:Zoltanleo> "User:Zoltanleo") 23:36, 1 December 2018 (CET): В корневом каталоге Lazarus'а после пересборки обычно содержится три исполняемых файла: lazarus (текущий запускаемый файл), startlazarus (лаучер для lazarus) и lazarus.old (старая версия исполняемого файла, существующая после последней удачной пересборки среды). В примечании, вероятнее всего, речь идет о них.
85106
86-------------------------------------------------------------------------
107+* * *
87108
88-Прим.перев. 23:36, 1 December 2018 (CET): В корневом каталоге Lazarus'а после пересборки обычно содержится три исполняемых файла: lazarus (текущий запускаемый файл), startlazarus (лаучер для lazarus) и lazarus.old (старая версия исполняемого файла, существующая после последней удачной пересборки среды). В примечании, вероятнее всего, речь идет о них.
109+### Добавление существующего модуля
89110
90-------------------------------------------------------------------------
111+Если у вас уже есть модуль, вы можете добавить его в пакет:
91112
92-### Добавление существующего модуля
113+[![package existing unit.png](/wiki-images/a/a4/package_existing_unit.png)](</File:package_existing_unit.png>)
93114
94-Если у вас уже есть модуль, вы можете добавить его в пакет:
115+ * Нажмите кнопку **Add** , перейдите к вкладке **Add Files**. В [колонке] file name модуля добавьте ваш существующий файл. Нажмите **Add files to package**. Если диспетчер пакетов жалуется, что модуль находится вне заданных к модулям путей, нажмите "Да", чтобы добавить каталог в пути к модулям.
116+ * Нажмите кнопку **Add** снова, перейдите на вкладку **Add Files** , найдите файл _.lrs_ и нажмите "OK" (см. Шаг 3 о создании файла иконки).
117+ * Снова нажмите кнопку **Add** , перейдите к вкладке **New Requirement** [(новая зависимость)]. В имени пакета выберите **LCL** и нажмите OK.
95118
96-![](/wiki-images/1/11/Package_existing_unit.png)\
119+Конечный результат должен выглядеть следующим образом:
97120
98-- Нажмите кнопку **Add**, перейдите к вкладке **Add Files**. В \[колонке\] file name модуля добавьте ваш существующий файл. Нажмите **Add files to package**. Если диспетчер пакетов жалуется, что модуль находится вне заданных к модулям путей, нажмите "Да", чтобы добавить каталог в пути к модулям.
99-- Нажмите кнопку **Add** снова, перейдите на вкладку **Add Files**, найдите файл *.lrs* и нажмите "OK" (см. Шаг 3 о создании файла иконки).
100-- Снова нажмите кнопку **Add**, перейдите к вкладке **New Requirement** \[(новая зависимость)\]. В имени пакета выберите **LCL** и нажмите OK.
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")
101122
102-Конечный результат должен выглядеть следующим образом:\
103-![Package Maker](/wiki-images/d/d9/How_to_write_lazarus_component_package_maker_done.png)\
123+ * Щелкните по дереву файлов в диспетчере пакетов. В свойствах файла убедитесь, что установлен флажок _Register unit_.
124+ * Нажмите кнопку Options. Перейдите на вкладку IDE Integration. В опции Package Type убедитесь, что выбраны [режимы] Designtime и Runtime.
125+ * Нажмите кнопку Compile, чтобы проверить, файлы компилируются без ошибок.
126+ * Нажмите кнопку Install. Lazarus автоматически пересоберется и перезагрузится.
104127
105-- Щелкните по дереву файлов в диспетчере пакетов. В свойствах файла убедитесь, что установлен флажок *Register unit*.
106-- Нажмите кнопку Options. Перейдите на вкладку IDE Integration. В опции Package Type убедитесь, что выбраны \[режимы\] Designtime и Runtime.
107-- Нажмите кнопку Compile, чтобы проверить, файлы компилируются без ошибок.
108-- Нажмите кнопку Install. Lazarus автоматически пересоберется и перезагрузится.
128+Компонент создан и готов к использованию:
109129
110-Компонент создан и готов к использованию:\
111-![Component Created](/wiki-images/3/3c/How_to_write_lazarus_component_created.png)\
130+[![Component Created](/wiki-images/3/3c/How_to_write_lazarus_component_created.png)](</File:How_to_write_lazarus_component_created.png> "Component Created")
112131
113132## Шаг 3: Создание значков для пакета
114133
115-Вы должны создать PNG-файлы размером 24x24 пикселя в виде значков. Если для Lazarus 1.8+ вы хотите, чтобы значки палитры масштабировались при более высоких разрешениях экрана, вы также должны предоставлять значки 36x36 и 48x48 пикселей. Имена более крупных значков требуют добавления \[суффиксов\] "_150" и "_200" к имени файла, соответственно \[увеличению разрешения\] ("_150" для 150%, "_200" для 200%).
134+Вы должны создать PNG-файлы размером 24x24 пикселя в виде значков. Если для Lazarus 1.8+ вы хотите, чтобы значки палитры масштабировались при более высоких разрешениях экрана, вы также должны предоставлять значки 36x36 и 48x48 пикселей. Имена более крупных значков требуют добавления [суффиксов] "_150" и "_200" к имени файла, соответственно [увеличению разрешения] ("_150" для 150%, "_200" для 200%).
116135
117-FPC способен использовать стандартные файлы ресурсов `.rc` или скомпилированные ресурсы `.res`, \[начиная\] с версии fpc 2.6. См. [[Lazarus Resources/ru|FPC ресурсы]]. \[О файлах\] `.lrs`: см.ниже.
136+FPC способен использовать стандартные файлы ресурсов `.rc` или скомпилированные ресурсы `.res`, [начиная] с версии fpc 2.6. См. [[Lazarus Resources/ru|FPC ресурсы]]. [О файлах] `.lrs`: см.ниже.
118137
119138### Использование редактора изображений Lazarus
120139
121-Вы можете использовать [[Lazarus Image Editor]] для создания изображений в .lrs формате.
140+Вы можете использовать [[Lazarus Image Editor]] для создания изображений в .lrs формате.
122141
123-------------------------------------------------------------------------
142+
124143
125-Прим.перев. 17:13, 3 December 2018 (CET): Поскольку старшие версии Лазаруса (насколько я помню, после v.1.6.х точно) позволяют задавать иконку изображения в png-формате, то удобнее всего для их создания использовать бесплатный векторный редактор [InkScape](https://inkscape.org/ru), "родным" для которого является формат SVG. Среди его преимуществ:
144+* * *
126145
127-- работа со слоями
128-- поддержка альфа-канала
129-- предосмотр иконок в разных разрешениях (в файле настроек можно задать даже нестандартные значения)
130-- вменяемый и оперативный саппорт (можно напрямую пообщаться с разработчиками в [чате](https://inkscape.org/ru/community/discussion))
131-- экспорт изображений в png-формат
146+[Прим.перев.](</User:Zoltanleo> "User:Zoltanleo") 17:13, 3 December 2018 (CET): Поскольку старшие версии Лазаруса (насколько я помню, после v.1.6.х точно) позволяют задавать иконку изображения в png-формате, то удобнее всего для их создания использовать бесплатный векторный редактор [InkScape](<https://inkscape.org/ru>), "родным" для которого является формат SVG. Среди его преимуществ:
132147
133-------------------------------------------------------------------------
148+ * работа со слоями
149+ * поддержка альфа-канала
150+ * предосмотр иконок в разных разрешениях (в файле настроек можно задать даже нестандартные значения)
151+ * вменяемый и оперативный саппорт (можно напрямую пообщаться с разработчиками в [чате](<https://inkscape.org/ru/community/discussion>))
152+ * экспорт изображений в png-формат
134153
154+* * *
155+
135156### Использование lazres
136157
137-`lazres` обычно находится в каталоге инструментов Lazarus.
158+`lazres` обычно находится в каталоге инструментов Lazarus.
138159
139-Вам может понадобиться скомпилировать [[lazres]] при первом использовании. Просто откройте *lazres.lpi* в среде IDE и нажмите **run \> build** в меню.
160+Вам может понадобиться скомпилировать [[lazres]] при первом использовании. Просто откройте _lazres.lpi_ в среде IDE и нажмите **run > build** в меню.
140161
141162#### Создание lrs-файла
142163
143-Для создания lrs-файла запустите:
144-
145-``` pascal
164+Для создания lrs-файла запустите:
165+```
146166~/lazarus/tools/lazres samplepackage.lrs TMyCom.png
147167```
148168
149-или, если доступны изображения с высоким разрешением
150-
151-``` pascal
169+или, если доступны изображения с высоким разрешением
170+```
152171~/lazarus/tools/lazres samplepackage.lrs TMyCom.png TMyCom_150.pgn TMyCom_200.png
153172```
154173
155-где
156-
157-- *samplepackage* - имя вашего пакета
158-- *TMyCom* - имя вашего компонента. Имя изображения должно совпадать с именем вашего компонента!
174+где
159175
160-Вы можете добавить несколько изображений в файл lrs, добавив имя файла изображения в конец \[команды\]. Например:
176+ * _samplepackage_ \- имя вашего пакета
177+ * _TMyCom_ \- имя вашего компонента. Имя изображения должно совпадать с именем вашего компонента!
161178
162-``` pascal
179+Вы можете добавить несколько изображений в файл lrs, добавив имя файла изображения в конец [команды]. Например:
180+```
163181~/lazarus/tools/lazres samplepackage.lrs TMyCom.png TMyOtherCom.png ...
164182```
165183
184+
166185**Пример**
167186
168-Ниже приведен образец полученного файла *samplepackage.lrs*.
169-
170-``` pascal
187+Ниже приведен образец полученного файла _samplepackage.lrs_.
188+```
171189LazarusResources.Add('TMyCom','PNG',[
172- #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
173- +#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0'|IDAT8O'#237#212#209#10#192' '#8
174- +#5'P'#247#231#251's'#215#138#133#164#166'\'#220#195'`'#209'c'#157'L'#173#131
175- +#153#169'd4'#168'dP'#137'r_'#235'5'#136'@Zmk'#16'd9'#144#176#232#164'1'#247
176- +'I'#8#160'IL'#206'C'#179#144#12#199#140'.'#134#244#141'~'#168#247#209'S~;'#29
177- +'V+'#196#201'^'#10#15#150'?'#255#18#227#206'NZ>42'#181#159#226#144#15'@'#201
178- +#148#168'e'#224'7f<@4'#130'u_YD'#23#213#131#134'Q]'#158#188#135#0#0#0#0'IEND'
179- +#174'B`'#130
180-]);
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+ ]);
181199```
182200
183-Обязательно включите свой файл ресурсов в исходник нового компонента, добавив нижеследующее в модуль вашего компонента и включив "LResources" в раздел uses
184-
185-``` pascal
201+Обязательно включите свой файл ресурсов в исходник нового компонента, добавив нижеследующее в модуль вашего компонента и включив "LResources" в раздел uses
202+```
186203initialization
187- {$I samplepackage.lrs}
204+ {$I samplepackage.lrs}
188205```
189206
190-#### Создание res-файла
207+
191208
192-lazres также может создать скомпилированный файл ресурсов, просто укажите файл с расширением .res, например:
209+#### Создание res-файла
193210
194-``` pascal
211+lazres также может создать скомпилированный файл ресурсов, просто укажите файл с расширением .res, например:
212+```
195213~/lazarus/tools/lazres samplepackage.res TMyCom.png
196214```
197215
198-или, для иконок с высоким разрешением:
199-
200-``` pascal
216+или, для иконок с высоким разрешением:
217+```
201218~/lazarus/tools/lazres samplepackage.res TMyCom.png TMyCom_150.png TMyCom_200.png
202219```
203220
204-В этом случае вместо включения файла lrs в разделе инициализации просто укажите файл ресурсов в любом месте исходного файла компонента
205-
206-``` pascal
207- {$R samplepackage.res}
221+В этом случае вместо включения файла lrs в разделе инициализации просто укажите файл ресурсов в любом месте исходного файла компонента
208222```
223+{$R samplepackage.res}
224+```
209225
210226### Использование glazres
211227
212-**GLazRes** это графическая версия `lazres`, которая может собирать файлы в файл ресурсов Lazarus (.lrs). Его можно найти в каталоге инструментов установки Lazarus.
228+**GLazRes** это графическая версия `lazres`, которая может собирать файлы в файл ресурсов Lazarus (.lrs). Его можно найти в каталоге инструментов установки Lazarus.
213229
214230## Перекомпиляция пакетов
215231
216-Вам нужно пересобирать пакет каждый раз, когда вы вносите изменения в файл *mycom.pas*. Чтобы пересобрать пакет, откройте файл *samplepackage.lpk* в диспетчере пакетов и нажмите кнопку Install.
232+Вам нужно пересобирать пакет каждый раз, когда вы вносите изменения в файл _mycom.pas_. Чтобы пересобрать пакет, откройте файл _samplepackage.lpk_ в диспетчере пакетов и нажмите кнопку Install.
217233
218234## Удаление пакетов
219235
220-- Чтобы удалить установленные компоненты: в меню IDE выберите Package \> Configure installed packages. На следующем рисунке показан инструмент Installed Packages.
236+ * Чтобы удалить установленные компоненты: в меню IDE выберите Package > Configure installed packages. На следующем рисунке показан инструмент Installed Packages.
221237
222-![`Installed Components`](/wiki-images/0/0e/How_to_write_lazarus_component_installed_components.png)
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+```
223241
224-- Выберите пакет, который вы хотите удалить, и нажмите Uninstall selection.
242+ * Выберите пакет, который вы хотите удалить, и нажмите Uninstall selection.
225243
226-Если что-то пойдет не так с пакетом (например, каталог пакета удаляется без деинсталляции \[пакета в первую очередь\]), Lazarus может не разрешить вам удалять пакеты. Чтобы устранить проблему, в меню IDE выберите Tools \> Build Lazarus. Lazarus пересоберет все пакеты и перезапустит их. Теперь вы можете удалить проблемные пакеты.
244+Если что-то пойдет не так с пакетом (например, каталог пакета удаляется без деинсталляции [пакета в первую очередь]), Lazarus может не разрешить вам удалять пакеты. Чтобы устранить проблему, в меню IDE выберите Tools > Build Lazarus. Lazarus пересоберет все пакеты и перезапустит их. Теперь вы можете удалить проблемные пакеты.
227245
228246## Усовершенствование mycom.pas
229247
230-- Код в *mycom.pas* выше дает вам основы того, что вам нужно для создания компонента. Далее приведена усовершенствованная версия с некоторыми советами о том, как писать процедуры и события для компонентов.
231-- *OnChange2* показывает, как создавать события.
232-- *OnSample* показывает, как создавать пользовательские события.
233-- *MyText* и *MyText2* показывает различные способы записи свойств.
234-- Вы можете использовать TComboBox вместо TCustomComboBox в качестве базового класса, который \[объявляет\] публичными все свойства как TComboBox.
235-- Если TCustomComboBox используется в качестве базового класса, вы заметите, что в Инспекторе объектов IDE будет отсутствовать множество свойств и событий. Чтобы добавить эти свойства и события, просто скопируйте и вставьте свойства, перечисленные ниже \[комментария\] *// properties from TComboBox*. Этот список свойств можно получить из объявления TComboBox в модуле StdCtrls. Исключите \[из списка\] любое свойство, которое вы хотите \[определить\] самостоятельно.
248+ * Код в _mycom.pas_ выше дает вам основы того, что вам нужно для создания компонента. Далее приведена усовершенствованная версия с некоторыми советами о том, как писать процедуры и события для компонентов.
249+ * _OnChange2_ показывает, как создавать события.
250+ * _OnSample_ показывает, как создавать пользовательские события.
251+ * _MyText_ и _MyText2_ показывает различные способы записи свойств.
252+ * Вы можете использовать TComboBox вместо TCustomComboBox в качестве базового класса, который [объявляет] публичными все свойства как TComboBox.
253+ * Если TCustomComboBox используется в качестве базового класса, вы заметите, что в Инспекторе объектов IDE будет отсутствовать множество свойств и событий. Чтобы добавить эти свойства и события, просто скопируйте и вставьте свойства, перечисленные ниже [комментария] _// properties from TComboBox_. Этот список свойств можно получить из объявления TComboBox в модуле StdCtrls. Исключите [из списка] любое свойство, которое вы хотите [определить] самостоятельно.
236254
237-``` pascal
255+```
238256unit mycom;
239-
240-{$mode objfpc}{$H+}
241-
242-interface
243-
244-uses
245- Classes, SysUtils, StdCtrls, Forms, Dialogs,
246- LCLType,LCLIntf,lresources,LCLProc;
247-
248-type
249-
250- TSampleEvent = procedure(MyText: String) of Object;
251-
252- TMyCom = class (TCustomComboBox)
253- private
254- FMyText: String;
255- FOnChange2: TNotifyEvent;
256- FOnSample: TSampleEvent;
257- public
258- constructor Create(TheOwner: TComponent); override;
259- procedure CreateWnd; override;
260- procedure Change; override;
261- protected
262- function GetMyText2: String;
263- procedure SetMyText2(MyText: String);
264- published
265- property MyText: String read FMyText write FMyText;
266- property MyText2: String read GetMyText2 write SetMyText2;
267- property OnChange2: TNotifyEvent read FOnChange2 write FOnChange2;
268- property OnSample: TSampleEvent read FOnSample write FOnSample;
269257
270- // properties from TComboBox
271- property Align;
272- property Anchors;
273- property ArrowKeysTraverseList;
274- property AutoComplete;
275- property AutoCompleteText;
276- property AutoDropDown;
277- property AutoSelect;
278- property AutoSize;
279- property BidiMode;
280- property BorderSpacing;
281- property CharCase;
282- property Color;
283- property Ctl3D;
284- property Constraints;
285- property DragCursor;
286- property DragMode;
287- property DropDownCount;
288- property Enabled;
289- property Font;
290- property ItemHeight;
291- property ItemIndex;
292- property Items;
293- property ItemWidth;
294- property MaxLength;
295- property OnChange;
296- property OnChangeBounds;
297- property OnClick;
298- property OnCloseUp;
299- property OnContextPopup;
300- property OnDblClick;
301- property OnDragDrop;
302- property OnDragOver;
303- property OnDrawItem;
304- property OnEndDrag;
305- property OnDropDown;
306- property OnEditingDone;
307- property OnEnter;
308- property OnExit;
309- property OnGetItems;
310- property OnKeyDown;
311- property OnKeyPress;
312- property OnKeyUp;
313- property OnMeasureItem;
314- property OnMouseDown;
315- property OnMouseMove;
316- property OnMouseUp;
317- property OnStartDrag;
318- property OnSelect;
319- property OnUTF8KeyPress;
320- property ParentBidiMode;
321- property ParentColor;
322- property ParentCtl3D;
323- property ParentFont;
324- property ParentShowHint;
325- property PopupMenu;
326- property ReadOnly;
327- property ShowHint;
328- property Sorted;
329- property Style;
330- property TabOrder;
331- property TabStop;
332- property Text;
333- property Visible;
334- end;
335-
336-procedure Register;
337-
338-implementation
339-
340-procedure Register;
341-begin
342- RegisterComponents('Sample',[TMyCom]);
343-end;
344-
345-constructor TMyCom.Create(TheOwner: TComponent);
346-begin
347- inherited Create(TheOwner);
348- Self.Style := csDropDownList;
349-end;
350-
351-procedure TMyCom.CreateWnd;
352-begin
353- inherited CreateWnd;
354- Items.Assign(Screen.Fonts);
355-end;
356-
357-procedure TMyCom.Change;
358-begin
359- inherited;
360- if Assigned(FOnChange2) then FOnChange2(Self);
361- if Assigned(FOnSample) then FOnSample(FMyText);
362-end;
363-
364-function TMyCom.GetMyText2: String;
365-begin
366- Result:=FMyText;
367-end;
368-
369-procedure TMyCom.SetMyText2(MyText: String);
370-begin
371- FMyText:=MyText;
372-end;
373-
374-initialization
375- {$I samplepackage.lrs}
376-
377-end.
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}
394+
395+ end.
378396```
379397
380-Также вы заметите, что в Инспекторе объектов IDE существуют некоторые необъявленные и, возможно, нежелательные элементы. Чтобы удалить те из них, которые вам не нужны, вы можете переобъявить их в разделе *Published* как простые переменные. Например:
381-
382-``` pascal
398+Также вы заметите, что в Инспекторе объектов IDE существуют некоторые необъявленные и, возможно, нежелательные элементы. Чтобы удалить те из них, которые вам не нужны, вы можете переобъявить их в разделе _Published_ как простые переменные. Например:
399+```
383400Published
384-...
385- property Height: Integer;
386- property Width: Integer;
387-...
401+ ...
402+ property Height: Integer;
403+ property Width: Integer;
404+ ...
388405```
389406
390407## Использование встроенных (визуальных) компонентов
391408
392-Можно использовать стандартные компоненты, встроенные в ваши собственные компоненты (посмотрите для примера на TLabeledEdit или TButtonPanel).
393-
394-Предположим, вы хотите создать пользовательскую панель с TLabel на ней. С помощью описанных выше шагов можно создать базовый пакет и исходные файлы. Теперь сделайте следующее для добавления TLabel в компонент:
409+Можно использовать стандартные компоненты, встроенные в ваши собственные компоненты (посмотрите для примера на TLabeledEdit или TButtonPanel).
395410
396-- Добавьте приватный атрибут (поле) для компонента label (`FEmbeddedLabel: TLabel;`).
397-- Добавьте published-свойство только для чтения для компонента label (`property EmbeddedLabel: TLabel read FEmbeddedLabel;`)
398-- Создайте label в конструкторе (переопределенном) компонента (`FEmbeddedLabel: = TLabel.Create(self);`)
399-- Задайте родительский элемент компонента (`FEmbeddedLabel.Parent: = self;`)
400-- Если встроенный компонент не является 'субкомпонентом' по умолчанию (например, TBoundLabel, TPanelBitBtn и т.д.), то добавьте вызов в SetSubComponent. Это необходимо для IDE, чтобы она знала, что она также должна хранить свойства встроенного компонента. По умолчанию TLabel не является субкомпонентом, поэтому необходимо добавить вызов метода (`FEmbeddedLabel.SetSubComponent(true);`).
411+Предположим, вы хотите создать пользовательскую панель с TLabel на ней. С помощью описанных выше шагов можно создать базовый пакет и исходные файлы. Теперь сделайте следующее для добавления TLabel в компонент:
401412
402-В итоге вы получите что-то вроде этого (показаны только основные части):
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);`).
403418
404-``` pascal
419+В итоге вы получите что-то вроде этого (показаны только основные части):
420+```
405421TEnhancedPanel = class(TCustomControl)
406-private
407- { Новые аттрибуты для встроенного label }
408- FEmbeddedLabel: TLabel;
409-
410-public
411- { Конструктор должен быть переопределен, чтобы label могла быть создана}
412- constructor Create(AOwner: TComponent); override;
413-
414-published
415- { Сделаем label видимым в IDE }
416- property EmbeddedLabel: TLabel read FEmbeddedLabel;
417-end;
418-
419-implementation
420-
421-constructor TEnhancedPanel.Create(AOwner: TComponent);
422-begin
423- inherited Create(AOwner);
424-
425- // Устанавливаем дефолтовые width и height
426- with GetControlClassDefaultSize do
427- SetInitialBounds(0, 0, CX, CY);
428-
429- // Добавляем встроенный label
430- FEmbeddedLabel := TLabel.Create(Self); // Добавляем встроенный label
431- FEmbeddedLabel.Parent := self; // Показываем label на panel
432- FEmbeddedLabel.SetSubComponent(true); // Говорим IDE сохранять измененные свойства
433- FLabel.Name := 'EmbeddedLabel';
434- FLabel.Caption := 'Howdy World!';
435-
436- // Убеждаемся, что встроенная label не может быть выделена/удалена средствами IDE
437- FLabel.ControlStyle := FLabel.ControlStyle - [csNoDesignSelectable];
438-
439- // Задаем другие свойства, если необходимо
440- //...
441-
442-end;
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;
443459```
444460
445461## Использование пользовательской процедуры рисования
446462
447-Вы всегда можете переопределить компонент внутри вашей программы. Например, это реализует пользовательскую процедуру Paint для TLabel:
448-
449-``` pascal
463+Вы всегда можете переопределить компонент внутри вашей программы. Например, это реализует пользовательскую процедуру Paint для TLabel:
464+```
450465type
451- TMyLabel = class(TLabel)
452- protected
453- procedure Paint; override;
454- end;
455-{...}
456-implementation
457-{...}
458-procedure TMyLabel.Paint;
459-begin
460- // ваш код для реализации Paint, например
461- Canvas.TextOut(0,0,Caption);
462-end;
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;
463478```
464479
465-Теперь вы можете создать MyLabel внутри вашей программы во время выполнения с этой переопределенной процедурой Paint вместо стандартной.
466-
467-Для большинства компонентов и для большинства методов было бы полезно вызвать унаследованную процедуру внутри него:
480+Теперь вы можете создать MyLabel внутри вашей программы во время выполнения с этой переопределенной процедурой Paint вместо стандартной.
468481
469-``` pascal
482+Для большинства компонентов и для большинства методов было бы полезно вызвать унаследованную процедуру внутри него:
483+```
470484procedure TMyLabel.Paint;
471-begin
472-
473- inherited Paint; /////////////////////
474-
475- // ваш код для реализации Paint, например
476- Canvas.TextOut(0,0,Caption);
477-end;
485+ begin
486+
487+ inherited Paint; /////////////////////
488+
489+ // ваш код для реализации Paint, например
490+ Canvas.TextOut(0,0,Caption);
491+ end;
478492```
479493
480-Однако унаследованное поведение нежелательно в этом случае, поскольку второе действие записи будет перекрывать первый (унаследованный).
494+Однако унаследованное поведение нежелательно в этом случае, поскольку второе действие записи будет перекрывать первый (унаследованный).
481495
482496## Интеграция компонента с IDE
483497
484498### Редакторы свойств
485499
486-Редакторы свойств предоставляют настраиваемые диалоги для редактирования свойств в инспекторе объектов. Для большинства свойств, таких как строки, строковые списки, изображения, перечисленные типы и другие, уже есть редакторы свойств по умолчанию, но если у пользовательского компонента есть особый вид свойства, для изменения свойства может потребоваться настраиваемый диалог.
487-
488-Каждый редактор свойств - это класс, который должен происходить из TPropertyEditor или одного из его потомков и реализовывать методы этого базового класса. Они должны быть зарегистрированы в процедуре 'Register', используя функцию RegisterPropertyEditor из модуля PropEdits. Это стандарт для имен редакторов свойств с именем свойства, за которым следует \[слово\] 'Property', например \[имя\] TFieldProperty для редактора свойств свойства TField.
500+Редакторы свойств предоставляют настраиваемые диалоги для редактирования свойств в инспекторе объектов. Для большинства свойств, таких как строки, строковые списки, изображения, перечисленные типы и другие, уже есть редакторы свойств по умолчанию, но если у пользовательского компонента есть особый вид свойства, для изменения свойства может потребоваться настраиваемый диалог.
489501
490-``` pascal
491- TPropertyEditor = class
492- public
493- function AllEqual: Boolean; Virtual;
494- function AutoFill: Boolean; Virtual;
495- procedure Edit; Virtual; // Активируется двойным щелчком по значению свойства
496- procedure ShowValue; Virtual; // Активируется щелчком по элементу управления значения свойства
497- function GetAttributes: TPropertyAttributes; Virtual;
498- function GetEditLimit: Integer; Virtual;
499- function GetName: ShortString; Virtual;
500- procedure GetProperties(Proc: TGetPropEditProc); Virtual;
501- function GetHint(HintType: TPropEditHint; x, y: integer): String; Virtual;
502- function GetDefaultValue: AnsiString; Virtual;
503- procedure GetValues(Proc: TGetStrProc); Virtual;
504- procedure SetValue(const NewValue: AnsiString); Virtual;
505- procedure UpdateSubProperties; Virtual;
506- function SubPropertiesNeedsUpdate: Boolean; Virtual;
507- function IsDefaultValue: Boolean; Virtual;
508- function IsNotDefaultValue: Boolean; Virtual;
509- // ... укорочено
510- end;
502+Каждый редактор свойств - это класс, который должен происходить из TPropertyEditor или одного из его потомков и реализовывать методы этого базового класса. Они должны быть зарегистрированы в процедуре 'Register', используя функцию RegisterPropertyEditor из модуля PropEdits. Это стандарт для имен редакторов свойств с именем свойства, за которым следует [слово] 'Property', например [имя] TFieldProperty для редактора свойств свойства TField.
511503```
512-
513-Хорошим примером для редактора свойств является редактор свойств TFont.
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;
524+```
514525
515-Один из наиболее распространенных случаев для редакторов свойств - это свойства, которые являются классами. Поскольку классы имеют много полей и могут иметь различные форматы, Lazarus не может иметь \[универсальное\] поле редактирования в инспекторе объектов, способное их редактировать, \[как это сделано,\] например, для строк и числовых типов.
526+Хорошим примером для редактора свойств является редактор свойств TFont.
516527
517-Для классов соглашение состоит в том, чтобы в поле значений постоянно отображалось имя класса в круглых скобках, например "(TFont)", а кнопка "..." показывала диалог для редактирования этого класса. Это поведение, за исключением диалога, реализуется стандартным редактором свойств для классов, называемых TClassPropertyEditor, который может быть унаследован при создании редакторов свойств для классов:
528+Один из наиболее распространенных случаев для редакторов свойств - это свойства, которые являются классами. Поскольку классы имеют много полей и могут иметь различные форматы, Lazarus не может иметь [универсальное] поле редактирования в инспекторе объектов, способное их редактировать, [как это сделано,] например, для строк и числовых типов.
518529
519-``` pascal
530+Для классов соглашение состоит в том, чтобы в поле значений постоянно отображалось имя класса в круглых скобках, например "(TFont)", а кнопка "..." показывала диалог для редактирования этого класса. Это поведение, за исключением диалога, реализуется стандартным редактором свойств для классов, называемых TClassPropertyEditor, который может быть унаследован при создании редакторов свойств для классов:
531+```
520532TClassPropertyEditor = class(TPropertyEditor)
521-public
522- constructor Create(Hook: TPropertyEditorHook; APropCount: Integer); Override;
523- function GetAttributes: TPropertyAttributes; Override;
524- procedure GetProperties(Proc: TGetPropEditProc); Override;
525- function GetValue: AnsiString; Override;
526- property SubPropsTypeFilter: TTypeKinds Read FSubPropsTypeFilter
527- Write SetSubPropsTypeFilter
528- Default tkAny;
529-end;
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;
530542```
531543
532-Возвращаясь к примеру TFont, наследование от TClassPropertyEditor уже предлагает часть желаемого поведения, а затем классу TFontPropertyEditor необходимо реализовать отображение диалога в методе Edit и установить атрибуты для редактора:
533-
534-``` pascal
535- TFontPropertyEditor = class(TClassPropertyEditor)
536- public
537- procedure Edit; Override;
538- function GetAttributes: TPropertyAttributes; Override;
539- end;
540-
541-procedure TFontPropertyEditor.Edit;
542-var
543- FontDialog: TFontDialog;
544-begin
545- FontDialog := TFontDialog.Create(NIL);
546- try
547- FontDialog.Font := TFont(GetObjectValue(TFont));
548- FontDialog.Options := FontDialog.Options + [fdShowHelp, fdForceFontExist];
549- if FontDialog.Execute then SetPtrValue(FontDialog.Font);
550- finally
551- FontDialog.Free;
552- end;
553-end;
554-
555-function TFontPropertyEditor.GetAttributes: TPropertyAttributes;
556-begin
557- Result := [paMultiSelect, paSubProperties, paDialog, paReadOnly];
558-end;
544+Возвращаясь к примеру TFont, наследование от TClassPropertyEditor уже предлагает часть желаемого поведения, а затем классу TFontPropertyEditor необходимо реализовать отображение диалога в методе Edit и установить атрибуты для редактора:
559545```
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;
570+```
560571
561572### Редакторы компонентов
562573
563-Редакторы компонентов управляют поведением компонентов по щелчку правой кнопкой мыши и двойному щелчку в дизайнере форм.
564-
565-Каждый редактор компонентов - это класс, который должен происходить от TComponentEditor или одного из его потомков и реализовывать методы из этого базового класса. Он должен быть зарегистрирован в процедуре 'Register', использущей функцию RegisterComponentEditor из модуля ComponentEditors. Это стандарт для именования редакторов компонентов с именем компонента, за которым следует \[слово\] 'Editor', например TStringGridComponentEditor для редактора свойств компонента TStringGrid. Хотя редакторы пользовательских компонентов должны быть основаны на TComponentEditor, большинство его методов на самом деле \[берут начало\] от предка, поэтому необходимо также знать TBaseComponentEditor:
574+Редакторы компонентов управляют поведением компонентов по щелчку правой кнопкой мыши и двойному щелчку в дизайнере форм.
566575
567-``` pascal
568- TBaseComponentEditor = class
569- protected
570- public
571- constructor Create(AComponent: TComponent;
572- ADesigner: TComponentEditorDesigner); Virtual;
573- procedure Edit; Virtual; Abstract;
574- procedure ExecuteVerb(Index: Integer); Virtual; Abstract;
575- function GetVerb(Index: Integer): String; Virtual; Abstract;
576- function GetVerbCount: Integer; Virtual; Abstract;
577- procedure PrepareItem(Index: Integer; const AnItem: TMenuItem); Virtual; Abstract;
578- procedure Copy; Virtual; Abstract;
579- function IsInInlined: Boolean; Virtual; Abstract;
580- function GetComponent: TComponent; Virtual; Abstract;
581- function GetDesigner: TComponentEditorDesigner; Virtual; Abstract;
582- function GetHook(out Hook: TPropertyEditorHook): Boolean; Virtual; Abstract;
583- procedure Modified; Virtual; Abstract;
584- end;
576+Каждый редактор компонентов - это класс, который должен происходить от TComponentEditor или одного из его потомков и реализовывать методы из этого базового класса. Он должен быть зарегистрирован в процедуре 'Register', использущей функцию RegisterComponentEditor из модуля ComponentEditors. Это стандарт для именования редакторов компонентов с именем компонента, за которым следует [слово] 'Editor', например TStringGridComponentEditor для редактора свойств компонента TStringGrid. Хотя редакторы пользовательских компонентов должны быть основаны на TComponentEditor, большинство его методов на самом деле [берут начало] от предка, поэтому необходимо также знать TBaseComponentEditor:
585577```
586-
587-Наиболее важным методом редактора компонентов является \[метод\] Edit, который вызывается по двойному щелчку на компоненте. Когда вызывается контекстное меню для компонента, запрашивается метод GetVerbCount и GetVerb для создания меню. Если выбран один из глаголов (что означает пункты меню в этом случае), вызывается ExecuteVerb. Существует редактор компонентов по умолчанию (TDefaultEditor), который реализует Edit для поиска свойств компонента для наиболее подходящего для редактирования. Обычно он выбирает событие, которое будет редактироваться, путем добавления скелета кода в редактор кода и установки курсора в это место.
588-
589-Другими важными методами из TBaseComponentEditor являются:
590-
591-- **ExecuteVerb(Index)** - Выполняет один из дополнительных пунктов меню, расположенных во всплывающем меню правой кнопки мыши;
592-- **GetVerb** – Возвращает имя каждого дополнительного пункта всплывающего меню. Обратите внимание, что редактор компонентов должен размещать специальные символы заголовка элемента, такие как &, для создания ускорителя клавиатуры и "-" для создания разделителя;
593-- **GetVerbCount** – Возвращает количество элементов, которые будут добавлены во всплывающее меню. Индекс для подпрограмм GetVerb и ExecuteVerb равен нулю, начиная от 0 до GetVerbCount - 1;
594-- **PrepareItem** – Вызывается для каждого глагола \[(GetVerbCount и GetVerb)\] после создания пункта меню. Позволяет настраивать элемент меню, например, добавляя подэлементы, добавляя флажок или даже скрывая его, устанавливая Visible в false;
595-- **Copy** - Вызывается, когда компонент копируется в буфер обмена. Данные компонента при использовании Lazarus'ом всегда будут \[только\] добавляться и не могут быть изменены. Этот метод предназначен для добавления различных типов из буфера обмена при вставке компонента в другие приложения, но не будет влиять на вставку в Lazarus'е.
596-
597-Простым и интересным примером является редактор компонентов TCheckListBox, который создает диалоговое окно для редактирования. Более удобный, чем реализация всех методов из TBaseComponentEditor, \[он\] наследуется от TComponentEditor, и это то, что делает TCheckListBoxEditor. Этот базовый класс добавляет пустые реализации для большинства методов и некоторые умолчательные для других. Для \[метода\] Edit он вызывает ExecuteVerb(0), поэтому, если первый пункт \[popup menu\] будет сопоставлен действию двойного щелчка мыши, что является условным обозначением для редактора, то нет необходимости в \[ручной\] реализации \[кода метода\] Edit. Это основное действие для двойного щелчка и первого элемента меню часто является диалогом, и для TCheckListBox это также реализуется \[так\]:
598-
599-``` pascal
600- TCheckListBoxComponentEditor = class(TComponentEditor)
601- protected
602- procedure DoShowEditor;
603- public
604- procedure ExecuteVerb(Index: Integer); override;
605- function GetVerb(Index: Integer): String; override;
606- function GetVerbCount: Integer; override;
607- end;
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;
595+```
608596
609-procedure TCheckGroupComponentEditor.DoShowEditor;
610-var
611- Dlg: TCheckGroupEditorDlg;
612-begin
613- Dlg := TCheckGroupEditorDlg.Create(NIL);
614- try
615- // .. укорочено
616- Dlg.ShowModal;
617- // .. укорочено
618- finally
619- Dlg.Free;
620- end;
621-end;
597+Наиболее важным методом редактора компонентов является [метод] Edit, который вызывается по двойному щелчку на компоненте. Когда вызывается контекстное меню для компонента, запрашивается метод GetVerbCount и GetVerb для создания меню. Если выбран один из глаголов (что означает пункты меню в этом случае), вызывается ExecuteVerb. Существует редактор компонентов по умолчанию (TDefaultEditor), который реализует Edit для поиска свойств компонента для наиболее подходящего для редактирования. Обычно он выбирает событие, которое будет редактироваться, путем добавления скелета кода в редактор кода и установки курсора в это место.
622598
623-procedure TCheckGroupComponentEditor.ExecuteVerb(Index: Integer);
624-begin
625- case Index of
626- 0: DoShowEditor;
627- end;
628-end;
599+Другими важными методами из TBaseComponentEditor являются:
629600
630-function TCheckGroupComponentEditor.GetVerb(Index: Integer): String;
631-begin
632- Result := 'CheckBox Editor...';
633-end;
601+ * **ExecuteVerb(Index)** \- Выполняет один из дополнительных пунктов меню, расположенных во всплывающем меню правой кнопки мыши;
602+ * **GetVerb** – Возвращает имя каждого дополнительного пункта всплывающего меню. Обратите внимание, что редактор компонентов должен размещать специальные символы заголовка элемента, такие как &, для создания ускорителя клавиатуры и "-" для создания разделителя;
603+ * **GetVerbCount** – Возвращает количество элементов, которые будут добавлены во всплывающее меню. Индекс для подпрограмм GetVerb и ExecuteVerb равен нулю, начиная от 0 до GetVerbCount - 1;
604+ * **PrepareItem** – Вызывается для каждого глагола [(GetVerbCount и GetVerb)] после создания пункта меню. Позволяет настраивать элемент меню, например, добавляя подэлементы, добавляя флажок или даже скрывая его, устанавливая Visible в false;
605+ * **Copy** \- Вызывается, когда компонент копируется в буфер обмена. Данные компонента при использовании Lazarus'ом всегда будут [только] добавляться и не могут быть изменены. Этот метод предназначен для добавления различных типов из буфера обмена при вставке компонента в другие приложения, но не будет влиять на вставку в Lazarus'е.
634606
635-function TCheckGroupComponentEditor.GetVerbCount: Integer;
636-begin
637- Result := 1;
638-end;
607+Простым и интересным примером является редактор компонентов TCheckListBox, который создает диалоговое окно для редактирования. Более удобный, чем реализация всех методов из TBaseComponentEditor, [он] наследуется от TComponentEditor, и это то, что делает TCheckListBoxEditor. Этот базовый класс добавляет пустые реализации для большинства методов и некоторые умолчательные для других. Для [метода] Edit он вызывает ExecuteVerb(0), поэтому, если первый пункт [popup menu] будет сопоставлен действию двойного щелчка мыши, что является условным обозначением для редактора, то нет необходимости в [ручной] реализации [кода метода] Edit. Это основное действие для двойного щелчка и первого элемента меню часто является диалогом, и для TCheckListBox это также реализуется [так]:
639608```
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;
648+```
640649
641650## Отладка компонента в Design-time
642651
643-Чтобы отловить ошибки времени разработки во (вновь созданном) *dbgcomponent*:
652+Чтобы отловить ошибки времени разработки во (вновь созданном) _dbgcomponent_ :
644653
645-- откройте проект `C:\lazarus\ide\lazarus.lpi`;
646-- запустите проект;
647-- установите точку останова в *dbgcomponent* в главном (1-ом) приложении;
648-- используйте паскалевский код *dbgcomponent* во втором приложении;
649-- выполнить пошагово код компонента времени разработки в режиме отладки; делайте все, что необходимо;
654+ * откройте проект `C:\lazarus\ide\lazarus.lpi`;
655+ * запустите проект;
656+ * установите точку останова в _dbgcomponent_ в главном (1-ом) приложении;
657+ * используйте паскалевский код _dbgcomponent_ во втором приложении;
658+ * выполнить пошагово код компонента времени разработки в режиме отладки; делайте все, что необходимо;
650659
651660## См. также
652661
653-- [[Extending the IDE/ru|Extending the IDE]]
654-- [[Lazarus Packages/ru|Lazarus Packages]] - A guide for creating a package under Lazarus
655-- [[Components and Code examples/ru|Components and Code examples]]
656-- [[Lazarus Components]]
657-- [[IDE Window: Add to Package]]
658-- [[IDE Window: Create new package component]]
659-- [Создание визуальных компонент для Lazarus](http://freepascal.ru/article/lazarus/20050530152619) - статья Сергея Смирнова с русскоязычного ресурса
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>) \- статья Сергея Смирнова с русскоязычного ресурса
660669
661-Все вопросы вы можете оставлять также [на этой](http://forum.lazarus.freepascal.org/index.php/topic,5789.0.html) странице
670+Все вопросы вы можете оставлять также [на этой](<http://forum.lazarus.freepascal.org/index.php/topic,5789.0.html>) странице
662671
663672---
664-*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).*
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).*

Back to history