<?xml version="1.0" encoding="utf-8"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Форум программистов и сисадминов Киберфорум - Блоги - От простого к сложному. Автор ashsvis</title>
		<link>https://www.cyberforum.ru/blogs/1359876/</link>
		<description>КиберФорум - форум программистов, системных администраторов, администраторов баз данных, компьютерный форум, форум по электронике и бытовой технике, обсуждение софта. Бесплатная помощь в решении задач по программированию и наукам, решение проблем с компьютером, операционными системам</description>
		<language>ru</language>
		<lastBuildDate>Mon, 07 Sep 2026 00:25:32 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>60</ttl>
		<image>
			<url>https://www.cyberforum.ru//cyberstatic.net/images/misc/rss.jpg</url>
			<title>Форум программистов и сисадминов Киберфорум - Блоги - От простого к сложному. Автор ashsvis</title>
			<link>https://www.cyberforum.ru/blogs/1359876/</link>
		</image>
		<item>
			<title>Каждый раз одно и то же</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5758.html</link>
			<pubDate>Thu, 11 Apr 2019 17:09:30 GMT</pubDate>
			<description>Когда начинаешь какую-нибудь вещицу, в которой много таблиц и справочников, то непременно хочется...</description>
			<content:encoded><![CDATA[<div>Когда начинаешь какую-нибудь вещицу, в которой много таблиц и справочников, то непременно хочется поскорее увидеть результат её работы.<br />
Сначала создаёшь модель, какую-нибудь сущность, так, класс с набором свойств. Потом делаешь на основе него список.<br />
Ну, список - это уже нужна табличка, кнопки по созданию новой записи, изменению текущей...<br />
Для редактирования записи нужна форма. На форме размещаем надписи, редакторы значений, потом пишем код для заполнения этого хозяйства, обработку ввода... <br />
<br />
И для каждой сущности так... Каждый раз одно и то же! И, главное, всё типовое - метки, редакторы, выбор значений из списка...<br />
<br />
В общем, с этим надо что-делать. :scratch:<br />
<br />
Например, пишем приложение, где есть таблица сотрудников. Базовый класс выглядит примерно так:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="608881588"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="608881588" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> <span class="kw4">class</span> Employee <span class="sy0">:</span> IComparable<span class="sy0">&lt;</span>Employee<span class="sy0">&gt;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">//Ключевое поле</span>
&nbsp; &nbsp; <span class="kw1">public</span> Guid IdEmployee <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span> <span class="sy0">=</span> Guid<span class="sy0">.</span><span class="me1">NewGuid</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">//Фамилия</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">string</span> Surname <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="co1">//Имя</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">string</span> FirstName <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="co1">//Отчество</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">string</span> LastName <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="co1">//Должность</span>
&nbsp; &nbsp; <span class="kw1">public</span> Guid IdAppointment <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> CompareTo<span class="br0">&#40;</span>Employee other<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw4">string</span><span class="sy0">.</span><span class="me1">Compare</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, other<span class="sy0">.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">override</span> <span class="kw4">string</span> ToString<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> $<span class="st0">&quot;{Surname} {FirstName} {LastName}&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>... и хочется сразу получить примерно такое:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=5326&amp;d=1555000121" rel="Lightbox" id="attachment5326" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=5326&amp;thumb=1&amp;d=1555000121" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: Желаемая форма ввода.png
Просмотров: 1346
Размер:	10.8 Кб
ID:	5326" style="margin: 5px" /></a><br />
<br />
Что же, благодаря рефлексии это можно сделать!<br />
<br />
Для создания и вызова формы редактирования напишем несколько строк:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="887717739"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="887717739" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1">btnAdd<span class="sy0">.</span><span class="me1">Click</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp;<span class="co1">// создаём пустой объект требуемого типа</span>
&nbsp; &nbsp;<span class="kw1">var</span> item <span class="sy0">=</span> Activator<span class="sy0">.</span><span class="me1">CreateInstance</span><span class="br0">&#40;</span>userClass<span class="sy0">.</span><span class="me1">GetType</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp;<span class="co1">// вызываем диалог для заполнения свойств объекта</span>
&nbsp; &nbsp;<span class="kw1">var</span> frm <span class="sy0">=</span> PropertyPanelBuilder<span class="sy0">.</span><span class="me1">ShowPropertyFormDialog</span><span class="br0">&#40;</span>userModel, item<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp;<span class="co1">// если не была нажата клавиша &quot;Ввод&quot;, выходим</span>
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>frm<span class="sy0">.</span><span class="me1">DialogResult</span> <span class="sy0">!=</span> DialogResult<span class="sy0">.</span><span class="me1">OK</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp;<span class="sy0">...</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>где userClass и userModel - это параметры типа object, ссылки на экземпляры некоторых типов.<br />
Допустим, через userClass передаётся объект типа Employee, а через userModel - корневой объект модели,<br />
который, допустим, содержит, в том числе свойство типа List&lt;Employee&gt; с именем Employees.<br />
<br />
Метод ShowPropertyFormDialog() выглядит следующим образом:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="826399472"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="826399472" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Показ формы с полями для класса параметра</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;userClass&quot;&gt;Класс для формирования полей редактирования&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;Объект формы диалога&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">static</span> Form ShowPropertyFormDialog<span class="br0">&#40;</span><span class="kw4">object</span> userModel, <span class="kw4">object</span> userClass, <span class="kw4">string</span> fontName <span class="sy0">=</span> <span class="st0">&quot;Microsoft Sans Serif&quot;</span>, <span class="kw4">float</span> fontSize <span class="sy0">=</span> 8<span class="sy0">.</span>25f<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// заготовка для формы диалога</span>
&nbsp; &nbsp; <span class="kw1">var</span> frm <span class="sy0">=</span> <span class="kw3">new</span> Form<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> GetClassCaption<span class="br0">&#40;</span>userClass<span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; AutoSize <span class="sy0">=</span> <span class="kw1">true</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// размер подстраивается под содержимое</span>
&nbsp; &nbsp; &nbsp; &nbsp; AutoSizeMode <span class="sy0">=</span> AutoSizeMode<span class="sy0">.</span><span class="me1">GrowAndShrink</span>, &nbsp; &nbsp; &nbsp;<span class="co1">// автоматически увеличивает или уменьшает размер</span>
&nbsp; &nbsp; &nbsp; &nbsp; StartPosition <span class="sy0">=</span> FormStartPosition<span class="sy0">.</span><span class="me1">CenterParent</span>, <span class="co1">// показывает форму по центру родительского окна</span>
&nbsp; &nbsp; &nbsp; &nbsp; FormBorderStyle <span class="sy0">=</span> FormBorderStyle<span class="sy0">.</span><span class="me1">FixedDialog</span>, &nbsp;<span class="co1">// формат рамки формы</span>
&nbsp; &nbsp; &nbsp; &nbsp; MaximizeBox <span class="sy0">=</span> <span class="kw1">false</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// не показывать кнопку &quot;Развернуть&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; MinimizeBox <span class="sy0">=</span> <span class="kw1">false</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// не показывать кнопку &quot;Свернуть&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; ShowInTaskbar <span class="sy0">=</span> <span class="kw1">false</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// не показывать в панели задач</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; frm<span class="sy0">.</span><span class="me1">Font</span> <span class="sy0">=</span> <span class="kw3">new</span> Font<span class="br0">&#40;</span>fontName, fontSize<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// создаём заготовку панели свойств </span>
&nbsp; &nbsp; <span class="kw1">var</span> ppb <span class="sy0">=</span> <span class="kw3">new</span> PropertyPanelBuilder<span class="br0">&#40;</span>frm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// размещаем панель на форме</span>
&nbsp; &nbsp; frm<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>ppb<span class="sy0">.</span><span class="me1">BuildPropertyPanel</span><span class="br0">&#40;</span>userModel, userClass<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// показываем форму диалога</span>
&nbsp; &nbsp; frm<span class="sy0">.</span><span class="me1">ShowDialog</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// возвращаем ссылку на объект формы</span>
&nbsp; &nbsp; <span class="kw1">return</span> frm<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Пока ничего супер сложного. Создаём объект формы, настраиваем её как диалоговую форму (сколько тысяч раз я это делал каждый раз?).<br />
В качестве содержимого формы будет динамически создаваемая панель свойств, которую и размещаем на форме.<br />
Потом показываем диалог. Всё.<br />
<br />
Что же внутри BuildPropertyPanel()?<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="943997979"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="943997979" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Построение панели свойств по ссылке на экземпляр класса</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;userClass&quot;&gt;Ссылка на экземпляр класса&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;Ссылка на панель&lt;/returns&gt;</span>
<span class="kw1">public</span> UserControl BuildPropertyPanel<span class="br0">&#40;</span><span class="kw4">object</span> userModel, <span class="kw4">object</span> userClass<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// накопительный список действий, выполняемых при возврате изменённого значения в свойство объекта класса userClass</span>
&nbsp; &nbsp; <span class="kw1">var</span> actions <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>Action<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// кнопка &quot;Ввод&quot; панели свойств для диалога формы</span>
&nbsp; &nbsp; <span class="kw1">var</span> btnOk <span class="sy0">=</span> <span class="kw3">new</span> Button
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> <span class="st0">&quot;Ввод&quot;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; DialogResult <span class="sy0">=</span> DialogResult<span class="sy0">.</span><span class="me1">None</span>, &nbsp; <span class="co1">// специально не содержит закрытия по умолчанию</span>
&nbsp; &nbsp; &nbsp; &nbsp; Enabled <span class="sy0">=</span> <span class="kw1">false</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// изначально запрещена</span>
&nbsp; &nbsp; &nbsp; &nbsp; Anchor <span class="sy0">=</span> AnchorStyles<span class="sy0">.</span><span class="me1">Right</span>, &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// прижимается к правой стороне</span>
&nbsp; &nbsp; &nbsp; &nbsp; AutoSize <span class="sy0">=</span> <span class="kw1">true</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// увеличивается, если текст на кнопке не помещается</span>
&nbsp; &nbsp; &nbsp; &nbsp; Tag <span class="sy0">=</span> _form &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// здесь передаётся ссылка на форму диалога, для обработчика нажатия</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// кнопка &quot;Отмена&quot; панели свойств для диалога формы</span>
&nbsp; &nbsp; <span class="kw1">var</span> btnCancel <span class="sy0">=</span> <span class="kw3">new</span> Button
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> <span class="st0">&quot;Отменить&quot;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; DialogResult <span class="sy0">=</span> DialogResult<span class="sy0">.</span><span class="me1">Cancel</span>, <span class="co1">// содержит по умолчанию отмену редактирования и закрытие формы диалога</span>
&nbsp; &nbsp; &nbsp; &nbsp; Anchor <span class="sy0">=</span> AnchorStyles<span class="sy0">.</span><span class="me1">Right</span>, &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// прижимается к правой стороне</span>
&nbsp; &nbsp; &nbsp; &nbsp; AutoSize <span class="sy0">=</span> <span class="kw1">true</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// увеличивается, если текст на кнопке не помещается</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// заготовка для панели свойств</span>
&nbsp; &nbsp; <span class="kw1">var</span> userControl <span class="sy0">=</span> <span class="kw3">new</span> UserControl
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; AutoSize <span class="sy0">=</span> <span class="kw1">true</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// размер подстраивается под содержимое</span>
&nbsp; &nbsp; &nbsp; &nbsp; AutoSizeMode <span class="sy0">=</span> AutoSizeMode<span class="sy0">.</span><span class="me1">GrowAndShrink</span> &nbsp; <span class="co1">// автоматически увеличивает или уменьшает размер</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> type <span class="sy0">=</span> userClass<span class="sy0">.</span><span class="me1">GetType</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// получаем тип объекта, переданного через параметр</span>
&nbsp; &nbsp; MemberInfo<span class="br0">&#91;</span><span class="br0">&#93;</span> m <span class="sy0">=</span> type<span class="sy0">.</span><span class="me1">GetProperties</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="co1">// получаем массив свойств объекта</span>
&nbsp; &nbsp; <span class="co1">// создаём сетку для компоновки</span>
&nbsp; &nbsp; <span class="kw1">var</span> grid <span class="sy0">=</span> <span class="kw3">new</span> TableLayoutPanel<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Padding <span class="sy0">=</span> <span class="kw3">new</span> Padding<span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// внешний отступ от краёв сетки, для красоты</span>
&nbsp; &nbsp; &nbsp; &nbsp; AutoSize <span class="sy0">=</span> <span class="kw1">true</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// размер подстраивается под содержимое</span>
&nbsp; &nbsp; &nbsp; &nbsp; AutoSizeMode <span class="sy0">=</span> AutoSizeMode<span class="sy0">.</span><span class="me1">GrowAndShrink</span>, &nbsp;<span class="co1">// автоматически увеличивает или уменьшает размер</span>
&nbsp; &nbsp; &nbsp; &nbsp; ColumnCount <span class="sy0">=</span> <span class="nu0">2</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// будет два столбца - слева название, справа - поле редактирования</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// добавим два столбца в сетку, с автоматическим изменением размера (поведение по умолчанию)</span>
&nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">ColumnStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> ColumnStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">ColumnStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> ColumnStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// добавим сетку на панель свойств</span>
&nbsp; &nbsp; userControl<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>grid<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// вначале строк в сетке нет</span>
&nbsp; &nbsp; <span class="kw1">var</span> row <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> info <span class="kw1">in</span> m<span class="br0">&#41;</span> <span class="co1">// для каждого свойства из массива свойств</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// получаем ссылку на свойство по его имени</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> prop <span class="sy0">=</span> type<span class="sy0">.</span><span class="me1">GetProperty</span><span class="br0">&#40;</span>info<span class="sy0">.</span><span class="me1">Name</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// получаем наименование свойства из дескриптора</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> caption <span class="sy0">=</span> GetPropertyCaption<span class="br0">&#40;</span>userClass, prop<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// метка поля редактирования (размещаемая в первом столбце сетки, слева)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> label <span class="sy0">=</span> <span class="kw3">new</span> Label
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name <span class="sy0">=</span> <span class="st0">&quot;lb&quot;</span> <span class="sy0">+</span> prop<span class="sy0">.</span><span class="me1">Name</span>, &nbsp; &nbsp;<span class="co1">// имя метки, это имя свойства с префиксом &quot;lb&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// содержимое метки - наименование свойства из дескриптора, а если нет, то имя свойства из класса </span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">string</span><span class="sy0">.</span><span class="me1">IsNullOrWhiteSpace</span><span class="br0">&#40;</span>caption<span class="br0">&#41;</span> <span class="sy0">?</span> prop<span class="sy0">.</span><span class="me1">Name</span> <span class="sy0">:</span> caption<span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">&quot;:&quot;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Fill</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// растягивается на всю возможную поверхность ячейки в сетке </span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TextAlign <span class="sy0">=</span> ContentAlignment<span class="sy0">.</span><span class="me1">MiddleRight</span>, &nbsp; <span class="co1">// текст метки прижимается вправо и по центру вертикального размера</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AutoSize <span class="sy0">=</span> <span class="kw1">true</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// размер подстраивается под содержимое</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; TextBox textBox<span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// ссылка на редактор текстового свойства</span>
&nbsp; &nbsp; &nbsp; &nbsp; NumericUpDown numericUpDown<span class="sy0">;</span> &nbsp; &nbsp;<span class="co1">// ссылка на редактор числового свойства</span>
&nbsp; &nbsp; &nbsp; &nbsp; ComboBox comboBox<span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// ссылка на селектор значения</span>
&nbsp; &nbsp; &nbsp; &nbsp; DateTimePicker dateTimePicker<span class="sy0">;</span> &nbsp;<span class="co1">// ссылка на редактор значения даты</span>
&nbsp; &nbsp; &nbsp; &nbsp; CheckBox checkBox<span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// ссылка на редактор логического свойства</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// получим имя типа свойства как строку символов</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> typeName <span class="sy0">=</span> prop<span class="sy0">.</span><span class="me1">PropertyType</span><span class="sy0">.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// для часто встречающихся случаев</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>typeName<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&quot;System.String&quot;</span><span class="sy0">:</span> <span class="co1">// для строковых свойств</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowCount</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// указываем количество строк сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> RowStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// добавляем стиль строки сетки, с автоматическим изменением размера (поведение по умолчанию)</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>label, <span class="nu0">0</span>, row<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; <span class="co1">// добавляем метку в первый столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// формируем редактор текстовой строки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textBox <span class="sy0">=</span> <span class="kw3">new</span> TextBox
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name <span class="sy0">=</span> <span class="st0">&quot;tb&quot;</span> <span class="sy0">+</span> prop<span class="sy0">.</span><span class="me1">Name</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// имя компонента, это имя свойства с перфиксом &quot;tb&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> prop<span class="sy0">.</span><span class="me1">GetValue</span><span class="br0">&#40;</span>userClass<span class="br0">&#41;</span><span class="sy0">?.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, &nbsp; &nbsp;<span class="co1">// заполняем текст значением из свойства</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Fill</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// занимает всю ячейку сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BorderStyle <span class="sy0">=</span> BorderStyle<span class="sy0">.</span><span class="me1">FixedSingle</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// стильная рамка</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> <span class="nu0">160</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// ширина текстового поля (так настроил)</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TabIndex <span class="sy0">=</span> row &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// индекс перехода по табуляции</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// устанавливаем количество символов значения из атрибута DataRangeAttibute</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetRange<span class="br0">&#40;</span>userClass, prop, textBox<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// установка символа защиты пароля по атрибуту DataPassword</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> safeEditMode <span class="sy0">=</span> SetPasswordMode<span class="br0">&#40;</span>userClass, prop, textBox<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// при изменении содержимого в текстовом поле кнопка &quot;Ввод&quot; становится доступной</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textBox<span class="sy0">.</span><span class="me1">TextChanged</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="br0">&#123;</span> btnOk<span class="sy0">.</span><span class="me1">Enabled</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем редактор текста во второй столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>textBox, <span class="nu0">1</span>, row<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем обработчик для этого редактора в список действий</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; actions<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>safeEditMode <span class="sy0">?</span> PasswordValue<span class="br0">&#40;</span>userClass, prop, textBox<span class="br0">&#41;</span> <span class="sy0">:</span> TextValue<span class="br0">&#40;</span>userClass, prop, textBox<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>safeEditMode<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row<span class="sy0">++;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowCount</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// указываем количество строк сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> RowStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// добавляем стиль строки сетки, с автоматическим изменением размера (поведение по умолчанию)</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; label <span class="sy0">=</span> <span class="kw3">new</span> Label
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name <span class="sy0">=</span> <span class="st0">&quot;lbRepeat&quot;</span> <span class="sy0">+</span> prop<span class="sy0">.</span><span class="me1">Name</span>, &nbsp; &nbsp;<span class="co1">// имя метки, это имя свойства с перфиксом &quot;lb&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// содержимое метки - наименование свойства из дескриптора, а если нет, то имя свойства из класса </span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">string</span><span class="sy0">.</span><span class="me1">IsNullOrWhiteSpace</span><span class="br0">&#40;</span>caption<span class="br0">&#41;</span> <span class="sy0">?</span> $<span class="st0">&quot;{prop.Name} (repeat):&quot;</span> <span class="sy0">:</span> $<span class="st0">&quot;{caption} (ещё раз):&quot;</span><span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Fill</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// растягивается на всю возможную поверхность ячейки в сетке </span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TextAlign <span class="sy0">=</span> ContentAlignment<span class="sy0">.</span><span class="me1">MiddleRight</span>, &nbsp; <span class="co1">// текст метки прижимается вправо и по центру вертикального размера</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AutoSize <span class="sy0">=</span> <span class="kw1">true</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// размер подстраивается под содержимое</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>label, <span class="nu0">0</span>, row<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; <span class="co1">// добавляем метку в первый столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// формируем редактор повтора текстовой строки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> textBoxRepeat <span class="sy0">=</span> <span class="kw3">new</span> TextBox
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name <span class="sy0">=</span> <span class="st0">&quot;tbRepeat&quot;</span> <span class="sy0">+</span> prop<span class="sy0">.</span><span class="me1">Name</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// имя компонента, это имя свойства с перфиксом &quot;tb&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> prop<span class="sy0">.</span><span class="me1">GetValue</span><span class="br0">&#40;</span>userClass<span class="br0">&#41;</span><span class="sy0">?.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, &nbsp; &nbsp;<span class="co1">// заполняем текст значением из свойства</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Fill</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// занимает всю ячейку сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BorderStyle <span class="sy0">=</span> BorderStyle<span class="sy0">.</span><span class="me1">FixedSingle</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// стильная рамка</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> <span class="nu0">160</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// ширина текстового поля (так настроил)</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TabIndex <span class="sy0">=</span> row &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// индекс перехода по табуляции</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// устанавливаем количество символов значения из атрибута DataRangeAttibute</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetRange<span class="br0">&#40;</span>userClass, prop, textBoxRepeat<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetPasswordMode<span class="br0">&#40;</span>userClass, prop, textBoxRepeat<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>textBoxRepeat, <span class="nu0">1</span>, row<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем обработчик для этого редактора в список действий</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; actions<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">=&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">string</span><span class="sy0">.</span><span class="me1">Compare</span><span class="br0">&#40;</span>textBox<span class="sy0">.</span><span class="me1">Text</span>, textBoxRepeat<span class="sy0">.</span><span class="me1">Text</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="nu0">0</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">throw</span> <span class="kw3">new</span> Exception<span class="br0">&#40;</span><span class="st0">&quot;Значение паролей не совпадают!&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&quot;System.Int32&quot;</span><span class="sy0">:</span> &nbsp; &nbsp;<span class="co1">// для целочисленных свойств</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&quot;System.Decimal&quot;</span><span class="sy0">:</span> &nbsp;<span class="co1">// для свойств с ценой</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowCount</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// указываем количество строк сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> RowStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// добавляем стиль строки сетки, с автоматическим изменением размера (поведение по умолчанию)</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>label, <span class="nu0">0</span>, row<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; <span class="co1">// добавляем метку в первый столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// формируем редактор числового значения</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; numericUpDown <span class="sy0">=</span> <span class="kw3">new</span> NumericUpDown
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name <span class="sy0">=</span> <span class="st0">&quot;nud&quot;</span> <span class="sy0">+</span> prop<span class="sy0">.</span><span class="me1">Name</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// имя компонента, это имя свойства с перфиксом &quot;nud&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Left</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// прижимаем влево</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TextAlign <span class="sy0">=</span> HorizontalAlignment<span class="sy0">.</span><span class="me1">Right</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// текст прижимаем вправо</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BorderStyle <span class="sy0">=</span> BorderStyle<span class="sy0">.</span><span class="me1">FixedSingle</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DecimalPlaces <span class="sy0">=</span> typeName <span class="sy0">==</span> <span class="st0">&quot;System.Decimal&quot;</span> <span class="sy0">?</span> <span class="nu0">2</span> <span class="sy0">:</span> <span class="nu0">0</span>, &nbsp; &nbsp; &nbsp; <span class="co1">// количество знаков для копеек для decimal</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Maximum <span class="sy0">=</span> typeName <span class="sy0">==</span> <span class="st0">&quot;System.Decimal&quot;</span> <span class="sy0">?</span> <span class="nu0">1000000</span> <span class="sy0">:</span> <span class="nu0">32767</span>, &nbsp; <span class="co1">// значения границ</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> <span class="nu0">70</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TabIndex <span class="sy0">=</span> row
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// устанавливаем диапазон изменения значения из атрибута DataRangeAttibute</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetRange<span class="br0">&#40;</span>userClass, prop, numericUpDown<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// получаем текущее значение</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> <span class="kw1">value</span> <span class="sy0">=</span> Convert<span class="sy0">.</span><span class="me1">ToDecimal</span><span class="br0">&#40;</span>prop<span class="sy0">.</span><span class="me1">GetValue</span><span class="br0">&#40;</span>userClass<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если полученное значение в разрешенном диапазоне</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">value</span> <span class="sy0">&gt;=</span> numericUpDown<span class="sy0">.</span><span class="me1">Minimum</span> <span class="sy0">&amp;&amp;</span> <span class="kw1">value</span> <span class="sy0">&lt;=</span> numericUpDown<span class="sy0">.</span><span class="me1">Maximum</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; numericUpDown<span class="sy0">.</span><span class="kw1">Value</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> &nbsp; &nbsp;<span class="co1">// присваиваем как значение редактора числа</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; numericUpDown<span class="sy0">.</span><span class="me1">TextChanged</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="br0">&#123;</span> btnOk<span class="sy0">.</span><span class="me1">Enabled</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; numericUpDown<span class="sy0">.</span><span class="me1">ValueChanged</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="br0">&#123;</span> btnOk<span class="sy0">.</span><span class="me1">Enabled</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем редактор чисел во второй столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>numericUpDown, <span class="nu0">1</span>, row<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем обработчик для этого редактора в список действий</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; actions<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>NumberValue<span class="br0">&#40;</span>userClass, prop, numericUpDown<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&quot;System.Guid&quot;</span><span class="sy0">:</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// для ключевых значений свойств</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>row <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="kw1">break</span><span class="sy0">;</span> &nbsp; &nbsp;<span class="co1">// принимаем, что если первым в классе объявлено свойство типа Guid - то это ключевое свойство и его не показываем</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowCount</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// указываем количество строк сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> RowStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// добавляем стиль строки сетки, с автоматическим изменением размера (поведение по умолчанию)</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>label, <span class="nu0">0</span>, row<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; <span class="co1">// добавляем метку в первый столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// формируем селектор ключевых значении</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; comboBox <span class="sy0">=</span> <span class="kw3">new</span> ComboBox
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name <span class="sy0">=</span> <span class="st0">&quot;cb&quot;</span> <span class="sy0">+</span> prop<span class="sy0">.</span><span class="me1">Name</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// имя компонента, это имя свойства с перфиксом &quot;cb&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Fill</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> <span class="nu0">160</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DropDownStyle <span class="sy0">=</span> ComboBoxStyle<span class="sy0">.</span><span class="me1">DropDownList</span>, &nbsp; &nbsp; <span class="co1">// только список для выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TabIndex <span class="sy0">=</span> row
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FillCombobox<span class="br0">&#40;</span>userModel, userClass, prop, comboBox<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// при подтверждении выбора разрешаем кнопку &quot;Ввод&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; comboBox<span class="sy0">.</span><span class="me1">SelectionChangeCommitted</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="br0">&#123;</span> btnOk<span class="sy0">.</span><span class="me1">Enabled</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем селектор во второй столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>comboBox, <span class="nu0">1</span>, row<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем обработчик для этого редактора в список действий</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; actions<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>GuidValue<span class="br0">&#40;</span>userClass, prop, comboBox<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&quot;System.DateTime&quot;</span><span class="sy0">:</span> <span class="co1">// для свойств с датой</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowCount</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> RowStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>label, <span class="nu0">0</span>, row<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dateTimePicker <span class="sy0">=</span> <span class="kw3">new</span> DateTimePicker
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name <span class="sy0">=</span> <span class="st0">&quot;dtp&quot;</span> <span class="sy0">+</span> prop<span class="sy0">.</span><span class="me1">Name</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> prop<span class="sy0">.</span><span class="me1">GetValue</span><span class="br0">&#40;</span>userClass<span class="br0">&#41;</span><span class="sy0">?.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Fill</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> <span class="nu0">70</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TabIndex <span class="sy0">=</span> row
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dateTimePicker<span class="sy0">.</span><span class="me1">TextChanged</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="br0">&#123;</span> btnOk<span class="sy0">.</span><span class="me1">Enabled</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dateTimePicker<span class="sy0">.</span><span class="me1">ValueChanged</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> <span class="br0">&#123;</span> btnOk<span class="sy0">.</span><span class="me1">Enabled</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем редактор даты во второй столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>dateTimePicker, <span class="nu0">1</span>, row<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем обработчик для этого редактора в список действий</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; actions<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>DateTimeValue<span class="br0">&#40;</span>userClass, prop, dateTimePicker<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> <span class="st0">&quot;System.Boolean&quot;</span><span class="sy0">:</span> <span class="co1">// для логических свойств</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowCount</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> RowStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>label, <span class="nu0">0</span>, row<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkBox <span class="sy0">=</span> <span class="kw3">new</span> CheckBox
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name <span class="sy0">=</span> <span class="st0">&quot;cb&quot;</span> <span class="sy0">+</span> prop<span class="sy0">.</span><span class="me1">Name</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">bool</span><span class="br0">&#41;</span>prop<span class="sy0">.</span><span class="me1">GetValue</span><span class="br0">&#40;</span>userClass<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Да&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Нет&quot;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Fill</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> <span class="nu0">70</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TabStop <span class="sy0">=</span> <span class="kw1">true</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TabIndex <span class="sy0">=</span> row
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// получаем текущее значение</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkBox<span class="sy0">.</span><span class="kw3">Checked</span> <span class="sy0">=</span> Convert<span class="sy0">.</span><span class="me1">ToBoolean</span><span class="br0">&#40;</span>prop<span class="sy0">.</span><span class="me1">GetValue</span><span class="br0">&#40;</span>userClass<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checkBox<span class="sy0">.</span><span class="me1">CheckedChanged</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ch <span class="sy0">=</span> <span class="br0">&#40;</span>CheckBox<span class="br0">&#41;</span>o<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ch<span class="sy0">.</span><span class="me1">Text</span> <span class="sy0">=</span> ch<span class="sy0">.</span><span class="kw3">Checked</span> <span class="sy0">?</span> <span class="st0">&quot;Да&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Нет&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; btnOk<span class="sy0">.</span><span class="me1">Enabled</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем редактор даты во второй столбец строки сетки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>checkBox, <span class="nu0">1</span>, row<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем обработчик для этого редактора в список действий</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; actions<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>BooleanValue<span class="br0">&#40;</span>userClass, prop, checkBox<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; row<span class="sy0">++;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co2">#region Панель кнопок &quot;Ввод&quot; и &quot;Отмена&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co1">// создадим панель для размещения кнопок</span>
&nbsp; &nbsp; <span class="kw1">var</span> flow <span class="sy0">=</span> <span class="kw3">new</span> FlowLayoutPanel
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; AutoSize <span class="sy0">=</span> <span class="kw1">true</span>,
&nbsp; &nbsp; &nbsp; &nbsp; AutoSizeMode <span class="sy0">=</span> AutoSizeMode<span class="sy0">.</span><span class="me1">GrowAndShrink</span>,
&nbsp; &nbsp; &nbsp; &nbsp; Dock <span class="sy0">=</span> DockStyle<span class="sy0">.</span><span class="me1">Right</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// прижимается вправо</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// добавляем строку в сетку</span>
&nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowCount</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">RowStyles</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span><span class="kw3">new</span> RowStyle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// с авто размером</span>
&nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>flow, <span class="nu0">0</span>, row<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; &nbsp;<span class="co1">// в первый столбец</span>
&nbsp; &nbsp; grid<span class="sy0">.</span><span class="me1">SetColumnSpan</span><span class="br0">&#40;</span>flow, <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// с растягиванием на два столбца</span>
&nbsp; &nbsp; <span class="co1">// настроим кнопке ввод индекс табуляции</span>
&nbsp; &nbsp; btnOk<span class="sy0">.</span><span class="me1">TabIndex</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// добавим её на панель свойств</span>
&nbsp; &nbsp; flow<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>btnOk<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// добавим обработчик нажатия кнопки &quot;Ввод&quot;</span>
&nbsp; &nbsp; btnOk<span class="sy0">.</span><span class="me1">Click</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, e<span class="br0">&#41;</span> <span class="sy0">=&gt;</span> 
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> frm <span class="sy0">=</span> <span class="br0">&#40;</span>Form<span class="br0">&#41;</span><span class="br0">&#40;</span><span class="br0">&#40;</span>Button<span class="br0">&#41;</span>o<span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">Tag</span><span class="sy0">;</span> &nbsp; &nbsp;<span class="co1">// получим ссылку на форму диалога</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// перешлём все значения из полей редактирования в свойства объекта</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> act <span class="kw1">in</span> actions<span class="br0">&#41;</span> act<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если ошибок присвоения не было, закрываем форму с признаком ОК</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; frm<span class="sy0">.</span><span class="me1">DialogResult</span> <span class="sy0">=</span> DialogResult<span class="sy0">.</span><span class="me1">OK</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">catch</span> <span class="br0">&#40;</span>Exception ex<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// выводим сообщение при первой ошибке</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MessageBox<span class="sy0">.</span><span class="me1">Show</span><span class="br0">&#40;</span>frm, ex<span class="sy0">.</span><span class="me1">Message</span>, <span class="st0">&quot;Ошибка в значении свойства&quot;</span>, MessageBoxButtons<span class="sy0">.</span><span class="me1">OK</span>, MessageBoxIcon<span class="sy0">.</span><span class="me1">Error</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// форма диалога при этом не закрывается</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// настроим кнопке ввод индекс табуляции</span>
&nbsp; &nbsp; btnCancel<span class="sy0">.</span><span class="me1">TabIndex</span> <span class="sy0">=</span> row <span class="sy0">+</span> <span class="nu0">2</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// добавим её на панель свойств</span>
&nbsp; &nbsp; flow<span class="sy0">.</span><span class="me1">Controls</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>btnCancel<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co2">#endregion</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> userControl<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
Ну, а внутри всё и начинается... Сплошная рефлексия, понимаешь...<br />
<br />
Для удобства работы пришлось подправить модельный класс:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="389447746"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="389447746" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1"><span class="br0">&#91;</span>Serializable<span class="br0">&#93;</span>
<span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">&quot;Сотрудник&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span>
<span class="kw1">public</span> <span class="kw4">class</span> Employee <span class="sy0">:</span> IComparable<span class="sy0">&lt;</span>Employee<span class="sy0">&gt;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">public</span> Guid IdEmployee <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span> <span class="sy0">=</span> Guid<span class="sy0">.</span><span class="me1">NewGuid</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">&quot;Фамилия&quot;</span><span class="br0">&#41;</span>, DataNotEmpty<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">string</span> Surname <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">&quot;Имя&quot;</span><span class="br0">&#41;</span>, DataNotEmpty<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">string</span> FirstName <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">&quot;Отчество&quot;</span><span class="br0">&#41;</span>, DataNotEmpty<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">string</span> LastName <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="br0">&#91;</span>Description<span class="br0">&#40;</span><span class="st0">&quot;Должность&quot;</span><span class="br0">&#41;</span>, DataLookup<span class="br0">&#40;</span><span class="st0">&quot;IdAppointment&quot;</span>, <span class="st0">&quot;Appointments&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> Guid IdAppointment <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> CompareTo<span class="br0">&#40;</span>Employee other<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw4">string</span><span class="sy0">.</span><span class="me1">Compare</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="sy0">.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, other<span class="sy0">.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">override</span> <span class="kw4">string</span> ToString<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> $<span class="st0">&quot;{Surname} {FirstName} {LastName}&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Добавить атрибуты, из которых динамически берутся названия свойств, источники справочников, границы числовых значений...<br />
<br />
В общем, кому интересно, заходите в репозиторий: <a rel="nofollow noopener noreferrer" href="https://github.com/ashsvis/SchoolOfficeWork" target="_blank" title="https://github.com/ashsvis/SchoolOfficeWork">https://github.com/ashsvis/SchoolOfficeWork</a></div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5758.html</guid>
		</item>
		<item>
			<title>Шаг 8 (Рефакторинг ГВР) Версия 0.2</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5536.html</link>
			<pubDate>Thu, 15 Nov 2018 11:12:15 GMT</pubDate>
			<description>Приветствую вас, уважаемые читатели! 
 
Вчера пропустил день публикации, думал, сделаю...</description>
			<content:encoded><![CDATA[<div>Приветствую вас, уважаемые читатели!<br />
<br />
Вчера пропустил день публикации, думал, сделаю перерывчег... :yahoo: Но доводить до ума программу надо, тем более что на вопиющие недостатки кода указали мне. Спасибо!<br />
<br />
Первым делом убрал это страшное по всему коду:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="6376546"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="6376546" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span>kind <span class="sy0">==</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawPolygon</span><span class="br0">&#40;</span>pen, points<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// рисование контура</span>
<span class="kw1">else</span>
&nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawLines</span><span class="br0">&#40;</span>pen, points<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><font color="Silver">[отступ]</font>Действительно, если &quot;мясо наращивать&quot;, то надо к этому всё приспособить. Правда у меня метод разработки такой. :-[<br />
Сперва есть идея, потом прототип, желательно минимально работающий, потом пытаемся его расширить и тут-то надобность<br />
и возникает в наследовании, интерфейсах и прочая...<br />
<br />
<font color="Silver">[отступ]</font>Действительно, когда потребовалось добавить круг (круг, Карл!), то базовый массив точек тут, конечно, не причём, ибо<br />
круг - это частный случай эллипса, а эллипс строится на прямоугольнике, у которого Location и Size, и никакого массива точек.<br />
Поэтому пришлось классы писать под прямоугольник, квадрат, эллипс и круг (ещё хотел ромб сделать, но не всё сразу... :jokingly:).<br />
<font color="Silver">[отступ]</font>Все эти классы наследуются от класса Figure (вернее, сделал, что наследуются Polyline, Polygon, Rect и Oval напрямую, потом<br />
от Oval наследуется Circle, а от Rect наследуется Square). Соответственно, пришлось с методами повозиться у базового класса<br />
Figure (и сделать его всё-таки абстрактным и базовые методы кое-какие абстрактные, а кое-какие вообще вынес под интерфейсы,<br />
так как, когда метод абстрактный, то его в каждом наследнике нужно переопределять, и бывает, в наследнике он вообще не<br />
нужен). Это, так сказать, первая большая переделка - создать древо (<i>древо</i> - красиво звучит!) классов.<br />
<br />
Вторая новость - вместо индексов маркеров (положительные числа для размерных маркеров, отрицательные - для узловых)<br />
создал маркеры настоящие, объектные. Да все их красиво назвал и расставил по нужным местам. 8-)<br />
<br />
В общем, размусоливать более не буду, вот версия для растерзания: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=5091&amp;d=1542279802" >SimpleVectorGraphicsEditor V0_2.zip</a><br />
<br />
<font color="Silver">[отступ]</font>Извиняюсь, что выложил здесь, а не на гитхабе. Опыта работы с ним не было, а с разбегу не получается. Это первое.<br />
А второе, по-поводу Undo/Redo с командами. С материалом по ссылкам я познакомился и (о ужас!) я не совсем уверен,<br />
нужно ли эту штуку применять в простом ГВР, если этот <i>примитивный</i> механизм и так справляется...<br />
<br />
P.S. А формат записи в файл надо будет менять, ибо совместимости записанных файлов от версии к версии нет. Нужно<br />
сделать xml, да ещё с контролем версий.<br />
<br />
Всем спасибо за внимание, пока!</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5536.html</guid>
		</item>
		<item>
			<title>Шаг 7 (графический векторный редактор) Версия 0.1</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5533.html</link>
			<pubDate>Tue, 13 Nov 2018 09:18:27 GMT</pubDate>
			<description>Сегодня хороший день, господа программисты, ибо я выпускаю в первое плавание мою лодку, 
под...</description>
			<content:encoded><![CDATA[<div>Сегодня хороший день, господа программисты, ибо я выпускаю в первое плавание мою лодку,<br />
под названием &quot;Простой векторный графический редактор&quot;.<br />
<br />
Пока это только корпус, никаких мачт, рей и такелажа, но корпус, я надеюсь, достаточно прочный, чтобы<br />
сразу не пойти ко дну... :D<br />
<br />
Я подготовил небольшой демо проект для демонстрации и обсуждения: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=5085&amp;d=1542095717" >SimpleVectorGraphicsEditor Demo V0_1.zip</a><br />
<br />
Проект состоит из шести классов редактора, всё остальное необходимо для демонстрации работы.<br />
На центральной части формы расположена панель типа Panel, у которой размер Dock = Dock.Fill привязан ко внешней таблице<br />
компоновки и установлено свойство AutoSize = true. На этой панели расположен компонент PictureBox, который<br />
и будет контейнером для нашего редактора. В свойство PictureBox BackgroundImage загружена картинка, имитирующая<br />
координатную сетку. Наш редактор подключается в конструкторе формы:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="561356088"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="561356088" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> <span class="kw1">partial</span> <span class="kw4">class</span> FormMain <span class="sy0">:</span> Form
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">readonly</span> PictureEditor _editor<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">const</span> <span class="kw4">string</span> Title <span class="sy0">=</span> <span class="st_h">@&quot;Простой векторный графический редактор (демо)&quot;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">public</span> FormMain<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; InitializeComponent<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// создаём хранилище созданных фигур, которое также и рисует их</span>
&nbsp; &nbsp; &nbsp; &nbsp; _editor <span class="sy0">=</span> <span class="kw3">new</span> PictureEditor<span class="br0">&#40;</span>pbCanvas<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BackgoundContextMenu <span class="sy0">=</span> cmsBkgPopup,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FigureContextMenu <span class="sy0">=</span> cmsFigPopup
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _editor<span class="sy0">.</span><span class="me1">FigureSelected</span> <span class="sy0">+=</span> EditorFigureSelected<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _editor<span class="sy0">.</span><span class="me1">EditorFarConnerUpdated</span> <span class="sy0">+=</span> EditorFarConnerUpdated<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cbWidth<span class="sy0">.</span><span class="me1">Items</span><span class="sy0">.</span><span class="me1">Clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> <span class="nu0">61</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span> cbWidth<span class="sy0">.</span><span class="me1">Items</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>i<span class="sy0">.</span><span class="me1">ToString</span><span class="br0">&#40;</span><span class="st0">&quot;0&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="sy0">....</span></pre></td></tr></table></div></td></tr></tbody></table></div>При создании экземпляра редактора PictureEditor в конструктор передаётся ссылка на контейнер PictureBox pbCanvas,<br />
затем подключаются два контекстных меню:<br />
<br />
pbCanvas.BackgoundContextMenu = cmsBkgPopup - для случая, когда ни одна фигура не выбрана (для общих настроек)<br />
pbCanvas.FigureContextMenu = cmsFigPopup - для вызова на выбранных фигурах.<br />
<br />
Содержимое контекстных меню подготавливается в дизайнере VS, а наш редактор только управляет их вызовом.<br />
Обработчики всех пунктов контекстных меню и главного меню также пишутся и подключаются в дизайнере VS.<br />
<br />
Редактор формирует два события: при выборе фигуры и при изменении расположения фигур, когда они перетаскиваются.<br />
Внешний обработчик синхронизируют внешние для редактора компоненты формы. Размер контейнера изменяется при<br />
изменении положения фигур в редакторе.<br />
<font color="Silver">[здесь хочу отступ]</font>Во внешнем обработчике этого события размер контейнера подгоняется под текущий размер поля редактора,<br />
а панель, на которой находится контейнер, отображает полосы прокрутки, если это необходимо. На данный момент жесткий<br />
размер поля редактирования не предусмотрен. Хотя он нужен, например, для проверок на возможность размещения.<br />
<br />
Для начала рисования фигур пользователь должен выбрать фигуру, нажав на значок с её изображением. При нажатии на<br />
любую из этих кнопочек выполняется обработчик:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="852561378"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="852561378" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw4">void</span> tsbSelectMode_Click<span class="br0">&#40;</span><span class="kw4">object</span> sender, EventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span>ToolStripButton btn <span class="kw1">in</span> tsFigures<span class="sy0">.</span><span class="me1">Items</span><span class="br0">&#41;</span> btn<span class="sy0">.</span><span class="kw3">Checked</span> <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="br0">&#40;</span>ToolStripButton<span class="br0">&#41;</span>sender<span class="br0">&#41;</span><span class="sy0">.</span><span class="kw3">Checked</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tsbPolyline<span class="sy0">.</span><span class="kw3">Checked</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _editor<span class="sy0">.</span><span class="me1">EditorMode</span> <span class="sy0">=</span> EditorMode<span class="sy0">.</span><span class="me1">AddLine</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>tsbPolygon<span class="sy0">.</span><span class="kw3">Checked</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _editor<span class="sy0">.</span><span class="me1">EditorMode</span> <span class="sy0">=</span> EditorMode<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; _editor<span class="sy0">.</span><span class="me1">EditorMode</span> <span class="sy0">=</span> EditorMode<span class="sy0">.</span><span class="me1">Selection</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В строке 3 мы сбрасываем все флажки, а потом устанавливаем отметку в кнопочке нажатия (строка 4).<br />
Далее переключаем режим редактора в зависимости от выбора пользователя. Пока всего только две фигуры можно нарисовать. <br />
Это полилиния и полигон.<br />
<br />
После выбора фигуры нажимаем мышкой на первую точку и, не отпуская левой кнопки, &quot;тянем&quot; до необходимого размера,<br />
потом отпускаем. Нужная фигура зафиксируется. Потом мы можем перемещать её, изменять размер, трансформировать и прочее.<br />
<br />
Дополнительно я тут подготовил небольшие &quot;плюшки&quot;, как то копирование и вырезание выделенных фигур в буфер обмена,<br />
вставку фигур из буфера обмена. Любопытно, что эта штука работает, даже если мы скопируем фигуры в одном приложении<br />
редактора, а вставим в другом запущенном приложении редактора.<br />
Другой &quot;плюшкой&quot; является поддержка возможности отмены действий редактирования и возврат после отмены. Для этой<br />
цели создан класс-помощник StackMemory:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="566030849"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="566030849" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
</pre></td><td class="de1"><pre class="de1"><span class="br0">&#91;</span>Serializable<span class="br0">&#93;</span>
<span class="kw1">public</span> <span class="kw4">class</span> StackMemory
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">readonly</span> <span class="kw4">int</span> _stackDepth<span class="sy0">;</span> <span class="co1">// глубина стека</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">readonly</span> List<span class="sy0">&lt;</span><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span><span class="sy0">&gt;</span> _list <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span><span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Конструктор</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;depth&quot;&gt;&lt;/param&gt;</span>
&nbsp; &nbsp; <span class="kw1">public</span> StackMemory<span class="br0">&#40;</span><span class="kw4">int</span> depth<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _stackDepth <span class="sy0">=</span> depth<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>depth <span class="sy0">&lt;</span> <span class="nu0">1</span><span class="br0">&#41;</span> _stackDepth <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _list<span class="sy0">.</span><span class="me1">Clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Помещаем данные в стек</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;stream&quot;&gt;&lt;/param&gt;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Push<span class="br0">&#40;</span>MemoryStream stream<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_list<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">&gt;</span> _stackDepth<span class="br0">&#41;</span> _list<span class="sy0">.</span><span class="me1">RemoveAt</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _list<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>stream<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Очищаем стек</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Clear<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _list<span class="sy0">.</span><span class="me1">Clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Количество сохранённых версий в стеке</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> Count
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="br0">&#40;</span>_list<span class="sy0">.</span><span class="me1">Count</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Извлечение данных из стека</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;stream&quot;&gt;&lt;/param&gt;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Pop<span class="br0">&#40;</span>MemoryStream stream<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_list<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">&lt;=</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> buff <span class="sy0">=</span> _list<span class="br0">&#91;</span>_list<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; stream<span class="sy0">.</span><span class="me1">Write</span><span class="br0">&#40;</span>buff, <span class="nu0">0</span>, buff<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _list<span class="sy0">.</span><span class="me1">RemoveAt</span><span class="br0">&#40;</span>_list<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В конструкторе класса задаётся &quot;глубина&quot; отката и реализованы основные методы для работы со стековой структурой.<br />
Применение этого класса также довольно простое, сначала создаем два стека Undo и Redo:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="719886637"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="719886637" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="kw1">readonly</span> StackMemory _undoStack <span class="sy0">=</span> <span class="kw3">new</span> StackMemory<span class="br0">&#40;</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">readonly</span> StackMemory _redoStack <span class="sy0">=</span> <span class="kw3">new</span> StackMemory<span class="br0">&#40;</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Затем будем использовать в свойстве редактора FileChanged:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="632001386"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="632001386" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Признак изменения данных.</span>
<span class="co1">/// ВНИМАНИЕ! Для правильной работы логики Undo|Redo</span>
<span class="co1">/// изменение этого свойства производить ДО изменения данных!</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">bool</span> FileChanged
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>_fileChanged<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _fileChanged <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; PrepareToUndo<span class="br0">&#40;</span>_fileChanged<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; PrepareToRedo<span class="br0">&#40;</span><span class="kw1">false</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Для отката действий необходимо запомнить состояние редактора ДО изменения его коллекции фигур, поэтому когда<br />
предстоит что-то изменить, например, закончили перетаскивание и перед тем как сместить фигуры, нужно присвоить<br />
свойству FileChanged значение True. В сеттере выполняться два метода подготовки для Undo и Redo.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="83388647"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="83388647" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Подготовка к отмене (сохранения состояния)</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;changed&quot;&gt;True - cохранить состояние&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> PrepareToUndo<span class="br0">&#40;</span><span class="kw4">bool</span> changed<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>changed<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> stream <span class="sy0">=</span> <span class="kw3">new</span> MemoryStream<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SaveToStream<span class="br0">&#40;</span>stream<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _undoStack<span class="sy0">.</span><span class="me1">Push</span><span class="br0">&#40;</span>stream<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; _undoStack<span class="sy0">.</span><span class="me1">Clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Метод для Redo такой же, только используется _redoStack. Методом SaveToStream() записываем всё в поток, а потом<br />
помещаем этот поток в стек. Вот код метода SaveToStream():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="799286616"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="799286616" style="height: 222px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Сохранить все фигуры в поток</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;stream&quot;&gt;поток в памяти&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;listToSave&quot;&gt;список для сохранения&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> SaveToStream<span class="br0">&#40;</span>Stream stream, List<span class="sy0">&lt;</span>Figure<span class="sy0">&gt;</span> listToSave <span class="sy0">=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> formatter <span class="sy0">=</span> <span class="kw3">new</span> BinaryFormatter<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> list <span class="sy0">=</span> <span class="br0">&#40;</span>listToSave <span class="sy0">??</span> _figures<span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">ToList</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; formatter<span class="sy0">.</span><span class="me1">Serialize</span><span class="br0">&#40;</span>stream, list<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; stream<span class="sy0">.</span><span class="me1">Position</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Возврат состояния происходит при при вызове метода UndoChanges():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="469851849"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="469851849" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Отмена действий, изменений</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> UndoChanges<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>CanUndoChanges<span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; PrepareToRedo<span class="br0">&#40;</span><span class="kw1">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; _selected<span class="sy0">.</span><span class="me1">Clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; _figures<span class="sy0">.</span><span class="me1">Clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; GC<span class="sy0">.</span><span class="me1">Collect</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> stream <span class="sy0">=</span> <span class="kw3">new</span> MemoryStream<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _undoStack<span class="sy0">.</span><span class="me1">Pop</span><span class="br0">&#40;</span>stream<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> list <span class="sy0">=</span> LoadFromStream<span class="br0">&#40;</span>stream<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> fig <span class="kw1">in</span> list<span class="br0">&#41;</span> _figures<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Вот, вкратце, что я имел сообщить по поводу строительства простого графического редактора. Далее <s>ставим мачты, паруса</s> можем дополнять код редактора всякими инструментами, например:<ul><li>Выравнивание групп фигур по сторонам и серединам во вертикали и горизонтали</li>
<li>Группировка фигур, чтобы вместе держались при перемещении и изменении размеров с общим размерным прямоугольником</li>
<li>Реализация редакторов отдельных свойств фигуры (я сделал только для цвета и толщины линии)</li>
<li>Было бы здорово сделать поддержку кривых Безье</li>
<li>Добавить к фигурам текст</li>
<li>Добавить маркеры привязки, чтобы можно было цеплять одну фигуру к другой</li>
<li>Добавить слои</li>
<li>Добавить экспорт в другие графические форматы (векторные и не векторные)</li>
<li>... (делайте свои предложения) </li>
</ul><br />
Большое спасибо за внимание! Буду благодарен за ваши советы, указание на ошибки (которые буду исправлять по <br />
возможности) и наставления.</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5533.html</guid>
		</item>
		<item>
			<title>Шаг 6 (графический векторный редактор). Изменение формы фигуры путём перетаскивания узловых маркеров</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5530.html</link>
			<pubDate>Mon, 12 Nov 2018 16:42:48 GMT</pubDate>
			<description>Приветствую вас, уважаемые изучатели моих способов строительства простого графического векторного...</description>
			<content:encoded><![CDATA[<div>Приветствую вас, уважаемые <i>изучатели</i> моих способов строительства простого графического векторного редактора.<br />
<br />
В этой статье рассмотрим работу с маркерами изменения узлов фигуры (точек, по которым рисуется фигура) и об алгоритме<br />
выбора узлов, добавления новых узлов и удалении существующих узлов. Это как раз тот материал, ради которого всё и <br />
затевалось.<br />
<br />
Когда мы переключаемся в режим изменения узлов, маркеры размеров скрываются и начинают рисоваться маркеры узлов.<br />
Переключиться в режим изменения узлов можно только для одной фигуры. Если выделено несколько фигур, то элемент<br />
контекстного меню на фигуре (по правой кнопке мышки) для включения режима изменения узлов не появится.<br />
<br />
Всего четыре действия мы можем сделать через меню:<ol style="list-style-type: decimal"><li>Начать изменение узлов.</li>
<li>Добавить узел.</li>
<li>Удалить узел.</li>
<li>Выйти из режима изменения узлов.</li>
</ol><br />
Для начала изменения узлов необходимо присвоить свойству NodeChaging значение True:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="221676139"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="221676139" style="height: 222px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Режим выбора и перетаскивания узловых точек (изменения узлов)</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">bool</span> NodeChanging
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _nodeChanging<span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _nodeChanging <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Свойство публичное, поэтому этот режим можно включить извне, из меню пользователя. При изменении свойства в<br />
сеттере делается запрос на перерисовку контейнера, что и понятно - размерные маркеры заменяются на узловые.<br />
<br />
Узловой маркер, также как и размерный, выбирается пользователем через метод клика мышки на контейнере<br />
ContainerMouseDown(), далее метод <b>MarkerIndex = PointInMarker(e.Location, out fig)</b> должен вернуть отрицательный<br />
индекс маркера, отрицательный - значит маркер изменения узла.<br />
<br />
В методе обработки перемещения мышки ContainerMouseMove() рассчитывается величина смещения от точки первого нажатия<br />
до текущего положения мышки (см. шаг 5 - метод расчёта смещения один, важен только режим NodeChanging).<br />
<br />
В рисующем методе DrawFocusFigure() для маркера изменения узла написано следующее:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="795724089"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="795724089" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw1">static</span> <span class="kw4">void</span> DrawFocusFigure<span class="br0">&#40;</span>Figure figure, Graphics graphics, PointF offset,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> markerIndex, <span class="kw4">bool</span> nodeChanging<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="sy0">....</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>nodeChanging <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>markerIndex <span class="sy0">&lt;</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// тянут мышкой за маркер, изменяющий положение узла</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">Kind</span> <span class="sy0">==</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddLines</span><span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> gp<span class="sy0">.</span><span class="me1">PathPoints</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> i <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>markerIndex<span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>i <span class="sy0">&gt;=</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>i <span class="sy0">&lt;</span> ps<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">+=</span> offset<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">+=</span> offset<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DrawCustomFigure<span class="br0">&#40;</span>graphics, ps, figure<span class="sy0">.</span><span class="me1">Kind</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="sy0">....</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>При помощи методов класса GraphicsPath сначала мы рисуем все точки фигуры, потом в строке 15 получаем массив точек<br />
пути, в строке 16 нормируем индекс узла (чтобы он был положительным числом и начинался с нуля), небольшая защита<br />
в строке 17, индекс i должен быть в диапазоне массива, а элемент массива ps[i] - это и есть та узловая точка, которую<br />
пользователь &quot;тащит&quot; мышкой. Поэтому смещаем только её. Метод DrawCustomFigure() рисует будущую фигуру.<br />
<br />
Фиксация новой формы фигуры производится в методе ContainerMouseUp():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="956784009"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="956784009" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw4">void</span> ContainerMouseUp<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">....</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>NodeChanging <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>MarkerIndex <span class="sy0">&lt;</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> _selected<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="co1">// тянут за маркер узла</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> fig <span class="sy0">=</span> _selected<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UpdateSize<span class="br0">&#40;</span>fig, _mouseOffset, MarkerIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">....</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В строке 6 получаем ссылку на одну единственную фигуру и вызываем для неё метод UpdateSize(), в котором:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="692785403"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="692785403" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> <span class="kw4">void</span> UpdateSize<span class="br0">&#40;</span>Figure fig, PointF offset, <span class="kw4">int</span> marker<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; PointF<span class="br0">&#91;</span><span class="br0">&#93;</span> pts<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp;<span class="sy0">....</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>NodeChanging <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>marker <span class="sy0">&lt;</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// перемещение узлов</span>
&nbsp; &nbsp; &nbsp; &nbsp; pts <span class="sy0">=</span> fig<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> index <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>marker<span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>index <span class="sy0">&gt;=</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>index <span class="sy0">&lt;</span> pts<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>index<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">+=</span> offset<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>index<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">+=</span> offset<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fig<span class="sy0">.</span><span class="me1">SetPoints</span><span class="br0">&#40;</span>pts<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В общем тоже самое что и в методе для рисования DrawFocusFigure(), только в строке 14 мы возвращаем все точки,<br />
вместе с одной изменённой обратно в массив точек фигуры методом fig.SetPoints(pts).<br />
<br />
Про перемещение узловых точек я рассказал. Но можно также добавлять новые точки на сторонах фигуры, делая её сложнее.<br />
Для этого имеется метод AddNode():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="916323999"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="916323999" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод добавления нового узла на выбранный сегмент линии</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> AddNode<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_selected<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">!=</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> figure <span class="sy0">=</span> _selected<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> pts <span class="sy0">=</span> <span class="kw3">new</span> PointF<span class="br0">&#91;</span>ps<span class="sy0">.</span><span class="me1">Length</span> <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; ps<span class="sy0">.</span><span class="me1">CopyTo</span><span class="br0">&#40;</span>pts, <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// замыкание контура фигуры</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span>pts<span class="sy0">.</span><span class="me1">Length</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> pts<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span>pts<span class="sy0">.</span><span class="me1">Length</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> pts<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> pts<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// поиск сегмента линии, куда бы можно добавить новый узел</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>PointInRange<span class="br0">&#40;</span>figure, MouseDownLocation, pts<span class="br0">&#91;</span>i <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span>, pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">continue</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span><span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; points<span class="sy0">.</span><span class="me1">Insert</span><span class="br0">&#40;</span>i, MouseDownLocation<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; figure<span class="sy0">.</span><span class="me1">SetPoints</span><span class="br0">&#40;</span>points<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Новый узел мы можем добавить только на какой-нибудь стороне фигуры, то есть на отрезке между двумя вершинами (узлами).<br />
Для этого в строке 17 мы вызываем метод PointInRange() последовательно для каждых двух соседних точек и проверяем<br />
попадание координат мышки в область отрезка с некоторым допуском.<br />
<br />
Таким образом, если попытаться добавить новый узел, кликнув на середине фигуры, то место для новой точки не будет <br />
найдено. В строке 19 мы вставляем новую точку с координатами MouseDownLocation между индексами i-1 и i, а потом <br />
&quot;заливаем&quot; все точки обратно в массив точек фигуры.<br />
<br />
Удаление узловой точки (вершины) фигуры. Для удаления узла имеется соответствующий метод  RemoveNode(markerIndex):<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="332958122"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="332958122" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод удаления выбранного маркера</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;markerIndex&quot;&gt;индекс маркера для удаления&lt;/param&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> RemoveNode<span class="br0">&#40;</span><span class="kw4">int</span> markerIndex <span class="sy0">=</span> <span class="nu0">0</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_selected<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">!=</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>markerIndex <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; markerIndex <span class="sy0">=</span> MarkerIndex<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> figure <span class="sy0">=</span> _selected<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>ps<span class="sy0">.</span><span class="me1">Length</span> <span class="sy0">&lt;=</span> <span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">Kind</span> <span class="sy0">==</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span> <span class="sy0">?</span> <span class="nu0">3</span> <span class="sy0">:</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">||</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span>markerIndex <span class="sy0">&gt;=</span> ps<span class="sy0">.</span><span class="me1">Length</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span><span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; points<span class="sy0">.</span><span class="me1">RemoveAt</span><span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>markerIndex<span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; figure<span class="sy0">.</span><span class="me1">SetPoints</span><span class="br0">&#40;</span>points<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>По индексу ищется элемент массива и удаляется. Перед удалением проверяется количество оставшихся точек фигуры.<br />
Если фигура замкнутая, то минимум точек у неё - три, а если линия, то минимум - две точки.<br />
<br />
Вот всё, что я хотел пояснить по поводу изменения узловых точек (вершин) фигуры.<br />
<br />
В следующей статье мы будем, наконец, применять наши классы в деле.<br />
<br />
Для этого я подготовил некую &quot;оболочку&quot;:<br />
<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=5083&amp;d=1542040611" rel="Lightbox" id="attachment5083" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=5083&amp;thumb=1&amp;d=1542040611" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: Скриншот рабочей версии.jpg
Просмотров: 1003
Размер:	132.8 Кб
ID:	5083" style="margin: 5px" /></a><br />
<br />
 До скорого!</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5530.html</guid>
		</item>
		<item>
			<title>Шаг 5 (графический векторный редактор). Изменение размеров фигур</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5528.html</link>
			<pubDate>Sun, 11 Nov 2018 16:41:39 GMT</pubDate>
			<description>Продолжаем, мои верные читатели, строительство простого векторного графического редактора. 
Сегодня...</description>
			<content:encoded><![CDATA[<div>Продолжаем, мои верные читатели, строительство простого векторного графического редактора.<br />
Сегодня у нас на очереди рассмотрение темы:<br />
<br />
<u>3. Изменение размеров фигур.</u><br />
<br />
[APLACE=&quot;Правила нумерации маркеров&quot;]Размеры фигур будем изменять при помощи маркеров размеров, которые появляются вокруг фигуры, когда мы выбираем её<br />
мышкой. Всего размерных маркеров восемь. Четыре по углам охватывающего прямоугольника, и ещё четыре - на серединах<br />
сторон этого прямоугольника. Маркеры размеров имеют квадратную форму и нумеруются числами от 1 по 8, начиная с левого<br />
верхнего угла и далее по ходу часовой стрелки.<br />
<br />
Также потом мы будем рассматривать маркеры узлов, которые в обычном режиме не рисуются и не обслуживаются. Маркеры<br />
узлов имеют круглую форму и нумеруются отрицательным значениями, начиная с -1 для первой узловой точки и так далее.<br />
Точек узлов может быть много и максимальная граница не рассматривается. Когда приходит время обработки узловых точек,<br />
берётся модуль значения индекса и вычитается единица. Таким образом получаем индекс в массиве точек, и, соответственно,<br />
доступ к изменению координат узлов.[/APLACE]<br />
<br />
Для расчёта положения <i>размерных</i> маркеров создан метод GetBoundMarkers():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="740651143"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="740651143" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод строит восемь маркеров на углах и серединах сторон</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;rect&quot;&gt;размерный прямоугольник&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;Возвращает перечисление из маркеров для изменения размера&lt;/returns&gt;</span>
<span class="kw1">private</span> <span class="kw1">static</span> IEnumerable<span class="sy0">&lt;</span>RectangleF<span class="sy0">&gt;</span> GetBoundMarkers<span class="br0">&#40;</span>RectangleF rect<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">&lt;=</span> <span class="nu0">10</span><span class="br0">&#41;</span> rect<span class="sy0">.</span><span class="me1">Inflate</span><span class="br0">&#40;</span><span class="nu0">5</span>, <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">&lt;=</span> <span class="nu0">10</span><span class="br0">&#41;</span> rect<span class="sy0">.</span><span class="me1">Inflate</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">5</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> pts <span class="sy0">=</span> <span class="kw3">new</span> PointF<span class="br0">&#91;</span><span class="nu0">8</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Left</span><span class="sy0">;</span> pts<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Top</span><span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">*</span> 0<span class="sy0">.</span>5f<span class="sy0">;</span> pts<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Top</span><span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Right</span><span class="sy0">;</span> pts<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Top</span><span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Right</span><span class="sy0">;</span> pts<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Top</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">*</span> 0<span class="sy0">.</span>5f<span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Right</span><span class="sy0">;</span> pts<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Bottom</span><span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span><span class="nu0">5</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">*</span> 0<span class="sy0">.</span>5f<span class="sy0">;</span> pts<span class="br0">&#91;</span><span class="nu0">5</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Bottom</span><span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span><span class="nu0">6</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Left</span><span class="sy0">;</span> pts<span class="br0">&#91;</span><span class="nu0">6</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Bottom</span><span class="sy0">;</span>
&nbsp; &nbsp; pts<span class="br0">&#91;</span><span class="nu0">7</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Left</span><span class="sy0">;</span> pts<span class="br0">&#91;</span><span class="nu0">7</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> rect<span class="sy0">.</span><span class="me1">Top</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">*</span> 0<span class="sy0">.</span>5F<span class="sy0">;</span>
&nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Inflate</span><span class="br0">&#40;</span><span class="sy0">-</span><span class="nu0">5</span>, <span class="sy0">-</span><span class="nu0">5</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> rects <span class="sy0">=</span> <span class="kw3">new</span> RectangleF<span class="br0">&#91;</span>pts<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> pts<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> k<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">&lt;=</span> <span class="nu0">5</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>i <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="br0">&#40;</span>i <span class="sy0">==</span> <span class="nu0">5</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; k <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">&lt;=</span> <span class="nu0">5</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>i <span class="sy0">==</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="br0">&#40;</span>i <span class="sy0">==</span> <span class="nu0">7</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; k <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; k <span class="sy0">=</span> <span class="nu0">3</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="sy0">=</span> RectangleF<span class="sy0">.</span><span class="me1">FromLTRB</span><span class="br0">&#40;</span>pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-</span> k, pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-</span> k,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">+</span> k, pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">+</span> k<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> rects<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>На входе передаётся охватывающий фигуру прямоугольник, потом создаётся массив из восьми ячеек, который заполняется<br />
центрами будущих маркеров размера. Затем создаётся массив прямоугольников с растяжкой от центров в три точки для<br />
обычных размеров и в оду точку, если фигура так мала, что маркер размера её будет закрывать. Для маленьких размеров<br />
сторон маркеры на середине сторон вообще не рисуются. Метод RectangleF.FromLTRB() создаёт прямоугольник по двум<br />
точкам главной диагонали.<br />
<br />
Рассмотренный выше метод GetBoundMarkers() используется в методе рисования ContainerPaint() выбранных фигур и в<br />
методе MarkerSelected(), который проверяет попадание &quot;мышиного&quot; указателя на маркер размера:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="504773344"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="504773344" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Поиск номера маркера в разных режимах редактора</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;pt&quot;&gt;точка &quot;нажатия&quot; мышки&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;figure&quot;&gt;проверяемая фигура&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;индекс маркера&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw4">int</span><span class="sy0">?</span> MarkerSelected<span class="br0">&#40;</span>PointF pt, Figure figure<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>NodeChanging<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// в режиме изменения узлов</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> rects <span class="sy0">=</span> GetNodeMarkers<span class="br0">&#40;</span>figure<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> rects<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Contains</span><span class="br0">&#40;</span>pt<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="sy0">-</span><span class="br0">&#40;</span>i <span class="sy0">+</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// в режиме изменения размеров или перемещения</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> bounds <span class="sy0">=</span> figure<span class="sy0">.</span><span class="me1">GetBounds</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> rects <span class="sy0">=</span> GetBoundMarkers<span class="br0">&#40;</span>bounds<span class="br0">&#41;</span><span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> rects<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Contains</span><span class="br0">&#40;</span>pt<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> i <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">null</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Как видно из кода - применяется метод RectangleF.Contains() для поиска попадания координат точки в координаты<br />
прямоугольника маркера. Если совпадение случилось, то возвращаем индекс маркера согласно [ALINK=&quot;Правила нумерации маркеров&quot;]правилу нумерации маркеров[/ALINK] размера и узлов.<br />
<br />
Метод MarkerSelected(), через метод PointInMarker(), используется в обработчиках нажатия и перемещения мыши над<br />
поверхностью контейнера и при вызове контекстного меню:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="727266502"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="727266502" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Проверка нажатия на маркер в фигуре</span>
<span class="co1">/// положительные индексы - это маркеры размеров,</span>
<span class="co1">/// отрицательные - маркеры узлов,</span>
<span class="co1">/// ноль - тело фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;location&quot;&gt;точка выбора&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;figure&quot;&gt;указатель на фигуру&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;индекс маркера&lt;/returns&gt;</span>
<span class="kw1">private</span> <span class="kw4">int</span> PointInMarker<span class="br0">&#40;</span>PointF location, <span class="kw1">out</span> Figure figure<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; figure <span class="sy0">=</span> <span class="kw1">null</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// проверка нажатия на маркерах</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> _selected<span class="sy0">.</span><span class="me1">Count</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="sy0">;</span> i <span class="sy0">&gt;=</span> <span class="nu0">0</span><span class="sy0">;</span> i<span class="sy0">--</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// смотрим на выбранные фигуры, начиная с хвоста списка</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> fig <span class="sy0">=</span> _selected<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> found <span class="sy0">=</span> MarkerSelected<span class="br0">&#40;</span>location, fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>found <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span> <span class="kw1">continue</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; figure <span class="sy0">=</span> fig<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>found<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Нужно подчеркнуть, что проверка попадания курсора в маркер начинается с конца списка хранения фигур  _selected,<br />
так как по способу рисования наиболее &quot;верхние&quot; фигуры рисуются последними. Метод PointInMarker() возвращает<br />
индекс маркера или ноль, а также ссылку на фигуру в параметре <b>out Figure figure</b>, если мышка попала на маркер.<br />
Основное назначение метода PointInMarker() - поиск маркера. Если маркера не найдено, то фигура далее ищется методом<br />
PointInFigure(e.Location).<br />
<br />
Если маркер размера обнаружен, то его значение запоминается в контекстном свойстве MarkerIndex, также, как и величина<br />
смещения мышки _mouseOffset. И оба эти значения служат для расчета будущего размера фигуры в методе DrawFocusFigure():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="581457239"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="581457239" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw1">static</span> <span class="kw4">void</span> DrawFocusFigure<span class="br0">&#40;</span>Figure figure, Graphics graphics, PointF offset,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> markerIndex, <span class="kw4">bool</span> nodeChanging<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="sy0">....</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nodeChanging <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>markerIndex <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// тянут за размерный маркер</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> oldrect <span class="sy0">=</span> CalcFocusRect<span class="br0">&#40;</span><span class="kw3">new</span> PointF<span class="br0">&#40;</span><span class="br0">&#41;</span>, figure, markerIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> newrect <span class="sy0">=</span> CalcFocusRect<span class="br0">&#40;</span>offset, figure, markerIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> ps<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> newrect<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">+</span> <span class="br0">&#40;</span>ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-</span> oldrect<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span> <span class="sy0">/</span> oldrect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">*</span> newrect<span class="sy0">.</span><span class="me1">Width</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> newrect<span class="sy0">.</span><span class="me1">Top</span> <span class="sy0">+</span> <span class="br0">&#40;</span>ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-</span> oldrect<span class="sy0">.</span><span class="me1">Top</span><span class="br0">&#41;</span> <span class="sy0">/</span> oldrect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">*</span> newrect<span class="sy0">.</span><span class="me1">Height</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; DrawCustomFigure<span class="br0">&#40;</span>graphics, ps, figure<span class="sy0">.</span><span class="me1">Kind</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Фиксация новых размеров фигуры происходит в методе обработки события ContainerMouseUp():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="683834906"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="683834906" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw4">void</span> ContainerMouseUp<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// если мышь была захвачена</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_container<span class="sy0">.</span><span class="me1">Capture</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// освобождаем захват мышки</span>
&nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Capture</span> <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если нажата левая кнопка</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>EditorMode<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// перетаскивание выбранных фигур &quot;мышкой&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> EditorMode<span class="sy0">.</span><span class="me1">Dragging</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">....</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>NodeChanging <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>MarkerIndex <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="co1">// тянут за размерный маркер</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// перебираем все выделенные фигуры и меняем размер</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> fig <span class="kw1">in</span> _selected<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UpdateSize<span class="br0">&#40;</span>fig, _mouseOffset, MarkerIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">....</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">....</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В методе UpdateSize(), выполняемом для каждой выбранной фигуры, происходит следующее:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="263788670"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="263788670" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Изменение внутреннего массива точек фигуры при работе с маркерами</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;fig&quot;&gt;объект фигуры&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;offset&quot;&gt;смещение&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;marker&quot;&gt;индекс маркера&lt;/param&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> UpdateSize<span class="br0">&#40;</span>Figure fig, PointF offset, <span class="kw4">int</span> marker<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; PointF<span class="br0">&#91;</span><span class="br0">&#93;</span> pts<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>NodeChanging <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>marker <span class="sy0">&gt;</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// перемещение границ</span>
&nbsp; &nbsp; &nbsp; &nbsp; pts <span class="sy0">=</span> fig<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> oldrect <span class="sy0">=</span> CalcFocusRect<span class="br0">&#40;</span>PointF<span class="sy0">.</span><span class="me1">Empty</span>, fig, marker<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> newrect <span class="sy0">=</span> CalcFocusRect<span class="br0">&#40;</span>offset, fig, marker<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> pts<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> newrect<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">+</span> <span class="br0">&#40;</span>pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-</span> oldrect<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span> <span class="sy0">/</span> oldrect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">*</span> newrect<span class="sy0">.</span><span class="me1">Width</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> newrect<span class="sy0">.</span><span class="me1">Top</span> <span class="sy0">+</span> <span class="br0">&#40;</span>pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-</span> oldrect<span class="sy0">.</span><span class="me1">Top</span><span class="br0">&#41;</span> <span class="sy0">/</span> oldrect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">*</span> newrect<span class="sy0">.</span><span class="me1">Height</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; fig<span class="sy0">.</span><span class="me1">SetPoints</span><span class="br0">&#40;</span>pts<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>NodeChanging <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>marker <span class="sy0">&lt;</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// перемещение узлов</span>
&nbsp; &nbsp; &nbsp; &nbsp; pts <span class="sy0">=</span> fig<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> index <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>marker<span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>index <span class="sy0">&gt;=</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>index <span class="sy0">&lt;</span> pts<span class="sy0">.</span><span class="me1">Length</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>index<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">+=</span> offset<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>index<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">+=</span> offset<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fig<span class="sy0">.</span><span class="me1">SetPoints</span><span class="br0">&#40;</span>pts<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Для перерасчёта координат точек, из которых состоит фигура, в строках 14 и 15 мы получаем прямоугольники без смещения и<br />
с учётом смещения, которые вычисляются при помощи метода CalcFocusRect(). Далее в цикле, в строках 18 и 19, каждая<br />
координата точки пропорционально смещается относительно нового размера стороны нового прямоугольника. То есть,<br />
если фигура расширяется, то все точки, которые распределены по фигуре, также равномерно растянутся. Тоже касается и<br />
высоты фигуры. Если высота уменьшается, то и внутренние точки будут ближе друг к другу.<br />
<br />
Вот вся информация про изменение размеров фигур. В следующей статье немного остановимся на маркерах изменения узлов<br />
и об алгоритме выбора узлов, добавления новых узлов и удалении существующих.<br />
<br />
До скорого!</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5528.html</guid>
		</item>
		<item>
			<title>Шаг четвёртый (графический векторный редактор). Перемещение фигур</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5525.html</link>
			<pubDate>Sat, 10 Nov 2018 14:14:35 GMT</pubDate>
			<description>Итак, мои уважаемые читатели, я продолжаю рассматривать животрепещущую тему строительства...</description>
			<content:encoded><![CDATA[<div>Итак, мои уважаемые читатели, я продолжаю рассматривать животрепещущую тему строительства <i>самолепного</i>,<br />
простого векторного графического редактора.<br />
<br />
<u>2. Перемещение фигур</u><br />
<br />
Для перемещения фигур у нас пока задействована только мышка и мы будем рассматривать взаимодействие пользователя<br />
с фигурами через события _container.MouseDown, _container.MouseMove и _container.MouseUp. Я об этом не упоминал ранее,<br />
а теперь скажу, что имеется конструктор класса Picture, в котором и производится привязка событий контейнера к нашим<br />
обработчикам событий:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="700510833"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="700510833" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> Picture<span class="br0">&#40;</span>Control container<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; _container <span class="sy0">=</span> container<span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// подключаемся к необходимым событиям на контейнере</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseDown</span> <span class="sy0">+=</span> ContainerMouseDown<span class="sy0">;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseMove</span> <span class="sy0">+=</span> ContainerMouseMove<span class="sy0">;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseUp</span> <span class="sy0">+=</span> ContainerMouseUp<span class="sy0">;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Paint</span> <span class="sy0">+=</span> ContainerPaint<span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// подключаем объект выбора рамкой</span>
&nbsp; &nbsp; _ribbonSelector <span class="sy0">=</span> <span class="kw3">new</span> RectangleRibbonSelector<span class="br0">&#40;</span>_container<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; _ribbonSelector<span class="sy0">.</span><span class="me1">OnSelected</span> <span class="sy0">+=</span> RibbonSelectorOnSelected<span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// а здесь пробуем найти ссылку на форму, на которой расположен PaintBox</span>
&nbsp; &nbsp; <span class="kw1">var</span> parent <span class="sy0">=</span> _container<span class="sy0">.</span><span class="me1">Parent</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// пока не найдём форму или пустой Parent</span>
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="br0">&#40;</span>parent <span class="kw3">is</span> Form<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>parent <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span> <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; parent <span class="sy0">=</span> parent<span class="sy0">.</span><span class="me1">Parent</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; _form <span class="sy0">=</span> parent <span class="kw1">as</span> Form<span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// если найдена форма</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_form <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// то подключим к ней обработчик нажатия клавиш</span>
&nbsp; &nbsp; &nbsp; &nbsp; _form<span class="sy0">.</span><span class="me1">KeyDown</span> <span class="sy0">+=</span> FormKeyDown<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _form<span class="sy0">.</span><span class="me1">KeyUp</span> <span class="sy0">+=</span> FormKeyUp<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// включим признак предварительного просмотра нажатия клавиш</span>
&nbsp; &nbsp; &nbsp; &nbsp; _form<span class="sy0">.</span><span class="me1">KeyPreview</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="co1">// при изменении выбора выключаем режим изменения узлов</span>
&nbsp; &nbsp; _selected<span class="sy0">.</span><span class="me1">CollectionChanged</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>sender, args<span class="br0">&#41;</span> <span class="sy0">=&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NodeChanging <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В строках с 5 по 8 подключаем в цепочку вызовов собственные обработчики событий на нажатие кнопок мышки и<br />
её перемещение, а также обработчик события рисования на канве контейнера.<br />
В строках 10 и 11 создаём объект для выбора рамкой и подключаем ему обработчик события:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Обработчик события завершение выбора прямоугольником</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="24252074"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="24252074" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Обработчик события завершение выбора прямоугольником</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;</span>
<span class="kw4">void</span> RibbonSelectorOnSelected<span class="br0">&#40;</span><span class="kw4">object</span> sender, RibbonSelectedEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>EditorMode <span class="sy0">!=</span> EditorMode<span class="sy0">.</span><span class="me1">Selection</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// нормализация параметров для прямоугольника выбора</span>
&nbsp; &nbsp; <span class="kw1">var</span> rect <span class="sy0">=</span> e<span class="sy0">.</span><span class="me1">RectangleSelected</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// добавляем все фигуры, которые оказались охваченными прямоугольником выбора</span>
&nbsp; &nbsp; <span class="co1">// в список выбранных фигур</span>
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> fig <span class="kw1">in</span> _figures<span class="sy0">.</span><span class="kw1">Where</span><span class="br0">&#40;</span>fig <span class="sy0">=&gt;</span> rect<span class="sy0">.</span><span class="me1">Contains</span><span class="br0">&#40;</span>Rectangle<span class="sy0">.</span><span class="me1">Ceiling</span><span class="br0">&#40;</span>fig<span class="sy0">.</span><span class="me1">GetBounds</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _selected<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>fig<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
В строках с 13 по 20 пробуем среди череды предков (Parent) найти компонент типа Form, у которого имеются<br />
события нажатия клавиш на клавиатуре _form.KeyDown и _form.KeyUp, к которым мы также подключаем<br />
собственные обработчики событий в строках 25 и 26  для сохранения состояния управляющей клавиши Ctrl,<br />
и которое используется в алгоритме множественного выбора фигур.<br />
В строке 28 мы включаем у контейнерной формы режим пред-просмотра нажатия клавиш на контролах формы.<br />
Вот эти обработчики: <br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Обработчики событий нажатия клавиш клавиатуры</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="801325548"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="801325548" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Во внешней форме нажата клавиша</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> FormKeyDown<span class="br0">&#40;</span><span class="kw4">object</span> sender, KeyEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// проверяем нажатие Ctrl</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Control</span><span class="br0">&#41;</span> _controlPressed <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Во внешней форме отпущена клавиша</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> FormKeyUp<span class="br0">&#40;</span><span class="kw4">object</span> sender, KeyEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// проверяем отпускание Ctrl</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>e<span class="sy0">.</span><span class="me1">Control</span><span class="br0">&#41;</span> _controlPressed <span class="sy0">=</span> <span class="kw1">false</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
В строках с 31 по 34 мы программируем событие изменения списка выбора, где сбрасывается режим изменения узлов<br />
NodeChanging.<br />
<br />
При выборе фигур мышкой они попадают в список выбранных, точка нажатия запоминается в переменной _mouseDownLocation,<br />
а переменная смещения координат мышки _mouseOffset относительно  _mouseDownLocation - обнуляется.<br />
Если была нажата левая кнопка мышки, то производится захват мышки контейнером <b>_container.Capture = true;</b> <br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="723062877"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="723062877" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Нажатие кнопки &quot;мышки&quot; на PaintBox</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> ContainerMouseDown<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// запоминаем точку первую точку для прямоугольника выбора</span>
&nbsp; &nbsp; _mouseDownLocation <span class="sy0">=</span> e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">;</span>
&nbsp; &nbsp; _mouseOffset <span class="sy0">=</span> Point<span class="sy0">.</span><span class="me1">Empty</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// если установлен другой режим, кроме выбора прямоугольником</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>EditorMode <span class="sy0">!=</span> EditorMode<span class="sy0">.</span><span class="me1">Selection</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _selected<span class="sy0">.</span><span class="me1">Clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> &nbsp; <span class="co1">// очищаем список выбранных</span>
&nbsp;
&nbsp; &nbsp; Figure fig<span class="sy0">;</span>
&nbsp; &nbsp; _markerIndex <span class="sy0">=</span> PointInMarker<span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Location</span>, <span class="kw1">out</span> fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// ищем фигуру в точке нажатия</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>fig <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span> fig <span class="sy0">=</span> PointInFigure<span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Location</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Capture</span> <span class="sy0">=</span> <span class="kw1">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">...</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Когда пользователь &quot;тащит&quot; фигуру мышкой, левая кнопка удерживается нажатой и при этом пересчитывается величина<br />
смещения курсора мышки относительно точки первоначального нажатия в переменной _mouseOffset.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="707636123"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="707636123" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Перемещение мышки над PaintBox</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> ContainerMouseMove<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_mouseDownLocation <span class="sy0">==</span> e<span class="sy0">.</span><span class="me1">Location</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// если удерживается левая кнопка и мышка захвачена</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">&amp;&amp;</span> _container<span class="sy0">.</span><span class="me1">Capture</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// пересчитываем смещение мышки</span>
&nbsp; &nbsp; &nbsp; &nbsp; _mouseOffset<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> e<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-</span> _mouseDownLocation<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _mouseOffset<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> e<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-</span> _mouseDownLocation<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// просим перерисовать</span>
&nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">!=</span> MouseButtons<span class="sy0">.</span><span class="me1">None</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">...</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Когда мы просим _container.Invalidate(), то в событии ContainerPaint для всех выбранных фигур<br />
вызывается метод DrawFocusFigure():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="968686029"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="968686029" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw4">void</span> ContainerPaint<span class="br0">&#40;</span><span class="kw4">object</span> sender, PaintEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="sy0">...</span>
&nbsp; &nbsp; <span class="co1">// при перетаскивании</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>EditorMode <span class="sy0">!=</span> EditorMode<span class="sy0">.</span><span class="me1">Dragging</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> fig <span class="kw1">in</span> _selected<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; DrawFocusFigure<span class="br0">&#40;</span>fig, e<span class="sy0">.</span><span class="me1">Graphics</span>, _mouseOffset, _markerIndex, NodeChanging<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В методе DrawFocusFigure() при перетаскивании фигуры происходит следующее:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="367294905"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="367294905" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="de1"><pre class="de1"><span class="sy0">....</span>
<span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">Kind</span> <span class="sy0">==</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// добавляем в полигон все точки фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddLines</span><span class="br0">&#40;</span>figure<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// получаем графический путь</span>
&nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> gp<span class="sy0">.</span><span class="me1">PathPoints</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// для всех точек пути</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> ps<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// делаем смещение</span>
&nbsp; &nbsp; &nbsp; &nbsp; ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">+=</span> offset<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">+=</span> offset<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; DrawCustomFigure<span class="br0">&#40;</span>graphics, ps, figure<span class="sy0">.</span><span class="me1">Kind</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="sy0">....</span></pre></td></tr></table></div></td></tr></tbody></table></div>По точкам фигуры строится графический путь (строки 4-8), из этого пути берётся реальный массив точек для рисования (строка 10) и<br />
в цикле всем точкам передаётся текущее смещение мышки на данный момент (строки 12-17), ну а метод DrawCustomFigure()<br />
просто рисует фигуру по точкам, пунктиром, на новом месте.<br />
<br />
То есть <i>реального</i> перемещения фигур в событии ContainerMouseMove не делается, а только показывается их будущее положение.<br />
<br />
Фиксация фигур на новых местах происходит при обработке события ContainerMouseUp().<br />
Когда перетаскивание фигур заканчивается, то для всех выбранных фигур (из списка _selected) выполняется метод UpdateLocation(fig, _mouseOffset),<br />
который фиксирует положение фигур на новом месте:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="904350167"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="904350167" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Перемещение фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;fig&quot;&gt;объект фигуры&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;offset&quot;&gt;смещение&lt;/param&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> UpdateLocation<span class="br0">&#40;</span>Figure fig, PointF offset<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// перемещение фигуры</span>
&nbsp; &nbsp; <span class="kw1">var</span> pts <span class="sy0">=</span> fig<span class="sy0">.</span><span class="me1">GetPoints</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> oldrect <span class="sy0">=</span> CalcFocusRect<span class="br0">&#40;</span>PointF<span class="sy0">.</span><span class="me1">Empty</span>, fig, <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> newrect <span class="sy0">=</span> CalcFocusRect<span class="br0">&#40;</span>offset, fig, <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> pts<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> newrect<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">+</span> <span class="br0">&#40;</span>pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-</span> oldrect<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> newrect<span class="sy0">.</span><span class="me1">Top</span> <span class="sy0">+</span> <span class="br0">&#40;</span>pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-</span> oldrect<span class="sy0">.</span><span class="me1">Top</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; fig<span class="sy0">.</span><span class="me1">SetPoints</span><span class="br0">&#40;</span>pts<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В стоке 9 все точки фигуры собираются в массив, затем при помощи метода CalcFocusRect() по этому массиву точек<br />
строятся два охватывающего прямоугольника, и в цикле для всех точек производится коррекция положения.<br />
В строке 17 массив точек заливается обратно в фигуру.<br />
<br />
Так фигура у нас перемещается на новое место.<br />
<br />
Я всё думаю о том, что такая модель хранения абсолютных координат точек в фигуре не совсем хороша.<br />
Как-то не по феншую... Было бы лучше хранить не самые координаты точек, а их смешения относительно некой одной<br />
точки (Origin) и алгоритм рисования делать исходя из этого. Тогда достаточно было бы смещать координаты только одной<br />
этой точки, не трогая остальной массив.<br />
С другой стороны, при изменении размеров фигуры пересчёт координат всех точек производить бы пришлось...<br />
<br />
С перемещением фигур также закончили.<br />
Но, чем дальше, тем интереснее: нас ждут изменение размеров и изменение узловых точек. <br />
<br />
До встречи!</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5525.html</guid>
		</item>
		<item>
			<title>Шаг третий (графический векторный редактор). Тестовая расстановка фигур</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5522.html</link>
			<pubDate>Fri, 09 Nov 2018 15:45:16 GMT</pubDate>
			<description>Некоторые изменения я внёс в названия свойств классов Stroke и Fill (чисто косметические, благо это...</description>
			<content:encoded><![CDATA[<div>Некоторые изменения я внёс в названия свойств классов Stroke и Fill (чисто косметические, благо это не продакшен).<br />
В классе Figure удалил этот ужасно некрасивый метод OneBuff(), а метод PointInFigure, где он использовался, теперь выглядит<br />
следующим образом (спасибо <b>Storm23</b> за подсказку):<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="320345820"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="320345820" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод проверяет принадлежность точки фигуре</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;point&quot;&gt;проверяемая точка&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;True - точка принадлежит фигуре&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">virtual</span> Boolean PointInFigure<span class="br0">&#40;</span>PointF point<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>Kind<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>gp<span class="sy0">.</span><span class="me1">IsVisible</span><span class="br0">&#40;</span>point<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> DrawingKind<span class="sy0">.</span><span class="me1">Polyline</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> ps<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">StartFigure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddLine</span><span class="br0">&#40;</span>ps<span class="br0">&#91;</span>i <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span>, ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">CloseFigure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> pen <span class="sy0">=</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span>, Stroke<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">*</span> 5f<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> gp<span class="sy0">.</span><span class="me1">IsOutlineVisible</span><span class="br0">&#40;</span>point, pen<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">false</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Далее упрощать классы Stroke, Fill и Figure пока не буду, главным образом из-за того, что при<br />
записи в xml-файл, настройки для карандаша и кисти будут в отдельных ветках и это будет очень гармонично смотреться.<br />
<br />
Да, и ещё я сделал класс Figure не абстрактным и не буду создавать от него потомков типа Polygon и Polyline,<br />
а буду пользоваться свойством Kind. В этом есть своё удобство, в том плане, что можно легко переходить от полигона<br />
к полилинии и обратно, меняя это свойство.<br />
<br />
Но всё же переходим к написанию класса <b>Picture</b> (или PictureEditor ?), пусть это будет его рабочее название.<br />
<br />
<u>Что я хочу, чтобы делал этот класс? </u><ol style="list-style-type: decimal"><li>Размещение фигур</li>
<li>Перемещение фигур</li>
<li>Изменение размеров</li>
<li>Изменение узлов</li>
<li>и ещё много чего хочу, но не всё сразу...</li>
</ol><br />
Ну, первое - это хранение элементов Figure. Будет два списка, первый:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="55458330"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="55458330" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co1">// список созданных фигур</span>
<span class="kw1">private</span> <span class="kw1">readonly</span> List<span class="sy0">&lt;</span>Figure<span class="sy0">&gt;</span> _figures <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>Figure<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В нём будем хранить все нарисованные фигуры. Порядок расположения фигур в этом списке определяет, как фигуры<br />
будут накладываться друг на друга. Сначала рисуется первая фигура (с индексом 0), потом вторая, при этом последующие<br />
фигуры могут частично или полностью закрывать ранее нарисованные.<br />
А вот когда мы кликаем на них мышкой, то выбираться будут сначала фигуры, которые нарисованы позже всех.<br />
В &quot;умных&quot; книжках это называется z-ордером.<br />
<br />
Второй список будет хранить выбранные элементы. Это подмножество первого списка, но тип его мы возьмём другой,<br />
более удобный в плане оповещения об изменениях в списке выбранных элементов:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="83780922"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="83780922" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co1">// список выбранных фигур</span>
<span class="kw1">private</span> <span class="kw1">readonly</span> ObservableCollection<span class="sy0">&lt;</span>Figure<span class="sy0">&gt;</span> _selected <span class="sy0">=</span> <span class="kw3">new</span> ObservableCollection<span class="sy0">&lt;</span>Figure<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Выбор элементов делается мышкой, кликая по ним; можно выбрать несколько, делая выбор рамкой (которую в первом шаге делали).<br />
Можно выбирать фигуры или исключать из уже выбранных, кликая мышкой с удерживанием клавиши Ctrl на клавиатуре.<br />
Во всех этих случаях список выбора _selected будет изменяться, а при его изменении мы будем сбрасывать режим работы<br />
редактора в обычный - для выбора фигур и изменения их размеров.<br />
<br />
Специальный режим работы редактора - изменение положение узлов одной выбранной фигуры.<br />
Режим работы с маркерами: &quot;обычный&quot; и &quot;режим изменения узлов&quot;, и переключается при помощи свойства:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="527180016"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="527180016" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Режим выбора и перетаскивания узловых точек (изменения узлов)</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">bool</span> NodeChanging <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В режиме изменения узлов можно перетаскивать угловые точки у прямоугольника или концы простых отрезков линий,<br />
а также добавлять новые узловые точки, превращая четырёхугольник в пятиугольник или простой отрезок линии в<br />
ломанную, состоящую из двух сегментов. Узлы также можно удалять и оставлять не менее двух для линий и не менее<br />
трёх - для полигонов.<br />
<br />
С точки зрения перетаскивания фигур &quot;мышкой&quot; или изменения их размеров, создано свойство EditorMode:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="306603580"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="306603580" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Режим работы редактора</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> EditorMode EditorMode
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _editorMode<span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _editorMode <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// выбор рамкой запрещён во всех режимах, кроме EditorMode.Selection</span>
&nbsp; &nbsp; &nbsp; &nbsp; _ribbonSelector<span class="sy0">.</span><span class="me1">Disabled</span> <span class="sy0">=</span> _editorMode <span class="sy0">!=</span> EditorMode<span class="sy0">.</span><span class="me1">Selection</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Тип свойства EditorMode - это перечисление и объявлено как:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="457587571"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="457587571" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Режимы редактора</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">enum</span> EditorMode
<span class="br0">&#123;</span>
&nbsp; &nbsp; Selection,
&nbsp; &nbsp; Dragging
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Когда режим редактора установлен в EditorMode.Selection, то мы выбираем фигуры или группы фигур. Когда режим редактора EditorMode.Dragging - мы тащим либо фигуры<br />
(или группы фигур) целиком или изменяем их размер (при помощи маркеров).<br />
<br />
<u>1. Размещение фигур</u><br />
<br />
Для текущей стадии разработки редактора необходимо уже размещать фигуру и тренироваться на ней. Поэтому, чтобы<br />
особо не заморачивать вам голову (повторюсь: только на этой стадии тестирования!) добавлять фигуры будем прямо из<br />
кода этого редактора, используя контекстное меню, которое будем создавать &quot;на лету&quot;.<br />
<br />
В обработчике нажатия правой кнопки &quot;мышки&quot; запишем:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="46272391"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="46272391" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Нажатие кнопки &quot;мышки&quot; на PaintBox</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> ContainerMouseDown<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="sy0">...</span>
&nbsp; &nbsp;
&nbsp; &nbsp; <span class="co1">// если нажата правая кнопка мышки</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">!=</span> MouseButtons<span class="sy0">.</span><span class="me1">Right</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// переключаем режим на выбор рамкой</span>
&nbsp; &nbsp; EditorMode <span class="sy0">=</span> EditorMode<span class="sy0">.</span><span class="me1">Selection</span><span class="sy0">;</span>
&nbsp; &nbsp; ShowContextMenu<span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Location</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">...</span> 
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В методе ShowContextMenu() создаются пункты контекстного меню для создания тестовых фигур:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="482871053"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="482871053" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Вызов контекстного меню</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;location&quot;&gt;точка вызова контекстного меню&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> ShowContextMenu<span class="br0">&#40;</span>Point location<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; _contextMenuStrip<span class="sy0">.</span><span class="me1">Items</span><span class="sy0">.</span><span class="me1">Clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; Figure fig<span class="sy0">;</span>
&nbsp; &nbsp; PointInMarker<span class="br0">&#40;</span>location, <span class="kw1">out</span> fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// ищем фигуру в точке нажатия</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>fig <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; fig <span class="sy0">=</span> PointInFigure<span class="br0">&#40;</span>location<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// есть ли фигура под курсором мышки?</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>fig <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span> <span class="co1">// это не фигура, показываем общее меню</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// создаём пункт меню</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> miRectangle <span class="sy0">=</span> <span class="kw3">new</span> ToolStripMenuItem<span class="br0">&#40;</span><span class="st0">&quot;Добавить фигуру&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// подключаем обработчик</span>
&nbsp; &nbsp; &nbsp; &nbsp; miRectangle<span class="sy0">.</span><span class="me1">Click</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, args<span class="br0">&#41;</span> <span class="sy0">=&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> rect <span class="sy0">=</span> RectangleF<span class="sy0">.</span><span class="me1">FromLTRB</span><span class="br0">&#40;</span>location<span class="sy0">.</span><span class="me1">X</span>, location<span class="sy0">.</span><span class="me1">Y</span>,location<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">+</span> <span class="nu0">50</span>, location<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">+</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> PointF<span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Left</span>, rect<span class="sy0">.</span><span class="me1">Top</span><span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> PointF<span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Width</span>, rect<span class="sy0">.</span><span class="me1">Top</span><span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> PointF<span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Width</span>, rect<span class="sy0">.</span><span class="me1">Top</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Height</span><span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> PointF<span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Left</span>, rect<span class="sy0">.</span><span class="me1">Top</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Height</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fig <span class="sy0">=</span> <span class="kw3">new</span> Figure<span class="br0">&#40;</span>DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _figures<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _selected<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// и добавляем его к меню</span>
&nbsp; &nbsp; &nbsp; &nbsp; _contextMenuStrip<span class="sy0">.</span><span class="me1">Items</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>miRectangle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// создаём пункт меню</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> miLine <span class="sy0">=</span> <span class="kw3">new</span> ToolStripMenuItem<span class="br0">&#40;</span><span class="st0">&quot;Добавить линию&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// подключаем обработчик</span>
&nbsp; &nbsp; &nbsp; &nbsp; miLine<span class="sy0">.</span><span class="me1">Click</span> <span class="sy0">+=</span> <span class="br0">&#40;</span>o, args<span class="br0">&#41;</span> <span class="sy0">=&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> rect <span class="sy0">=</span> RectangleF<span class="sy0">.</span><span class="me1">FromLTRB</span><span class="br0">&#40;</span>location<span class="sy0">.</span><span class="me1">X</span>, location<span class="sy0">.</span><span class="me1">Y</span>, location<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">+</span> <span class="nu0">50</span>, location<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">+</span> <span class="nu0">50</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> PointF<span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Left</span>, rect<span class="sy0">.</span><span class="me1">Top</span><span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">new</span> PointF<span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Left</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Width</span>, rect<span class="sy0">.</span><span class="me1">Top</span> <span class="sy0">+</span> rect<span class="sy0">.</span><span class="me1">Height</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fig <span class="sy0">=</span> <span class="kw3">new</span> Figure<span class="br0">&#40;</span>DrawingKind<span class="sy0">.</span><span class="me1">Polyline</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _figures<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _selected<span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// и добавляем его к меню</span>
&nbsp; &nbsp; &nbsp; &nbsp; _contextMenuStrip<span class="sy0">.</span><span class="me1">Items</span><span class="sy0">.</span><span class="kw1">Add</span><span class="br0">&#40;</span>miLine<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// показываем контекстное меню</span>
&nbsp; &nbsp; _contextMenuStrip<span class="sy0">.</span><span class="me1">Show</span><span class="br0">&#40;</span>_container, location<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В этом методе, если пользователь нажимает правую кнопку &quot;мышки&quot; вне созданных фигур, то контекстное меню<br />
очищается (строка 7), потом проверяется, было ли нажатие на маркере (строка 9), если было, переменная fig будет<br />
содержать ссылку на фигуру, у которой нажато на маркер. Если переменная fig пуста, то проверяется нажатие<br />
на теле фигуры, в строках 11, 12. В строке 14 убеждаемся, что нажатие на фигурах не было и поэтому показываем<br />
общее меню.<br />
<br />
В строках с 17 по 35 создаём пункт меню для создания полигона, в строках с 37 по 54 создаём пункт меню для создания<br />
полилинии. Обработчики, подключаемые здесь же, содержат код, создающий массивы из 4-х точек для полигона и из 2-х<br />
точек для линии. Размер по умолчанию фигур - 50х50 пикселей, а положение - где пользователь клинул мышкой (это верхний<br />
левый угол контекстного меню).<br />
<br />
Потом создаётся объект Figure, с указанием типа фигуры и передаются ему в конструктор точки массива.<br />
Созданная фигура добавляется в основной список _figures и сразу в список выбранных _selected.<br />
В конце вызывается метод _container.Invalidate() с требованием о перерисовке поверхности контейнера. <br />
То есть выполняется метод ContainerPaint, приведу его код целиком:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="661647632"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="661647632" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Обработчик события рисования на поверхности контейнера</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством Graphics&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> ContainerPaint<span class="br0">&#40;</span><span class="kw4">object</span> sender, PaintEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// рисуем все созданные фигуры</span>
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> fig <span class="kw1">in</span> _figures<span class="br0">&#41;</span> fig<span class="sy0">.</span><span class="me1">DrawFigure</span><span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Graphics</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>EditorMode <span class="sy0">!=</span> EditorMode<span class="sy0">.</span><span class="me1">Dragging</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>NodeChanging<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// маркеры узлов рисуем круглыми</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> fig <span class="kw1">in</span> _selected<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> rects <span class="sy0">=</span> GetNodeMarkers<span class="br0">&#40;</span>fig<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> t <span class="kw1">in</span> rects<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddEllipse</span><span class="br0">&#40;</span>t<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e<span class="sy0">.</span><span class="me1">Graphics</span><span class="sy0">.</span><span class="me1">FillPath</span><span class="br0">&#40;</span>Brushes<span class="sy0">.</span><span class="me1">White</span>, gp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> pen <span class="sy0">=</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pen<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e<span class="sy0">.</span><span class="me1">Graphics</span><span class="sy0">.</span><span class="me1">DrawPath</span><span class="br0">&#40;</span>pen, gp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// рисуем маркеры размеров у выбранных фигур</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> fig <span class="kw1">in</span> _selected<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> sizeMarkers <span class="sy0">=</span> GetBoundMarkers<span class="br0">&#40;</span>fig<span class="sy0">.</span><span class="me1">GetBounds</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> t <span class="kw1">in</span> sizeMarkers<span class="sy0">.</span><span class="kw1">Where</span><span class="br0">&#40;</span>t <span class="sy0">=&gt;</span> t<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">&gt;</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddRectangle</span><span class="br0">&#40;</span>t<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e<span class="sy0">.</span><span class="me1">Graphics</span><span class="sy0">.</span><span class="me1">FillPath</span><span class="br0">&#40;</span>Brushes<span class="sy0">.</span><span class="me1">White</span>, gp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> pen <span class="sy0">=</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pen<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e<span class="sy0">.</span><span class="me1">Graphics</span><span class="sy0">.</span><span class="me1">DrawPath</span><span class="br0">&#40;</span>pen, gp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="co1">// при перетаскивании</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>EditorMode <span class="sy0">!=</span> EditorMode<span class="sy0">.</span><span class="me1">Dragging</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="kw1">var</span> fig <span class="kw1">in</span> _selected<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; DrawFocusFigure<span class="br0">&#40;</span>fig, e<span class="sy0">.</span><span class="me1">Graphics</span>, _mouseOffset, _markerIndex, NodeChanging<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Посмотрим, что здесь для чего. В строке 9 у всех созданных фигур по порядку вызывается метод DrawFigure(e.Graphics).<br />
Напомню, что там:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="227638079"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="227638079" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод рисования фигуры по точкам базового списка</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;graphics&quot;&gt;&quot;холст&quot; - объект для рисования&lt;/param&gt;</span>
<span class="kw1">public</span> <span class="kw1">virtual</span> <span class="kw4">void</span> DrawFigure<span class="br0">&#40;</span>Graphics graphics<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> Points<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Kind <span class="sy0">==</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// заливаем фон кистью</span>
&nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">FillPolygon</span><span class="br0">&#40;</span>Fill<span class="sy0">.</span><span class="me1">Brush</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// рисуем контур карандашом</span>
&nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawPolygon</span><span class="br0">&#40;</span>Stroke<span class="sy0">.</span><span class="me1">Pen</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// рисуем контур карандашом</span>
&nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawLines</span><span class="br0">&#40;</span>Stroke<span class="sy0">.</span><span class="me1">Pen</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
Здесь мы рисуем либо полигон, либо набор линий, в зависимости от настройки свойства Kind фигуры.<br />
В строках с 10 по 50 мы рисуем маркеры на выбранных фигурах. Маркеры квадратные, по углам и на серединах<br />
сторон, если специальный режим NodeChanging не включен (обычный режим для изменения размеров фигур <br />
при помощи маркеров) и маркеры круглые, если включен режим NodeChanging изменения узлов. В этом режиме<br />
мы можем менять положения узловых точек фигуры, настраивая её форму как нам вздумается.<br />
<br />
В строках 53,54 для всех выбранных фигур вызывается метод DrawFocusFigure(), который будет вызываться при<br />
начале &quot;перетаскивания&quot; маркеров, показывая будущую форму фигуры пунктирной линией.<br />
Код метода DrawFocusFigure() будем разбирать, когда будем рассматривать пункт 3. Изменение размеров.<br />
<br />
С размещением всё. Не будем нагружать более эту статью.<br />
Ну а для нетерпеливых кладу полный код класса сюда: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=5082&amp;d=1541777934" >Stroke_Fill_Figure_Picture.zip</a><br />
<br />
Продолжение следует...</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5522.html</guid>
		</item>
		<item>
			<title>Шаг второй (работа над ошибками)</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5520.html</link>
			<pubDate>Thu, 08 Nov 2018 07:37:54 GMT</pubDate>
			<description>Благодаря замечаниям в комментариях к статье от Storm23, я внёс необходимые исправления в код...</description>
			<content:encoded><![CDATA[<div>Благодаря замечаниям в комментариях к статье от <b>Storm23</b>, я внёс необходимые исправления в код классов <b>Stroke</b> и<b> Fill</b>,<br />
а также немного переработал код класса <b>Drawing</b>, который переименован в <b>Figure</b>.<br />
<br />
<u>Изменения в классе Stroke:</u><br />
<br />
Оставлен один конструктор, без параметров, в котором создаётся закрытое поле Pen _pen, которое используется<br />
в геттерах/сеттерах свойств.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="569471148"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="569471148" style="height: 174px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw1">readonly</span> Pen _pen<span class="sy0">;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Конструктор без параметров, со свойствами по умолчанию</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; _pen <span class="sy0">=</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В класс добавлена поддержка интерфейса IDisposable, а также добавлен деструктор класса<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="980873513"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="980873513" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Деструктор объекта</span>
<span class="co1">/// &lt;/summary&gt;</span>
~Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Реализация интерфейса IDisposable</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_pen <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span> _pen<span class="sy0">.</span><span class="me1">Dispose</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Свойства класса Stroke теперь выглядят так:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="623127579"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="623127579" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Цвет линии фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Color Color
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Ширина линии фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Single Width
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">Width</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль линии фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> DashStyle DashStyle
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">DashStyle</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Яркость:</span>
<span class="co1">/// 0 - полностью прозрачный,</span>
<span class="co1">/// 255 - полноцветный</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">int</span> Alpha
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">.</span><span class="me1">A</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span><span class="kw1">value</span>, _pen<span class="sy0">.</span><span class="me1">Color</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль начала линии</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> LineCap StartCap
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">StartCap</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">StartCap</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль конца линии</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> LineCap EndCap
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">EndCap</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">EndCap</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль соединения двух отрезков линии</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> LineJoin LineJoin
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">LineJoin</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">LineJoin</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Метод Pen() заменён свойством для чтения GetPen и сильно упрощён:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="39722789"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="39722789" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Свойство возвращает &quot;карандаш&quot;, настроенный по текущим свойствам stroke</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Pen GetPen
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div><u>Изменения в классе Fill:</u><br />
<br />
Оставлен один конструктор, без параметров, в котором создаётся закрытое поле SolidBrush _brush, которое используется<br />
в геттерах/сеттерах свойств.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="131493956"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="131493956" style="height: 174px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
</pre></td><td class="de1"><pre class="de1"><span class="kw1">private</span> <span class="kw1">readonly</span> SolidBrush _brush<span class="sy0">;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Конструктор без параметров, с цветом по умолчанию</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; _brush <span class="sy0">=</span> <span class="kw3">new</span> SolidBrush<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">White</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В класс добавлена поддержка интерфейса IDisposable, а также добавлен деструктор класса<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="534757789"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="534757789" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Деструктор объекта</span>
<span class="co1">/// &lt;/summary&gt;</span>
~Fill<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Реализация интерфейса IDisposable</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_brush <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span> _brush<span class="sy0">.</span><span class="me1">Dispose</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Свойства класса Fill теперь выглядят так:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="846985813"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="846985813" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Цвет заливки</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Color Color
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _brush<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _brush<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Яркость:</span>
<span class="co1">/// 0 - полностью прозрачный,</span>
<span class="co1">/// 255 - полноцветный</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">int</span> Alpha
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _brush<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">.</span><span class="me1">A</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _brush<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span><span class="kw1">value</span>, _brush<span class="sy0">.</span><span class="me1">Color</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Я решил убрать поддержку других кистей, кроме SolidBrush. На данном этапе излишняя функциональность пока не нужна.<br />
<br />
Метод Brush() заменён свойством для чтения GetBrush и сильно упрощён:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="729385175"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="729385175" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Свойство возвращает &quot;кисть&quot;, настроенный по текущим свойствам fill</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;returns&gt;Настроенная кисть для заполнения контура фигуры&lt;/returns&gt;</span>
<span class="kw1">public</span> Brush GetBrush
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _brush<span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div><u>Изменения в классе Figure (теперь будет вместо Drawing):</u><br />
<br />
Оставлен один безпараметрический конструктор, в котором создаются два объекта-спутника:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="287428344"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="287428344" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// &nbsp;Конструктор без параметра с настройкой по умолчанию</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">protected</span> Figure<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Stroke <span class="sy0">=</span> <span class="kw3">new</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; Fill <span class="sy0">=</span> <span class="kw3">new</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Изменён метод рисования, согласно изменениям в классах Stroke и Fill:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="288937394"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="288937394" style="height: 222px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод рисования фигуры по точкам базового списка</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;graphics&quot;&gt;&quot;холст&quot; - объект для рисования&lt;/param&gt;</span>
<span class="kw1">public</span> <span class="kw1">virtual</span> <span class="kw4">void</span> DrawFigure<span class="br0">&#40;</span>Graphics graphics<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> Points<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// заливаем фон кистью</span>
&nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">FillPolygon</span><span class="br0">&#40;</span>Fill<span class="sy0">.</span><span class="me1">GetBrush</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// рисуем контур карандашом</span>
&nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawPolygon</span><span class="br0">&#40;</span>Stroke<span class="sy0">.</span><span class="me1">GetPen</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Полный код классов Stroke, Fill и Figure здесь:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <br />
Класс Stroke<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="805430013"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="805430013" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing.Drawing2D</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SimpleVectorGraphicsEditor
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Описание класса хранения свойств для рисования контура фигуры</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="br0">&#91;</span>Serializable<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> Stroke<span class="sy0">:</span> IDisposable
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">readonly</span> Pen _pen<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Конструктор без параметров, со свойствами по умолчанию</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _pen <span class="sy0">=</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Деструктор объекта</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; ~Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Цвет линии фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Color Color
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Ширина линии фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Single Width
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">Width</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль линии фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> DashStyle DashStyle
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">DashStyle</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Яркость:</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// 0 - полностью прозрачный,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// 255 - полноцветный</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> Alpha
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">.</span><span class="me1">A</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span><span class="kw1">value</span>, _pen<span class="sy0">.</span><span class="me1">Color</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль начала линии</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> LineCap StartCap
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">StartCap</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">StartCap</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль конца линии</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> LineCap EndCap
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">EndCap</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">EndCap</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль соединения двух отрезков линии</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> LineJoin LineJoin
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">.</span><span class="me1">LineJoin</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _pen<span class="sy0">.</span><span class="me1">LineJoin</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Свойство возвращает &quot;карандаш&quot;, настроенный по текущим свойствам stroke</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Pen GetPen
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _pen<span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Реализация интерфейса IDisposable</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_pen <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span> _pen<span class="sy0">.</span><span class="me1">Dispose</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Класс Fill<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="144902274"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="144902274" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SimpleVectorGraphicsEditor
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Описание класса хранения свойств для закрашивания поверхности фигуры</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="br0">&#91;</span>Serializable<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> Fill <span class="sy0">:</span> IDisposable
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">readonly</span> SolidBrush _brush<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Конструктор без параметров, с цветом по умолчанию</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _brush <span class="sy0">=</span> <span class="kw3">new</span> SolidBrush<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">White</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Деструктор объекта</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; ~Fill<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Цвет заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Color Color
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _brush<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _brush<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Яркость:</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// 0 - полностью прозрачный,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// 255 - полноцветный</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> Alpha
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _brush<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">.</span><span class="me1">A</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span> <span class="br0">&#123;</span> _brush<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span><span class="kw1">value</span>, _brush<span class="sy0">.</span><span class="me1">Color</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Свойство возвращает &quot;кисть&quot;, настроенный по текущим свойствам fill</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;Настроенная кисть для заполнения контура фигуры&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Brush GetBrush
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span> <span class="br0">&#123;</span> <span class="kw1">return</span> _brush<span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Реализация интерфейса IDisposable</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Dispose<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_brush <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span> _brush<span class="sy0">.</span><span class="me1">Dispose</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Класс Figure<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="446106969"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="446106969" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Collections.Generic</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing.Drawing2D</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SimpleVectorGraphicsEditor
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">enum</span> DrawingKind
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Polygon,
&nbsp; &nbsp; &nbsp; &nbsp; Polyline
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Описание класса базовой фигуры </span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="br0">&#91;</span>Serializable<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">abstract</span> <span class="kw4">class</span> Figure
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// контейнер для хранения точек фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw1">readonly</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span> Points <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &nbsp;Конструктор без параметра с настройкой по умолчанию</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> Figure<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Stroke <span class="sy0">=</span> <span class="kw3">new</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Fill <span class="sy0">=</span> <span class="kw3">new</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Свойство определяющее вид фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> DrawingKind Kind <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Базовая точка, обычно левый верхний угол прямоугольника,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// описывающего фигуру</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> PointF Location <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Размер фигуры, ширина и высота прямоугольника,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// описывающего фигуру</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> SizeF Size <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Прямоугольник, описывающий фигуру</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> RectangleF BoundsRect
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">new</span> RectangleF<span class="br0">&#40;</span>Location, Size<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Карандаш для рисования контура фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Stroke Stroke <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Кисть для заливки контура фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Fill Fill <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод рисования фигуры по точкам базового списка</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;graphics&quot;&gt;&quot;холст&quot; - объект для рисования&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> <span class="kw4">void</span> DrawFigure<span class="br0">&#40;</span>Graphics graphics<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> Points<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// заливаем фон кистью</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">FillPolygon</span><span class="br0">&#40;</span>Fill<span class="sy0">.</span><span class="me1">GetBrush</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// рисуем контур карандашом</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawPolygon</span><span class="br0">&#40;</span>Stroke<span class="sy0">.</span><span class="me1">GetPen</span>, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод проверяет принадлежность точки фигуре</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;point&quot;&gt;проверяемая точка&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;True - точка принадлежит фигуре&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> Boolean PointInFigure<span class="br0">&#40;</span>PointF point<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>Kind<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>gp<span class="sy0">.</span><span class="me1">IsVisible</span><span class="br0">&#40;</span>point<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> DrawingKind<span class="sy0">.</span><span class="me1">Polyline</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> ps<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">StartFigure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>Onebuff<span class="br0">&#40;</span>ps<span class="br0">&#91;</span>i <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span>, ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">CloseFigure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>gp<span class="sy0">.</span><span class="me1">IsVisible</span><span class="br0">&#40;</span>point<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Вспомогательный метод, строит прямоугольник на перпендикулярах</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// на концах отрезка между двух точек</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;p1&quot;&gt;первая точка&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;p2&quot;&gt;вторая точка&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;массив точек четырёхугольника, охватывающего отрезок&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> PointF<span class="br0">&#91;</span><span class="br0">&#93;</span> Onebuff<span class="br0">&#40;</span>PointF p1, PointF p2<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> selWidth <span class="sy0">=</span> Stroke<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">*</span> 0<span class="sy0">.</span>5F<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>selWidth <span class="sy0">&lt;</span> 4F<span class="br0">&#41;</span> <span class="sy0">||</span> <span class="br0">&#40;</span>Stroke<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">==</span> DashStyle<span class="sy0">.</span><span class="me1">Custom</span><span class="br0">&#41;</span><span class="br0">&#41;</span> selWidth <span class="sy0">=</span> 4F<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> x1 <span class="sy0">=</span> p1<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> y1 <span class="sy0">=</span> p1<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> x2 <span class="sy0">=</span> p2<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> y2 <span class="sy0">=</span> p2<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> k <span class="sy0">=</span> <span class="br0">&#40;</span>y2 <span class="sy0">-</span> y1<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="br0">&#40;</span>x2 <span class="sy0">-</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> fi1 <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span><span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Atan</span><span class="br0">&#40;</span>k<span class="br0">&#41;</span> <span class="sy0">+</span> Math<span class="sy0">.</span><span class="me1">PI</span> <span class="sy0">*</span> <span class="nu0">0.5</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> fi2 <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span><span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Atan</span><span class="br0">&#40;</span>k<span class="br0">&#41;</span> <span class="sy0">-</span> Math<span class="sy0">.</span><span class="me1">PI</span> <span class="sy0">*</span> <span class="nu0">0.5</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> buff <span class="sy0">=</span> <span class="kw3">new</span> PointF<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> x2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> y2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> x2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> y2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>buff<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Свойство возвращает реальный прямоугольник, охватывающий точки фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> RectangleF GetBounds
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> rect <span class="sy0">=</span> gp<span class="sy0">.</span><span class="me1">GetBounds</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если фигура очень узкая по горизонтали</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">-</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="kw4">float</span><span class="sy0">.</span><span class="me1">Epsilon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-=</span> <span class="nu0">2</span><span class="sy0">;</span> 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если фигура очень узкая по вертикали</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">-</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="kw4">float</span><span class="sy0">.</span><span class="me1">Epsilon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-=</span> <span class="nu0">2</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>rect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод возвращает массив точек фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;Массив, копия списка точек фигуры&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> PointF<span class="br0">&#91;</span><span class="br0">&#93;</span> GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// возвращает массив точек линии</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> <span class="kw3">new</span> PointF<span class="br0">&#91;</span>Points<span class="sy0">.</span><span class="me1">Count</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Points<span class="sy0">.</span><span class="me1">CopyTo</span><span class="br0">&#40;</span>ps<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>ps<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
На следующем шаге я планировал описать класс DrawingEditor, который всё таки будет назван <b>Picture</b>,<br />
в котором будут применены все наши наработки на этот момент и который будет управлять размещением и размерами потомков базового класса <b>Figure</b>.<br />
<br />
Будем, наконец, двигать фигурами и изменять их размер мышкой при помощи маркеров.</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5520.html</guid>
		</item>
		<item>
			<title>Шаг второй (продолжение). Спутники базового класса.</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5516.html</link>
			<pubDate>Wed, 07 Nov 2018 11:07:19 GMT</pubDate>
			<description>Продолжаем разрабатывать простой векторный графический редактор. 
Я обещал подробно разобрать...</description>
			<content:encoded><![CDATA[<div>Продолжаем разрабатывать простой векторный графический редактор.<br />
Я обещал подробно разобрать классы для хранения настроек рисования <b>Stroke</b> и <b>Fill</b>, так теперь приступим:<br />
<br />
Начнём с класса попроще.<br />
Класс <b>Stroke</b> предназначен для хранения и предоставления базовому классу Drawing информации о том, как<br />
рисовать линию контура замкнутой фигуры или саму линию фигуры не замкнутой.<br />
Конструкторы класса Stroke выглядят так:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="356589481"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="356589481" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Конструктор без параметров, со свойствами по умолчанию</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">:</span> <span class="kw1">this</span><span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span>, 1<span class="sy0">.</span>0F<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Конструктор с параметрами</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;color&quot;&gt;Цвет линии&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;width&quot;&gt;Ширина линии&lt;/param&gt;</span>
<span class="kw1">public</span> Stroke<span class="br0">&#40;</span>Color color, Single width<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Color <span class="sy0">=</span> color<span class="sy0">;</span>
&nbsp; &nbsp; Width <span class="sy0">=</span> width<span class="sy0">;</span>
&nbsp; &nbsp; DashStyle <span class="sy0">=</span> DashStyle<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">;</span>
&nbsp; &nbsp; Alpha <span class="sy0">=</span> <span class="nu0">255</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Первый конструктор без параметров, создает объект Stroke с настройками по умолчанию, как то:<br />
цвет линии чёрный, толщиной в 1 единицу.<br />
<br />
Второй конструктор имеет два параметра, позволяющие задать при создании объекта два наиболее используемых<br />
свойства - цвет и толщину линии. В конструкторе также задаётся тип линии DashStyle.Solid - сплошная, и значение<br />
для канала яркости максимальное - 255 единиц. Настройка канала яркости позволяет создавать полупрозрачные <br />
границы фигуры, что может понадобиться в некоторых случаях.<br />
<br />
Свойства класса:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="999761278"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="999761278" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Цвет линии фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Color Color <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Ширина линии фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Single Width <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль линии фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> DashStyle DashStyle <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Яркость:</span>
<span class="co1">/// 0 - полностью прозрачный,</span>
<span class="co1">/// 255 - полноцветный</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">int</span> Alpha <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль начала линии</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> LineCap StartCap <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль конца линии</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> LineCap EndCap <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль соединения двух отрезков линии</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> LineJoin LineJoin <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>позволят также настроить тип линии (пунктиром, штрих-пунктиром), тип отображения концов незамкнутых линий,<br />
и тип отображения углов фигуры, что хорошо видно при больших значениях толщины линий.<br />
<br />
Имеется также полезный метод присваивания свойств из другого объекта этого типа:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="839200031"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="839200031" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод присваивания свойств другого stroke</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;stroke&quot;&gt;Источник значений свойств stroke&lt;/param&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> Assign<span class="br0">&#40;</span>Stroke stroke<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>stroke <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; Color <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">;</span>
&nbsp; &nbsp; Width <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">Width</span><span class="sy0">;</span>
&nbsp; &nbsp; DashStyle <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">DashStyle</span><span class="sy0">;</span>
&nbsp; &nbsp; Alpha <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">Alpha</span><span class="sy0">;</span>
&nbsp; &nbsp; LineJoin <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">LineJoin</span><span class="sy0">;</span>
&nbsp; &nbsp; StartCap <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">StartCap</span><span class="sy0">;</span>
&nbsp; &nbsp; EndCap <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">EndCap</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>а для реализации интерфейса ICloneable класс содержит метод Clone(), в котором и используется метод Assing():<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="45836590"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="45836590" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Реализация интерфейса ICloneable</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;returns&gt;Возвращаем копию Stroke&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw4">object</span> Clone<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> stroke <span class="sy0">=</span> <span class="kw3">new</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; stroke<span class="sy0">.</span><span class="me1">Assign</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> stroke<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Когда приходит время воспользоваться преимуществами применения такого класса настройки &quot;карандаша&quot;,<br />
мы будем использовать метод Pen(), который создаёт графический объект класса System.Drawing.Pen и делает ему<br />
все необходимые настройки:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="656500155"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="656500155" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод возвращает &quot;карандаш&quot;, настроенный по текущим свойствам stroke</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Pen Pen<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> pen <span class="sy0">=</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, Color<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> Width,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LineJoin <span class="sy0">=</span> LineJoin,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StartCap <span class="sy0">=</span> StartCap,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EndCap <span class="sy0">=</span> EndCap
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>DashStyle <span class="sy0">==</span> DashStyle<span class="sy0">.</span><span class="me1">Custom</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; pen<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">=</span> DashStyle<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; pen<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> Color<span class="sy0">.</span><span class="me1">Transparent</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; pen<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">=</span> DashStyle<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>pen<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Здесь сразу замечу, что применять такой метод следует при помощи обёртки using, чтобы гарантированно освобождать<br />
системные ресурсы (примерчик):<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="778065566"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="778065566" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="co1">// рисуем контур карандашом</span>
<span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> pen <span class="sy0">=</span> Stroke<span class="sy0">.</span><span class="me1">Pen</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawPolygon</span><span class="br0">&#40;</span>pen, points<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Следующий класс <b>Fill</b> предназначен для хранения и использования настроек при закрашивании поверхности<br />
фигуры с замкнутым контуром.<br />
<br />
Вот конструкторы класса Fill:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="883150861"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="883150861" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Конструктор без параметров, с цветом по умолчанию</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">:</span> <span class="kw1">this</span><span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">White</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Конструктор с параметром</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;color&quot;&gt;Цвет заливки фона&lt;/param&gt;</span>
<span class="kw1">public</span> Fill<span class="br0">&#40;</span>Color color<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Color <span class="sy0">=</span> color<span class="sy0">;</span>
&nbsp; &nbsp; Alpha <span class="sy0">=</span> <span class="nu0">255</span><span class="sy0">;</span>
&nbsp; &nbsp; PatternColor <span class="sy0">=</span> Color<span class="sy0">.</span><span class="me1">Black</span><span class="sy0">;</span>
&nbsp; &nbsp; PatternIndex <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> <span class="co1">// FillMode.Solid;</span>
&nbsp; &nbsp; Mode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">;</span>
&nbsp; &nbsp; HatchMode <span class="sy0">=</span> HatchStyle<span class="sy0">.</span><span class="me1">Percent50</span><span class="sy0">;</span>
&nbsp; &nbsp; LinearMode <span class="sy0">=</span> LinearGradientMode<span class="sy0">.</span><span class="me1">Horizontal</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Тут конструктор без параметров ссылается на второй конструктор с параметром, чтобы настроить основное свойство<br />
фона - цвет фона. Все остальные поля класса настраиваются на часто употребляемые начальные значения.<br />
<br />
Теперь свойства:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="725623214"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="725623214" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Цвет заливки</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Color Color <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Яркость:</span>
<span class="co1">/// 0 - полностью прозрачный,</span>
<span class="co1">/// 255 - полноцветный</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">int</span> Alpha <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Цвет линий при заливке выбранной битовой маской</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Color PatternColor <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль заполнения битовой маской</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> HatchStyle HatchMode <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Стиль заполнения градиентной кистью</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> LinearGradientMode LinearMode <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Поверхность может закрашиваться несколькими способами, для управления этим<br />
служит свойство:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="900185986"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="900185986" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Режим заполнения поверхности фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> FillMode Mode <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>где тип этого свойства FillMode описан как:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="205935995"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="205935995" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Перечисление для типа заполнения</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">enum</span> FillMode
<span class="br0">&#123;</span>
&nbsp; &nbsp; None <span class="sy0">=</span> <span class="nu0">0</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// без заливки</span>
&nbsp; &nbsp; Solid <span class="sy0">=</span> <span class="nu0">1</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// сплошная заливка</span>
&nbsp; &nbsp; Hatch <span class="sy0">=</span> <span class="nu0">2</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// битовая маска из набора</span>
&nbsp; &nbsp; LinearGradient <span class="sy0">=</span> <span class="nu0">3</span> &nbsp;<span class="co1">// линейный градиент</span>
<span class="br0">&#125;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Вот главный (рисующий) метод Brush(), в котором можно посмотреть, как используется свойство Mode:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="348097752"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="348097752" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод возвращает &quot;кисть&quot;, настроенный по текущим свойствам fill</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;rect&quot;&gt;прямоугольная область для заливки градиентом&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;Настроенная кисть для заполнения контура фигуры&lt;/returns&gt;</span>
<span class="kw1">public</span> Brush Brush<span class="br0">&#40;</span>RectangleF rect<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Brush brush <span class="sy0">=</span> <span class="kw1">null</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>Mode<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> FillMode<span class="sy0">.</span><span class="me1">None</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// нет заливки, берём прозрачный цвет</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brush <span class="sy0">=</span> <span class="kw3">new</span> SolidBrush<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Transparent</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> FillMode<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// сплошная заливка, берём цвет и канал яркости</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brush <span class="sy0">=</span> <span class="kw3">new</span> SolidBrush<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, Color<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> FillMode<span class="sy0">.</span><span class="me1">Hatch</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brush <span class="sy0">=</span> <span class="kw3">new</span> HatchBrush<span class="br0">&#40;</span>HatchMode,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, PatternColor<span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, Color<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> FillMode<span class="sy0">.</span><span class="me1">LinearGradient</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brush <span class="sy0">=</span> <span class="kw3">new</span> LinearGradientBrush<span class="br0">&#40;</span>rect, Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, PatternColor<span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, Color<span class="br0">&#41;</span>, LinearMode<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>brush<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Для штриховой заливки используется системная кисть типа HatchBrush, для градиентной заливки<br />
используется системная кисть типа LinearGradientBrush, для простого фона - кисть SolidBrush.<br />
И каждая из кистей требует отдельного свойства для настройки.<br />
<br />
Настраивать кисть, имея столько параметров - не просто. Поэтому, для управления всем этим хозяйством,<br />
создано свойство поддержки индекса типа заливки:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="428621690"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="428621690" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Свойство для настройки fill по индексу шаблона,</span>
<span class="co1">/// применяемого для заливки.</span>
<span class="co1">/// Имена всех шаблонов возвращает метод string[] GetAllPatternNames()</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw4">int</span> PatternIndex
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>_patternIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">set</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _patternIndex <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Mode <span class="sy0">=</span> FillModeFromIndex<span class="br0">&#40;</span>_patternIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; HatchMode <span class="sy0">=</span> HatchStyleFromIndex<span class="br0">&#40;</span>_patternIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; LinearMode <span class="sy0">=</span> LinearGradientModeFromIndex<span class="br0">&#40;</span>_patternIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В этом свойстве принимаемое значение сквозного индекса, раскладывается по индексам, специфическим к<br />
своим кистям. Для пользователя создан вспомогательный метод, возвращающий текстовые названия всех<br />
шаблонов:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="107585797"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="107585797" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод, возвращающий имена всех доступных шаблонов для заливки контура фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;returns&gt;Массив имён шаблонов заливки&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">string</span><span class="br0">&#91;</span><span class="br0">&#93;</span> GetAllPatternNames<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> hatchNameArray <span class="sy0">=</span> <span class="kw4">Enum</span><span class="sy0">.</span><span class="me1">GetNames</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>HatchStyle<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> linearGradientNameArray <span class="sy0">=</span> <span class="kw4">Enum</span><span class="sy0">.</span><span class="me1">GetNames</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>LinearGradientMode<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> n <span class="sy0">=</span> <span class="nu0">2</span> <span class="sy0">+</span> LinearGradientModeCount <span class="sy0">+</span> HatchStyleCount<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> names <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">string</span><span class="br0">&#91;</span>n<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; names<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st0">&quot;Прозрачный&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; names<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st0">&quot;Сплошной&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">2</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> j <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> j <span class="sy0">&lt;</span> LinearGradientModeCount<span class="sy0">;</span> j<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; names<span class="br0">&#91;</span>i<span class="sy0">++</span><span class="br0">&#93;</span> <span class="sy0">=</span> linearGradientNameArray<span class="br0">&#91;</span>j<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> j <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> j <span class="sy0">&lt;</span> HatchStyleCount<span class="sy0">;</span> j<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; names<span class="br0">&#91;</span>i<span class="sy0">++</span><span class="br0">&#93;</span> <span class="sy0">=</span> hatchNameArray<span class="br0">&#91;</span>j<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>names<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Можно заполнить строками этого метода компонент ComboBox на форме редактора и пользователь,<br />
выбирая из списка, будет указывать свойству PatternIndex индекс для настройки по выбранному шаблону:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="303813877"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="303813877" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод определения типа заливки по индексу шаблона заливки</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;тип заполнения&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">static</span> FillMode FillModeFromIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">None</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>IsNonePatternIndex<span class="br0">&#40;</span>index<span class="br0">&#41;</span><span class="br0">&#41;</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">None</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>IsSolidPatternIndex<span class="br0">&#40;</span>index<span class="br0">&#41;</span><span class="br0">&#41;</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>IsLinearGradientPatternIndex<span class="br0">&#40;</span>index<span class="br0">&#41;</span><span class="br0">&#41;</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">LinearGradient</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>IsHatchPatternIndex<span class="br0">&#40;</span>index<span class="br0">&#41;</span><span class="br0">&#41;</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">Hatch</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>fillmode<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Для поддержки градиентной кисти служат следующие методы:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="257463511"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="257463511" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод для вычисления стиля градиентной заливки из индекса шаблона</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;Возвращает стиль градиентной заливки&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">static</span> LinearGradientMode LinearGradientModeFromIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">checked</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>LinearGradientMode<span class="br0">&#41;</span><span class="br0">&#40;</span>index <span class="sy0">-</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Вспомогательный массив со стилями направлений градиентной заливки</span>
<span class="kw1">static</span> <span class="kw1">readonly</span> LinearGradientMode<span class="br0">&#91;</span><span class="br0">&#93;</span> LinearGradientModeArray <span class="sy0">=</span>
&nbsp; &nbsp; <span class="br0">&#40;</span>LinearGradientMode<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="kw4">Enum</span><span class="sy0">.</span><span class="me1">GetValues</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>LinearGradientMode<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Длина вспомогательного массива со стилями направлений градиентной заливки</span>
<span class="kw1">static</span> <span class="kw1">readonly</span> <span class="kw4">int</span> LinearGradientModeCount <span class="sy0">=</span> LinearGradientModeArray<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Для поддержки кисти для битовой (штриховой) заливки служат следующие методы:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="572610113"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="572610113" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод для вычисления стиля битовой заливки</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">static</span> HatchStyle HatchStyleFromIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">checked</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>HatchStyle<span class="br0">&#41;</span><span class="br0">&#40;</span>index <span class="sy0">-</span> <span class="nu0">2</span> <span class="sy0">-</span> LinearGradientModeCount<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод для определения того факта, что применяется битовая заливка</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;True - заливка по битовой маске&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">bool</span> IsHatchPatternIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">checked</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> idx <span class="sy0">=</span> index <span class="sy0">-</span> <span class="nu0">2</span> <span class="sy0">-</span> LinearGradientModeCount<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>idx <span class="sy0">&gt;=</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>idx <span class="sy0">&lt;</span> HatchStyleCount<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Вспомогательный массив со стилями битовой заливки по маске</span>
<span class="kw1">static</span> <span class="kw1">readonly</span> HatchStyle<span class="br0">&#91;</span><span class="br0">&#93;</span> HatchStyleArray <span class="sy0">=</span> <span class="br0">&#40;</span>HatchStyle<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="kw4">Enum</span><span class="sy0">.</span><span class="me1">GetValues</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>HatchStyle<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Длина вспомогательного массива со стилями битовой заливки по маске</span>
<span class="kw1">static</span> <span class="kw1">readonly</span> <span class="kw4">int</span> HatchStyleCount <span class="sy0">=</span> HatchStyleArray<span class="sy0">.</span><span class="me1">Length</span> <span class="sy0">-</span> <span class="nu0">3</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Для поддержки сплошной заливки (наиболее часто используемой) служат следующие методы:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="844348009"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="844348009" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод для определения того факта, что заливка не применяется</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;True - заливки нет&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">bool</span> IsNonePatternIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>index <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод для определения того факта, что применяется сплошная заливка</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;True - сплошная заливка&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">bool</span> IsSolidPatternIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>index <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Ну и на закуску. Два метода для поддержки копирования объектов типа Fill:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="307486642"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="307486642" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод присваивания свойств другого fill</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;fill&quot;&gt;Источник значений свойств fill&lt;/param&gt;</span>
<span class="kw1">public</span> <span class="kw4">void</span> Assign<span class="br0">&#40;</span>Fill fill<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>fill <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; Color <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">;</span>
&nbsp; &nbsp; Alpha <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">Alpha</span><span class="sy0">;</span>
&nbsp; &nbsp; PatternColor <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">PatternColor</span><span class="sy0">;</span>
&nbsp; &nbsp; PatternIndex <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">PatternIndex</span><span class="sy0">;</span>
&nbsp; &nbsp; Mode <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">Mode</span><span class="sy0">;</span>
&nbsp; &nbsp; HatchMode <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">HatchMode</span><span class="sy0">;</span>
&nbsp; &nbsp; LinearMode <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">LinearMode</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Реализация интерфейса ICloneable</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;returns&gt;Возвращаем копию Fill&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw4">object</span> Clone<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> fill <span class="sy0">=</span> <span class="kw3">new</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; fill<span class="sy0">.</span><span class="me1">Assign</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> fill<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Да, что-то многовато материала на этот раз... Но это всё нужно и будет работать на благо построения<br />
нашего простого векторного графического редактора!<br />
<br />
На следующем шаге я планирую описать класс <b>DrawingEditor</b>, в котором будут применены<br />
все наши наработки на этот момент и который будет управлять размещением и размерами потомков базового<br />
класса Drawing. До встречи!</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5516.html</guid>
		</item>
		<item>
			<title>Шаг второй. Базовый класс и его спутники.</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5514.html</link>
			<pubDate>Tue, 06 Nov 2018 16:31:40 GMT</pubDate>
			<description>Наверняка, многие из вас, др*у*ги мои юные программисты, читая про создание векторного редактора с...</description>
			<content:encoded><![CDATA[<div>Наверняка, многие из вас, др<b>у</b>ги мои юные программисты, читая про создание векторного редактора с нуля, <br />
ждут, ну когда же будем наконец что-то рисовать... Терпение, др<b>у</b>ги мои... Всё по порядку и я продолжаю.<br />
<br />
Выбор функционала для базового класса, на котором будут основаны все другие фигуры, уже придуманные и те,<br />
которые ещё будут придуманы, очень важен, поэтому сначала постараюсь изложить, что именно я хочу получить<br />
в краткосрочной перспективе от этого редактора:<ol style="list-style-type: decimal"><li>Базовые возможности, как-то: создание, перемещение и изменение размеров простых геометрических фигур.</li>
<li>Простые трансформации фигур, как-то: повороты на 90°, отражения по горизонтали и вертикали.</li>
<li>Изменение свойств линии контура и свойств заполнения замкнутых фигур.</li>
<li>Было бы здорово делать объединения или вычитания фигур, чтобы получались более сложные фигуры.</li>
</ol>Ну, пока хватит.<br />
Первые три пункта ничего особенного не представляют, а вот четвёртый пункт интересный! <br />
Для операций с фигурами необходим в конечном счёте внутренний массив точек (или узлов), по которым строится фигура.<br />
Для треугольника необходимо три точки, для прямоугольника - четыре, ну и так далее.<br />
<br />
Так вот, задумка в том, чтобы не городить кучу наследников базового класса, типа class Triangle {}, class Rectangle {}.<br />
И сделать пока базовый класс, внутри которого хранится массив точек, ну а количество узлов можно задавать сначала<br />
базовое количество, а потом добавлять по необходимости...<br />
<br />
Теперь, по-поводу пункта три. Необходимо, чтобы настройки свойств контура и заливки были поинтереснее.<br />
<br />
С лирикой пока всё, приступим к практической части:<br />
Создадим абстрактный класс <b>Drawing</b>, который имеет внутренний массив точек и вот два его конструктора:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="34180385"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="34180385" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1"><span class="co1">// контейнер для хранения точек фигуры</span>
<span class="kw1">protected</span> <span class="kw1">readonly</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span> Points <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// &nbsp;Конструктор без параметра с настройкой по умолчанию</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">protected</span> Drawing<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw1">this</span><span class="br0">&#40;</span><span class="kw3">new</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="kw3">new</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Конструктор с параметрами</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;stroke&quot;&gt;Объект настроек карандаша&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;fill&quot;&gt;Объект настроек кисти&lt;/param&gt;</span>
<span class="kw1">protected</span> Drawing<span class="br0">&#40;</span>Stroke stroke, Fill fill<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Stroke <span class="sy0">=</span> stroke<span class="sy0">;</span>
&nbsp; &nbsp; Fill <span class="sy0">=</span> fill<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Почему абстрактный класс? Только для того, чтобы его не создавали для работы, а пользовались его<br />
интерфейсом и базовыми методами. Классы-наследники будут проще и нагляднее.<br />
<br />
Тип точек массива выбран PointF с той перспективой, чтобы делать масштабирование векторных рисунков,<br />
как это сейчас модно, крутнул колёсико мышки на себя и всё стало большое и красивое, крутнул от себя,<br />
и весь рисунок уместился на экране... Ну, это в перспективе, как вы понимаете.<br />
<br />
Вернёмся к конструкторам. Конструктор  параметрами принимает два параметра - объекта, задающих<br />
свойства карандаша и кисти для нашего объекта. Мы пока рассматривать их подробно не будем, ну а кому<br />
очень невтерпёж, то прошу под спойлер:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <br />
Класс для хранения свойств контура фигуры:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="560484587"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="560484587" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing.Drawing2D</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SimpleVectorGraphicsEditor
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Описание класса хранения свойств для рисования контура фигуры</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="br0">&#91;</span>Serializable<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> Stroke<span class="sy0">:</span> ICloneable
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Конструктор без параметров, со свойствами по умолчанию</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">:</span> <span class="kw1">this</span><span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span>, 1<span class="sy0">.</span>0F<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Конструктор с параметрами</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;color&quot;&gt;Цвет линии&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;width&quot;&gt;Ширина линии&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Stroke<span class="br0">&#40;</span>Color color, Single width<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color <span class="sy0">=</span> color<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> width<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DashStyle <span class="sy0">=</span> DashStyle<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Alpha <span class="sy0">=</span> <span class="nu0">255</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Цвет линии фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Color Color <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Ширина линии фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Single Width <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль линии фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> DashStyle DashStyle <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Яркость:</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// 0 - полностью прозрачный,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// 255 - полноцветный</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> Alpha <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль начала линии</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> LineCap StartCap <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль конца линии</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> LineCap EndCap <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль соединения двух отрезков линии</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> LineJoin LineJoin <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод присваивания свойств другого stroke</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;stroke&quot;&gt;Источник значений свойств stroke&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Assign<span class="br0">&#40;</span>Stroke stroke<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>stroke <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">Width</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DashStyle <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">DashStyle</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Alpha <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">Alpha</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LineJoin <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">LineJoin</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StartCap <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">StartCap</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EndCap <span class="sy0">=</span> stroke<span class="sy0">.</span><span class="me1">EndCap</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод возвращает &quot;карандаш&quot;, настроенный по текущим свойствам stroke</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Pen Pen<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> pen <span class="sy0">=</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, Color<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width <span class="sy0">=</span> Width,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LineJoin <span class="sy0">=</span> LineJoin,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StartCap <span class="sy0">=</span> StartCap,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EndCap <span class="sy0">=</span> EndCap
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>DashStyle <span class="sy0">==</span> DashStyle<span class="sy0">.</span><span class="me1">Custom</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pen<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">=</span> DashStyle<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pen<span class="sy0">.</span><span class="me1">Color</span> <span class="sy0">=</span> Color<span class="sy0">.</span><span class="me1">Transparent</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pen<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">=</span> DashStyle<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>pen<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Реализация интерфейса ICloneable</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;Возвращаем копию Stroke&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">object</span> Clone<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> stroke <span class="sy0">=</span> <span class="kw3">new</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stroke<span class="sy0">.</span><span class="me1">Assign</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> stroke<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Класс для хранения свойств заливки поверхности замкнутой фигуры:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="248319696"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="248319696" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing.Drawing2D</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SimpleVectorGraphicsEditor
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Перечисление для типа заполнения</span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">enum</span> FillMode
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; None <span class="sy0">=</span> <span class="nu0">0</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// без заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; Solid <span class="sy0">=</span> <span class="nu0">1</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// сплошная заливка</span>
&nbsp; &nbsp; &nbsp; &nbsp; Hatch <span class="sy0">=</span> <span class="nu0">2</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// битовая маска из набора</span>
&nbsp; &nbsp; &nbsp; &nbsp; LinearGradient <span class="sy0">=</span> <span class="nu0">3</span> &nbsp;<span class="co1">// линейный градиент</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="br0">&#91;</span>Serializable<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> Fill <span class="sy0">:</span> ICloneable
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// индекс шаблона заливки по умолчанию</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">int</span> _patternIndex <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Конструктор без параметров, с цветом по умолчанию</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">:</span> <span class="kw1">this</span><span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">White</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Конструктор с параметром</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;color&quot;&gt;Цвет заливки фона&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Fill<span class="br0">&#40;</span>Color color<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color <span class="sy0">=</span> color<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Alpha <span class="sy0">=</span> <span class="nu0">255</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PatternColor <span class="sy0">=</span> Color<span class="sy0">.</span><span class="me1">Black</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PatternIndex <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> <span class="co1">// FillMode.Solid;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HatchMode <span class="sy0">=</span> HatchStyle<span class="sy0">.</span><span class="me1">Percent50</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LinearMode <span class="sy0">=</span> LinearGradientMode<span class="sy0">.</span><span class="me1">Horizontal</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Цвет заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Color Color <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Яркость:</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// 0 - полностью прозрачный,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// 255 - полноцветный</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> Alpha <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Цвет линий при заливке выбранной битовой маской</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Color PatternColor <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Режим заполнения поверхности фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> FillMode Mode <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль заполнения битовой маской</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> HatchStyle HatchMode <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Стиль заполнения градиентной кистью</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> LinearGradientMode LinearMode <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Свойство для настройки fill по индексу шаблона,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// применяемого для заливки.</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Имена всех шаблонов возвращает метод string[] GetAllPatternNames()</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">int</span> PatternIndex
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>_patternIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">set</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _patternIndex <span class="sy0">=</span> <span class="kw1">value</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mode <span class="sy0">=</span> FillModeFromIndex<span class="br0">&#40;</span>_patternIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HatchMode <span class="sy0">=</span> HatchStyleFromIndex<span class="br0">&#40;</span>_patternIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LinearMode <span class="sy0">=</span> LinearGradientModeFromIndex<span class="br0">&#40;</span>_patternIndex<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод для вычисления стиля градиентной заливки из индекса шаблона</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;Возвращает стиль градиентной заливки&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> LinearGradientMode LinearGradientModeFromIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">checked</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>LinearGradientMode<span class="br0">&#41;</span><span class="br0">&#40;</span>index <span class="sy0">-</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод для вычисления стиля битовой заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> HatchStyle HatchStyleFromIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">checked</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>HatchStyle<span class="br0">&#41;</span><span class="br0">&#40;</span>index <span class="sy0">-</span> <span class="nu0">2</span> <span class="sy0">-</span> LinearGradientModeCount<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод для определения того факта, что заливка не применяется</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;True - заливки нет&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">bool</span> IsNonePatternIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>index <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод для определения того факта, что применяется сплошная заливка</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;True - сплошная заливка&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">bool</span> IsSolidPatternIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>index <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод для определения того факта, что применяется градиентная заливка</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;True - градиентная заливка&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">bool</span> IsLinearGradientPatternIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">checked</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> idx <span class="sy0">=</span> index <span class="sy0">-</span> <span class="nu0">2</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>idx <span class="sy0">&gt;=</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>idx <span class="sy0">&lt;</span> LinearGradientModeCount<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод для определения того факта, что применяется битовая заливка</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;True - заливка по битовой маске&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">bool</span> IsHatchPatternIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">checked</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> idx <span class="sy0">=</span> index <span class="sy0">-</span> <span class="nu0">2</span> <span class="sy0">-</span> LinearGradientModeCount<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>idx <span class="sy0">&gt;=</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="br0">&#40;</span>idx <span class="sy0">&lt;</span> HatchStyleCount<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Вспомогательный массив со стилями направлений градиентной заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">static</span> <span class="kw1">readonly</span> LinearGradientMode<span class="br0">&#91;</span><span class="br0">&#93;</span> LinearGradientModeArray <span class="sy0">=</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span>LinearGradientMode<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="kw4">Enum</span><span class="sy0">.</span><span class="me1">GetValues</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>LinearGradientMode<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Длина вспомогательного массива со стилями направлений градиентной заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">static</span> <span class="kw1">readonly</span> <span class="kw4">int</span> LinearGradientModeCount <span class="sy0">=</span> LinearGradientModeArray<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Вспомогательный массив со стилями битовой заливки по маске</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">static</span> <span class="kw1">readonly</span> HatchStyle<span class="br0">&#91;</span><span class="br0">&#93;</span> HatchStyleArray <span class="sy0">=</span> <span class="br0">&#40;</span>HatchStyle<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="kw4">Enum</span><span class="sy0">.</span><span class="me1">GetValues</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>HatchStyle<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Длина вспомогательного массива со стилями битовой заливки по маске</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">static</span> <span class="kw1">readonly</span> <span class="kw4">int</span> HatchStyleCount <span class="sy0">=</span> HatchStyleArray<span class="sy0">.</span><span class="me1">Length</span> <span class="sy0">-</span> <span class="nu0">3</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод определения типа заливки по индексу шаблона заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;index&quot;&gt;применяемый индекс шаблона заливки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;тип заполнения&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> FillMode FillModeFromIndex<span class="br0">&#40;</span><span class="kw4">int</span> index<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">None</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>IsNonePatternIndex<span class="br0">&#40;</span>index<span class="br0">&#41;</span><span class="br0">&#41;</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">None</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>IsSolidPatternIndex<span class="br0">&#40;</span>index<span class="br0">&#41;</span><span class="br0">&#41;</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>IsLinearGradientPatternIndex<span class="br0">&#40;</span>index<span class="br0">&#41;</span><span class="br0">&#41;</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">LinearGradient</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>IsHatchPatternIndex<span class="br0">&#40;</span>index<span class="br0">&#41;</span><span class="br0">&#41;</span> fillmode <span class="sy0">=</span> FillMode<span class="sy0">.</span><span class="me1">Hatch</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>fillmode<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод возвращает &quot;кисть&quot;, настроенный по текущим свойствам fill</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;rect&quot;&gt;прямоугольная область для заливки градиентом&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;Настроенная кисть для заполнения контура фигуры&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Brush Brush<span class="br0">&#40;</span>RectangleF rect<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Brush brush <span class="sy0">=</span> <span class="kw1">null</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>Mode<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> FillMode<span class="sy0">.</span><span class="me1">None</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// нет заливки, берём прозрачный цвет</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brush <span class="sy0">=</span> <span class="kw3">new</span> SolidBrush<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Transparent</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> FillMode<span class="sy0">.</span><span class="me1">Solid</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// сплошная заливка, берём цвет и канал яркости</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brush <span class="sy0">=</span> <span class="kw3">new</span> SolidBrush<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, Color<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> FillMode<span class="sy0">.</span><span class="me1">Hatch</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brush <span class="sy0">=</span> <span class="kw3">new</span> HatchBrush<span class="br0">&#40;</span>HatchMode,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, PatternColor<span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, Color<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> FillMode<span class="sy0">.</span><span class="me1">LinearGradient</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brush <span class="sy0">=</span> <span class="kw3">new</span> LinearGradientBrush<span class="br0">&#40;</span>rect, Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, PatternColor<span class="br0">&#41;</span>,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color<span class="sy0">.</span><span class="me1">FromArgb</span><span class="br0">&#40;</span>Alpha, Color<span class="br0">&#41;</span>, LinearMode<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>brush<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод, возвращающий имена всех доступных шаблонов для заливки контура фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;Массив имён шаблонов заливки&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">string</span><span class="br0">&#91;</span><span class="br0">&#93;</span> GetAllPatternNames<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> hatchNameArray <span class="sy0">=</span> <span class="kw4">Enum</span><span class="sy0">.</span><span class="me1">GetNames</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>HatchStyle<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> linearGradientNameArray <span class="sy0">=</span> <span class="kw4">Enum</span><span class="sy0">.</span><span class="me1">GetNames</span><span class="br0">&#40;</span><span class="kw3">typeof</span><span class="br0">&#40;</span>LinearGradientMode<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> n <span class="sy0">=</span> <span class="nu0">2</span> <span class="sy0">+</span> LinearGradientModeCount <span class="sy0">+</span> HatchStyleCount<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> names <span class="sy0">=</span> <span class="kw3">new</span> <span class="kw4">string</span><span class="br0">&#91;</span>n<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; names<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st0">&quot;Прозрачный&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; names<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st0">&quot;Сплошной&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">2</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> j <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> j <span class="sy0">&lt;</span> LinearGradientModeCount<span class="sy0">;</span> j<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; names<span class="br0">&#91;</span>i<span class="sy0">++</span><span class="br0">&#93;</span> <span class="sy0">=</span> linearGradientNameArray<span class="br0">&#91;</span>j<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> j <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> j <span class="sy0">&lt;</span> HatchStyleCount<span class="sy0">;</span> j<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; names<span class="br0">&#91;</span>i<span class="sy0">++</span><span class="br0">&#93;</span> <span class="sy0">=</span> hatchNameArray<span class="br0">&#91;</span>j<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>names<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод присваивания свойств другого fill</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;fill&quot;&gt;Источник значений свойств fill&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">void</span> Assign<span class="br0">&#40;</span>Fill fill<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>fill <span class="sy0">==</span> <span class="kw1">null</span><span class="br0">&#41;</span> <span class="kw1">return</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Color <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">Color</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Alpha <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">Alpha</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PatternColor <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">PatternColor</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PatternIndex <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">PatternIndex</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mode <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">Mode</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HatchMode <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">HatchMode</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LinearMode <span class="sy0">=</span> fill<span class="sy0">.</span><span class="me1">LinearMode</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Реализация интерфейса ICloneable</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;Возвращаем копию Fill&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">object</span> Clone<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> fill <span class="sy0">=</span> <span class="kw3">new</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fill<span class="sy0">.</span><span class="me1">Assign</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> fill<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
Теперь о свойствах.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="950988028"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="950988028" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Свойство определяющее вид фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> DrawingKind Kind <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Свойство Kind имеет тип-перечисление и это перечисление выглядит вот так:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="413547957"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="413547957" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> <span class="kw4">enum</span> DrawingKind
<span class="br0">&#123;</span>
&nbsp; &nbsp; Polygon,
&nbsp; &nbsp; Polyline
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Этим я говорю, что моя фигура - это замкнутый контур или некая ломаная.<br />
<br />
Свойства для поддержки размещения и размеров фигуры:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="826796471"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="826796471" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Базовая точка, обычно левый верхний угол прямоугольника,</span>
<span class="co1">/// описывающего фигуру</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw1">virtual</span> PointF Location <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Размер фигуры, ширина и высота прямоугольника,</span>
<span class="co1">/// описывающего фигуру</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw1">virtual</span> SizeF Size <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Прямоугольник, описывающий фигуру</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> RectangleF BoundsRect
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">new</span> RectangleF<span class="br0">&#40;</span>Location, Size<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Свойство возвращает реальный прямоугольник, охватывающий точки фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> <span class="kw1">virtual</span> RectangleF GetBounds
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> rect <span class="sy0">=</span> gp<span class="sy0">.</span><span class="me1">GetBounds</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если фигура очень узкая по горизонтали</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">-</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="kw4">float</span><span class="sy0">.</span><span class="me1">Epsilon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-=</span> <span class="nu0">2</span><span class="sy0">;</span> 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если фигура очень узкая по вертикали</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">-</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="kw4">float</span><span class="sy0">.</span><span class="me1">Epsilon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-=</span> <span class="nu0">2</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>rect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Свойства, предназначенные для поддержки визуальной составляющей:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="566066560"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="566066560" style="height: 174px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Карандаш для рисования контура фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Stroke Stroke <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Кисть для заливки контура фигуры</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="kw1">public</span> Fill Fill <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Теперь методы.<br />
Вот основной метод, который всё рисует (наконец-то!):<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="182650467"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="182650467" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод рисования фигуры по точкам базового списка</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;graphics&quot;&gt;&quot;холст&quot; - объект для рисования&lt;/param&gt;</span>
<span class="kw1">public</span> <span class="kw1">virtual</span> <span class="kw4">void</span> DrawFigure<span class="br0">&#40;</span>Graphics graphics<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> Points<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// если можно заливать</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Kind <span class="sy0">==</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span> <span class="sy0">&amp;&amp;</span> Fill <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> brush <span class="sy0">=</span> Fill<span class="sy0">.</span><span class="me1">Brush</span><span class="br0">&#40;</span>GetBounds<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">FillPolygon</span><span class="br0">&#40;</span>brush, points<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// заливаем фон кистью</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="co1">// рисуем контур карандашом</span>
&nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> pen <span class="sy0">=</span> Stroke<span class="sy0">.</span><span class="me1">Pen</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">??</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawPolygon</span><span class="br0">&#40;</span>pen, points<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Когда мы рисуем фигуру, то сначала делаем заливку, а потом &quot;обводим&quot;.<br />
Заливка возможна, если у нас замкнутый контур и если объект Fill свойств заливки задан.<br />
<br />
Метод Fill.Brush(GetBounds) возвращает настроенную кисть, в том числе и градиентную,<br />
для которой требуется указать размеры поверхности для работы в виде прямоугольника,<br />
который возвращает свойство GetBounds.<br />
<br />
Метод Stroke.Pen() возвращает настроенный карандаш, а если нет, то берётся чёрный.<br />
<br />
И два вспомогательных метода.<br />
Метод, проверяющий принадлежность точки фигуре:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="896244806"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="896244806" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод проверяет принадлежность точки фигуре</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;point&quot;&gt;проверяемая точка&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;True - точка принадлежит фигуре&lt;/returns&gt;</span>
<span class="kw1">public</span> <span class="kw1">virtual</span> Boolean PointInFigure<span class="br0">&#40;</span>PointF point<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>Kind<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>gp<span class="sy0">.</span><span class="me1">IsVisible</span><span class="br0">&#40;</span>point<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> DrawingKind<span class="sy0">.</span><span class="me1">Polyline</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> ps<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">StartFigure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>Onebuff<span class="br0">&#40;</span>ps<span class="br0">&#91;</span>i <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span>, ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">CloseFigure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>gp<span class="sy0">.</span><span class="me1">IsVisible</span><span class="br0">&#40;</span>point<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">false</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Метод, возвращающий полигон из четырёх точек вокруг отрезка прямой,<br />
для работы с линиями, у которых вырождаются либо ширина, либо высота.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="424680540"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="424680540" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Вспомогательный метод, строит прямоугольник на перпендикулярах</span>
<span class="co1">/// на концах отрезка между двух точек</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;p1&quot;&gt;первая точка&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;p2&quot;&gt;вторая точка&lt;/param&gt;</span>
<span class="co1">/// &lt;returns&gt;массив точек четырёхугольника, охватывающего отрезок&lt;/returns&gt;</span>
<span class="kw1">private</span> PointF<span class="br0">&#91;</span><span class="br0">&#93;</span> Onebuff<span class="br0">&#40;</span>PointF p1, PointF p2<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">var</span> selWidth <span class="sy0">=</span> Stroke<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">*</span> 0<span class="sy0">.</span>5F<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>selWidth <span class="sy0">&lt;</span> 4F<span class="br0">&#41;</span> <span class="sy0">||</span> <span class="br0">&#40;</span>Stroke<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">==</span> DashStyle<span class="sy0">.</span><span class="me1">Custom</span><span class="br0">&#41;</span><span class="br0">&#41;</span> selWidth <span class="sy0">=</span> 4F<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> x1 <span class="sy0">=</span> p1<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> y1 <span class="sy0">=</span> p1<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> x2 <span class="sy0">=</span> p2<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> y2 <span class="sy0">=</span> p2<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> k <span class="sy0">=</span> <span class="br0">&#40;</span>y2 <span class="sy0">-</span> y1<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="br0">&#40;</span>x2 <span class="sy0">-</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> fi1 <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span><span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Atan</span><span class="br0">&#40;</span>k<span class="br0">&#41;</span> <span class="sy0">+</span> Math<span class="sy0">.</span><span class="me1">PI</span> <span class="sy0">*</span> <span class="nu0">0.5</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> fi2 <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span><span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Atan</span><span class="br0">&#40;</span>k<span class="br0">&#41;</span> <span class="sy0">-</span> Math<span class="sy0">.</span><span class="me1">PI</span> <span class="sy0">*</span> <span class="nu0">0.5</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">var</span> buff <span class="sy0">=</span> <span class="kw3">new</span> PointF<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> x2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> y2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> x2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> y2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>buff<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Ну, хватит пока. В следующем шаге разберём подробно устройство<br />
классов-спутников Stroke и Fill.<br />
<br />
Вот весь код класса Drawing:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="774062017"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="774062017" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Collections.Generic</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing.Drawing2D</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SimpleVectorGraphicsEditor
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">enum</span> DrawingKind
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; Polygon,
&nbsp; &nbsp; &nbsp; &nbsp; Polyline
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; <span class="co1">/// Описание класса базовой фигуры </span>
&nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; <span class="br0">&#91;</span>Serializable<span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">abstract</span> <span class="kw4">class</span> Drawing
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// контейнер для хранения точек фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw1">readonly</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span> Points <span class="sy0">=</span> <span class="kw3">new</span> List<span class="sy0">&lt;</span>PointF<span class="sy0">&gt;</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &nbsp;Конструктор без параметра с настройкой по умолчанию</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> Drawing<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="kw1">this</span><span class="br0">&#40;</span><span class="kw3">new</span> Stroke<span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="kw3">new</span> Fill<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Конструктор с параметрами</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;stroke&quot;&gt;Объект настроек карандаша&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;fill&quot;&gt;Объект настроек кисти&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> Drawing<span class="br0">&#40;</span>Stroke stroke, Fill fill<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Stroke <span class="sy0">=</span> stroke<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Fill <span class="sy0">=</span> fill<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Свойство определяющее вид фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> DrawingKind Kind <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Базовая точка, обычно левый верхний угол прямоугольника,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// описывающего фигуру</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> PointF Location <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Размер фигуры, ширина и высота прямоугольника,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// описывающего фигуру</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> SizeF Size <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Прямоугольник, описывающий фигуру</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> RectangleF BoundsRect
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">new</span> RectangleF<span class="br0">&#40;</span>Location, Size<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Карандаш для рисования контура фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Stroke Stroke <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Кисть для заливки контура фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Fill Fill <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод рисования фигуры по точкам базового списка</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;graphics&quot;&gt;&quot;холст&quot; - объект для рисования&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> <span class="kw4">void</span> DrawFigure<span class="br0">&#40;</span>Graphics graphics<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> points <span class="sy0">=</span> Points<span class="sy0">.</span><span class="me1">ToArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если можно заливать</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Kind <span class="sy0">==</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span> <span class="sy0">&amp;&amp;</span> Fill <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> brush <span class="sy0">=</span> Fill<span class="sy0">.</span><span class="me1">Brush</span><span class="br0">&#40;</span>GetBounds<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">FillPolygon</span><span class="br0">&#40;</span>brush, points<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// заливаем фон кистью</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// рисуем контур карандашом</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> pen <span class="sy0">=</span> Stroke<span class="sy0">.</span><span class="me1">Pen</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">??</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; graphics<span class="sy0">.</span><span class="me1">DrawPolygon</span><span class="br0">&#40;</span>pen, points<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод проверяет принадлежность точки фигуре</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;point&quot;&gt;проверяемая точка&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;True - точка принадлежит фигуре&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> Boolean PointInFigure<span class="br0">&#40;</span>PointF point<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span>Kind<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> DrawingKind<span class="sy0">.</span><span class="me1">Polygon</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>gp<span class="sy0">.</span><span class="me1">IsVisible</span><span class="br0">&#40;</span>point<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> DrawingKind<span class="sy0">.</span><span class="me1">Polyline</span><span class="sy0">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw1">var</span> i <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> ps<span class="sy0">.</span><span class="me1">Length</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">StartFigure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>Onebuff<span class="br0">&#40;</span>ps<span class="br0">&#91;</span>i <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">&#93;</span>, ps<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">CloseFigure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>gp<span class="sy0">.</span><span class="me1">IsVisible</span><span class="br0">&#40;</span>point<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw1">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Вспомогательный метод, строит прямоугольник на перпендикулярах</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// на концах отрезка между двух точек</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;p1&quot;&gt;первая точка&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;p2&quot;&gt;вторая точка&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;массив точек четырёхугольника, охватывающего отрезок&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> PointF<span class="br0">&#91;</span><span class="br0">&#93;</span> Onebuff<span class="br0">&#40;</span>PointF p1, PointF p2<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> selWidth <span class="sy0">=</span> Stroke<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">*</span> 0<span class="sy0">.</span>5F<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>selWidth <span class="sy0">&lt;</span> 4F<span class="br0">&#41;</span> <span class="sy0">||</span> <span class="br0">&#40;</span>Stroke<span class="sy0">.</span><span class="me1">DashStyle</span> <span class="sy0">==</span> DashStyle<span class="sy0">.</span><span class="me1">Custom</span><span class="br0">&#41;</span><span class="br0">&#41;</span> selWidth <span class="sy0">=</span> 4F<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> x1 <span class="sy0">=</span> p1<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> y1 <span class="sy0">=</span> p1<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> x2 <span class="sy0">=</span> p2<span class="sy0">.</span><span class="me1">X</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> y2 <span class="sy0">=</span> p2<span class="sy0">.</span><span class="me1">Y</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> k <span class="sy0">=</span> <span class="br0">&#40;</span>y2 <span class="sy0">-</span> y1<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="br0">&#40;</span>x2 <span class="sy0">-</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> fi1 <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span><span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Atan</span><span class="br0">&#40;</span>k<span class="br0">&#41;</span> <span class="sy0">+</span> Math<span class="sy0">.</span><span class="me1">PI</span> <span class="sy0">*</span> <span class="nu0">0.5</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> fi2 <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span><span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Atan</span><span class="br0">&#40;</span>k<span class="br0">&#41;</span> <span class="sy0">-</span> Math<span class="sy0">.</span><span class="me1">PI</span> <span class="sy0">*</span> <span class="nu0">0.5</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> buff <span class="sy0">=</span> <span class="kw3">new</span> PointF<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> x1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> x2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi2<span class="br0">&#41;</span> <span class="sy0">+</span> y2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Cos</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> x2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buff<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>Single<span class="br0">&#41;</span>Math<span class="sy0">.</span><span class="me1">Round</span><span class="br0">&#40;</span>selWidth <span class="sy0">*</span> Math<span class="sy0">.</span><span class="me1">Sin</span><span class="br0">&#40;</span>fi1<span class="br0">&#41;</span> <span class="sy0">+</span> y2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>buff<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Свойство возвращает реальный прямоугольник, охватывающий точки фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> RectangleF GetBounds
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">get</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">using</span> <span class="br0">&#40;</span><span class="kw1">var</span> gp <span class="sy0">=</span> <span class="kw3">new</span> GraphicsPath<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gp<span class="sy0">.</span><span class="me1">AddPolygon</span><span class="br0">&#40;</span>GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> rect <span class="sy0">=</span> gp<span class="sy0">.</span><span class="me1">GetBounds</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если фигура очень узкая по горизонтали</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">-</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="kw4">float</span><span class="sy0">.</span><span class="me1">Epsilon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-=</span> <span class="nu0">2</span><span class="sy0">;</span> 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если фигура очень узкая по вертикали</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">-</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="sy0">&lt;</span> <span class="kw4">float</span><span class="sy0">.</span><span class="me1">Epsilon</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-=</span> <span class="nu0">2</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">+=</span> <span class="nu0">4</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>rect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод возвращает массив точек фигуры</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;returns&gt;Массив, копия списка точек фигуры&lt;/returns&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">virtual</span> PointF<span class="br0">&#91;</span><span class="br0">&#93;</span> GetPoints<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// возвращает массив точек линии</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">var</span> ps <span class="sy0">=</span> <span class="kw3">new</span> PointF<span class="br0">&#91;</span>Points<span class="sy0">.</span><span class="me1">Count</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Points<span class="sy0">.</span><span class="me1">CopyTo</span><span class="br0">&#40;</span>ps<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>ps<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
До скорого!</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5514.html</guid>
		</item>
		<item>
			<title>Шаг первый. Создаём рамку выбора для графического редактора.</title>
			<link>https://www.cyberforum.ru/blogs/1359876/5510.html</link>
			<pubDate>Mon, 05 Nov 2018 07:41:42 GMT</pubDate>
			<description>Когда речь заходит о всяческих полезняшках, например, о простом, встроенном в моё приложение,...</description>
			<content:encoded><![CDATA[<div>Когда речь заходит о всяческих полезняшках, например, о простом, встроенном в моё приложение,<br />
графическом редакторе, у меня это вызывает некоторый трепет... Сколько возможностей открывается!<br />
Игровой движок с редактором уровней, редактор пользовательских форм и так далее и тому подобное.<br />
<br />
Первое, что приходит в голову при создании любого редактора, это средство выбора чего-либо на поверхности рисования,<br />
или указания прямоугольной области, куда что-то нужно разместить. Или выбрать группу нарисованных объектов.<br />
<br />
Итак, начнём!<br />
<br />
Сначала разработаем класс и назовём его <b>RectangleRibbonSelector</b>. Экземпляр этого класса будет<br />
создаваться пользователем в конструкторе формы, содержащей &quot;холст&quot; для рисования. Например,<br />
компонент PictureBox, у которого есть поверхность для рисования, доступная через событие Paint, а также<br />
он поддерживает реакцию на события нажатия кнопок и перемещения &quot;мышки&quot; при помощи событий MouseDown,<br />
MouseMove и MouseUp.<br />
<br />
Таким образом, нашему классу необходим конструктор, в который мы будем передавать этот &quot;холст&quot; через параметр<br />
типа Control, определённого в пространстве имён System.Windows.Forms.<br />
Кроме того, сразу же подумаем о том, что рамка выбора может иметь свои настраиваемые параметры для<br />
цвета и толщины границ, и возможно, цвета заливки внутренней области.<br />
Для этого определим ещё два необязательный параметра для карандаша и кисти.<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="567902717"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="567902717" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Конструктор с параметрами для перехвата и обработки событий</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;container&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;borderPen&quot;&gt;карандаш для рисования рамки&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;fillBrush&quot;&gt;кисть для закрашивания рамки&lt;/param&gt;</span>
<span class="kw1">public</span> RectangleRibbonSelector<span class="br0">&#40;</span>Control container, Pen borderPen <span class="sy0">=</span> <span class="kw1">null</span>, Brush fillBrush <span class="sy0">=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// запоминаем ссылку на контейнер для рисования</span>
&nbsp; &nbsp; _container <span class="sy0">=</span> container<span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// по умолчанию рамка пунктирная, чёрного цвета</span>
&nbsp; &nbsp; _borderPen <span class="sy0">=</span> borderPen <span class="sy0">??</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> DashStyle <span class="sy0">=</span> <span class="kw5">System.<span class="me1">Drawing</span><span class="sy0">.</span><span class="me1">Drawing2D</span></span><span class="sy0">.</span><span class="me1">DashStyle</span><span class="sy0">.</span><span class="me1">Dot</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; _fillBrush <span class="sy0">=</span> fillBrush<span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// подключаемся к необходимым событиям на контейнере</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseDown</span> <span class="sy0">+=</span> Control_MouseDown<span class="sy0">;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseMove</span> <span class="sy0">+=</span> _control_MouseMove<span class="sy0">;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseUp</span> <span class="sy0">+=</span> Control_MouseUp<span class="sy0">;</span>
&nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Paint</span> <span class="sy0">+=</span> _control_Paint<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В теле конструктора запоминаем параметры в локальных переменных, а для переданного в параметре container<br />
компонента подключаем свои обработчики событий для &quot;мышки&quot; и рисования.<br />
Теперь к обработчикам событий.<br />
Вот, что напишем в обработчике события рисования Paint:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="322254365"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="322254365" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Обработчик события рисования на поверхности контейнера</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством Graphics&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> _control_Paint<span class="br0">&#40;</span><span class="kw4">object</span> sender, PaintEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// если прямоугольник выбора не пуст</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>_ribbonRect<span class="sy0">.</span><span class="me1">IsEmpty</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span> &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если указана кисть заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_fillBrush <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e<span class="sy0">.</span><span class="me1">Graphics</span><span class="sy0">.</span><span class="me1">FillRectangle</span><span class="br0">&#40;</span>_fillBrush, _ribbonRect<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// то выполняем закрашивание</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// рисуем рамку прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; e<span class="sy0">.</span><span class="me1">Graphics</span><span class="sy0">.</span><span class="me1">DrawRectangle</span><span class="br0">&#40;</span>_borderPen, _ribbonRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>У нас есть локальная переменная _ribbonRect типа Rectangle, которая настраивается в событиях перемещения &quot;мышки&quot;,<br />
а используется в методе события рисования. Если _ribbonRect имеет ширину и высоту, отличные от нуля,<br />
то этот прямоугольник рисуется на канве контейнера _container, при помощи метода e.Graphics.DrawRectangle(...).<br />
<br />
Метод обработки события нажатия левой кнопки &quot;мышки&quot;:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="640082764"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="640082764" style="height: 286px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Обработчик события нажатия кнопки мышки</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством Location&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> Control_MouseDown<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// обрабатываем событие, если была нажата левая кнопка мышки</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// обнуление прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect <span class="sy0">=</span> Rectangle<span class="sy0">.</span><span class="me1">Empty</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// запоминаем точку первую точку выбора начала рисования прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; _mouseDownLocation <span class="sy0">=</span> e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>В том методе мы запоминаем координаты нажатия для последующего использования в локальную переменную _mouseDownLocation, а локальная переменная _ribbonRect очищается.<br />
<br />
Метод обработки события перемещения &quot;мышки&quot; с нажатой левой кнопкой:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="196082313"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="196082313" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Обработчик события перемещения мышки</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством Location&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> _control_MouseMove<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// обрабатываем событие, если была нажата левая кнопка мышки</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// нормализация параметров для прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// в случае, если мы &quot;растягиваем&quot; прямоугольник не только по &quot;главной&quot; диагонали</span>
&nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Min</span><span class="br0">&#40;</span>_mouseDownLocation<span class="sy0">.</span><span class="me1">X</span>, e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">.</span><span class="me1">X</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Min</span><span class="br0">&#40;</span>_mouseDownLocation<span class="sy0">.</span><span class="me1">Y</span>, e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">.</span><span class="me1">Y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// размеры должны быть всегда положительные числа</span>
&nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>_mouseDownLocation<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-</span> e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">.</span><span class="me1">X</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>_mouseDownLocation<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-</span> e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">.</span><span class="me1">Y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// запрашиваем контейнер для рисования, чтобы обновился</span>
&nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Сначала проверяем, что левая кнопка &quot;мышки&quot; нажата. Для рисования прямоугольника у нас есть теперь<br />
две точки: начальная точка в переменной _mouseDownLocation и текущая точка, передаваемая нам в параметре<br />
вызова этого события MouseEventArgs e.Location. Здесь также важно заметить, что разница между координатами X<br />
(и координатами Y) этих двух точек должна быть положительной.<br />
Это не так, если начальная точка нажатия &quot;мышки&quot; расположена ниже  текущей точки курсора &quot;мышки&quot;.<br />
Поэтому нужно для координат X и Y прямоугольника _ribbonRect выбрать минимальные координаты из двух,<br />
а для ширины и высоты прямоугольника взять абсолютное значение разницы между координатами двух точек.<br />
<br />
Метод обработки события отпускания левой кнопки &quot;мышки&quot;:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="92264121"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="92264121" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="de1"><pre class="de1"><span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Обработчик события отпускания кнопки мышки</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события&lt;/param&gt;</span>
<span class="kw1">private</span> <span class="kw4">void</span> Control_MouseUp<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// инициация события при окончании выбора прямоугольником</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>_ribbonRect<span class="sy0">.</span><span class="me1">IsEmpty</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// создаём объект аргумента для возбуждения события</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RibbonSelectedEventArgs args <span class="sy0">=</span> <span class="kw3">new</span> RibbonSelectedEventArgs
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// и передаём выбранный прямоугольник</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RectangleSelected <span class="sy0">=</span> _ribbonRect
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// возбуждаем событие окончания выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OnRibbonSelected<span class="br0">&#40;</span>args<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// обнуление прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect <span class="sy0">=</span> Rectangle<span class="sy0">.</span><span class="me1">Empty</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// запрашиваем контейнер для рисования, чтобы обновился</span>
&nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">/// &lt;summary&gt;</span>
<span class="co1">/// Метод инициации события по окончании процесса выбора прямоугольником</span>
<span class="co1">/// &lt;/summary&gt;</span>
<span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством RectangleSelected&lt;/param&gt;</span>
<span class="kw1">protected</span> <span class="kw1">virtual</span> <span class="kw4">void</span> OnRibbonSelected<span class="br0">&#40;</span>RibbonSelectedEventArgs e<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// если на событие подписались, то вызываем его</span>
&nbsp; &nbsp; OnSelected<span class="sy0">?.</span><span class="me1">Invoke</span><span class="br0">&#40;</span><span class="kw1">this</span>, e<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Когда мы отпускаем левую кнопку &quot;мышки&quot;, не плохо бы передать это событие во внешний код,<br />
где размещён экземпляр нашего класса RectangleRibbonSelector. Сначала проверяем, что прямоугольник<br />
выбора не пуст, а потом вызываем метод OnRibbonSelected() с подготовленным объектом <br />
параметра RibbonSelectedEventArgs e со свойством RectangleSelected, через которое и передаём <br />
результирующий прямоугольник выбора.<br />
<br />
Класс параметра выглядит так:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="961759269"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="961759269" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> <span class="kw4">class</span> RibbonSelectedEventArgs <span class="sy0">:</span> EventArgs
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">public</span> Rectangle RectangleSelected <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>а поле события в нашем классе RectangleRibbonSelector определяется так:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="537463182"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="537463182" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> <span class="kw1">event</span> EventHandler<span class="sy0">&lt;</span>RibbonSelectedEventArgs<span class="sy0">&gt;</span> OnSelected<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Ну а теперь самое &quot;вкусненькое&quot;:<br />
Вот как будем использовать класс RectangleRibbonSelector в форме, содержащей контейнер для рисования:<br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="3242905"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="3242905" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1"><span class="kw1">public</span> <span class="kw1">partial</span> <span class="kw4">class</span> FormMain <span class="sy0">:</span> Form
<span class="br0">&#123;</span>
&nbsp; &nbsp; RectangleRibbonSelector ribbonSelector<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">public</span> FormMain<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; InitializeComponent<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// создаём объект рамки выбора фигур</span>
&nbsp; &nbsp; &nbsp; &nbsp; ribbonSelector <span class="sy0">=</span> <span class="kw3">new</span> RectangleRibbonSelector<span class="br0">&#40;</span>pictureBoxCanvas<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; ribbonSelector<span class="sy0">.</span><span class="me1">OnSelected</span> <span class="sy0">+=</span> RibbonSelector_OnSelected<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> RibbonSelector_OnSelected<span class="br0">&#40;</span><span class="kw4">object</span> sender, RibbonSelectedEventArgs e<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// пока что просто выводим в консоль координаты выбора прямоугольником</span>
&nbsp; &nbsp; &nbsp; &nbsp; Console<span class="sy0">.</span><span class="me1">WriteLine</span><span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">RectangleSelected</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Ни какого лишнего кода в главной форме приложения!<br />
<br />
Код класса RectangleRibbonSelector целиком:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <br />
<div class="codeblock"><table class="csharp"><thead><tr><td colspan="2" id="204217315"  class="head">C#</td></tr></thead><tbody><tr class="li1"><td><div id="204217315" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
</pre></td><td class="de1"><pre class="de1"><span class="kw1">using</span> <span class="co3">System</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Drawing</span><span class="sy0">;</span>
<span class="kw1">using</span> <span class="co3">System.Windows.Forms</span><span class="sy0">;</span>
&nbsp;
<span class="kw1">namespace</span> SimpleVectorGraphicsEditor
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> RibbonSelectedEventArgs <span class="sy0">:</span> EventArgs
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> Rectangle RectangleSelected <span class="br0">&#123;</span> <span class="kw1">get</span><span class="sy0">;</span> <span class="kw1">set</span><span class="sy0">;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">public</span> <span class="kw4">class</span> RectangleRibbonSelector
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">readonly</span> Control _container<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">readonly</span> Pen _borderPen<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw1">readonly</span> Brush _fillBrush<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> Point _mouseDownLocation <span class="sy0">=</span> Point<span class="sy0">.</span><span class="me1">Empty</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> Rectangle _ribbonRect <span class="sy0">=</span> <span class="kw3">new</span> Rectangle<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> <span class="kw1">event</span> EventHandler<span class="sy0">&lt;</span>RibbonSelectedEventArgs<span class="sy0">&gt;</span> OnSelected<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Конструктор с параметрами для перехвата и обработки событий</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;container&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;borderPen&quot;&gt;карандаш для рисования рамки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;fillBrush&quot;&gt;кисть для закрашивания рамки&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">public</span> RectangleRibbonSelector<span class="br0">&#40;</span>Control container, Pen borderPen <span class="sy0">=</span> <span class="kw1">null</span>, Brush fillBrush <span class="sy0">=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// запоминаем ссылку на контейнер для рисования</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container <span class="sy0">=</span> container<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// по умолчанию рамка пунктирная, чёрного цвета</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _borderPen <span class="sy0">=</span> borderPen <span class="sy0">??</span> <span class="kw3">new</span> Pen<span class="br0">&#40;</span>Color<span class="sy0">.</span><span class="me1">Black</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> DashStyle <span class="sy0">=</span> <span class="kw5">System.<span class="me1">Drawing</span><span class="sy0">.</span><span class="me1">Drawing2D</span></span><span class="sy0">.</span><span class="me1">DashStyle</span><span class="sy0">.</span><span class="me1">Dot</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _fillBrush <span class="sy0">=</span> fillBrush<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// подключаемся к необходимым событиям на контейнере</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseDown</span> <span class="sy0">+=</span> Control_MouseDown<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseMove</span> <span class="sy0">+=</span> _control_MouseMove<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">MouseUp</span> <span class="sy0">+=</span> Control_MouseUp<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Paint</span> <span class="sy0">+=</span> _control_Paint<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Обработчик события рисования на поверхности контейнера</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством Graphics&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> _control_Paint<span class="br0">&#40;</span><span class="kw4">object</span> sender, PaintEventArgs e<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если прямоугольник выбора не пуст</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>_ribbonRect<span class="sy0">.</span><span class="me1">IsEmpty</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если указана кисть заливки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_fillBrush <span class="sy0">!=</span> <span class="kw1">null</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e<span class="sy0">.</span><span class="me1">Graphics</span><span class="sy0">.</span><span class="me1">FillRectangle</span><span class="br0">&#40;</span>_fillBrush, _ribbonRect<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// то выполняем закрашивание</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// рисуем рамку прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e<span class="sy0">.</span><span class="me1">Graphics</span><span class="sy0">.</span><span class="me1">DrawRectangle</span><span class="br0">&#40;</span>_borderPen, _ribbonRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Обработчик события нажатия кнопки мышки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством Location&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> Control_MouseDown<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// обрабатываем событие, если была нажата левая кнопка мышки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// обнуление прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect <span class="sy0">=</span> Rectangle<span class="sy0">.</span><span class="me1">Empty</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// запоминаем точку первую точку выбора начала рисования прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _mouseDownLocation <span class="sy0">=</span> e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Обработчик события перемещения мышки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством Location&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> _control_MouseMove<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// обрабатываем событие, если была нажата левая кнопка мышки</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// нормализация параметров для прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// в случае, если мы &quot;растягиваем&quot; прямоугольник не только по &quot;главной&quot; диагонали</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Min</span><span class="br0">&#40;</span>_mouseDownLocation<span class="sy0">.</span><span class="me1">X</span>, e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">.</span><span class="me1">X</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Min</span><span class="br0">&#40;</span>_mouseDownLocation<span class="sy0">.</span><span class="me1">Y</span>, e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">.</span><span class="me1">Y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// размеры должны быть всегда положительные числа</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect<span class="sy0">.</span><span class="me1">Width</span> <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>_mouseDownLocation<span class="sy0">.</span><span class="me1">X</span> <span class="sy0">-</span> e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">.</span><span class="me1">X</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect<span class="sy0">.</span><span class="me1">Height</span> <span class="sy0">=</span> Math<span class="sy0">.</span><span class="me1">Abs</span><span class="br0">&#40;</span>_mouseDownLocation<span class="sy0">.</span><span class="me1">Y</span> <span class="sy0">-</span> e<span class="sy0">.</span><span class="me1">Location</span><span class="sy0">.</span><span class="me1">Y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// запрашиваем контейнер для рисования, чтобы обновился</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Обработчик события отпускания кнопки мышки</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;sender&quot;&gt;визуальный компонент с поверхностью для рисования&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">private</span> <span class="kw4">void</span> Control_MouseUp<span class="br0">&#40;</span><span class="kw4">object</span> sender, MouseEventArgs e<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>e<span class="sy0">.</span><span class="me1">Button</span> <span class="sy0">==</span> MouseButtons<span class="sy0">.</span><span class="me1">Left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// инициация события при окончании выбора прямоугольником</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>_ribbonRect<span class="sy0">.</span><span class="me1">IsEmpty</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// создаём объект аргумента для возбуждения события</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RibbonSelectedEventArgs args <span class="sy0">=</span> <span class="kw3">new</span> RibbonSelectedEventArgs
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// и передаём выбранный прямоугольник</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RectangleSelected <span class="sy0">=</span> _ribbonRect
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// возбуждаем событие окончания выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OnRibbonSelected<span class="br0">&#40;</span>args<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// обнуление прямоугольника выбора</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _ribbonRect <span class="sy0">=</span> Rectangle<span class="sy0">.</span><span class="me1">Empty</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// запрашиваем контейнер для рисования, чтобы обновился</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _container<span class="sy0">.</span><span class="me1">Invalidate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// Метод инициации события по окончании процесса выбора прямоугольником</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;/summary&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">/// &lt;param name=&quot;e&quot;&gt;объект параметров события со свойством RectangleSelected&lt;/param&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">protected</span> <span class="kw1">virtual</span> <span class="kw4">void</span> OnRibbonSelected<span class="br0">&#40;</span>RibbonSelectedEventArgs e<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// если на событие подписались, то вызываем его</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OnSelected<span class="sy0">?.</span><span class="me1">Invoke</span><span class="br0">&#40;</span><span class="kw1">this</span>, e<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />
Вот, пожалуй и всё для первого шага. Далее нужно будет создавать фигуры для рисования,<br />
передавая в их конструктор начальный размер при помощи параметра e.RectangleSelected в<br />
событии RibbonSelector_OnSelected.<br />
Нужно будет создать класс-основу для таких фигур, а также контейнер для хранения фигур,<br />
который будет хранить их, управлять ими и рисовать их на &quot;холсте&quot;.</div>

]]></content:encoded>
			<dc:creator>ashsvis</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1359876/5510.html</guid>
		</item>
	</channel>
</rss>
