<?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>Форум программистов и сисадминов Киберфорум - Блоги - krapotkin</title>
		<link>https://www.cyberforum.ru/blogs/469693/</link>
		<description>КиберФорум - форум программистов, системных администраторов, администраторов баз данных, компьютерный форум, форум по электронике и бытовой технике, обсуждение софта. Бесплатная помощь в решении задач по программированию и наукам, решение проблем с компьютером, операционными системам</description>
		<language>ru</language>
		<lastBuildDate>Fri, 21 Aug 2026 16:02:12 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>60</ttl>
		<image>
			<url>https://www.cyberforum.ru//cyberstatic.net/images/misc/rss.jpg</url>
			<title>Форум программистов и сисадминов Киберфорум - Блоги - krapotkin</title>
			<link>https://www.cyberforum.ru/blogs/469693/</link>
		</image>
		<item>
			<title>Создание Single Page Application на фреймах</title>
			<link>https://www.cyberforum.ru/blogs/469693/10675.html</link>
			<pubDate>Sun, 16 Nov 2025 17:20:21 GMT</pubDate>
			<description>Статья исключительно для начинающих. Подходы оригинальностью не блещут. 
 
В век Веб все очень...</description>
			<content:encoded><![CDATA[<div>Статья исключительно для начинающих. Подходы оригинальностью не блещут.<br />
<br />
В век Веб все очень привыкли к дизайну Single-Page-Application .<br />
Быстренько разберем подход &quot;на фреймах&quot;.<br />
Мы делаем одну главную форму, на которой меняем &quot;начинку&quot;.<br />
Разница с &quot;классическим&quot; подходом - каждая страница это не форма, а фрейм, который создается и вставляется в главную форму. <br />
С т.з. программирования фрейм мало чем от формы отличается.<br />
Отдельные формы в приложении будут, в основном, всевозможные диалоги.<br />
<br />
Приступим.<br />
<br />
1. Пусть в главной форме есть разные панели, меню и всякая другая фигня, типа дерева слева, как в делфи.<br />
Заведем какую-нибудь панель для наших фреймов, пусть pnlMain.<br />
<br />
2. Создадим новый пустой фрейм, назовем его BaseFrame (тогда класс автоматически назовется TBaseFrame) и создадим тип TBaseFrameClass. Сохраним в файле UBaseFrame.pas<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="585183760"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="585183760" 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">type</span>
TBaseFrame <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TFrame<span class="br0">&#41;</span>
<span class="kw1">public</span>
&nbsp; <span class="kw1">procedure</span> Init<span class="sy1">;</span> &nbsp;<span class="kw1">virtual</span><span class="sy1">;</span>
<span class="sy1">...</span>
<span class="kw1">end</span><span class="sy1">;</span>
TBaseFrameClass <span class="sy3">=</span> <span class="kw1">class</span> <span class="kw1">of</span> TBaseFrame<span class="sy1">;</span>
<span class="sy1">...</span>
<span class="kw1">implementation</span>
<span class="kw1">procedure</span> TBaseFrame<span class="sy1">.</span><span class="me1">Init</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="co1">// в базовом фрейме - ничего, а в наследниках скорее всего пригодится</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><br />
3. В классе формы заводим поле и процедуру<br />
(по-хорошему, надо бы поле вынести отдельной глобальной переменной в отдельный файл, но в целом и так сойдет)<br />
и и метод для смены фреймов<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="431190410"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="431190410" 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="kw1">uses</span> <span class="sy1">....</span>
<span class="me1">UBaseFrame</span><span class="sy1">;</span>
TForm1 <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
<span class="kw1">public</span>
&nbsp; CurrentFrame <span class="sy1">:</span> TBaseFrame<span class="sy1">;</span>
&nbsp; <span class="kw1">procedure</span> CreateFrame<span class="br0">&#40;</span>AClass<span class="sy1">:</span> TBaseFrameClass<span class="br0">&#41;</span>
<span class="kw1">end</span><span class="sy1">;</span>
<span class="sy1">...</span>
<span class="kw1">implementation</span> 
<span class="kw1">procedure</span> TFrom1<span class="sy1">.</span><span class="me1">CreateFrame</span><span class="br0">&#40;</span>AClass<span class="sy1">:</span> TBaseFrameClass<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">if</span> <span class="kw3">Assigned</span><span class="br0">&#40;</span>CurrentFrame<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; CurrentFrame<span class="sy1">.</span><span class="me1">Free</span><span class="sy1">;</span>
&nbsp;
&nbsp; CurrentFrame <span class="sy1">:</span><span class="sy3">=</span> AClass<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">Self</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; CurrentFrame<span class="sy1">.</span><span class="me1">Parent</span> <span class="sy1">:</span><span class="sy3">=</span> pnlMain<span class="sy1">;</span>
&nbsp; CurrentFrame<span class="sy1">.</span><span class="me1">Align</span> <span class="sy1">:</span><span class="sy3">=</span> alClient<span class="sy1">;</span>
&nbsp; CurrentFrame<span class="sy1">.</span><span class="me1">Init</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>4. Теперь о том, как мы будем создавать новые фреймы<br />
File -&gt; New -&gt; Other -&gt; Inheritable Items -&gt; найти класс BaseFrame<br />
Появится новый фрейм, называйте его как угодно - TMyFrame1<br />
Но на нем будет все то, что вы разместите в базовом фрейме.<br />
Ну и всем им нужно будет при старте что-то загружать и настраивать.<br />
Для этого мы придумали метод Init<br />
<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="168566924"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="168566924" 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">TMyFrame1 <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TBaseFrame<span class="br0">&#41;</span>
<span class="kw1">public</span>
&nbsp; aaa<span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
&nbsp; <span class="kw1">procedure</span> Init<span class="sy1">;</span> <span class="kw1">override</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMyFrame1<span class="sy1">.</span><span class="me1">Init</span><span class="sy1">;</span> 
<span class="kw1">begin</span>
&nbsp; &nbsp;aaa <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">5</span><span class="sy1">;</span> &nbsp;
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><br />
5. В программе при необходимости перехода на новую страницу нашего приложения<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="326021059"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="326021059" 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">CreateFrame<span class="br0">&#40;</span>TFrame1<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="sy1">...</span>
<span class="me1">CreateFrame</span><span class="br0">&#40;</span>TFrame5<span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>для любого фрейма, которые вы насоздаете.</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/10675.html</guid>
		</item>
		<item>
			<title>Реализуем вызовы HTTP API</title>
			<link>https://www.cyberforum.ru/blogs/469693/8272.html</link>
			<pubDate>Sun, 01 Oct 2023 09:54:58 GMT</pubDate>
			<description>Мотивация 
 
В настоящее время на смену родному для делфи клиент-серверному приложению,...</description>
			<content:encoded><![CDATA[<div><font size="4">Мотивация</font><br />
<br />
В настоящее время на смену родному для делфи клиент-серверному приложению, подключенному намертво к базе данных,<br />
пришли те, что получают данные через HTTP запросы к какому-то API.<br />
В современных версиях делфи есть библиотека REST API, но к ней иногда возникают вопросики по работоспособности.<br />
Чтобы не разбирать чужой сложный код, можно быстро и на коленке написать свою маленькую библиотечку, где будут вызовы к некоему API.<br />
Поехали.<br />
<br />
<font size="4">Общий подход</font><br />
<br />
В общем случае все API примерно одинаковы. REST или нет - все равно.<br />
Поэтому сначала создадим класс, который решает задачу &quot;вообще&quot;, а потом отнаследуем от него другой, который будет обращаться уже к нашему конкретному API.<br />
<br />
У нас всегда есть базовый адрес и конкретные пути для каждого метода API. <br />
Т.е. в класс помещаем поле BaseUrl: string а пути для методов будем добавлять уже при заросе.<br />
Также, для идентификации абонента сервер обычно принимает некий токен. Его получают либо раз и навсегда, либо каждый раз мы должны выполнять метод логин и получать его на сессию работы. <br />
Но поле Token: String тоже добавляем в класс.<br />
Токен чаще всего передается в заголовках запроса, которые имеют вид Name = Value и в делфи есть готовый тип для них в модуле System.Net.URLClient:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="601316975"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="601316975" 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">&nbsp; TNameValuePair <span class="sy3">=</span> <span class="kw1">record</span>
&nbsp; &nbsp; Name<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; Value<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">constructor</span> Create<span class="br0">&#40;</span><span class="kw1">const</span> AName<span class="sy1">,</span> AValue<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; TNameValueArray <span class="sy3">=</span> TArray&lt;TNameValuePair&gt;<span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
Поэтому в нашем классе будет еще поле Headers : TNameValueArray;<br />
и метод, который эти заголовки заполняет.<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="55178205"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="55178205" 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">procedure</span> SetHeaders<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="kw1">virtual</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>естественно, виртуальный, ведь мы не знаем, какие заголовки потребует потом конкретный API-наследник.<br />
Хотя в целом обычно все одинаково. Поэтому изначально смело делаем так, и нам редко придется это менять<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="503219907"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="503219907" 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="kw1">procedure</span> THttpApi<span class="sy1">.</span><span class="me1">SetHeaders</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw3">SetLength</span><span class="br0">&#40;</span>Headers<span class="sy1">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> TNameValuePair<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">'Content-Type'</span><span class="sy1">,</span><span class="st0">'application/json'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> TNameValuePair<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">'Accept'</span><span class="sy1">,</span><span class="st0">'application/json'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> TNameValuePair<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">'Authorization'</span><span class="sy1">,</span>Token<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>предполагаем, что у нас будет API, где туда-обратно будут ходить JSON-строки, поэтому для послылки и для приема данных сделаем поля типа TStringStream<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="639875708"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="639875708" 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">SrcStream <span class="sy1">:</span> TStringStream<span class="sy1">;</span>
ResStream <span class="sy1">:</span> TStringStream<span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><font size="4">Врезочка </font><br />
<br />
для тех, кто не очень в курсе про HTTP<br />
полный адрес (или URI, как его называют) состоит из нескольких частей <br />
(кратко и своими словами. Правильно и полно - например тут <a rel="nofollow noopener noreferrer" href="https://www.geeksforgeeks.org/components-of-a-url/" target="_blank" title="https://www.geeksforgeeks.org/components-of-a-url/">https://www.geeksforgeeks.org/components-of-a-url/</a>)<br />
<div class="codeblock"><table class="html5"><thead><tr><td colspan="2" id="835326876"  class="head">HTML5</td></tr></thead><tbody><tr class="li1"><td><div id="835326876" 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">http://myserver.com/api/v2/orders/2314/item/12?deleted=1<span class="sc1">&amp;sort=name&amp;lang=ru</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>http</b> (иногда https, или еще что-то) - протокол или схема<br />
<b>myserver.com</b> - хост. адрес сервера<br />
<b>api/v2/orders/2314/item/12</b> - путь, или собственно URL - ресурс, который мы запрашиваем у сервера<br />
обратите внимание, в URL бывают параметры - как тут - заказ 2314, строка 12<br />
<b>?deleted=1&amp;sort=name&amp;lang=ru</b>  - query parameters - дополнительные параметры запроса. Отделяются ? и разделены &amp;.<br />
<br />
<font size="4">Возвращаемся к теме</font><br />
<br />
Для формирования итоговой строки URL мы будем использовать BaseUrl = схема + хост + неизменный кусок для API<br />
плюс для каждого метода формируем как остаток URL, так и query params.<br />
Т.е. нам нужны поля<br />
<b>UrlParams, QueryParams</b> и метод <b>MakeUrl : string; virtual;</b><br />
чтобы собрать потом готовый URL для вызова<br />
и то и другое - это обычный TStringList. только первый - просто строки, а второй будет использовать встроенный в StringList функционал Name=Value.<br />
<br />
<font size="4">JSON</font><br />
<br />
В каждый запрос нам нужно передавать JSON. И принимать JSON. И свои объекты упаковывать в JSON и пришедший JSON парсить и создавать по нему объекты. Это называется сериализация и десериализация.<br />
В Делфи есть пара независимых друг от друга реализаций библиотек работы с JSON, можно пользоваться ими. Но мне не нравится их синтаксис, поэтому я обычно пользуюсь симпатичноый маленькой и очень удобной библиотекой <a rel="nofollow noopener noreferrer" href="https://github.com/onryldz/x-superobject" target="_blank" title="https://github.com/onryldz/x-superobject">XSuperObject</a>.<br />
Про сериализацию смотрите отдельный пост этого блога.<br />
<br />
<font size="4">Первый итог</font><br />
<br />
Все готово к тому, чтобы представить базовый класс для совершения запросов на сервер и получения результатов<br />
Поместим его в отдельный юнит и потом будем использовать где попало.<br />
Если б не неrоторые условности, то метод MakeUrl выглядел бы так<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="365162798"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="365162798" 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">function</span> THttpApi<span class="sy1">.</span><span class="me1">MakeUrl</span><span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; result <span class="sy1">:</span><span class="sy3">=</span> BaseURL <span class="sy3">+</span> UrlParams<span class="sy1">.</span><span class="me1">DelimitedText</span> <span class="sy3">+</span> <span class="st0">'?'</span> <span class="sy3">+</span> QueryParams<span class="sy1">.</span><span class="me1">DelimitedText</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>но для передачи параметров не все символы передаются в открытом виде, их надо URL-кодировать<br />
можно самостоятельно, но в Делфи есть класс TUri, который сделает все за нас,<br />
но к нему надо подкинуть недостающие методы. Чтобы не пихать эти методы прямо в API, я сбросил их в отдельный файл.<br />
UUriHelper.pas<br />
без объяснения. просто надо положить рядом<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="942602974"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="942602974" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">unit</span> UUriHelper<span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
<span class="kw1">uses</span> System<span class="sy1">.</span><span class="me1">NetEncoding</span><span class="sy1">,</span> System<span class="sy1">.</span><span class="me1">Net</span><span class="sy1">.</span><span class="me1">URLClient</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">type</span>
&nbsp; TURIHelper <span class="sy3">=</span> <span class="kw1">record</span> helper <span class="kw1">for</span> TURI
&nbsp; &nbsp; <span class="kw1">function</span> FindParameterIndex<span class="br0">&#40;</span><span class="kw1">const</span> AName<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">function</span> ParamExists<span class="br0">&#40;</span><span class="kw1">const</span> AName<span class="sy1">:</span><span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">Boolean</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> AddOrSetParamByName<span class="br0">&#40;</span><span class="kw1">const</span> AName<span class="sy1">,</span>AValue<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; System<span class="sy1">.</span><span class="me1">SysUtils</span><span class="sy1">;</span>
&nbsp;
<span class="coMULTI">{ TURIHelper }</span>
&nbsp;
<span class="kw1">procedure</span> TURIHelper<span class="sy1">.</span><span class="me1">AddOrSetParamByName</span><span class="br0">&#40;</span><span class="kw1">const</span> AName<span class="sy1">,</span> AValue<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; LIndex<span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; LIndex <span class="sy1">:</span><span class="sy3">=</span> FindParameterIndex<span class="br0">&#40;</span>AName<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> LIndex &gt;<span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">then</span>
&nbsp; &nbsp; Parameter<span class="br0">&#91;</span>LIndex<span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> TURIParameter<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span> TNetEncoding<span class="sy1">.</span><span class="me1">URL</span><span class="sy1">.</span><span class="me1">EncodeQuery</span><span class="br0">&#40;</span>AName<span class="br0">&#41;</span><span class="sy1">,</span> TNetEncoding<span class="sy1">.</span><span class="me1">URL</span><span class="sy1">.</span><span class="me1">EncodeQuery</span><span class="br0">&#40;</span>AValue<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; AddParameter<span class="br0">&#40;</span>AName<span class="sy1">,</span> AValue<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">function</span> TURIHelper<span class="sy1">.</span><span class="me1">FindParameterIndex</span><span class="br0">&#40;</span><span class="kw1">const</span> AName<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; I<span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
&nbsp; LName<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Result <span class="sy1">:</span><span class="sy3">=</span> <span class="sy3">-</span><span class="nu0">1</span><span class="sy1">;</span>
&nbsp; LName <span class="sy1">:</span><span class="sy3">=</span> TNetEncoding<span class="sy1">.</span><span class="me1">URL</span><span class="sy1">.</span><span class="me1">EncodeQuery</span><span class="br0">&#40;</span>AName<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">for</span> I <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">to</span> <span class="kw3">Length</span><span class="br0">&#40;</span>Params<span class="br0">&#41;</span> <span class="sy3">-</span> <span class="nu0">1</span> <span class="kw1">do</span>
&nbsp; &nbsp; <span class="kw1">if</span> Params<span class="br0">&#91;</span>I<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Name</span> <span class="sy3">=</span> LName <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; <span class="kw3">Exit</span><span class="br0">&#40;</span>I<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">function</span> TURIHelper<span class="sy1">.</span><span class="me1">ParamExists</span><span class="br0">&#40;</span><span class="kw1">const</span> AName<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">Boolean</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Result <span class="sy1">:</span><span class="sy3">=</span> FindParameterIndex<span class="br0">&#40;</span>AName<span class="br0">&#41;</span>&lt;&gt;<span class="sy3">-</span><span class="nu0">1</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
поэтому будет чуть сложнее и MakeUrl переделан под использование FUri<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="409976521"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="409976521" 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">function</span> THttpApi<span class="sy1">.</span><span class="me1">MakeUrl</span><span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; s <span class="sy1">:</span> <span class="kw4">String</span><span class="sy1">;</span>
&nbsp; name <span class="sy1">:</span> <span class="kw4">String</span><span class="sy1">;</span>
&nbsp; i <span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; s <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">IncludeTrailingPathDelimiter</span><span class="br0">&#40;</span>BaseURL<span class="br0">&#41;</span> <span class="sy3">+</span> UrlParams<span class="sy1">.</span><span class="me1">DelimitedText</span><span class="sy1">;</span>
&nbsp; <span class="co1">// FURI это RECORD поэтому не нужно FURI := TUri.Create(s).</span>
&nbsp; <span class="co1">// можно просто вызвать Create для инициализации полей</span>
&nbsp; FURI<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>s<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">for</span> i <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">to</span> QueryParams<span class="sy1">.</span><span class="me1">Count</span><span class="sy3">-</span><span class="nu0">1</span> <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; name <span class="sy1">:</span><span class="sy3">=</span> QueryParams<span class="sy1">.</span><span class="me1">Names</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; &nbsp; FURI<span class="sy1">.</span><span class="me1">AddOrSetParamByName</span><span class="br0">&#40;</span>name<span class="sy1">,</span>QueryParams<span class="sy1">.</span><span class="me1">Values</span><span class="br0">&#91;</span>name<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; result <span class="sy1">:</span><span class="sy3">=</span> FURI<span class="sy1">.</span><span class="me1">ToString</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="945579109"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="945579109" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">unit</span> HttpApi<span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
<span class="kw1">uses</span>
&nbsp; System<span class="sy1">.</span><span class="me1">Classes</span><span class="sy1">,</span>
&nbsp; System<span class="sy1">.</span><span class="me1">SysUtils</span><span class="sy1">,</span>
&nbsp;
&nbsp; system<span class="sy1">.</span><span class="me1">Net</span><span class="sy1">.</span><span class="me1">HttpClient</span><span class="sy1">,</span>
&nbsp; system<span class="sy1">.</span><span class="me1">Net</span><span class="sy1">.</span><span class="me1">URLClient</span><span class="sy1">,</span>
&nbsp;
&nbsp; XSuperObject
&nbsp; <span class="sy1">;</span>
&nbsp;
<span class="kw1">type</span>
&nbsp; THttpApi <span class="sy3">=</span> <span class="kw1">class</span>
&nbsp; <span class="kw1">protected</span>
&nbsp; &nbsp; FURI<span class="sy1">:</span> TURI<span class="sy1">;</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; BaseURL <span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; Headers<span class="sy1">:</span> TNameValueArray<span class="sy1">;</span>
&nbsp; &nbsp; ResStream<span class="sy1">:</span> TStringStream<span class="sy1">;</span>
&nbsp; &nbsp; SrcStream<span class="sy1">:</span> TStringStream<span class="sy1">;</span>
&nbsp; &nbsp; Token <span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; Response <span class="sy1">:</span> IHTTPResponse<span class="sy1">;</span>
&nbsp; &nbsp; ResultString <span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; ResultJson <span class="sy1">:</span> ISuperObject<span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; UrlParams <span class="sy1">:</span> TStringList<span class="sy1">;</span>
&nbsp; &nbsp; QueryParams <span class="sy1">:</span> TStringList<span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">constructor</span> Create<span class="br0">&#40;</span>ABaseUrl<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="kw1">virtual</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">destructor</span> Destroy<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="kw1">override</span><span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">procedure</span> ClearParams<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> SetHeaders<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="kw1">virtual</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">function</span> MakeUrl <span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">procedure</span> Request<span class="br0">&#40;</span>AHttpMethod<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="coMULTI">{ THttpApi }</span>
&nbsp;
<span class="kw1">constructor</span> THttpApi<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>ABaseUrl <span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; BaseURL <span class="sy1">:</span><span class="sy3">=</span> ABaseUrl<span class="sy1">;</span>
&nbsp; UrlParams <span class="sy1">:</span><span class="sy3">=</span> TStringList<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
&nbsp; UrlParams<span class="sy1">.</span><span class="me1">Delimiter</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'/'</span><span class="sy1">;</span>
&nbsp; QueryParams <span class="sy1">:</span><span class="sy3">=</span> TStringList<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
&nbsp; QueryParams<span class="sy1">.</span><span class="me1">Delimiter</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'&amp;'</span><span class="sy1">;</span>
&nbsp; ResStream <span class="sy1">:</span><span class="sy3">=</span> TStringStream<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">''</span><span class="sy1">,</span> TEncoding<span class="sy1">.</span><span class="me1">UTF8</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; SrcStream <span class="sy1">:</span><span class="sy3">=</span> TStringStream<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">''</span><span class="sy1">,</span> TEncoding<span class="sy1">.</span><span class="me1">UTF8</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">destructor</span> THttpApi<span class="sy1">.</span><span class="me1">Destroy</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>UrlParams<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>QueryParams<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>SrcStream<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>ResStream<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">inherited</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="kw1">function</span> THttpApi<span class="sy1">.</span><span class="me1">MakeUrl</span><span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; s <span class="sy1">:</span> <span class="kw4">String</span><span class="sy1">;</span>
&nbsp; name <span class="sy1">:</span> <span class="kw4">String</span><span class="sy1">;</span>
&nbsp; i <span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; s <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">IncludeTrailingPathDelimiter</span><span class="br0">&#40;</span>BaseURL<span class="br0">&#41;</span> <span class="sy3">+</span> UrlParams<span class="sy1">.</span><span class="me1">DelimitedText</span><span class="sy1">;</span>
&nbsp; <span class="co1">// FURI это RECORD поэтому не нужно FURI := TUri.Create(s).</span>
&nbsp; <span class="co1">// можно просто вызвать Create для инициализации полей</span>
&nbsp; FURI<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>s<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">for</span> i <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">to</span> QueryParams<span class="sy1">.</span><span class="me1">Count</span><span class="sy3">-</span><span class="nu0">1</span> <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; name <span class="sy1">:</span><span class="sy3">=</span> QueryParams<span class="sy1">.</span><span class="me1">Names</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; &nbsp; FURI<span class="sy1">.</span><span class="me1">AddOrSetParamByName</span><span class="br0">&#40;</span>name<span class="sy1">,</span>QueryParams<span class="sy1">.</span><span class="me1">Values</span><span class="br0">&#91;</span>name<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; result <span class="sy1">:</span><span class="sy3">=</span> FURI<span class="sy1">.</span><span class="me1">ToString</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="co1">// перед вызовом Request уже подготовлены все данные в SrcStream </span>
<span class="co1">// и заданы UrlParams и QueruParams</span>
<span class="kw1">procedure</span> THttpApi<span class="sy1">.</span><span class="me1">Request</span><span class="br0">&#40;</span>AHttpMethod<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; http <span class="sy1">:</span> THttpClient<span class="sy1">;</span>
&nbsp; url <span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; http <span class="sy1">:</span><span class="sy3">=</span> THttpClient<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
&nbsp; <span class="kw1">try</span>
&nbsp;
&nbsp; &nbsp; url <span class="sy1">:</span><span class="sy3">=</span> MakeUrl<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; SetHeaders<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> AHttpMethod <span class="sy3">=</span> <span class="st0">'POST'</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; Response <span class="sy1">:</span><span class="sy3">=</span> http<span class="sy1">.</span><span class="me1">Post</span><span class="br0">&#40;</span>url<span class="sy1">,</span> SrcStream<span class="sy1">,</span> ResStream<span class="sy1">,</span> Headers<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> AHttpMethod <span class="sy3">=</span> <span class="st0">'GET'</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; <span class="co1">/// Response := http.get .....</span>
&nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> AHttpMethod <span class="sy3">=</span> <span class="st0">'PUT'</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; <span class="co1">/// Response := http.put .....</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>Response<span class="sy1">.</span><span class="me1">StatusCode</span> <span class="kw1">div</span> <span class="nu0">100</span><span class="br0">&#41;</span> &lt;&gt; <span class="nu0">2</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// если все прошло нормально, код должен быть 2xx (201, 202...) https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">raise</span> Exception<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">'Http request error'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; ResultString <span class="sy1">:</span><span class="sy3">=</span> Response<span class="sy1">.</span><span class="me1">ContentAsString</span><span class="br0">&#40;</span>TEncoding<span class="sy1">.</span><span class="me1">UTF8</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="co1">/// Если все хорошо, то можно попытаться из ResultString получить ResultJson</span>
&nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; ResultJson <span class="sy1">:</span><span class="sy3">=</span> SO<span class="br0">&#40;</span>ResultString<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">except</span>
&nbsp; &nbsp; &nbsp; <span class="co1">/// если строка - не JSON, здесь можно обработать ошибку</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; <span class="kw1">finally</span>
&nbsp; &nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>http<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> THttpApi<span class="sy1">.</span><span class="me1">SetHeaders</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw3">SetLength</span><span class="br0">&#40;</span>Headers<span class="sy1">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Name</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'Content-Type'</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'application/json'</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Name</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'Accept'</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'application/json'</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Name</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'Authorization'</span><span class="sy1">;</span>
&nbsp; Headers<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> Token<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> THttpApi<span class="sy1">.</span><span class="me1">ClearParams</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; UrlParams<span class="sy1">.</span><span class="me1">Clear</span><span class="sy1">;</span>
&nbsp; QueryParams<span class="sy1">.</span><span class="me1">Clear</span><span class="sy1">;</span>
&nbsp; SrcStream<span class="sy1">.</span><span class="me1">Clear</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
в приведенном коде реализован только метод POST, вызовы остальных реализуйте сами по аналогии<br />
отличается только GET, куда не передается SrcStream, т.к. у него нет тела запроса.<br />
<br />
<font size="4">Реализация конкретного API </font><br />
Итак, инструмент у нас теперь есть, давайте посмотрим как его использовать.<br />
Делать это нужно в соответствии с документацией на ваш API.<br />
<br />
Заведем отдельный модуль и класс-наследник общего THttpApi. Этот модуль должен использовать объекты вашей модели данных, предположим, они описаны в модуле MyClasses.pas<br />
Предположим, у нас есть API на адресе <b><a rel="nofollow noopener noreferrer" href="https://server.com/api/v2/" target="_blank" title="https://server.com/api/v2/">https://server.com/api/v2/</a></b><br />
и токен нам дали при регистрации на сайте - XXX-XXX-YYYY<br />
и его нужно помещать в заголовок вида <b>Authorization: Bearer XXX-XXX-YYYY</b><br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="650653492"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="650653492" 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="kw1">unit</span> My<span class="sy1">.</span><span class="me1">Api</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
<span class="kw1">uses</span>
&nbsp; System<span class="sy1">.</span><span class="me1">Classes</span><span class="sy1">,</span>
&nbsp; System<span class="sy1">.</span><span class="me1">SysUtils</span><span class="sy1">,</span>
&nbsp;
&nbsp; system<span class="sy1">.</span><span class="me1">Net</span><span class="sy1">.</span><span class="me1">HttpClient</span><span class="sy1">,</span>
&nbsp;
&nbsp; HttpApi<span class="sy1">,</span>
&nbsp; MyClasses
&nbsp; <span class="sy1">;</span>
&nbsp;
<span class="kw1">type</span>
&nbsp; TMyApi <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>THttpApi<span class="br0">&#41;</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; <span class="kw1">constructor</span> Create<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="coMULTI">{ TMyApi }</span>
&nbsp;
<span class="kw1">constructor</span> TMyApi<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">inherited</span> Create<span class="br0">&#40;</span><span class="st0">'https://server.com/api/v2/'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; token <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'Bearer XXX-XXX-YYYY'</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
теперь разбирая документацию API мы видим метод &quot;добавить заказ&quot;<br />
POST /orders/<br />
туда надо передать JSON<br />
<div class="codeblock"><table class="json"><thead><tr><td colspan="2" id="520569518"  class="head">JSON</td></tr></thead><tbody><tr class="li1"><td><div id="520569518" 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="br0">&#123;</span> items<span class="sy0">:</span> 
&nbsp; <span class="br0">&#91;</span>
&nbsp; <span class="br0">&#123;</span> <span class="st0">&quot;id&quot;</span> <span class="sy0">:</span> <span class="nu0">12</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp;<span class="st0">&quot;name&quot;</span><span class="sy0">:</span><span class="st0">&quot;Товар 1&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp;<span class="st0">&quot;qty&quot;</span> <span class="sy0">:</span> <span class="nu0">5</span>
&nbsp; <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp; <span class="br0">&#123;</span> <span class="st0">&quot;id&quot;</span> <span class="sy0">:</span> <span class="nu0">777</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp;<span class="st0">&quot;name&quot;</span><span class="sy0">:</span><span class="st0">&quot;Товар 2&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp;<span class="st0">&quot;qty&quot;</span> <span class="sy0">:</span> <span class="nu0">11</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#93;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>оттуда придет JSON <br />
<div class="codeblock"><table class="json"><thead><tr><td colspan="2" id="328695580"  class="head">JSON</td></tr></thead><tbody><tr class="li1"><td><div id="328695580" 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="br0">&#123;</span>
&nbsp; <span class="st0">&quot;result&quot;</span><span class="sy0">:</span><span class="st0">&quot;success&quot;</span><span class="sy0">,</span>
&nbsp; <span class="st0">&quot;orderId&quot;</span><span class="sy0">:</span><span class="nu0">174839</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>ессно у нас в модели данных (MyClasses.pas) должен быть подходящий класс<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="264303194"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="264303194" 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">TOrderItem <span class="sy3">=</span> <span class="kw1">class</span>
&nbsp; id <span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
&nbsp; name <span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; qty <span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
TOrder <span class="sy3">=</span> <span class="kw1">class</span>
&nbsp; items <span class="sy1">:</span> TArray&lt;TOrderItem&gt;<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
TOrderRequestResult <span class="sy3">=</span> <span class="kw1">class</span>
&nbsp; result <span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; orderId <span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Все готово для реализации метода &quot;разместить заказ&quot;<br />
<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="868095686"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="868095686" 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="kw1">procedure</span> TMyApi<span class="sy1">.</span><span class="me1">PlaceOrder</span><span class="br0">&#40;</span>AOrder <span class="sy1">:</span> TOrder<span class="sy1">;</span> AResult <span class="sy1">:</span> TOrderRequestResult<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; s <span class="sy1">:</span> <span class="kw4">String</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; ClearParams<span class="sy1">;</span>
&nbsp; UrlParams<span class="sy1">.</span><span class="me1">Add</span><span class="br0">&#40;</span><span class="st0">'orders'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; s <span class="sy1">:</span><span class="sy3">=</span> AOrder<span class="sy1">.</span><span class="me1">AsJSON</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; SrcStream<span class="sy1">.</span><span class="me1">WriteString</span><span class="br0">&#40;</span>s<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; SrcStream<span class="sy1">.</span><span class="me1">Position</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span><span class="sy1">;</span>
&nbsp; Request<span class="br0">&#40;</span><span class="st0">'POST'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="co1">// результат уходит из JSON в переменную AResult</span>
&nbsp; <span class="co1">// иначе она остается как есть</span>
&nbsp; <span class="kw1">if</span> ResultJson &lt;&gt; <span class="kw1">NIL</span> <span class="kw1">then</span>
&nbsp; &nbsp; AResult<span class="sy1">.</span><span class="me1">AssignFromJSON</span><span class="br0">&#40;</span>ResultJson<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>мы подготовили параметры и сделали вызов Request('POST')<br />
если все норм, то у нас есть ResultJson в котором есть поля result и orderId<br />
<br />
в самой программе мы можем единожды создать наш объект<br />
и пользоваться им все время<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="26870159"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="26870159" 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">var</span> api <span class="sy1">:</span> TMyAPI<span class="sy1">;</span>
<span class="sy1">..</span>
<span class="me1">api</span> <span class="sy1">:</span><span class="sy3">=</span> &nbsp;TMyAPI<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="sy1">....</span>
<span class="me1">order</span> <span class="sy1">:</span><span class="sy3">=</span> TOrder<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw3">Setlength</span><span class="br0">&#40;</span>order<span class="sy1">.</span><span class="me1">items</span><span class="sy1">,</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy1">;</span>
order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> &nbsp;TOrderItem<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">id</span> <span class="sy1">:</span><span class="sy3">=</span><span class="nu0">12</span><span class="sy1">;</span>
order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">name</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'Товар 1'</span><span class="sy1">;</span>
order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">qty</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">5</span><span class="sy1">;</span>
order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> &nbsp;TOrderItem<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">id</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">777</span><span class="sy1">;</span>
order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">name</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'Товар 2'</span><span class="sy1">;</span>
order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">qty</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">11</span><span class="sy1">;</span>
res <span class="sy1">:</span><span class="sy3">=</span> TOrderRequestResult<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
api<span class="sy1">.</span><span class="me1">PlaceOrder</span><span class="br0">&#40;</span>order<span class="sy1">,</span> res<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="co1">// в res - результат вызова. в т.ч. id заказа</span>
<span class="kw1">if</span> res<span class="sy1">.</span><span class="me1">result</span> <span class="sy3">=</span> <span class="st0">'success'</span> <span class="kw1">then</span>
&nbsp; newOrderId <span class="sy1">:</span><span class="sy3">=</span> res<span class="sy1">.</span><span class="me1">orderId</span><span class="sy1">;</span>
<span class="co1">// теперь разрушим все что не нужно больше</span>
<span class="kw1">for</span> i <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">to</span> <span class="kw3">length</span><span class="br0">&#40;</span>order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#41;</span> <span class="sy3">-</span> <span class="nu0">1</span> <span class="kw1">do</span>
&nbsp; order<span class="sy1">.</span><span class="me1">items</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">free</span><span class="sy1">;</span>
<span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>order<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>res<span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>P.S.<br />
в коде могут быть неточности, условности и недостача кусков, потому что это не реальный проект, а лишь макет</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/8272.html</guid>
		</item>
		<item>
			<title>How To Store Cross Platform App Settings In JSON</title>
			<link>https://www.cyberforum.ru/blogs/469693/7865.html</link>
			<pubDate>Mon, 19 Dec 2022 08:33:38 GMT</pubDate>
			<description>написал вот статейку ...</description>
			<content:encoded><![CDATA[<div>написал вот статейку <br />
<a rel="nofollow noopener noreferrer" href="https://blogs.embarcadero.com/this-is-how-to-store-cross-platform-app-settings-in-json" target="_blank" title="https://blogs.embarcadero.com/this-is-how-to-store-cross-platform-app-settings-in-json">https://blogs.embarcadero.com/... gs-in-json</a></div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/7865.html</guid>
		</item>
		<item>
			<title><![CDATA[Про "таски"]]></title>
			<link>https://www.cyberforum.ru/blogs/469693/7008.html</link>
			<pubDate>Wed, 03 Mar 2021 05:37:12 GMT</pubDate>
			<description>Про TThread  (https://www.cyberforum.ru/blogs/469693/blog4875.html)стало понятнее. Давайте про...</description>
			<content:encoded><![CDATA[<div>Про <a href="https://www.cyberforum.ru/blogs/469693/blog4875.html">TThread </a>стало понятнее. Давайте про TTask поговорим.<br />
<br />
Обычно все начинают с чтения <a rel="nofollow noopener noreferrer" href="http://www.proghouse.ru/programming/36-delphi-xe7-ppl" target="_blank" title="http://www.proghouse.ru/programming/36-delphi-xe7-ppl">этого </a>блога. Там все написано хорошо, но иногда остаются вопросы.<br />
<br />
Про таски надо размышлять так:<br />
видали в полицейских боевиках брифинг перед операцией?<br />
вот это то же самое<br />
мы проводим брифинг, раздаем каждому задачи, кто что БУДЕТ делать<br />
потом говорим - все! пошли!<br />
и они уходят<br />
а мы остаемся в своем главном потоке <br />
поэтому писать TTask.WaitForAll(tasks); - это плохо<br />
поток встал и ждет когда все вернутся<br />
<br />
более нормальный способ - это сделать новое поле формы <br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="15216959"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="15216959" 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">FRunningTaskCount<span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>перед запуском тасков <br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="984095289"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="984095289" 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">FRunningTaskCount <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">length</span><span class="br0">&#40;</span>tasks<span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>и к каждому заданию прикрутить в конец еще одну часть<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="658733080"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="658733080" 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">TThread<span class="sy1">.</span><span class="me1">Synchronize</span><span class="br0">&#40;</span><span class="kw1">nil</span><span class="sy1">,</span> <span class="kw1">procedure</span> <span class="kw1">begin</span>
&nbsp; <span class="kw3">dec</span><span class="br0">&#40;</span>FRunningTaskCount<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> FRunningTaskCount <span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">then</span>
&nbsp; &nbsp;showMessage<span class="br0">&#40;</span><span class="st0">'Мы всё, босс!'</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>кто закончит последним, тот и поднимет флажок<br />
<br />
у каждой технологии есть свои области применения<br />
поэтому нельзя сказать. что что-то лучше, что-то хуже<br />
надо добавлять &quot;... для выполнения вот этой вот задачи&quot;<br />
<br />
если надо по-быстрому что-то несложное выполнить в потоке - да, таски самое то. <br />
я постоянно ими пользуюсь<br />
НО у них есть ограничения.<br />
<br />
Вернемся на брифинг. Вот ребята, на стене фото преступников, их надо поймать! Все за работу!<br />
И тут выясняется, что работать они убежали наружу, а фото так и остались в комнате на стене!<br />
Т.е. если у вас есть локальная переменная, ее в тасках использовать получится не всегда.<br />
Там есть целая наука про захват переменных, почитаете потом. Но в целом считайте, что ваши фото в кабинете недоступны.<br />
Их надо поместить например, на внешний сервер (сделать глобальную переменную, но лучше поле формы) чтобы все могли их получить.<br />
<br />
Как вы понимаете, под капотом у тасков те же треды, что и ранее, только синтаксис упрощен, чтобы можно было на ходу какие-то вещи делать.<br />
Но в целом, если вам надо выполнить какие-то более-менее сложные вещи, и требуются параметры, лучше завести отдельный класс, как написано в <a href="https://www.cyberforum.ru/blogs/469693/blog4875.html">том месте</a>...<br />
----------------------------------------------------------<br />
<br />
Пример:<br />
<br />
Казалось бы:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="603468676"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="603468676" 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">TForm1 <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
<span class="sy1">....</span>
<span class="me1">FUrlList</span> <span class="sy1">:</span> TStringList<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="sy1">...</span>
<span class="me1">FUrlList</span> <span class="sy1">:</span><span class="sy3">=</span> TStringList<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
FUrlList<span class="sy1">.</span><span class="me1">Add</span><span class="br0">&#40;</span>Url1<span class="br0">&#41;</span><span class="sy1">;</span>
FUrlList<span class="sy1">.</span><span class="me1">Add</span><span class="br0">&#40;</span>Url2<span class="br0">&#41;</span><span class="sy1">;</span>
FUrlList<span class="sy1">.</span><span class="me1">Add</span><span class="br0">&#40;</span>Url3<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw3">setlength</span><span class="br0">&#40;</span>tasks<span class="sy1">,</span> FUrlList<span class="sy1">.</span><span class="me1">count</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">for</span> i <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">to</span> FUrlList<span class="sy1">.</span><span class="me1">count</span> <span class="sy3">-</span> <span class="nu0">1</span> <span class="kw1">do</span>
<span class="kw1">begin</span>
&nbsp; task <span class="sy1">:</span><span class="sy3">=</span> TTask<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">procedure</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy1">.....</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;http <span class="sy1">:</span><span class="sy3">=</span> THttpClient<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;res <span class="sy1">:</span><span class="sy3">=</span> http<span class="sy1">.</span><span class="me1">Get</span><span class="br0">&#40;</span>FUrlList<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy1">..........</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><span class="br0">&#41;</span>
&nbsp; tasks<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> task<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
TTask<span class="sy1">.</span><span class="me1">Start</span><span class="br0">&#40;</span>tasks<span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>мы вроде даем каждому потоку один Url из списка, и он его Get<br />
А вот НЕТ! Это работать не будет.<br />
Всегда помним, что <b>это </b>начнет работать только ПОТОМ, скорее всего когда мы уже даже выйдем из процедуры!<br />
Поэтому никакой переменной I уже не будет и FUrlList[i] будет полной бессмыслицей<br />
так что никаких параметров внутрь вам не передать. сорри.</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/7008.html</guid>
		</item>
		<item>
			<title>Учет ТМЦ</title>
			<link>https://www.cyberforum.ru/blogs/469693/5855.html</link>
			<pubDate>Thu, 13 Jun 2019 06:44:25 GMT</pubDate>
			<description><![CDATA[Очень часто встречаются темы "как перенести товары из одной таблицы в другую", "как при продаже...]]></description>
			<content:encoded><![CDATA[<div>Очень часто встречаются темы &quot;как перенести товары из одной таблицы в другую&quot;, &quot;как при продаже обновить остатки&quot;, &quot;как перед продажей проверить количество на складе&quot;<br />
И все эти темы относятся к классическому <a rel="nofollow noopener noreferrer" href="http://www.gunsmoker.ru/2008/10/x-y-z.html" target="_blank" title="http://www.gunsmoker.ru/2008/10/x-y-z.html">XYZ</a>.<br />
Не нужно так делать.<br />
<br />
Золотой пули конечно нет, но общий подход при любой работе с ценностями - товарами, деньгами, информацией - таков:<br />
ничего не стоит редактировать и удалять, нужно вести <b>регистрацию </b>событий.<br />
<br />
в простейшем чисто учебном случае для магазина нам нужны ДВЕ таблицы<br />
1.справочник товаров<br />
2.таблица движения товаров<br />
<table cellspacing="1" cellpadding="5" class="stg_table tborder"><tbody><tr class="alt2"><td>ID</td><td>время_регистрации</td><td>ID товара</td><td>Количество</td></tr></tbody></table>если количество товара &gt;0 это приход<br />
если количество &lt;0 это расход<br />
тогда кол-во на складе на момент XXX<br />
<div class="codeblock"><table class="sql"><thead><tr><td colspan="2" id="796668881"  class="head">SQL</td></tr></thead><tbody><tr class="li1"><td><div id="796668881" 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">SELECT</span> <span class="kw1">SUM</span><span class="br0">&#40;</span>количество<span class="br0">&#41;</span> <span class="kw1">FROM</span> таблица_движения <span class="kw1">WHERE</span> ID_товара<span class="sy0">=</span>:GOODS_ID <span class="kw1">AND</span> время_регистрации<span class="sy0">&lt;=</span>:XXX</pre></td></tr></table></div></td></tr></tbody></table></div>к этой схеме добавятся клиенты, склады, деньги и т.д. и т.п.<br />
но смысл останется прежний<br />
если что-то можно вычислить выборкой по базе - нужно вычислять...</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5855.html</guid>
		</item>
		<item>
			<title>Резюмешечка)</title>
			<link>https://www.cyberforum.ru/blogs/469693/5765.html</link>
			<pubDate>Tue, 16 Apr 2019 07:07:46 GMT</pubDate>
			<description>Что я успел за эти годы поделать на Делфи? 
Каждый раз, глядя в свое резюме, перебираю в памяти эти...</description>
			<content:encoded><![CDATA[<div>Что я успел за эти годы поделать на Делфи?<br />
Каждый раз, глядя в свое резюме, перебираю в памяти эти программки.<br />
<br />
Первая моя работа - на делфи 2 - я писал распознавание диаграммных лент.<br />
В то время, да и сейчас, работа со сканером - это нифига не общий момент. Пришлось разбираться с TWAIN, сканировать, а потом самое вкусное - распознавать диаграмму, снятую с самописца.<br />
Очень было интересно. Результат - разница с ручной обработкой - до 15-20% ! Это были газовые электростанции. Представляете, с какой точностью считалось там всё? Около 200 диаграммных лент в день...<br />
<br />
Потом была учетная система - свой 1С для компьютерного магазина. Склад, выписка счетов. Работало это в до-интернетную эпоху. Работало хорошо до последних дней маленьких фирм, как наша...<br />
<br />
Потом к теме продаж я возвращался, работая в фирме, поставляющей ПО для аптек. С нуля переписывал Кассу. Очень много узнал и про товары и про аптеки, про фискальные регистраторы, банковские терминалы. Все это сделал плюс систему карт лояльности и сертификатов. Пользователи хвалили. <br />
<br />
Потом была еще маленькая система, не доведенная до коробочного состояния, но рабочая - фотобудка на базе зеркалок Canon.<br />
Съемка, автоматический монтаж с наложением шаблонов, печать на профессиональном фотопринтере. <br />
<br />
Самой большой по объему работой является моя диспетчерская система для Екатеринбургского трамвайно-троллейбусного управления. Сервер по сбору координат всего электротранспорта, обработка, привязка к маршрутам и расписанию, открытие-закрытие линий. Оригинальный движок карты с использованием DirectX. Клиентская программа для диспетчеров. Web-клиенты для диспетчеров. Сервисы для пассажиров. Результаты 10-летного сотрудничества можно посмотреть на ettu.ru<br />
<br />
Два года работал в стартапе ПО для такси. Сделал Android и IOS - приложения на кроссплатформе Delphi. Диспетчерскую программу на Windows. Не знаю, какова сейчас судьба этого стартапа, когда вокруг сплошной Yandex... )))<br />
<br />
Для личных целей с 1991 года создавал систему Autoskating для обслуживания танцевальных турниров. Туда входят БД, клиентская программа для Windows, судейское приложение для Android, web-сервер для онлайн-табло.<br />
В настоящее время на базе этой системы работает сайт ftsso.ru и новый стартап - danceoffice.online, проводятся соревнования по спортивным танцам, а также различные социальные фесты...<br />
<br />
На момент написания этого текста трудился программистом в компании Эльдорадо...<br />
С тех пор прошло еще много лет.<br />
<br />
Сейчас работаю в финтех-ит-компании в СПб. <br />
Тоже на Делфи.</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5765.html</guid>
		</item>
		<item>
			<title>Что не так с Form1.Caption</title>
			<link>https://www.cyberforum.ru/blogs/469693/5465.html</link>
			<pubDate>Tue, 18 Sep 2018 19:19:58 GMT</pubDate>
			<description>Очень распространенная ошибка новичков это обращение в методах класса к переменным этого же класса...</description>
			<content:encoded><![CDATA[<div>Очень распространенная ошибка новичков это обращение в методах класса к переменным этого же класса<br />
Почему это распространено - да потому что Delphi с доисторических времен при создании формы создает не только класс, ее описывающий, но и переменную этого класса, и даже автоматически создает объект и хранит его в этой переменной<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="617597131"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="617597131" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">TForm1<span class="sy3">=</span><span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
<span class="sy1">...</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">var</span>
&nbsp; Form1<span class="sy1">:</span> TForm1<span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>и новичкам кажется что это такое специальное волшебство и так и должно быть.<br />
Я думаю, как раз наоборот, если бы этого не было, огромного количества ошибок архитектурных и всяких других можно было бы избежать...<br />
Немного про формы я писал тут <a href="https://www.cyberforum.ru/blogs/469693/blog4873.html">https://www.cyberforum.ru/blog... g4873.html</a><br />
<br />
Очень подходит аналогия, что TForm1 - это комплект чертежей некоего автомобиля<br />
а Form1 - это готовый созданный автомобиль с личным номером.<br />
<br />
Если мы в чертежах используем этот личный номер, то все работает только пока этот объект выпускается в единственном экземпляре. Формы у начинающих примерно так и работают. Одна форма - одна переменная. На самом деле это вовсе не так.<br />
Мы должны помнить, что поля и методы класса доступны в других методах этого же класса<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="85314112"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="85314112" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="kw1">procedure</span> TForm1<span class="sy1">.</span><span class="me1">MyProcedure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Caption <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'123'</span><span class="sy1">;</span>
&nbsp; Width <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">800</span><span class="sy1">;</span>
&nbsp; Hieght <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">600</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>при этом одинаковых форм такого типа мы можем создать сколько угодно.<br />
желательно еще и не используя глобальные переменные (опять посылаю прочитать статью о формах)<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="384651130"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="384651130" 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">form1 <span class="sy1">:</span><span class="sy3">=</span> TForm1<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">NIL</span><span class="br0">&#41;</span><span class="sy1">;</span>
f<span class="sy1">:</span><span class="sy3">=</span>TForm1<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">NIL</span><span class="br0">&#41;</span><span class="sy1">;</span>
aaaaa <span class="sy1">:</span><span class="sy3">=</span> TForm1<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">NIL</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>но если мы напишем<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="232520536"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="232520536" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="kw1">procedure</span> TForm1<span class="sy1">.</span><span class="me1">MyProcedure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; form1<span class="sy1">.</span><span class="me1">Caption</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'123'</span><span class="sy1">;</span>
&nbsp; form1<span class="sy1">.</span><span class="me1">Width</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">800</span><span class="sy1">;</span>
&nbsp; form1<span class="sy1">.</span><span class="me1">Hieght</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">600</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>а потом <br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="660405481"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="660405481" 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">f<span class="sy1">:</span><span class="sy3">=</span>TForm1<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">NIL</span><span class="br0">&#41;</span><span class="sy1">;</span>
f<span class="sy1">.</span><span class="me1">MyProcedure</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>то выскочит ошибка Access Violation, потому что в методе мы вместо полей объекта F который только что создали, обращаемся к Form1, который даже и не создан<br />
А если он создан, то на форуме появляются темы. Я ставлю Width := 800 а форма не меняется<br />
При этом форма создана заново, а все изменения уходят в Form1, которая например, не видна сейчас...</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5465.html</guid>
		</item>
		<item>
			<title>Delphi Community Edition</title>
			<link>https://www.cyberforum.ru/blogs/469693/5369.html</link>
			<pubDate>Sun, 29 Jul 2018 13:48:09 GMT</pubDate>
			<description>Свершилось чудо. 
Июль 2018 ! 
Делфи получила бесплатную версию. Community Edition 
Про Starter не...</description>
			<content:encoded><![CDATA[<div>Свершилось чудо.<br />
Июль 2018 !<br />
Делфи получила бесплатную версию. Community Edition<br />
Про Starter не напоминайте. Она урезана по самое не хочу.<br />
<br />
Это практически полная версия Delphi Professional. Не забываем, что недавно в Professional поместили еще и Mobile Pack!!!<br />
Можно писать для Win32, Win64, Andriod. Про IOS пока точно не скажу. Должно быть.<br />
Ограничение в $5000 дохода.<br />
Если вы получите столько со своего Делфи-продукта - должны купить.<br />
<br />
Ну, еще клиент FireDAC имеет доступ только к локальным серверам БД<br />
<br />
Так что все, кто еще на пиратской D7, пора обновляться!<br />
<a rel="nofollow noopener noreferrer" href="https://www.embarcadero.com/ru/products/delphi/starter" target="_blank" title="https://www.embarcadero.com/ru/products/delphi/starter">https://www.embarcadero.com/ru... hi/starter</a><br />
<br />
<a rel="nofollow noopener noreferrer" href="https://youtu.be/_DXtU_8QdVE" target="_blank" title="https://youtu.be/_DXtU_8QdVE">https://youtu.be/_DXtU_8QdVE</a></div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5369.html</guid>
		</item>
		<item>
			<title>Индикатор загрузки</title>
			<link>https://www.cyberforum.ru/blogs/469693/5310.html</link>
			<pubDate>Sun, 24 Jun 2018 06:08:53 GMT</pubDate>
			<description>Встречаются два вида долгих операций 
Прогресс одних мы знаем и можем вывести в процентах....</description>
			<content:encoded><![CDATA[<div>Встречаются два вида долгих операций<br />
Прогресс одних мы знаем и можем вывести в процентах. Например, состояние расчета или скачивание большого файла.<br />
Другие операции неизвестно сколько времени займут, а иногда и вообще неизвестно, закончатся ли.<br />
<br />
При проектировании интерфейса нужно запомнить одно<br />
Сама <b>операция </b>должна быть вынесена в <b>отдельный </b>поток. А <b>индикатор </b>должен крутиться <b>в главном</b>.<br />
<br />
Общая идея<br />
1. Стартовать индикатор (открыть форму, сделать активной анимацию или еще что-то в этом духе)<br />
2. Создать класс потока<br />
3. Если у потока есть прогресс, то дать потоку ссылку на обработчик прогресса<br />
4. Дать потоку ссылку на обработчик окончания потока<br />
5. Запустить поток<br />
подробнее о потоках - тут<br />
<a href="https://www.cyberforum.ru/blogs/469693/blog4875.html">https://www.cyberforum.ru/blog... g4875.html</a><br />
Если мы хотим сделать таймаут, то можно воспользоваться простым таймером на N мсек<br />
В классе потока предусмотреть флажок Актуальный.<br />
Если происходит выход по OnTerminate, проверять, если поток НЕ актуальный, просто ничего не делать.<br />
Он убьет себя сам. (в статье выше предлагается использование FreeOnTerminate потоков)<br />
Если поток актуальный, то нужно не забыть остановить таймер.<br />
Если таймер сработает, значит, его не отключали и нужно сделать поток НЕ Актуальным.<br />
Возможно в этот момент нужно сообщить пользователю про таймаут и спросить, не хочет ли он попробовать еще раз.</div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/7z.gif" alt="Тип файла: 7z" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=8434&amp;d=1703432362">ProgressBarThread.7z</a> (1.6 Кб, 269 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5310.html</guid>
		</item>
		<item>
			<title>Использование Firebird вместо ADO</title>
			<link>https://www.cyberforum.ru/blogs/469693/5298.html</link>
			<pubDate>Tue, 12 Jun 2018 06:16:08 GMT</pubDate>
			<description>Итак, после статьи Что не так с ADO (https://www.cyberforum.ru/blogs/469693/blog5297.html) нужно...</description>
			<content:encoded><![CDATA[<div>Итак, после статьи <a href="https://www.cyberforum.ru/blogs/469693/blog5297.html">Что не так с ADO</a> нужно предложить альтернативу страдающим школьникам на древней как фекалии мамонта D7.<br />
<br />
Начиная с Delphi 7 есть прекрасный альтернативный вариант - бесплатная (а не пиратский Access !) БД Firebird и компоненты IBX<br />
с чудной документацией <a rel="nofollow noopener noreferrer" href="https://www.ibase.ru/ibx/" target="_blank" title="https://www.ibase.ru/ibx/">https://www.ibase.ru/ibx/</a><br />
Для управления этой БД так же лицензионно-халявно идет IBExpert - прекрасное средство управления БД Firebird/Interbase<br />
<a rel="nofollow noopener noreferrer" href="http://www.ibexpert.com/rus/ibe_sfx.exe" target="_blank" title="http://www.ibexpert.com/rus/ibe_sfx.exe">http://www.ibexpert.com/rus/ibe_sfx.exe</a><br />
если вы не хотите/не можете установить себе полный сервер, можете скачать Embedded вариант, не требующий установки<br />
это несколько DLL, которые нужны для работы в ОДНОПОЛЬЗОВАТЕЛЬСКОМ режиме<br />
Если положить файлы из прикрепленного архива <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4852&amp;d=1528783255" >FB_embed_25.7z</a> рядом с вашим EXE, то можно работать с базой вообще не устанавливая сервер<br />
<br />
Для тех, кто сервер будет устанавливать, лучше взять версию 2.5. Она проще для начальной настройки.<br />
Пара моментов перед установкой<br />
1. Брать версию Win32. Ваша программа - 32бит.Работать она будет в 32 бит окружении. Несмотря на то, что Windows - 64 бит<br />
2. При установке вместо далекого каталога C:\Program Files\blablablba... выберите что поближе - к-нить простой C:\Firebird<br />
Лучше, если вы впишете это руками, там в установщике баг, и если выбрать C:\Firebird, то сервер встанет в C:\Firebird\Firebird...<br />
3. Устанавливать вариант Full server install<br />
4. Не надо копировать fbclient.dll в GDS32 для старых программ. Также не надо копировать fbclient.dll в системный каталог. <br />
5. Не надо устанавливать Guardian сервис. Это для времен Win98. Сейчас - не надо вообще.<br />
<br />
инсталлятор брать тут. Win 32 !<br />
<a rel="nofollow noopener noreferrer" href="http://www.firebirdsql.org/en/firebird-2-5/" target="_blank" title="http://www.firebirdsql.org/en/firebird-2-5/">http://www.firebirdsql.org/en/firebird-2-5/</a><br />
<br />
Лучшая проверка, что все встало нормально - запустить IBExpert и подключиться к какой-нибудь БД<br />
Или создать новую БД. Не забудьте указывать полный путь к fbclient.dll чтобы все было нормально.<br />
<br />
Если вам повезло, и вы сидите на новой версии Delphi XE4 и выше, то для вас из коробки есть комплект доступа к БД FireDAC<br />
Им и пользуйтесь.<br />
Документация на оф сайте отменная. Переводчик гугл справляется с ней прекрасно</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5298.html</guid>
		</item>
		<item>
			<title>Что не так с ADO</title>
			<link>https://www.cyberforum.ru/blogs/469693/5297.html</link>
			<pubDate>Tue, 12 Jun 2018 05:54:15 GMT</pubDate>
			<description>Технология и компоненты ADO в силу некоторых причин на этом форуме пользуется абсолютно...</description>
			<content:encoded><![CDATA[<div>Технология и компоненты ADO в силу некоторых причин на этом форуме пользуется абсолютно незаслуженной популярностью.<br />
На самом же деле, ОСОБЕННО если вы новичок, то вы получаете не более простое, а наоборот, <b>наиболее сложное</b> решение ваших задач по работе с БД.<br />
<br />
<font size="3"><font color="DarkRed">Как правильно подключаться к БД</font></font><br />
Ваша программа и БД только во время разработки будет лежать в определенном вами месте. Как только вы перейдете на другой компьютер, все начнет ломаться. Поэтому делайте так:<br />
<a href="https://www.cyberforum.ru/delphi-database/thread957133.html#post5070920">https://www.cyberforum.ru/delp... ost5070920</a><br />
<br />
<font size="3"><font color="DarkRed">ADOTable - плохо</font></font><br />
Вернемся к работе с БД<br />
Самый казалось бы простой способ - это подключаться к таблицам через <b>ADOTable</b>.<br />
И это капец как <b>плохо</b>.<br />
Если вы обучаетесь работать с БД, вы сразу должны иметь в виду, что к одной БД всегда подключается много пользователей.<br />
Если одна ваша программа утянет к себе какую-нибудь таблицу и начнет у себя ее менять, другая, третья, то при записи выяснится, что у нас несколько копий одной и той же таблицы. В лучшем случае вторая копия сотрет первую, третья - вторую, и мы получим - кто последний сохранился, те данные и будут жить в БД. Жестоко. А если к этим данным привязаны (а должны быть привязаны! это же реляционная БД) данные из других таблиц, то все рассыплется окончательно.<br />
Так что лучший вариант, если один залез в БД, другого уже не пускать. <br />
Отличная система получилась? Один сервер - один клиент. Один магазин - одна касса. Один паспортный стол - одно окно, и т.д. <br />
Я уже уверен, что ваши будущие клиенты оценят )))<br />
<br />
<font size="3"><font color="darkred">ADOQuery - лучше</font></font><br />
Так что хочешь - не хочешь, придется писать запросы и действовать через ADOQuery<br />
Что нужно знать.<br />
Запросы пишутся на универсальном языке SQL и бывают четырех видов<br />
SELECT, UPDATE, INSERT, DELETE<br />
Только SELECT возвращает вам набор данных (датасет) для работы с ними или отображения на экране<br />
Если в Query - SELECT, то запрос &quot;открывается&quot;. Нужно писать Query.Open.<br />
Если в Query - INSERT, UPDATE, DELETE, то запрос &quot;исполняется&quot; и соответственно мы пишем Query.ExecSQL<br />
учебник по SQL здесь<br />
<a rel="nofollow noopener noreferrer" href="http://www.sql.ru/docs/sql/u_sql/" target="_blank" title="http://www.sql.ru/docs/sql/u_sql/">http://www.sql.ru/docs/sql/u_sql/</a><br />
справочников много, например вот<br />
<a rel="nofollow noopener noreferrer" href="https://www.w3schools.com/sql/default.asp" target="_blank" title="https://www.w3schools.com/sql/default.asp">https://www.w3schools.com/sql/default.asp</a><br />
<br />
<font size="3"><font color="darkred">Где размещать компоненты</font></font><br />
Конечно, на отдельном <b>модуле данных</b>. Он похож на форму, только невидим во время работы программы.<br />
На нем будет один компонент подключения к БД ADOConnection, и к нему будут подключаться все ваши датасеты.<br />
<br />
Для начинающих писателей хочу порекомендовать два способа создания модуля данных в программе.<br />
Каждый из них начинается с File -- New -- Other -- Delphi Files -- Datamodule<br />
В свойство Name модуля данных напишите DM. Нажмите Ctrl+S и дайте файлу имя например UDM.pas<br />
Не забудьте во всех модулях (юнитах) своей программы, которые будут обращаться к БД, вписать в USES обращение к UDM!<br />
Примерно так<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="333580279"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="333580279" 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">uses</span>
&nbsp; Windows<span class="sy1">,</span> Classes<span class="sy1">,</span> Types<span class="sy1">,</span> <span class="sy1">.......,</span> UDM<span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Теперь <b>первый вариант</b><br />
После этого зайдите в Project -- Options -- Forms и удалите из списка AutoCreate ВСЕ формы, КРОМЕ модуля данных и главной формы вашего приложения. При этом модуль данных поставьте в списке первым.<br />
По поводу форм <a href="https://www.cyberforum.ru/blogs/469693/blog4873.html">читайте здесь</a><br />
В событии OnCreate модуля данных впишите подключение к БД способом, который я описал выше в разделе &quot;Как правильно подключаться к БД&quot;<br />
<br />
<b>Второй вариант</b> более продвинутый и более верный в реальной жизни.<br />
Его лучше применять, когда у вашей программы есть еще какие-нибудь настройки. В том числе и к какой БД подключаться.<br />
Как хранить настройки программы, есть рекомендация <a href="https://www.cyberforum.ru/blogs/469693/blog4883.html">тут</a><br />
А весь процесс старта программы вместе с чтением настроек и подключением к БД я описал <a href="https://www.cyberforum.ru/blogs/469693/blog4884.html">тут</a><br />
Так вот. В этом случае логично все делать при создании главной формы - и прочитать настройки и создать модуль данных<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="533180637"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="533180637" 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">DM <span class="sy1">:</span><span class="sy3">=</span> TDM<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">Self</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Поэтому мы опять же идём в Project -- Options -- Forms, но удаляем из списка AutoCreate вообще ВСЕ формы, кроме главной формы<br />
<br />
Теперь при подключении DB-компонентов, например TDataSource, в свойстве Dataset у вас будут отображаться и те Query, которые находятся на вашем модуле данных. Если это не так, значит, вы пропустили мимо ушей мое замечание насчет Uses несколькими строками выше.<br />
<br />
Соответственно, в программе обращение к компоненту Query1 на модуле данных будет выглядеть так:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="245794402"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="245794402" 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">dm<span class="sy1">.</span><span class="me1">Query1</span><span class="sy1">.</span>блаблабла</pre></td></tr></table></div></td></tr></tbody></table></div><font size="3"><font color="darkred">Так что с редактированием?</font></font><br />
Допустим, мы сделали запрос в БД, и показали его результаты в DBGrid.<br />
Теперь нам нужно а) редактировать текущую запись б) вставить новую запись в) удалить текущую запись<br />
Как ни прискорбно, но ПОСЛЕ всех трех операций никакого результата в гриде вы не увидите. Ведь мы смотрим на РЕЗУЛЬТАТ запроса, который выполнили некоторое время назад, когда еще ничего не изменяли, не вставляли и не удаляли. <br />
Никакой магической связи между этими данными и БД нет!!!<br />
Хотите обновить информацию - делайте запрос заново.<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="305319024"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="305319024" 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">Query<span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
Query<span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><i>Что хочется сразу сказать.<br />
Дорогие писатели! Не жмотьтесь, не пытайтесь все запросы исполнять в одном Query компоненте<br />
Лучше всего все запросы, хотя бы все SELECT'ы, заранее, в design-time, собрать в отдельные Query в нашем модуле данных и оставить их в покое. Если вам нужны условия в этих запросах, то <a href="https://www.cyberforum.ru/blogs/469693/blog5254.html">прочтите это</a><br />
</i><br />
<br />
Так вот начнем с конца. в) <b>Удаление</b>.<br />
<a rel="nofollow noopener noreferrer" href="https://www.w3schools.com/Sql/sql_delete.asp" target="_blank" title="https://www.w3schools.com/Sql/sql_delete.asp">https://www.w3schools.com/Sql/sql_delete.asp</a><br />
Основной идеей работы с БД является то, что любая запись должна иметь КЛЮЧ - поле, или набор полей, по которому эту запись ОДНОЗНАЧНО можно найти среди всех других. Чаще всего это какое-то поле с названием ID, и чаще всего автоинкрементное, чтобы разработчику не пришлось придумывать его самостоятельно.<br />
Обычно это поле всегда нужно включать в запрос, но почти всегда его не нужно показывать пользователю, т.к. это служебная информация.<br />
Поэтому для удаления записи из qYourQuery берем к-нить (ДРУГОЙ!!!) query, назовем его qDelete, и выполняем<br />
(вы же уже прочли про параметры?)))<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="169109524"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="169109524" 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">dm<span class="sy1">.</span><span class="me1">qDelete</span><span class="sy1">.</span><span class="me1">SQL</span><span class="sy1">.</span><span class="me1">Text</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'DELETE from ВАШАТАБЛИЦА WHERE ID=:ID'</span><span class="sy1">;</span>
dm<span class="sy1">.</span><span class="me1">qDelete</span><span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'ID'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'ID'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsInteger</span><span class="sy1">;</span>
dm<span class="sy1">.</span><span class="me1">qDelete</span><span class="sy1">.</span><span class="me1">ExecSQL</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>и не забудем, что теперь нужно переоткрыть ваш запрос<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="377556679"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="377556679" 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">dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Запись исчезла<br />
<br />
а)<b> редактирование записи</b><br />
 Компонент DataSource обеспечивает некторое волшебство в вашей программе. Когда вы перемещаетесь по DBGrid любым способом, то точно так же перемещается указатель на текущую запись в подключенном к нему датасете. И наоборот. Если выполнить любую команду на перемещение в датасете - First, Last, Next, то в DBGrid'е вы сразу же переместитесь на текущую запись. Отсюда мораль. Если вы дважды кликнете на DBGrid, то можно просто открыть новую форму и работать в ней с текущей записью вашего датасета.<br />
Вот <a href="https://www.cyberforum.ru/blogs/469693/blog4873.html">тут</a> я уже говорил, что самое частое использование форм это - модальный диалог.<br />
Напишем вызов формы редактирования текущей записи по двойному клику на DBGrid'е<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="605274533"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="605274533" 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">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">DBGrid1DblClick</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span><span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; RunEditForm<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">RunEditForm</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span> f<span class="sy1">:</span>TEditForm<span class="sy1">;</span>
&nbsp; ID<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; f<span class="sy1">:</span><span class="sy3">=</span>TEditForm<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">NIL</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; <span class="co1">// подготавливаем форму к показу. заполняем ее поля. настраиваем настройки</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">Load</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="co1">// загрузка в Edit'ы текущих значений из датасета</span>
&nbsp; &nbsp; <span class="co1">// показываем модально и ждем результата</span>
&nbsp; &nbsp; <span class="kw1">if</span> f<span class="sy1">.</span><span class="me1">ShowModal</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy3">=</span>mrOK <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">Save</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="co1">// сохранение данных из формы в БД</span>
&nbsp; &nbsp; &nbsp; <span class="co1">// а это - чтобы после переоткрытия опять встать на ту запись, которую редактировали, а не на первую, как обычно</span>
&nbsp; &nbsp; &nbsp; ID<span class="sy1">:</span><span class="sy3">=</span>dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'ID'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsInteger</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">Locate</span><span class="br0">&#40;</span><span class="st0">'ID'</span><span class="sy1">,</span>ID<span class="sy1">,</span><span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; <span class="kw1">finally</span>
&nbsp; &nbsp; <span class="co1">// и уничтожаем форму</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">free</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>всё просто. создали форму, заполнили ее, показали, сохранили результат, убили, чтобы не болталась...<br />
в самой же форме редактирования мы расставляем edit'ы и пишем две процедуры, упомянутые в коде выше<br />
Load() и Save()<br />
(ясно ж, что для доступа к данным из модуля данных нам нужно в Uses у формы редактирования не забыть добавить UDM?)<br />
из головы выдумаем форму - на ней два Edit'а - Фамилия, Имя, один DateTimePicker - Дата рождения - в режиме отображения даты, и один RadioGroup - пол М/Ж соответственно.<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="412323191"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="412323191" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">procedure</span> TEditForm<span class="sy1">.</span><span class="me1">Load</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; eLastName<span class="sy1">.</span><span class="me1">Text</span> <span class="sy1">:</span><span class="sy3">=</span> dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'LastName'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsString</span><span class="sy1">;</span>
&nbsp; eFirstName<span class="sy1">.</span><span class="me1">Text</span> <span class="sy1">:</span><span class="sy3">=</span> dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'FirstName'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsString</span><span class="sy1">;</span>
&nbsp; dtBirthDate<span class="sy1">.</span><span class="me1">Date</span> <span class="sy1">:</span><span class="sy3">=</span> &nbsp;dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'BirthDate'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsDateTime</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'Gender'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsString</span> <span class="sy3">=</span> <span class="st0">'F'</span> <span class="kw1">then</span>
&nbsp; &nbsp; rgGender<span class="sy1">.</span><span class="me1">ItemIndex</span><span class="sy1">:</span><span class="sy3">=</span><span class="nu0">1</span>
&nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; rgGender<span class="sy1">.</span><span class="me1">ItemIndex</span><span class="sy1">:</span><span class="sy3">=</span><span class="nu0">0</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TEditForm<span class="sy1">.</span><span class="me1">Save</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; dm<span class="sy1">.</span><span class="me1">qUpdate</span><span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'LastName'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> eLastName<span class="sy1">.</span><span class="me1">Text</span><span class="sy1">;</span>
&nbsp; dm<span class="sy1">.</span><span class="me1">qUpdate</span><span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'FirstName'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> eFirstName<span class="sy1">.</span><span class="me1">Text</span><span class="sy1">;</span>
&nbsp; dm<span class="sy1">.</span><span class="me1">qUpdate</span><span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'BirthDate'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> dtBirthDate<span class="sy1">.</span><span class="me1">Date</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> rgGender<span class="sy1">.</span><span class="me1">ItemIndex</span> <span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">then</span>
&nbsp; &nbsp; dm<span class="sy1">.</span><span class="me1">qUpdate</span><span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'Gender'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'M'</span>
&nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; dm<span class="sy1">.</span><span class="me1">qUpdate</span><span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'Gender'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'F'</span><span class="sy1">;</span>
&nbsp; dm<span class="sy1">.</span><span class="me1">qUpdate</span><span class="sy1">.</span><span class="me1">ExecSQL</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>qUpdate - это наш запрос обновления записи<br />
описание тут <a rel="nofollow noopener noreferrer" href="https://www.w3schools.com/Sql/sql_update.asp" target="_blank" title="https://www.w3schools.com/Sql/sql_update.asp">https://www.w3schools.com/Sql/sql_update.asp</a><br />
ессссно используем <a href="https://www.cyberforum.ru/blogs/469693/blog5254.html">параметры</a>, потому что иначе проще убиться, чем написать запрос без ошибок<br />
<br />
<br />
и осталась у нас б) <b>вставка записи</b>.<br />
но постойте, не делать же другую форму для вставки?<br />
делать то надо то же самое, только поля в начале пустые и параметры сохранять надо не в qUpdate а в qInsert.<br />
(qInsert это еще один наш Query, в котором запрос на вставку данных)<br />
пишется вот так <a rel="nofollow noopener noreferrer" href="https://www.w3schools.com/Sql/sql_insert.asp" target="_blank" title="https://www.w3schools.com/Sql/sql_insert.asp">https://www.w3schools.com/Sql/sql_insert.asp</a><br />
<br />
сделаем офигенную хитрость<br />
параметры в запросах назовем одинаково, а сам Query будем передавать в процедуру Save параметром!!!<br />
итак!<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="701654748"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="701654748" 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">procedure</span> TEditForm<span class="sy1">.</span><span class="me1">Save</span><span class="br0">&#40;</span>q<span class="sy1">:</span>TQuery<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; q<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'LastName'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> eLastName<span class="sy1">.</span><span class="me1">Text</span><span class="sy1">;</span>
&nbsp; q<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'FirstName'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> eFirstName<span class="sy1">.</span><span class="me1">Text</span><span class="sy1">;</span>
&nbsp; q<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'BirthDate'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> dtBirthDate<span class="sy1">.</span><span class="me1">Date</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> rgGender<span class="sy1">.</span><span class="me1">ItemIndex</span> <span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">then</span>
&nbsp; &nbsp; q<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'Gender'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'M'</span>
&nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; q<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'Gender'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'F'</span><span class="sy1">;</span>
&nbsp; q<span class="sy1">.</span><span class="me1">ExecSQL</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>и всё!!!<br />
теперь перепишем чучуть вызов RunEditForm()<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="82769304"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="82769304" 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="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">RunEditForm</span><span class="br0">&#40;</span>InsertMode<span class="sy1">:</span><span class="kw4">boolean</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span> f<span class="sy1">:</span>TEditForm<span class="sy1">;</span>
&nbsp; ID<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; f<span class="sy1">:</span><span class="sy3">=</span>TEditForm<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">NIL</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> InsertMode <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">Load</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span> 
&nbsp; &nbsp; <span class="kw1">if</span> f<span class="sy1">.</span><span class="me1">ShowModal</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy3">=</span>mrOK <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> InsertMode <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">Save</span><span class="br0">&#40;</span>dm<span class="sy1">.</span><span class="me1">qInsert</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">Save</span><span class="br0">&#40;</span>dm<span class="sy1">.</span><span class="me1">qUpdate</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; ID<span class="sy1">:</span><span class="sy3">=</span>dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'ID'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsInteger</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; dm<span class="sy1">.</span><span class="me1">qYourQuery</span><span class="sy1">.</span><span class="me1">Locate</span><span class="br0">&#40;</span><span class="st0">'ID'</span><span class="sy1">,</span>ID<span class="sy1">,</span><span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; <span class="kw1">finally</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">free</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>соответственно при вставке вызываем теперь RunEditForm(true);<br />
при редактировании RunEditForm(false);<br />
<br />
и все это нагорожено исключительно из-за того, что у нас нет адекватного компонента DBDataset<br />
поэтому если есть любая возможность, не пользуйтесь ADO!<br />
А альтернативные варианты есть!<br />
<a href="https://www.cyberforum.ru/blogs/469693/blog5298.html">https://www.cyberforum.ru/blog... g5298.html</a></div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5297.html</guid>
		</item>
		<item>
			<title>Пишем тест. Уровень Beginner. Урок 1</title>
			<link>https://www.cyberforum.ru/blogs/469693/5262.html</link>
			<pubDate>Sat, 19 May 2018 15:28:13 GMT</pubDate>
			<description>Давайте еще раз. Напишем очередной тест 
 
Раз пошла такая пьянка, делаем полный разбор, начиная с...</description>
			<content:encoded><![CDATA[<div>Давайте еще раз. Напишем очередной тест<br />
<br />
Раз пошла такая пьянка, делаем полный разбор, начиная с проектирования<br />
Что нам нужно знать о программе<br />
<font size="3"><b>Хранение данных.</b> </font><br />
Первое что надо обдумать. Сейчас думать не будем вообще, потому что уровень Beginner.<br />
Пусть у нас есть текстовый файл, который содержит две строки в начале <br />
первая - какой-то текст, вторая - число - количество вопросов в файле<br />
а после этого идут блоки в соответстви с кол-вом вопросов. каждый блок состоит из 6 строк<br />
<b><i>текст вопроса<br />
вариант ответа1<br />
вариант ответа2<br />
вариант ответа3<br />
вариант ответа4<br />
номер правильного ответа</i></b><br />
после этого сразу блок следующего вопроса<br />
В программе вопрос пусть хранится в записи<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="855713957"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="855713957" 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">TQuestion<span class="sy3">=</span><span class="kw1">record</span>
&nbsp; Q<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span> <span class="co1">// текст вопроса</span>
&nbsp; A<span class="sy1">:</span><span class="kw1">array</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="sy1">..</span><span class="nu0">3</span><span class="br0">&#93;</span> <span class="kw1">of</span> <span class="kw4">string</span><span class="sy1">;</span> <span class="co1">// варианты ответа 1..4</span>
&nbsp; Right<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span> <span class="co1">// номер правильного варианта 1..4</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>соответственно, у нас есть массив вопросов<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="323773718"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="323773718" 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">var</span> &nbsp; &nbsp;Questions<span class="sy1">:</span><span class="kw1">array</span> <span class="kw1">of</span> TQuestion<span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Думаю, что пусть будет и массив ответов<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="396787895"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="396787895" 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">var</span> &nbsp; &nbsp;Answers<span class="sy1">:</span><span class="kw1">array</span> <span class="kw1">of</span> <span class="kw4">integer</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>чтобы все было совсем хорошо, создадим отдельный юнит File--New--Unit, куда сложим все наши классы<br />
Комплект классов и переменных будет важно называться нашей моделью данных ))<br />
кроме TQuestion пусть там еще лежит класс глобальных переменных программы TMySettings<br />
и все процедуры, которые нужны для работы с моделью<br />
назовем юнит UMyClasses.pas<br />
обратим внимание на то, что этот юнит ничего не знает о форме, компонентах и прочей беде<br />
только работа с самими данными<br />
<br />
первая функция, которая туда попала - function ReadQuestionsFromFile(Filename:string):S tring;<br />
на входе имя файла, на выходе - та самая первая строка из файла. ХЗ почему, просто так, чужой файл взял для образца<br />
итого у нас сейчас вот такой файл UMyClasses.pas<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="417803480"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="417803480" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">unit</span> UMyClasses<span class="sy1">;</span> 
&nbsp;
<span class="kw1">interface</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; Classes<span class="sy1">,</span> Types<span class="sy1">,</span> Sysutils<span class="sy1">;</span>
&nbsp;
<span class="kw1">type</span>
&nbsp; TQuestion <span class="sy3">=</span> <span class="kw1">record</span>
&nbsp; &nbsp; Q<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; A<span class="sy1">:</span> <span class="kw1">array</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="sy1">..</span><span class="nu0">3</span><span class="br0">&#93;</span> <span class="kw1">of</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; Right<span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; TDBSettings <span class="sy3">=</span> <span class="kw1">record</span>
&nbsp; &nbsp; server<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; db<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; TMySettings <span class="sy3">=</span> <span class="kw1">class</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; Login<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; Role<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; DBSettings<span class="sy1">:</span> TDBSettings<span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">var</span>
&nbsp; Settings<span class="sy1">:</span> TMySettings<span class="sy1">;</span>
&nbsp; Questions<span class="sy1">:</span> <span class="kw1">array</span> <span class="kw1">of</span> TQuestion<span class="sy1">;</span>
&nbsp; Answers<span class="sy1">:</span> <span class="kw1">array</span> <span class="kw1">of</span> <span class="kw4">integer</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">function</span> ReadQuestionsFromFile<span class="br0">&#40;</span>FName<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="kw1">function</span> ReadQuestionsFromFile<span class="br0">&#40;</span>FName<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; List<span class="sy1">:</span> TStringList<span class="sy1">;</span>
&nbsp; VCount<span class="sy1">,</span> I<span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; List <span class="sy1">:</span><span class="sy3">=</span> TStringList<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; List<span class="sy1">.</span><span class="me1">LoadFromFile</span><span class="br0">&#40;</span>FName<span class="br0">&#41;</span><span class="sy1">;</span> <span class="co1">//прочитаем весь файл в список строк</span>
&nbsp; result <span class="sy1">:</span><span class="sy3">=</span> List<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy1">;</span> <span class="co1">// В первой строке у вас какой-то текст для заголовка</span>
&nbsp; VCount <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">StrToInt</span><span class="br0">&#40;</span>List<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="co1">// во второй строке - кол-во записей</span>
&nbsp; <span class="kw3">SetLength</span><span class="br0">&#40;</span>Questions<span class="sy1">,</span> VCount<span class="br0">&#41;</span><span class="sy1">;</span> &nbsp;<span class="co1">// теперь,зная это количество, установим размер массива Questions</span>
&nbsp; <span class="kw3">SetLength</span><span class="br0">&#40;</span>Answers<span class="sy1">,</span> VCount<span class="br0">&#41;</span><span class="sy1">;</span> <span class="co1">// и массива Answers</span>
&nbsp; I <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span><span class="sy1">;</span>
&nbsp; <span class="co1">/// начиная с третьей строки, читаем вопросы</span>
&nbsp; <span class="kw1">while</span> I &lt; VCount <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; Questions<span class="br0">&#91;</span>I<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Q</span> <span class="sy1">:</span><span class="sy3">=</span> List<span class="br0">&#91;</span><span class="nu0">2</span> <span class="sy3">+</span> I <span class="sy3">*</span> <span class="nu0">6</span> <span class="sy3">+</span> <span class="nu0">0</span><span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; &nbsp; Questions<span class="br0">&#91;</span>I<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">A</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> List<span class="br0">&#91;</span><span class="nu0">2</span> <span class="sy3">+</span> I <span class="sy3">*</span> <span class="nu0">6</span> <span class="sy3">+</span> <span class="nu0">1</span><span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; &nbsp; Questions<span class="br0">&#91;</span>I<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">A</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> List<span class="br0">&#91;</span><span class="nu0">2</span> <span class="sy3">+</span> I <span class="sy3">*</span> <span class="nu0">6</span> <span class="sy3">+</span> <span class="nu0">2</span><span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; &nbsp; Questions<span class="br0">&#91;</span>I<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">A</span><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> List<span class="br0">&#91;</span><span class="nu0">2</span> <span class="sy3">+</span> I <span class="sy3">*</span> <span class="nu0">6</span> <span class="sy3">+</span> <span class="nu0">3</span><span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; &nbsp; Questions<span class="br0">&#91;</span>I<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">A</span><span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> List<span class="br0">&#91;</span><span class="nu0">2</span> <span class="sy3">+</span> I <span class="sy3">*</span> <span class="nu0">6</span> <span class="sy3">+</span> <span class="nu0">4</span><span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; &nbsp; Questions<span class="br0">&#91;</span>I<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Right</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">strToInt</span><span class="br0">&#40;</span>List<span class="br0">&#91;</span><span class="nu0">2</span> <span class="sy3">+</span> I <span class="sy3">*</span> <span class="nu0">6</span> <span class="sy3">+</span> <span class="nu0">5</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; I <span class="sy1">:</span><span class="sy3">=</span> I <span class="sy3">+</span> <span class="nu0">1</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; List<span class="sy1">.</span><span class="me1">Free</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">initialization</span>
&nbsp; Settings <span class="sy1">:</span><span class="sy3">=</span> TMySettings<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">finalization</span>
&nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>Settings<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
теперь немного об интерфейсе<br />
сама тестовая форма выглядит так (Screen 166)<br />
чтобы туда попасть,нужно пройти авторизацию<br />
поэтому первая форма нашего приложения выглядит так (Screen 167)<br />
и содержит интересный код<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="698197184"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="698197184" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">type</span>
&nbsp; TfMainForm <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
&nbsp; &nbsp; grp1<span class="sy1">:</span> TGroupBox<span class="sy1">;</span>
&nbsp; &nbsp; eLogin<span class="sy1">:</span> TEdit<span class="sy1">;</span>
&nbsp; &nbsp; ePass<span class="sy1">:</span> TEdit<span class="sy1">;</span>
&nbsp; &nbsp; bOk<span class="sy1">:</span> TButton<span class="sy1">;</span>
&nbsp; &nbsp; lbl1<span class="sy1">:</span> TLabel<span class="sy1">;</span>
&nbsp; &nbsp; lbl2<span class="sy1">:</span> TLabel<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> bOkClick<span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">private</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> GoTest<span class="sy1">;</span>
&nbsp; <span class="kw1">public</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">var</span>
&nbsp; fMainForm<span class="sy1">:</span> TfMainForm<span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; UTestForm<span class="sy1">;</span>
&nbsp;
<span class="co2">{$R *.dfm}</span>
&nbsp;
<span class="kw1">procedure</span> TfMainForm<span class="sy1">.</span><span class="me1">bOkClick</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="co1">// здесь будет проверка логина, но пока просто переход к тесту</span>
&nbsp; GoTest<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TfMainForm<span class="sy1">.</span><span class="me1">GoTest</span><span class="sy1">;</span>
<span class="kw1">var</span> f<span class="sy1">:</span>TfTestForm<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Hide<span class="sy1">;</span>
&nbsp; f<span class="sy1">:</span><span class="sy3">=</span>TfTestForm<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">ShowModal</span><span class="sy1">;</span>
&nbsp; <span class="kw1">finally</span>
&nbsp; &nbsp; show<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>F<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
обратите внимание на то, что мы прячем главную форму<br />
создаем и показываем тестовую<br />
а потом опять показываем главную<br />
это тоже не огонь, но для Beginner - в самый раз<br />
кстати - TestForm удалена из Project options - Forms - Auto create !! ибо нефиг <a href="https://www.cyberforum.ru/blogs/469693/blog4873.html">https://www.cyberforum.ru/blog... g4873.html</a><br />
<br />
<b><font size="3">Форма для теста</font></b><br />
Вернемся к тестовой форме<br />
Заведем на ней поле - переменную - CurQuestion:integer;<br />
Она будет изменяться от 0 до количества вопросов -1<br />
И в пару к ней сделаем процедуру &quot;отобразить текущий тест&quot; ShowCurQuestion<br />
Там прямо примитивно всё<br />
Берем элемент массива Questions c индексом CurQuestion <br />
и переписываем то что там хранится в компоненты на экране<br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="30287621"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="30287621" 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="kw1">unit</span> UTestForm<span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; classes<span class="sy1">,</span> types<span class="sy1">,</span> forms<span class="sy1">,</span> Controls<span class="sy1">,</span> UMyClasses<span class="sy1">,</span> ExtCtrls<span class="sy1">,</span> StdCtrls<span class="sy1">;</span>
&nbsp;
<span class="kw1">type</span>
&nbsp;
&nbsp; TfTestForm <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
&nbsp; &nbsp; pnl1<span class="sy1">:</span> TPanel<span class="sy1">;</span>
&nbsp; &nbsp; lblQuestion<span class="sy1">:</span> TLabel<span class="sy1">;</span>
&nbsp; &nbsp; bNext<span class="sy1">:</span> TButton<span class="sy1">;</span>
&nbsp; &nbsp; rgVariants<span class="sy1">:</span> TRadioGroup<span class="sy1">;</span>
&nbsp; &nbsp; pnlQuectionNo<span class="sy1">:</span> TPanel<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> FormCreate<span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">private</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> ShowCurQuestion<span class="sy1">;</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; CurQuestion <span class="sy1">:</span> <span class="kw4">integer</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">var</span>
&nbsp; fTestForm<span class="sy1">:</span> TfTestForm<span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; sysutils<span class="sy1">;</span>
&nbsp;
<span class="co2">{$R *.dfm}</span>
&nbsp;
<span class="coMULTI">{ TMainForm }</span>
<span class="kw1">procedure</span> TfTestForm<span class="sy1">.</span><span class="me1">FormCreate</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; Filename<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Filename <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">extractFilePath</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy3">+</span><span class="st0">'questions.dat'</span><span class="sy1">;</span>
&nbsp; Caption <span class="sy1">:</span><span class="sy3">=</span> ReadQuestionsFromFile<span class="br0">&#40;</span>Filename<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; CurQuestion <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span><span class="sy1">;</span>
&nbsp; ShowCurQuestion<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TfTestForm<span class="sy1">.</span><span class="me1">ShowCurQuestion</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; i<span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; pnlQuectionNo<span class="sy1">.</span><span class="me1">Caption</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">Format</span><span class="br0">&#40;</span><span class="st0">'Вопрос %d / %d'</span><span class="sy1">,</span><span class="br0">&#91;</span>curQuestion<span class="sy3">+</span><span class="nu0">1</span><span class="sy1">,</span> <span class="kw3">Length</span><span class="br0">&#40;</span>Questions<span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; lblQuestion<span class="sy1">.</span><span class="me1">Caption</span> <span class="sy1">:</span><span class="sy3">=</span> questions<span class="br0">&#91;</span>CurQuestion<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">Q</span><span class="sy1">;</span>
&nbsp; rgVariants<span class="sy1">.</span><span class="me1">Items</span><span class="sy1">.</span><span class="me1">Clear</span><span class="sy1">;</span>
&nbsp; <span class="kw1">for</span> i <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">to</span> <span class="nu0">3</span> <span class="kw1">do</span>
&nbsp; &nbsp; rgVariants<span class="sy1">.</span><span class="me1">Items</span><span class="sy1">.</span><span class="me1">Add</span><span class="br0">&#40;</span>questions<span class="br0">&#91;</span>CurQuestion<span class="br0">&#93;</span><span class="sy1">.</span><span class="me1">A</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; rgVariants<span class="sy1">.</span><span class="me1">ItemIndex</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="sy3">-</span><span class="nu0">1</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
теперь если на кнопку Далее повесить обработчик, который сохраняет ответ пользователя в массив Answers, просто увеличивает CurQuestion и просит форму нарисовать вопрос, то в общем-то тестовая часть нашего проекта завершена!<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="366190483"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="366190483" 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="kw1">procedure</span> TfTestForm<span class="sy1">.</span><span class="me1">bNextClick</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="co1">// проверим, вдруг ничего не выбрано</span>
&nbsp; <span class="kw1">if</span> rgVariants<span class="sy1">.</span><span class="me1">ItemIndex</span><span class="sy3">=-</span><span class="nu0">1</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; showMessage<span class="br0">&#40;</span><span class="st0">'Выберите вариант ответа'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; exit<span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; Answers<span class="br0">&#91;</span>CurQuestion<span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> rgVariants<span class="sy1">.</span><span class="me1">ItemIndex</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> CurQuestion&lt;<span class="kw3">Length</span><span class="br0">&#40;</span>Questions<span class="br0">&#41;</span><span class="sy3">-</span><span class="nu0">1</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; CurQuestion <span class="sy1">:</span><span class="sy3">=</span> CurQuestion <span class="sy3">+</span> <span class="nu0">1</span><span class="sy1">;</span>
&nbsp; &nbsp; ShowCurQuestion<span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>хорошая идея если мы нажали Далее на последнем вопросе, то закрыть форму с тестом и вывести форму Итого, и возможно даже записать результаты в к-нить файл или даже БД, но это следующий урок.<br />
<br />
Приложу исполняемый файл и файл с вопросами, чтобы можно было посмотреть, что получилось...</div>


<!-- attachments -->
	<div style="margin-top:10px">

		
			<fieldset class="fieldset">
				<legend>Миниатюры</legend>
				<div style="padding:3px">
				
	<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4821&amp;d=1526744005" target="attachment" rel="Lightbox" id="attachment4821"><img loading="lazy" decoding="async" class="thumbnail" src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4821&amp;stc=1&amp;thumb=1&amp;d=1526744005" border="0" alt="Нажмите на изображение для увеличения
Название: QIP Shot - Screen 166.png
Просмотров: 1722
Размер:	30.1 Кб
ID:	4821" /></a>
	&nbsp;
	

	<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4822&amp;d=1526744162" target="attachment" rel="Lightbox" id="attachment4822"><img loading="lazy" decoding="async" class="thumbnail" src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4822&amp;stc=1&amp;thumb=1&amp;d=1526744162" border="0" alt="Нажмите на изображение для увеличения
Название: QIP Shot - Screen 167.png
Просмотров: 1415
Размер:	16.4 Кб
ID:	4822" /></a>
	&nbsp;
	

				</div>
			</fieldset>
		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/7z.gif" alt="Тип файла: 7z" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=4823&amp;d=1526745702">BeginnersTestStep1.7z</a> (2.25 Мб, 655 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5262.html</guid>
		</item>
		<item>
			<title>Что нужно знать о датасетах и DB-компонентах</title>
			<link>https://www.cyberforum.ru/blogs/469693/5259.html</link>
			<pubDate>Wed, 16 May 2018 06:10:37 GMT</pubDate>
			<description>Ахтунг! Аттеншн! Внимание! 
1. Все DB-компоненты ОТОБРАЖАЮТ текущую запись и поле датасета, к...</description>
			<content:encoded><![CDATA[<div><font size="4">Ахтунг! Аттеншн! Внимание!</font><br />
1. Все DB-компоненты ОТОБРАЖАЮТ текущую запись и поле датасета, к которому они подключены. НЕ ХРАНЯТ!!!<br />
Они являются элементами ИНТЕРФЕЙСА - т.е. штуками для работы <b>пользователя</b>! <b>Не программиста</b>!!!<br />
Нет смысла брать текст из DBEdit, его надо брать из поля датасета, к которому этот DBEdit подключен.<br />
И наоборот, писать туда значение - такая же дичь.<br />
<br />
Если узнаю, что вы так делаете, вычислю по IP и оборву что-нибудь важное! )<br />
<br />
P.S. Для тех, кто обзывает компоненты DBEdit1, в аду стоит отдельный котел.<br />
<br />
2 если ваши компоненты подключены к датасету через Datasource то при любом перемещении по компоненту, происходит перемещение и по датасету. И наоборот. Таким образом, датасет всегда стоит на той записи, которую видно в гриде<br />
поэтому данные просто берете из датасета<br />
<br />
3. если у вас несколько компонентов подключены к одному датасету, то изменения и перемещения происходят во всех подключенных компонентах одновременно. поэтому сколько бы форм не ссылалось на один датасет, если изменятся данные в одной, то и в другой тоже<br />
<br />
4. каждый датасет никак не связан с БД откуда он вытащил данные<br />
поэтому если два одинаковых датасета забрали одинаковые данные из БД, и в одном что-то поменять, или в БД что-то поменять, всем остальным пофиг. Для обновления данные нужно тащить заново.</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5259.html</guid>
		</item>
		<item>
			<title>SQL запросы и параметры</title>
			<link>https://www.cyberforum.ru/blogs/469693/5254.html</link>
			<pubDate>Fri, 11 May 2018 07:37:12 GMT</pubDate>
			<description>*ВВЕДЕНИЕ. ЛИКБЕЗ* 
Как всегда, в тот момент, когда несколько подзадолбало отвечать на одни и те же...</description>
			<content:encoded><![CDATA[<div><font size="4"><b>ВВЕДЕНИЕ. ЛИКБЕЗ</b></font><br />
Как всегда, в тот момент, когда несколько подзадолбало отвечать на одни и те же вопросы, садишься и пишешь статью, чтобы потом не разжевывать самые азы, а эффектно пулять ссылкой)<br />
<br />
Итак. Работа с БД - это то, из-за чего Делфи, как минимум, на десятилетие, стала сверхпопулярной.<br />
Все просто и эффективно.<br />
Концепция. <br />
Есть сервера БД, которые предоставляют возможность к себе обращаться и забирать данные в программу.<br />
Почти во всех случаях эти обращания идут на языке <a rel="nofollow noopener noreferrer" href="http://www.sql.ru/docs/sql/u_sql/" target="_blank" title="http://www.sql.ru/docs/sql/u_sql/">SQL</a>.<br />
Это обычная текстовая строка, в языке всего 4 команды, так что вам в любом случае придется немного почитать.<br />
Команды INSERT UPDATE DELETE производят <b>действия</b> на сервере.<br />
(Если вы &quot;я в школе немецкий учил&quot; и не представляете значение этих слов, то идите собирать деньги и покупать программиста, дальше вам все равно не пройти.)<br />
Команда SELECT <b>запрашивает данные</b> с сервера, и результат запроса по частям(!) отдается вашей программе.<br />
Это называется &quot;набор данных&quot; или &quot;датасет&quot;.<br />
Датасет - это набор строк (они же - записи), отвечающих условиям вашего запроса. Если условия не заданы, то вам придут вообще все данные. Не делайте так )))<br />
К датасетам через компонент DataSource умеют подключаться разные DB-компоненты. DBEdit, DBLabel, DBGrid и т.д.<br />
Пока что давайте в качестве образца датасета держать в уме какой-нибудь TQuery. Неважно TADOQuery, TDBQuery, TIBQuery, TFIBQuery. Сделаны они примерно одинаково.<br />
<br />
Давайте разберем главные моменты, что вы должны понимать в датасете.<br />
<br />
1. При запросе вы указываете ПОЛЯ датасета. <br />
<div class="codeblock"><table class="sql"><thead><tr><td colspan="2" id="229914742"  class="head">SQL</td></tr></thead><tbody><tr class="li1"><td><div id="229914742" 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">SELECT</span> T<span class="sy0">.</span>XXX<span class="sy0">,</span> T<span class="sy0">.</span>YYY <span class="kw1">FROM</span> <span class="kw1">TABLE</span> T <span class="kw1">WHERE</span> T<span class="sy0">.</span>ZZZ<span class="sy0">=</span><span class="st0">'12345'</span></pre></td></tr></table></div></td></tr></tbody></table></div>К этим полям потом можно обращаться, например<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="994373982"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="994373982" 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">s <span class="sy1">:</span><span class="sy3">=</span> Query1<span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'XXX'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsString</span><span class="sy1">;</span>
n <span class="sy1">:</span><span class="sy3">=</span> Query1<span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'YYY'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsInteger</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>2. В один момент времени вы видите только ОДНУ запись датасета. Чтобы работать с другой, вы должны переместиться по датасету<br />
Для этого служат методы First(), Last(), Next(), Prior() (Prior работает НЕ ДЛЯ ЛЮБОГО датасета)<br />
Если вашу запись можно точно найти по значениям полей, пользуйтесь функцией Locate()<br />
самая распространенная конструкция для работы это перебор всех записей датасета от начала до конца<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="412365668"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="412365668" 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">Query1<span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span> <span class="co1">// передать на сервер запрос, который хранится в Query1.SQL</span>
<span class="kw1">while</span> <span class="kw1">not</span> Query1<span class="sy1">.</span><span class="me1">EOF</span> <span class="kw1">do</span> <span class="co1">// пока датасет не дошел до конца</span>
<span class="kw1">begin</span>
&nbsp; <span class="co1">// что-то делать с текущей записью</span>
&nbsp; Query1<span class="sy1">.</span><span class="me1">Next</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="co1">// перейти на следующую запись</span>
<span class="kw1">end</span><span class="sy1">;</span>
Query1<span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span> <span class="co1">// закрыть датасет.</span></pre></td></tr></table></div></td></tr></tbody></table></div>3. Ахтунг! Аттеншн! Внимание!<br />
<a href="https://www.cyberforum.ru/blogs/469693/blog5259.html">https://www.cyberforum.ru/blog... g5259.html</a><br />
<br />
Далее. То, ради чего вообще начал это писать<br />
<font size="4"><b>ПАРАМЕТРЫ В SQL-ЗАПРОСАХ</b></font><br />
Всегда SQL запрос содержит какие-то условия. Что-то типа такого<br />
<div class="codeblock"><table class="sql"><thead><tr><td colspan="2" id="229616668"  class="head">SQL</td></tr></thead><tbody><tr class="li1"><td><div id="229616668" 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">SELECT</span> T<span class="sy0">.</span>Field1<span class="sy0">,</span> T<span class="sy0">.</span>Field2 <span class="kw1">FROM</span> <span class="kw1">TABLE</span> T <span class="kw1">WHERE</span> T<span class="sy0">.</span>Field3<span class="sy0">=</span> <span class="st0">'Ваня'</span></pre></td></tr></table></div></td></tr></tbody></table></div>на следующей строке нам нужно<br />
<div class="codeblock"><table class="sql"><thead><tr><td colspan="2" id="725041925"  class="head">SQL</td></tr></thead><tbody><tr class="li1"><td><div id="725041925" 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">SELECT</span> T<span class="sy0">.</span>Field1<span class="sy0">,</span> T<span class="sy0">.</span>Field2 <span class="kw1">FROM</span> <span class="kw1">TABLE</span> T <span class="kw1">WHERE</span> T<span class="sy0">.</span>Field3<span class="sy0">=</span> <span class="st0">'Таня'</span></pre></td></tr></table></div></td></tr></tbody></table></div>а потом<br />
<div class="codeblock"><table class="sql"><thead><tr><td colspan="2" id="661053811"  class="head">SQL</td></tr></thead><tbody><tr class="li1"><td><div id="661053811" 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">SELECT</span> T<span class="sy0">.</span>Field1<span class="sy0">,</span> T<span class="sy0">.</span>Field2 <span class="kw1">FROM</span> <span class="kw1">TABLE</span> T <span class="kw1">WHERE</span> T<span class="sy0">.</span>Field3<span class="sy0">=</span> <span class="st0">'Федор'</span></pre></td></tr></table></div></td></tr></tbody></table></div>первое, что приходит в голову, сделать строку, которая не меняется, и добавлять или вставлять в нее изменяющуюся часть <br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="689983410"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="689983410" 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">Common<span class="sy1">:</span><span class="sy3">=</span><span class="st0">'SELECT T.Field1, T.Field2 FROM table T WHERE T.Field3='</span><span class="sy1">;</span>
AName <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">QuotedStr</span><span class="br0">&#40;</span><span class="st0">'Таня'</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="co1">// QuotedStr - строковые данные в запросе нужно обрамлять апострофами или кавычками</span>
Query1<span class="sy1">.</span><span class="me1">SQL</span><span class="sy1">.</span><span class="me1">Text</span> <span class="sy1">:</span><span class="sy3">=</span> Common <span class="sy3">+</span> AName<span class="sy1">;</span>
Query1<span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>т.е. запрос будет каждый раз составляться заново. Рабочий вариант, но по нескольким причинам, выходящим за рамки статьи - не очень хороший.<br />
Но, как обычно, все придумано до нас! В запрос можно вставлять ПАРАМЕТРЫ!<br />
пишем один раз в начале программы (а еще лучше прямо в дизайнере формы)<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="504613653"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="504613653" 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">Query1<span class="sy1">.</span><span class="me1">SQL</span><span class="sy1">.</span><span class="me1">Text</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'SELECT T.Field1, T.Field2 FROM table T WHERE T.Field3=:param1'</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>вот param1 это и есть параметр<br />
для такого случая нам нужно только заполнить значение параметра и переоткрыть датасет<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="281714085"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="281714085" 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">Query1<span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
Query1<span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param1'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsString</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'Таня'</span><span class="sy1">;</span>
Query1<span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>нужно сразу упомянуть, что для ADOQuery синтаксис немного отличается<br />
там это происходит так<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="778319167"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="778319167" 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">Query1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param1'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Datatype</span> <span class="sy1">:</span><span class="sy3">=</span> ftString<span class="sy1">;</span>
Query1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param1'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'Таня'</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>При этом нас уже не волнует, что нужно ставить кавычки, апострофы или еще что-то. Движок сделает все за нас корректно.<br />
Приведу пример, который 100500 раз заново спрашивали юные падаваны, не знающие страха, упрека и кнопки &quot;Поиск&quot;.<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="112297380"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="112297380" 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">// где -то один раз в начале программы</span>
ADOQuery1<span class="sy1">.</span><span class="me1">SQL</span><span class="sy1">.</span><span class="me1">Text</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'SELECT T.Field1, T.Field2 FROM table T WHERE T.DateField3 between :param1 and :param2'</span><span class="sy1">;</span>
<span class="sy1">...</span>
<span class="co1">// а это там, где всё непосредственно происходит</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param1'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Datatype</span> <span class="sy1">:</span><span class="sy3">=</span> ftDate<span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param1'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> date1<span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param2'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Datatype</span> <span class="sy1">:</span><span class="sy3">=</span> ftDate<span class="sy1">;</span> 
ADOQuery1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param2'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> date2<span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>UPD: Важно! <br />
Выяснилось, что каждый раз тип параметра надо указывать заново.<br />
После каждого ExecSQL или Open query теряет тип, и повторное заполнение только value может уже не дать нужный результат.<br />
</b><br />
для не-адо компонентов:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="130608841"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="130608841" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">Query1<span class="sy1">.</span><span class="me1">SQL</span><span class="sy1">.</span><span class="me1">Text</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'SELECT T.Field1, T.Field2 FROM table T WHERE T.DateField3 between :param1 and :param2'</span><span class="sy1">;</span>
<span class="sy1">...</span>
<span class="me1">Query1</span><span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
Query1<span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param1'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsDateTime</span> <span class="sy1">:</span><span class="sy3">=</span> date1<span class="sy1">;</span>
Query1<span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'param2'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsDateTime</span> <span class="sy1">:</span><span class="sy3">=</span> date2<span class="sy1">;</span>
Query1<span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стоит запомнить еще одну вещь. Наш компонент DataSource следит за тем, как вносятся изменения в датасет, и при каждом изменении идет перерисовывать все компоненты, которые к нему подключены. Если ничего не предпринимать, то эта перерисовка станет главным пожирателем времени в вашей программе. Поэтому если нам нужно побегать по датасету, что-то поделать, и быстро, то нужно сделать такую конструкцию<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="95143512"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="95143512" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">Query1<span class="sy1">.</span><span class="me1">DisableControls</span><span class="sy1">;</span> <span class="co1">// отключаем перерисовку подключенных компонентов</span>
<span class="kw1">try</span>
&nbsp; <span class="sy1">...</span> <span class="co1">// работаем</span>
<span class="kw1">finally</span>
&nbsp; Query1<span class="sy1">.</span><span class="me1">EnableControls</span><span class="sy1">;</span> <span class="co1">// включаем обратно перерисовку подключенных компонентов</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Параметры работают и при вставке, изменении, удалении<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="354050372"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="354050372" 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">ADOQuery1<span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">SQL</span><span class="sy1">.</span><span class="me1">Text</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'INSERT INTO Tab3 (FIO, Bd) VALUES (:F,:D)'</span><span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'F'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">DataType</span> <span class="sy1">:</span><span class="sy3">=</span> ftString<span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'F'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> Edit1<span class="sy1">.</span><span class="me1">Text</span><span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'D'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">DataType</span> <span class="sy1">:</span><span class="sy3">=</span> ftDate<span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByName</span><span class="br0">&#40;</span><span class="st0">'D'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> DateTimePicker1<span class="sy1">.</span><span class="me1">Date</span><span class="sy1">;</span>
ADOQuery1<span class="sy1">.</span><span class="me1">ExecSQL</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><font size="4"><b>MASTER-DETAIL</b></font><br />
Давайте разберем еще одну тему.<br />
Как сделать, чтобы я выбирал строку с работником в гриде, а в другом гриде мне показывало все работы, связанные с этим работником. или что-то подобное.<br />
Эта связь называется мастер-деталь. В делфи есть встроенное средство для таких штук, но всегда лучше понимать как это работает и делать руками...<br />
Итак, у нас есть два запроса. первый - список работников, второй - список выполненных работ.<br />
Допустим, в первом условий вообще нет. Если даже есть они задаются где-то там и не относятся к нашей задаче.<br />
А вот условия во втором датасете - работы только для выбранного работника.<br />
Если хоть чучуть почитать про БД, или просто раскинуть мозгами, мы придумаем, что у каждого работника есть уникальный код. Его даже на экран выводить не нужно, но в таблице он должен быть. назовем его без придумок - ID.<br />
В таблице работ должно быть поле, которое ссылается на этот ID, например WORKER_ID<br />
Тогда формулируем задачу.<br />
При каждом перемещении по датасету qWorkers переоткрывать датасет qWorks c уcловием WORKER_ID равен текущему значению qWorkers.ID.<br />
Решение.<br />
qWorks.SQL выглядит как то так <div class="codeblock"><table class="sql"><thead><tr><td colspan="2" id="886068944"  class="head">SQL</td></tr></thead><tbody><tr class="li1"><td><div id="886068944" 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">SELECT</span> <span class="sy0">....</span> &nbsp;<span class="kw1">FROM</span> WORKS W <span class="kw1">WHERE</span> W<span class="sy0">.</span>WORKER_ID<span class="sy0">=</span>:worker_id</pre></td></tr></table></div></td></tr></tbody></table></div>В событии qWorkers.OnAfterScroll пишем код из трех строчек<br />
для ADO<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="930118434"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="930118434" 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">// это не в AfterScroll, а как всегда, где-то одноразово пораньше</span>
qWorks<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByname</span><span class="br0">&#40;</span><span class="st0">'worker_id'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">datatype</span> <span class="sy1">:</span><span class="sy3">=</span> ftInteger<span class="sy1">;</span>
<span class="sy1">...</span>
<span class="kw1">procedure</span> TForm1<span class="sy1">.</span><span class="me1">qWorkersAfterScroll</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span><span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; qWorks<span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
&nbsp; qWorks<span class="sy1">.</span><span class="me1">Parameters</span><span class="sy1">.</span><span class="me1">ParamByname</span><span class="br0">&#40;</span><span class="st0">'worker_id'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">Value</span> <span class="sy1">:</span><span class="sy3">=</span> qWorkers<span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'ID'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsInteger</span><span class="sy1">;</span>
&nbsp; qWorks<span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>для не-ADO просто<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="483241949"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="483241949" 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">procedure</span> TForm1<span class="sy1">.</span><span class="me1">qWorkersAfterScroll</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span><span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; qWorks<span class="sy1">.</span><span class="me1">Close</span><span class="sy1">;</span>
&nbsp; qWorks<span class="sy1">.</span><span class="me1">ParamByname</span><span class="br0">&#40;</span><span class="st0">'worker_id'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsInteger</span> <span class="sy1">:</span><span class="sy3">=</span> qWorkers<span class="sy1">.</span><span class="me1">FieldByName</span><span class="br0">&#40;</span><span class="st0">'ID'</span><span class="br0">&#41;</span><span class="sy1">.</span><span class="me1">AsInteger</span><span class="sy1">;</span>
&nbsp; qWorks<span class="sy1">.</span><span class="me1">Open</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>P.S. перестаньте давать русские имена ,а еще и с пробелами, таблицам, базам и полям. Ни одна нормальная БД вас не поймет, а вы будете потом засыпать форумы вопросами что за ошибка в запросе<br />
<div class="codeblock"><table class="sql"><thead><tr><td colspan="2" id="869800322"  class="head">SQL</td></tr></thead><tbody><tr class="li1"><td><div id="869800322" 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">SELECT</span> моё дебильное название поля <span class="kw1">FROM</span> таблица тоже огонь</pre></td></tr></table></div></td></tr></tbody></table></div><br />
<br />
в заключение приведу ссылку для тех, у кого ADO. У меня его нет, поэтому если что-то не так, смотрите там и ищите сами<br />
<a rel="nofollow noopener noreferrer" href="http://devdelphi.ru/?p=16" target="_blank" title="http://devdelphi.ru/?p=16">http://devdelphi.ru/?p=16</a></div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/5254.html</guid>
		</item>
		<item>
			<title>ProcessMessages</title>
			<link>https://www.cyberforum.ru/blogs/469693/4909.html</link>
			<pubDate>Wed, 30 Aug 2017 03:54:52 GMT</pubDate>
			<description>Как только я вижу в чьем-то коде Application.ProcessMessages, я сразу вспоминаю - 
несчастные...</description>
			<content:encoded><![CDATA[<div>Как только я вижу в чьем-то коде Application.ProcessMessages, я сразу вспоминаю -<br />
<a rel="nofollow noopener noreferrer" href="https://www.youtube.com/watch?v=p29ksSAZtDY" target="_blank" title="https://www.youtube.com/watch?v=p29ksSAZtDY">несчастные случаи на стройке</a><br />
<br />
Поясню:<br />
Вся программа на делфи выглядит примерно так<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="117266479"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="117266479" 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">Application<span class="sy1">.</span><span class="me1">Initialize</span><span class="sy1">;</span>
Application<span class="sy1">.</span><span class="me1">CreateForm</span><span class="br0">&#40;</span>Form1<span class="sy1">,</span>TForm1<span class="br0">&#41;</span><span class="sy1">;</span>
Application<span class="sy1">.</span><span class="me1">Run</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>вот если посмотреть код в Application.Run, мы увидим (весьма примерно)<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="481918253"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="481918253" 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">while</span> <span class="kw1">not</span> Application<span class="sy1">.</span><span class="me1">Terminated</span> <span class="kw1">do</span>
&nbsp; Application<span class="sy1">.</span><span class="me1">ProcessMessages</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>итого. пока приложению никто не сказал закрыться, оно всего лишь смотрит в свою очередь сообщений и вызывает обработчики этих сообщений.<br />
Сообщений сотни - каждое движение мыши, таймеры, перерисовка окантовки и заголовка окон, вообще все в Windows делается по сообщениям.<br />
И вот при обработке сообщения программа вызывает ваш обработчик события. Например, нажатия кнопки.<br />
А там вы делаете что-то очень важное для вас и хуже всего - длительное по времени.<br />
И тут встает проблема. Перерисовка окна и обработка ввода идут тоже через сообщения, а программа еще не вышла из вашего обработчика и никаких сообщений не обрабатывает, и все говорят - висит!<br />
Да нет, не висит, вы сами ее чем-то заняли, она работает. Чаще всего в к-нить вашем цикле, или качает что-то из интернета.<br />
И для простого решения проблемы &quot;зависания&quot; программист пишет Application.ProcessMessages!<br />
И вуаля - программа перерисовывает окно и даже вызывает еще какой-то обработчик мыши.<br />
И тут начинаются спецэффекты<br />
Напоминаю. Ваш обработчик вызван из какой-то процедуры компонента, которая по цепочке вызвана из обработчика события Application.ProcessMessages. И вы тоже вызываете ProcessMessages. Да еще в цикле!<br />
Получится <br />
ProcessMessages -- Обработчик сообщения -- Процедуры объектов -- Ваш обработчик -- ProcessMessages -- Обработчик сообщения -- Процедуры объектов -- ????<br />
и вот тут запросто может быть заново вызван ваш обработчик опять!!! И дальше все по кругу...<br />
Либо как вариант, компонент может полагаться на последовательные вызовы событий типа<br />
OnCreate -- OnShow -- OnActivate<br />
а тут еще Create не закончился, а уже Show. oO<br />
Программа становится НЕЛИНЕЙНОЙ!<br />
В нормальном состоянии ваши процедуры отрабатывают друг за другом, от начала и до конца. Никаких параллельностей.<br />
Тут же это не так! Следующие процедуры запросто вызываются, когда еще не закончилась текущая. А потом текущая продолжится!<br />
<br />
Конечно, не всегда это приводит к печальным последствиям, но делать так НЕ СТОИТ! <br />
А если сделали, не удивляйтесь!<br />
<br />
Иногда вместо ProcessMessages достаточно просто перерисовать компонент Component1.Update;<br />
Иногда длительное действие нужно вынести в отдельный поток.<br />
С потоками решение сложной задачи можно разбить на два этапа - старт задачи и, отдельно - получение результата, когда задача завершилась. Тогда программа может заниматься своими делами, когда расчет (или загрузка файла или...) будет закончен, вызовется обработчик, где вы решите, что делать с результатом.<br />
<br />
Решения есть. Не ленитесь.<br />
И перестаньте вставлять Application.ProcessMessages.<br />
<br />
P.S.<br />
Один из самых клевых результатов даёт нажатие на крестик Закрыть программу.<br />
И программа уже думает, что всё - уничтожает формы и данные, а ваш обработчик продолжает обращаться к этим формам и данным, ессно получая AV. Никаких ошибок - просто так задумано вами - программистом.</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/4909.html</guid>
		</item>
		<item>
			<title>Процесс инициализации программы, с настройками и подключением к БД</title>
			<link>https://www.cyberforum.ru/blogs/469693/4884.html</link>
			<pubDate>Sun, 20 Aug 2017 17:01:43 GMT</pubDate>
			<description>Пока не началось 
Все шаги по разбору на старте приложения я стараюсь выполнять в переопределенном...</description>
			<content:encoded><![CDATA[<div><font size="4">Пока не началось</font><br />
Все шаги по разбору на старте приложения я стараюсь выполнять в переопределенном конструкторе главной формы.<br />
Это не догма, просто так удобнее.<br />
Мы можем делать это и в событии OnCreate, но тогда если мы решили выйти из приложения, то сначала все равно создастся и криво покажется форма и после этого сразу мигнет и пойдет на выход.<br />
Чтобы исключить эти спецэффекты пишем в классе формы переопределение конструктора<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="930298474"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="930298474" 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">TMainForm<span class="sy3">=</span><span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
<span class="sy1">...</span>
&nbsp; <span class="kw1">constructor</span> Create<span class="br0">&#40;</span>AOwner<span class="sy1">:</span>TComponent<span class="br0">&#41;</span><span class="sy1">;</span> <span class="kw1">override</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>и в конструкторе всё, что нужно на старте.<br />
Вызов исключения в конструкторе приводит к НЕсозданию объекта (а еще вызову деструктора!), поэтому в случае выхода из программы никаких миганий - сразу до свидания...<br />
<br />
<font size="4">К главному</font><br />
Обычно я использую следующие шаги на старте приложения<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="860293294"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="860293294" 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="kw1">constructor</span> TMainForm<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>AOwner<span class="sy1">:</span> TComponent<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">inherited</span> Create<span class="br0">&#40;</span>AOwner<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="co1">// см. примечание </span>
&nbsp; ReadSettings<span class="br0">&#40;</span>Settings<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="co1">// в загруженные настройки иногда можно внести изменения, запуская программу с ключами командной строки</span>
&nbsp; <span class="co1">// поэтому выполним еще один метод</span>
&nbsp; ParseParams<span class="br0">&#40;</span>Settings<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="co1">// иногда, как в 1С, нужно при старте выбрать БД для подключения, или еше что-нибудь</span>
&nbsp; <span class="co1">// возможно, это просто форма для логина</span>
&nbsp; <span class="co1">// там же клиент может решить вообще отказаться от входа в программу</span>
&nbsp; ShowSettingsAndLoginForm<span class="br0">&#40;</span>Settings<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="co1">// если клиент отказался, то выходим</span>
&nbsp; <span class="kw1">if</span> Application<span class="sy1">.</span><span class="me1">Terminated</span> <span class="kw1">then</span>
&nbsp; &nbsp; Abort<span class="sy1">;</span> <span class="co1">// Abort в конструкторе главной формы приведет к мягкому и тихому выходу из приложения</span>
&nbsp; <span class="co1">// если Settings были изменены в форме, то можно их сохранить. Вот пример</span>
&nbsp; <span class="kw1">if</span> Settings<span class="sy1">.</span><span class="me1">RecentConnections</span><span class="sy1">.</span><span class="me1">IndexOf</span><span class="br0">&#40;</span>Settings<span class="sy1">.</span><span class="me1">Database</span><span class="sy1">.</span><span class="me1">ConnectionString</span><span class="br0">&#41;</span><span class="sy3">=-</span><span class="nu0">1</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; Settings<span class="sy1">.</span><span class="me1">RecentConnections</span><span class="sy1">.</span><span class="me1">Add</span><span class="br0">&#40;</span>Settings<span class="sy1">.</span><span class="me1">Database</span><span class="sy1">.</span><span class="me1">ConnectionString</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; Settings<span class="sy1">.</span><span class="me1">SaveToFile</span><span class="br0">&#40;</span>GetSettingsFilename<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy1">;</span><span class="kw1">end</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; <span class="co1">// создать модуль данных и подключиться к БД</span>
&nbsp; CreateDatamodule<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="co1">// метод Init для всякой остальной работы - прочитать справочники, заполнить структуры данных</span>
&nbsp; <span class="co1">// слазить в интернет, короче все, что нужно для запуска программы</span>
&nbsp; <span class="co1">// лучше всего запустить для этого отдельный поток а форма тем временем покажется и будет рисовать часики</span>
&nbsp; <span class="co1">// в общем, все, что угодно, что требуется для старта программы</span>
&nbsp; Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Примечание. Про <b>хранение</b> настроек программы я писал в <a href="https://www.cyberforum.ru/blogs/469693/blog4883.html">другой </a>заметке<br />
<br />
Обращу ваше внимание, что у меня есть глобальная переменная Settings, но в каждый метод я передаю её как параметр.<br />
Это связано с тем, что мы когда-нибудь можем решить, что нам нужны более одного комплекта настроек. Для разных пользователей, для проверки подключения к БД, да и просто для исключения любых зависимостей от глобальных переменных.<br />
Инкапсуляция - замечательная вещь. Все работают только с тем, что им дают непосредственно для работы.<br />
<br />
Давайте посмотрим, что может находиться внутри каждого из методов.<br />
<b>ReadSettings</b>. Тут все просто.<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="26509949"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="26509949" 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">&nbsp;Settings<span class="sy1">:</span><span class="sy3">=</span>TAS_Settings<span class="sy1">.</span><span class="me1">CreateFromFile</span><span class="br0">&#40;</span>GetSettingsFilename<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>ParseParams</b> <br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="110080955"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="110080955" 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="kw1">procedure</span> TfMain<span class="sy1">.</span><span class="me1">ParseParams</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; i<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Settings<span class="sy1">.</span><span class="me1">Database</span><span class="sy1">.</span><span class="me1">ParseParams</span><span class="sy1">;</span>
&nbsp;
&nbsp; i <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">1</span><span class="sy1">;</span>
&nbsp; <span class="kw1">while</span> i &lt;<span class="sy3">=</span> ParamCount <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">AnsiSameText</span><span class="br0">&#40;</span><span class="kw3">paramstr</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">,</span> <span class="st0">'-ClearReports'</span><span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; Settings<span class="sy1">.</span><span class="me1">ClearReports</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw2">true</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="kw3">AnsiSameText</span><span class="br0">&#40;</span><span class="kw3">paramstr</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">,</span> <span class="st0">'-lang'</span><span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span>i&lt;paramcount<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; Settings<span class="sy1">.</span><span class="me1">reportuiresource</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">paramstr</span><span class="br0">&#40;</span>i<span class="sy3">+</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
тут стоит обратить внимание, что настройки БД у меня сами умеют лазить по строке параметров и заполнять себя данными оттуда<br />
<br />
<b>ShowSettingsAndLoginForm</b><br />
Здесь стоит конструкция, описанная в заметке <a href="https://www.cyberforum.ru/blogs/469693/blog4874.html">Как правильно сделать форму логина</a><br />
может, с небольшими вариациями<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="667583532"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="667583532" 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">&nbsp; fSettings<span class="sy1">:</span><span class="sy3">=</span>tfsettings<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">Self</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; <span class="co1">// форма настроек заполняется из хранилища этих самых настроек</span>
&nbsp; &nbsp; <span class="co1">// которое передано в этот метод через параметр Settings</span>
&nbsp; &nbsp; fSettings<span class="sy1">.</span><span class="me1">LoadFrom</span><span class="br0">&#40;</span>Settings<span class="br0">&#41;</span><span class="sy1">;</span> 
&nbsp; &nbsp; <span class="kw1">repeat</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> fsettings<span class="sy1">.</span><span class="me1">showModal</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy3">=</span>mrOk <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// форма сохраняет то, что навводил пользователь, в хранилище нестроек</span>
&nbsp; &nbsp; &nbsp; &nbsp; fsettings<span class="sy1">.</span><span class="me1">saveTo</span><span class="br0">&#40;</span>Settings<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// пробуем подключиться к БД с теми настройками, что получились, включая логин/пароль </span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fSettings<span class="sy1">.</span><span class="me1">fDBSettingsFrame</span><span class="sy1">.</span><span class="me1">TryConnect</span><span class="br0">&#40;</span>Settings<span class="sy1">.</span><span class="me1">Database</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Break<span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">on</span> e<span class="sy1">:</span>Exception <span class="kw1">do</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ShowMessage<span class="br0">&#40;</span>e<span class="sy1">.</span><span class="kw1">Message</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; Application<span class="sy1">.</span><span class="me1">Terminate</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">until</span> Application<span class="sy1">.</span><span class="me1">Terminated</span><span class="sy1">;</span>
&nbsp; <span class="kw1">finally</span>
&nbsp; &nbsp; fSettings<span class="sy1">.</span><span class="me1">free</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />
<b>CreateDatamodule</b><br />
Именно здесь, а не в AutoCreate создается мой главный модуль данных. Ведь настройки для подключения мы читали и изменяли тоже здесь.<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="959408842"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="959408842" 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">&nbsp; dm<span class="sy1">:</span><span class="sy3">=</span>TDM<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>Application<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; dm<span class="sy1">.</span><span class="me1">tryConnect</span><span class="br0">&#40;</span>Settings<span class="sy1">.</span><span class="me1">database</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>попытка коннекта выглядит примерно так:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="288440964"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="288440964" 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="kw1">procedure</span> TDM<span class="sy1">.</span><span class="me1">TryConnect</span><span class="br0">&#40;</span>DBSettings<span class="sy1">:</span> TDBSettings<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Db<span class="sy1">.</span><span class="me1">DBParams</span><span class="sy1">.</span><span class="me1">Values</span><span class="br0">&#91;</span><span class="st0">'sql_role_name'</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> DBSettings<span class="sy1">.</span><span class="me1">Role</span><span class="sy1">;</span>
&nbsp; Db<span class="sy1">.</span><span class="me1">DBParams</span><span class="sy1">.</span><span class="me1">Values</span><span class="br0">&#91;</span><span class="st0">'user_name'</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> DBSettings<span class="sy1">.</span><span class="me1">user</span><span class="sy1">;</span>
&nbsp; Db<span class="sy1">.</span><span class="me1">DBParams</span><span class="sy1">.</span><span class="me1">Values</span><span class="br0">&#91;</span><span class="st0">'password'</span><span class="br0">&#93;</span> <span class="sy1">:</span><span class="sy3">=</span> DBSettings<span class="sy1">.</span><span class="me1">pass</span><span class="sy1">;</span>
&nbsp; Db<span class="sy1">.</span><span class="me1">DatabaseName</span> <span class="sy1">:</span><span class="sy3">=</span> DBSettings<span class="sy1">.</span><span class="me1">ConnectionString</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> DBSettings<span class="sy1">.</span><span class="me1">lib</span> &lt;&gt; <span class="st0">''</span> <span class="kw1">then</span>
&nbsp; &nbsp; Db<span class="sy1">.</span><span class="me1">LibraryName</span> <span class="sy1">:</span><span class="sy3">=</span> DBSettings<span class="sy1">.</span><span class="me1">lib</span><span class="sy1">;</span>
&nbsp; Db<span class="sy1">.</span><span class="me1">Open</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>кстати, коннект вообще говоря я проверял еще в ShowSettingsAndLoginForm<br />
но есть вероятность, что за эти несколько миллисекунд что-то пошло не так и подключение не состоится.<br />
Что ж. В этом случае мы получим Exception в конструкторе и, следовательно, выйдем из программы.</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/4884.html</guid>
		</item>
		<item>
			<title>Программа и ее настройки</title>
			<link>https://www.cyberforum.ru/blogs/469693/4883.html</link>
			<pubDate>Sun, 20 Aug 2017 14:55:07 GMT</pubDate>
			<description>Сразу после создания своей самой лучшей программы, встает вопрос, а нельзя ли например запоминать,...</description>
			<content:encoded><![CDATA[<div>Сразу после создания своей самой лучшей программы, встает вопрос, а нельзя ли например запоминать, к какой БД я подключался, каково состояние Form18.CheckBox1.Checked было при выходе из программы, и много других крайне нужных вещей.<br />
<br />
Ответ очевиден. Думать об этом стоит ДО создания самой лучшей программы.<br />
<br />
Итак, для хранения настроек программы нам понадобятся<br />
1. Класс <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="580737731"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="580737731" 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">TMySettings <span class="sy3">=</span> <span class="kw1">class</span> <span class="sy1">...</span> <span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>2. Класс или запись <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="252280975"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="252280975" 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">TDBSettings <span class="sy3">=</span> <span class="kw1">record</span>
&nbsp; server<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; port<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span>
&nbsp; db<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; role<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; charset<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; login<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; pass<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>3. Библиотека работы с JSON. Я использую <a rel="nofollow noopener noreferrer" href="https://github.com/onryldz/x-superobject" target="_blank" title="https://github.com/onryldz/x-superobject">XSuperObject</a><br />
// для старых версий Delphi можно брать заброшенный оригинал этой библиотеки <a rel="nofollow noopener noreferrer" href="https://github.com/hgourvest/superobject" target="_blank" title="https://github.com/hgourvest/superobject">SuperObject</a><br />
4. Советую также посмотреть <a rel="nofollow noopener noreferrer" href="https://www.youtube.com/watch?v=e6IKO8so-Is" target="_blank" title="https://www.youtube.com/watch?v=e6IKO8so-Is">видео</a><br />
5. для более простой работы с настройками я сделал себе класс <br />
TJsonableObject, который удобно использовать для создания класса настроек<br />
Можно взять его тут <a rel="nofollow noopener noreferrer" href="https://bitbucket.org/vkrapotkin/jsonableobject" target="_blank" title="https://bitbucket.org/vkrapotkin/jsonableobject">https://bitbucket.org/vkrapotkin/jsonableobject</a><br />
<br />
Главное, что требуется понять.<br />
Мы создали класс, объект которого будет хранить настройки программы<br />
Использовать его, скорее всего, придется в режиме Singleton, т.е. в начале программы создать один глобальный объект, загрузить его из файла или из интернета и пользоваться во всей программе.<br />
<br />
Для некоторых видов работ никто не запрещает нам создавать дополнительные объекты этого класса, например с целью редактирования и последующей перезаписи.<br />
Так, например, чтобы протестировать подключение к БД, я создаю копию TDBSettings, и пользуюсь своей стандартной процедурой подключения (также с отдельными объектами коннекта и запросов). <br />
На основную программу и основные настройки это никак не влияет.<br />
<br />
Все, что связано с настройками, уносим в отдельный юнит для каждой программы.<br />
Бывает, что некоторые классы устойчиво кочуют из программы в программу. Это как раз TDBSettings;<br />
Этот класс также вынесен в отдельный юнит.<br />
<br />
Вот пример из рабочего проекта с некоторыми изъятиями<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="37768575"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="37768575" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">unit</span> AS_Settings<span class="sy1">;</span>
<span class="kw1">interface</span>
<span class="kw1">uses</span> SysUtils <span class="sy1">,</span> classes<span class="sy1">,</span> XSuperObject<span class="sy1">,</span> JsonableObject<span class="sy1">,</span> UDBSettings<span class="sy1">;</span>
<span class="kw1">type</span>
&nbsp; TASFTPServerOptions <span class="sy3">=</span> <span class="kw1">record</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; Host<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; Folder<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; Login<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; Pass<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; TASPersCardFormOptions <span class="sy3">=</span> <span class="kw1">record</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; BaseCode<span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; TASCommonRegFormOptions <span class="sy3">=</span> <span class="kw1">record</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; Filter<span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; PrintNum<span class="sy1">:</span> <span class="kw4">Boolean</span><span class="sy1">;</span>
&nbsp; &nbsp; Preview<span class="sy1">:</span> <span class="kw4">Boolean</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp; TAS_Settings <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TJsonableObject<span class="br0">&#41;</span>
&nbsp; <span class="kw1">private</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; Database<span class="sy1">:</span>TDBSettings<span class="sy1">;</span>
&nbsp; &nbsp; LastImportDatabase<span class="sy1">:</span>TDBSettings<span class="sy1">;</span>
&nbsp; &nbsp; FTP<span class="sy1">:</span>TASFTPServerOptions<span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; <span class="br0">&#91;</span>DISABLE<span class="br0">&#93;</span> <span class="co1">// для JSON</span>
&nbsp; &nbsp; RecentConnections<span class="sy1">:</span> TStringList<span class="sy1">;</span>
&nbsp; &nbsp; <span class="br0">&#91;</span>ALIAS<span class="br0">&#40;</span><span class="st0">'RecentConnections'</span><span class="br0">&#41;</span><span class="br0">&#93;</span>
&nbsp; &nbsp; _RecentConnections<span class="sy1">:</span>TStringArray<span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; PersCardForm<span class="sy1">:</span> TASPersCardFormOptions<span class="sy1">;</span>
&nbsp; &nbsp; CommonRegForm<span class="sy1">:</span> TASCommonRegFormOptions<span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">procedure</span> BeforeSave<span class="br0">&#40;</span>X<span class="sy1">:</span>ISuperObject<span class="br0">&#41;</span><span class="sy1">;</span> <span class="kw1">override</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> Afterload<span class="br0">&#40;</span>X<span class="sy1">:</span>ISuperObject<span class="br0">&#41;</span><span class="sy1">;</span> <span class="kw1">override</span><span class="sy1">;</span>
&nbsp;
&nbsp;
&nbsp; &nbsp; <span class="kw1">constructor</span> Create<span class="sy1">;</span> &nbsp;<span class="kw1">override</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">destructor</span> Destroy<span class="sy1">;</span> <span class="kw1">override</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">const</span>
&nbsp; TargetNamespace <span class="sy3">=</span> <span class="st0">''</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">var</span>
&nbsp; Settings <span class="sy1">:</span> TAS_Settings<span class="sy1">;</span>
&nbsp;
<span class="kw1">function</span> GetSettingsFilename<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="kw1">function</span> GetSettingsFilename<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; result <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">ExtractFilePath</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy3">+</span><span class="st0">'settings.json'</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="coMULTI">{ TAS_Settings }</span>
&nbsp;
<span class="kw1">procedure</span> TAS_Settings<span class="sy1">.</span><span class="me1">Afterload</span><span class="br0">&#40;</span>X<span class="sy1">:</span>ISuperObject<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; i<span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Setter_ArrayToList<span class="br0">&#40;</span>_RecentConnections<span class="sy1">,</span> RecentConnections<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TAS_Settings<span class="sy1">.</span><span class="me1">BeforeSave</span><span class="br0">&#40;</span>X<span class="sy1">:</span>ISuperObject<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; i<span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; _RecentConnections<span class="sy1">:</span><span class="sy3">=</span>Getter_ListToArray<span class="br0">&#40;</span>RecentConnections<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">constructor</span> TAS_Settings<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">inherited</span><span class="sy1">;</span>
&nbsp; RecentConnections<span class="sy1">:</span><span class="sy3">=</span>TStringList<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">destructor</span> TAS_Settings<span class="sy1">.</span><span class="me1">Destroy</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw3">FreeAndNil</span><span class="br0">&#40;</span>RecentConnections<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">inherited</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
модуль UDBSettings у меня сейчас выглядит вот так<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="125338805"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="125338805" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">unit</span> UDBSettings<span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
<span class="kw1">type</span>
&nbsp; TDBSettings <span class="sy3">=</span> <span class="kw1">record</span>
&nbsp; &nbsp; server<span class="sy1">:</span><span class="kw4">String</span><span class="sy1">;</span>
&nbsp; &nbsp; port<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; db<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; lib<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp;
&nbsp; &nbsp; user<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; pass<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; role<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> parseParams<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> ParseConnectionString<span class="br0">&#40;</span>s<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">function</span> ConnectionString<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">function</span> Equals<span class="br0">&#40;</span>d<span class="sy1">:</span>TDBSettings<span class="br0">&#41;</span><span class="sy1">:</span><span class="kw4">Boolean</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
<span class="kw1">uses</span> System<span class="sy1">.</span><span class="me1">SysUtils</span><span class="sy1">;</span>
&nbsp;
<span class="coMULTI">{ TDBSettings }</span>
&nbsp;
<span class="kw1">function</span> TDBSettings<span class="sy1">.</span><span class="me1">ConnectionString</span><span class="sy1">:</span> <span class="kw4">string</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">if</span> server&lt;&gt;<span class="st0">''</span> <span class="kw1">then</span>
&nbsp; &nbsp; result<span class="sy1">:</span><span class="sy3">=</span>server
&nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; Result <span class="sy1">:</span><span class="sy3">=</span> <span class="st0">'localhost'</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> port&lt;&gt;<span class="st0">''</span> <span class="kw1">then</span>
&nbsp; &nbsp; result<span class="sy1">:</span><span class="sy3">=</span>result<span class="sy3">+</span><span class="st0">'/'</span><span class="sy3">+</span>port<span class="sy1">;</span>
&nbsp; Result <span class="sy1">:</span><span class="sy3">=</span> result <span class="sy3">+</span> <span class="st0">':'</span> <span class="sy3">+</span> db<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TDBSettings<span class="sy1">.</span><span class="me1">ParseConnectionString</span><span class="br0">&#40;</span>s<span class="sy1">:</span><span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; s1<span class="sy1">,</span>s2<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; p<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span>
&nbsp; a<span class="sy1">:</span>TArray&lt;string&gt;<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; p<span class="sy1">:</span><span class="sy3">=</span><span class="kw3">Pos</span><span class="br0">&#40;</span><span class="st0">':'</span><span class="sy1">,</span>s<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> p&gt;<span class="nu0">0</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; server<span class="sy1">:</span><span class="sy3">=</span><span class="kw3">Copy</span><span class="br0">&#40;</span>s<span class="sy1">,</span><span class="nu0">1</span><span class="sy1">,</span>p<span class="sy3">-</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; db<span class="sy1">:</span><span class="sy3">=</span><span class="kw3">Copy</span><span class="br0">&#40;</span>s<span class="sy1">,</span>p<span class="sy3">+</span><span class="nu0">1</span><span class="sy1">,</span>s<span class="sy1">.</span><span class="me1">Length</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span>
&nbsp; <span class="kw1">else</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; server<span class="sy1">:</span><span class="sy3">=</span><span class="st0">'localhost'</span><span class="sy1">;</span>
&nbsp; &nbsp; db<span class="sy1">:</span><span class="sy3">=</span>s<span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; a<span class="sy1">:</span><span class="sy3">=</span>server<span class="sy1">.</span><span class="me1">Split</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="st0">'/'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> <span class="kw3">Length</span><span class="br0">&#40;</span>a<span class="br0">&#41;</span>&gt;<span class="nu0">1</span> <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; server<span class="sy1">:</span><span class="sy3">=</span>a<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; &nbsp; port<span class="sy1">:</span><span class="sy3">=</span>a<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">function</span> TDBSettings<span class="sy1">.</span><span class="me1">Equals</span><span class="br0">&#40;</span>d<span class="sy1">:</span> TDBSettings<span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">Boolean</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; Result <span class="sy1">:</span><span class="sy3">=</span> <span class="br0">&#40;</span>server <span class="sy3">=</span> d<span class="sy1">.</span><span class="me1">server</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">and</span> <span class="br0">&#40;</span>port <span class="sy3">=</span> d<span class="sy1">.</span><span class="me1">port</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">and</span> <span class="br0">&#40;</span>db <span class="sy3">=</span> d<span class="sy1">.</span><span class="me1">db</span><span class="br0">&#41;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TDBSettings<span class="sy1">.</span><span class="me1">parseParams</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; i<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; i <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">1</span><span class="sy1">;</span>
&nbsp; <span class="kw1">while</span> i &lt;<span class="sy3">=</span> ParamCount <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">AnsiSameText</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">,</span> <span class="st0">'-D'</span><span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span>i&lt;paramCount<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; ParseConnectionString<span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i <span class="sy3">+</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="kw3">AnsiSameText</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">,</span> <span class="st0">'-R'</span><span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span>i&lt;paramCount<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; role <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">ParamStr</span><span class="br0">&#40;</span>i <span class="sy3">+</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="kw3">AnsiSameText</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">,</span> <span class="st0">'-U'</span><span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span>i&lt;paramCount<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; user <span class="sy1">:</span><span class="sy3">=</span> <span class="kw3">ParamStr</span><span class="br0">&#40;</span>i <span class="sy3">+</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="kw3">AnsiSameText</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">,</span> <span class="st0">'-P'</span><span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span>i&lt;paramCount<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; pass <span class="sy1">:</span><span class="sy3">=</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i <span class="sy3">+</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="kw3">AnsiSameText</span><span class="br0">&#40;</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">,</span> <span class="st0">'-L'</span><span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span>i&lt;paramCount<span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; lib <span class="sy1">:</span><span class="sy3">=</span><span class="kw3">ParamStr</span><span class="br0">&#40;</span>i <span class="sy3">+</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
здесь видно, что настройки программы хранят в себе настройки разных форм программы, настройки подключения к БД, еще порция настроек БД, где хранится последнее удачное подключение, настройки подключения к FTP, настройки интерфейса для нескольких форм.<br />
Если мы хотим добавить к настройкам какие-то данные, достаточно просто добавить нужные поля к классу и они автоматически начинают записываться и считываться, без написания дополнительного кода.<br />
Вот все, что я делаю для считывания настроек:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="750785256"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="750785256" 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">&nbsp;Settings<span class="sy1">:</span><span class="sy3">=</span>TAS_Settings<span class="sy1">.</span><span class="me1">CreateFromFile</span><span class="br0">&#40;</span>GetSettingsFilename<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>ну и для сохранения<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="973086838"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="973086838" 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">&nbsp;Settings<span class="sy1">.</span><span class="me1">SaveToFile</span><span class="br0">&#40;</span>GetSettingsFilename<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Есть нюанс при использовании свойств наследников TList - TStringList, TObjectList. Они пишут в файл множество своих ненужных public свойств. Для избавления от этого в коде виден механизм ([DIASBLE], [ALIAS...]), когда перед записью и после считывания мы используем временный массив нужных объектов. List не читается/пишется, вместо него работает подставной массив. Потом из массива мы переносим все в List, с которым гораздо удобнее работать, и продолжаем.<br />
<br />
Внутри программы глобальная переменная Settings используется где попало<br />
например<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="108955670"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="108955670" 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">TryConnect<span class="br0">&#40;</span> Settings<span class="sy1">.</span><span class="me1">Database</span> <span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>или<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="817447912"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="817447912" 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">&nbsp;<span class="kw1">if</span> Settings<span class="sy1">.</span><span class="me1">DiplomaFile</span>&lt;&gt;<span class="st0">''</span> <span class="kw1">then</span>
&nbsp; &nbsp; repDiploma<span class="sy1">.</span><span class="me1">LoadFromFile</span><span class="br0">&#40;</span>Settings<span class="sy1">.</span><span class="me1">DiplomaFile</span><span class="sy1">,</span><span class="kw2">true</span><span class="br0">&#41;</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Резюмирую. Отличный вариант работы с настройками программы.<br />
Просто. Удобно. Красиво.<br />
<br />
UPD<br />
обновленная версия статьи для кроссплатформы<br />
<a rel="nofollow noopener noreferrer" href="https://blogs.embarcadero.com/this-is-how-to-store-cross-platform-app-settings-in-json/" target="_blank" title="https://blogs.embarcadero.com/this-is-how-to-store-cross-platform-app-settings-in-json/">https://blogs.embarcadero.com/... s-in-json/</a></div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/4883.html</guid>
		</item>
		<item>
			<title>Про потоки</title>
			<link>https://www.cyberforum.ru/blogs/469693/4875.html</link>
			<pubDate>Sun, 13 Aug 2017 07:03:59 GMT</pubDate>
			<description>Сразу, в первой строке. 
Потоки не должны ничего читать и писать в формах и компонентах!!! 
Все,...</description>
			<content:encoded><![CDATA[<div>Сразу, в первой строке.<br />
Потоки не должны ничего читать и писать в формах и компонентах!!!<br />
Все, что нужно им для работы, задавайте им до старта, и забирайте результат после выполнения<br />
<br />
Сама концепция потоков проста. Вы можете мыслить их как корабль, отправляющийся в дальнее плавание. На Марс, например. Вроде как и можно устроить сеанс связи с Хьюстоном, но это геморрой, поэтому нужно на корабль погрузить все до старта, и только после возврата вы сможете разобрать трофеи. Лучше всего - запустить и забыть. Даже если вы запустите 20 кораблей, то возвращаться они будут по одному. И на каждом будет написан его бортовой номер, чтобы вы могли их отличать.<br />
Как-то так. <br />
И точно потоки не помогут вам ничего рисовать на экране или двигать компоненты. Зато они могут все рассчитать для этого, создать битмапы и заполнить какие-то структуры данных. А вы уже в главном потоке все это будете использовать для вывода на экран.<br />
<br />
Часто путают поток ОС с классом TThread<br />
Это не одно и то же. TThread призван запомнить все данные, нужные в потоке, запустить поток в операционной системе, выполнить действие в нем и вернуть результат. <br />
<br />
Жизнь потока состоит из трех этапов<br />
1. создание и инициализация (это еще не поток с т.з. ОС) <br />
2. запуск настоящего потока (вот тут настоящий поток ОС работает)<br />
3. окончание работы потока <br />
Обратите внимание! В пунктах 1 и 3 работа идет в главном потоке, там, где формы и пользовательский ввод.<br />
Только 2-я часть уходит в автономное плавание, забирая с собой все переменные, которые вы ей насовали с собой в части 1<br />
<br />
Начнем<br />
1. Нужно создать своего наследника TThread, имеющего все нужные поля. Заполнить эти поля. Запустить поток.<br />
Примечание.<br />
Все дополнительные классы выносите в дополнительные юниты! Пусть класс TMyThread будет жить в UMyThread.pas<br />
UMyThread мы должны прописать в uses у формы, откуда будет запускать свои потоки.<br />
Юнит UMyThread ничего о форме знать НЕ ДОЛЖЕН!<br />
<br />
2. Самая стандартная задача - сходить в потоке в интернет и что-то скачать. Результат вернуть и использовать в форме<br />
2.1. Залогиниться где-то один раз. <br />
2.2. Скачать со 100 страниц информацию и опять же что-то с ней сделать<br />
Разберем задачу 2.2. Она посложнее<br />
<br />
Лирическое отступление<br />
Класс TThread имеет замечательное свойство FreeOnTerminate. Если установить его в true, то не нужно будет хранить ссылку на созданный объект, чтобы потом удалить его вручную. Создали, запустили и забыли о нем. Память освободится сама. Сделать это лучше всего, переопределив конструктор нашего наследника, где и вписать FreeOnTerminate := true;<br />
В том же конструкторе мы должны вызвать конструктор предка - класса TThread - с параметром true<br />
Это значит, он не запустится сразу же, а даст нам сначала заполнить поля объекта, а мы потом его запустим командой Resume. (В свежих версиях Delphi вместо Resume нужно вызывать Start)<br />
<br />
3. Главное. Как мы получим данные от потока?<br />
У класса TThread есть обработчик OnTerminate. Если на него назначить нашу собственную процедуру, то она будет вызываться после Execute для каждого потока. Это удобно. Дважды удобно то, что OnTerminate работает уже в главном потоке  и не надо ничего делать для синхронизации, можно прямо писать в компоненты, например выводить в мемо, или заполнять структуры данных, не боясь, что другие потоки тоже лезут туда. Все синхронизировано по факту. Поэтому это лучший метод возврата результата из потока.<br />
Итак. Объявим метод формы с любым именем, лишь бы параметры были Sender: TObject<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="960930896"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="960930896" 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="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">ThreadTerm</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span> th<span class="sy1">:</span>TMyThread absolute Sender<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="co1">// th - это наш вернувшийся из плавания поток. можно использовать все его поля</span>
&nbsp; <span class="co1">// например если мы сделаем классу поле Answer, то здесь можно будет вывести его в Memo</span>
&nbsp; memo1<span class="sy1">.</span><span class="me1">lines</span><span class="sy1">.</span><span class="me1">add</span><span class="br0">&#40;</span>th<span class="sy1">.</span><span class="me1">answer</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Для красоты и простоты переопределим конструктор нашего наследника, чтобы можно было указывать этот метод<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="281348703"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="281348703" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="kw1">constructor</span> TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>ATermProc<span class="sy1">:</span>TNotifyEvent<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">inherited</span> Create<span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; FreeOnTerminate<span class="sy1">:</span><span class="sy3">=</span><span class="kw2">true</span><span class="sy1">;</span>
&nbsp; OnTerminate<span class="sy1">:</span><span class="sy3">=</span>ATermProc<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>соответственно создание потока с указанием ThreadTerm как обработчика OnTerminate:<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="789502357"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="789502357" 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">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">RunThread</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span> th<span class="sy1">:</span>TMyThread<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; th<span class="sy1">:</span><span class="sy3">=</span>TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>ThreadTerm<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Примечание.<br />
Рекомендуется не заполонять систему своими потоками. 3000 потоков вашей программы почти с гарантией поставят систему на колени. Поэтому одновременно запустим N потоков. После окончания каждого одного будем запускать один следующий, пока не стартуем нужное нам количество. При этом активно всегда будет не более N потоков.<br />
<br />
Итак, сценарий.<br />
Запустить N потоков.<br />
При завершении - проверять, нужно ли запустить еще, или нет.<br />
Также проверять, если все потоки завершены, то подвести итог.<br />
Кнопку запуска потоков сделаем неактивной до времени, когда закончится последний поток, чтобы нельзя было запустить процесс еще раз.<br />
Реализация<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="108539430"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="108539430" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">unit</span> UMainForm<span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; classes<span class="sy1">,</span> types<span class="sy1">,</span> forms<span class="sy1">,</span> Controls<span class="sy1">,</span> StdCtrls<span class="sy1">,</span> Dialogs<span class="sy1">,</span> SysUtils<span class="sy1">;</span>
&nbsp;
<span class="kw1">type</span>
&nbsp; TMainForm <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
&nbsp; &nbsp; bStart<span class="sy1">:</span> TButton<span class="sy1">;</span>
&nbsp; &nbsp; m1<span class="sy1">:</span> TMemo<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> bStartClick<span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">private</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> Log<span class="br0">&#40;</span><span class="kw1">const</span> s<span class="sy1">:</span> <span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> ThreadTerm<span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; Started<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span>
&nbsp; &nbsp; Finished<span class="sy1">:</span><span class="kw4">integer</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> RunThread<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">var</span>
&nbsp; MainForm<span class="sy1">:</span> TMainForm<span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; UMyThread<span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="kw1">const</span>
&nbsp; MAX_THREADS<span class="sy3">=</span><span class="nu0">100</span><span class="sy1">;</span>
&nbsp; SAME_TIME<span class="sy3">=</span><span class="nu0">25</span><span class="sy1">;</span>
&nbsp;
<span class="co2">{$R *.dfm}</span>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
<span class="coMULTI">{ TMainForm }</span>
&nbsp;
&nbsp;
<span class="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">Log</span><span class="br0">&#40;</span><span class="kw1">const</span> s<span class="sy1">:</span><span class="kw4">string</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; m1<span class="sy1">.</span><span class="me1">Lines</span><span class="sy1">.</span><span class="me1">Add</span><span class="br0">&#40;</span>s<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">ThreadTerm</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; th<span class="sy1">:</span>TMyThread absolute Sender<span class="sy1">;</span> <span class="co1">// очень древняя магия. обозначает th:=TMyThread(Sender)</span>
<span class="kw1">begin</span>
&nbsp; log<span class="br0">&#40;</span>th<span class="sy1">.</span><span class="me1">URL</span> <span class="sy3">+</span> <span class="st0">':'</span><span class="sy3">+</span>th<span class="sy1">.</span><span class="me1">answer</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>Finished<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> Started&lt;MAX_THREADS <span class="kw1">then</span>
&nbsp; &nbsp; RunThread<span class="sy1">;</span>
&nbsp; <span class="kw1">if</span> Finished<span class="sy3">=</span>MAX_THREADS <span class="kw1">then</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; log<span class="br0">&#40;</span><span class="st0">'==========================='</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; log<span class="br0">&#40;</span><span class="st0">'Работа окончена'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; bStart<span class="sy1">.</span><span class="me1">Enabled</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw2">true</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">bStartClick</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span> <span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; i<span class="sy1">:</span> <span class="kw4">Integer</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; bStart<span class="sy1">.</span><span class="me1">enabled</span><span class="sy1">:</span><span class="sy3">=</span><span class="kw2">false</span><span class="sy1">;</span>
&nbsp; <span class="kw1">for</span> i <span class="sy1">:</span><span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">to</span> SAME_TIME<span class="sy3">-</span><span class="nu0">1</span> <span class="kw1">do</span>
&nbsp; &nbsp; RunThread<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">RunThread</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; th<span class="sy1">:</span>TMyThread<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>Started<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; th<span class="sy1">:</span><span class="sy3">=</span>TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="st0">'URL '</span><span class="sy3">+</span><span class="kw3">inttostr</span><span class="br0">&#40;</span>Started<span class="br0">&#41;</span><span class="sy1">,</span> ThreadTerm <span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; Log<span class="br0">&#40;</span><span class="st0">'запущен '</span><span class="sy3">+</span>th<span class="sy1">.</span><span class="me1">url</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; th<span class="sy1">.</span><span class="me1">Resume</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="933242678"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="933242678" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">unit</span> UMyThread<span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
<span class="kw1">uses</span> Classes<span class="sy1">;</span>
<span class="kw1">type</span>
&nbsp; TMyThread<span class="sy3">=</span><span class="kw1">class</span><span class="br0">&#40;</span>TThread<span class="br0">&#41;</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; URL<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; answer<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> Execute<span class="sy1">;</span><span class="kw1">override</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">constructor</span> Create<span class="br0">&#40;</span>AURL<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span> TermProc<span class="sy1">:</span>TNotifyEvent<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
<span class="kw1">uses</span> Sysutils<span class="sy1">;</span>
&nbsp;
<span class="coMULTI">{ TMyThread }</span>
&nbsp;
<span class="kw1">constructor</span> TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>AURL<span class="sy1">:</span><span class="kw4">string</span><span class="sy1">;</span> TermProc<span class="sy1">:</span>TNotifyEvent<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">inherited</span> Create<span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; URL <span class="sy1">:</span><span class="sy3">=</span> AURL<span class="sy1">;</span>
&nbsp; FreeOnTerminate <span class="sy1">:</span><span class="sy3">=</span> <span class="kw2">true</span><span class="sy1">;</span>
&nbsp; OnTerminate <span class="sy1">:</span><span class="sy3">=</span> TermProc<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMyThread<span class="sy1">.</span><span class="me1">Execute</span><span class="sy1">;</span>
<span class="kw1">var</span> g<span class="sy1">:</span>TGUID<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="co1">// предположим, что здесь мы сходили в интернет и забрали с адреса URL</span>
&nbsp; <span class="co1">// что-то очень нужное. Ответ поместили в Answer</span>
&nbsp; <span class="co1">// сейчас просто генерируем уникальный ответ</span>
&nbsp; <span class="kw3">CreateGuid</span><span class="br0">&#40;</span>g<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; Answer<span class="sy1">:</span><span class="sy3">=</span>g<span class="sy1">.</span><span class="me1">ToString</span><span class="sy1">;</span>
&nbsp; <span class="co1">// сымитируем, что все потоки получат ответ с разной скоростью</span>
&nbsp; <span class="kw3">Sleep</span><span class="br0">&#40;</span><span class="kw3">Random</span><span class="br0">&#40;</span><span class="nu0">50</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />
Часто задают вопрос, что делать, пока потоки выполняются. И заводят какие-то безумные циклы<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="719819404"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="719819404" 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">while</span> <span class="kw2">true</span> <span class="kw1">and</span> Potoki&lt;<span class="nu0">100</span> <span class="kw1">do</span> &nbsp;Application<span class="sy1">.</span><span class="me1">ProcessMessages</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Это ужасно! Правильный ответ - ничего! Ваше &quot;ничего не делать&quot; для программы это куча нужной работы: <br />
отслеживание мыши, клавиатуры, перерисовка себя любимой, реагирование на всякие сообщения системы.<br />
Это ее нормальное состояние.<br />
Что-либо еще(!) делать она будет, когда возвращается поток.<br />
Например, как в данном случае, когда все потоки завершены, мы выводим запись в мемо.<br />
<br />
<br />
UPD<br />
Давайте рассмотрим еще несколько вопросов<br />
<br />
Пример 1<br />
Мы запустили поток. Он занят чем-то продолжительным но не единым действием, а в цикле.<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   например<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="878844358"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="878844358" 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">while</span> i&lt;<span class="nu0">1000</span> <span class="kw1">do</span>
<span class="kw1">begin</span>
&nbsp; doSomething<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>для остановки потока в классе TThread есть простой флаг Terminated<br />
тогда модифицируем условие<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="669242953"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="669242953" 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">while</span> <span class="br0">&#40;</span>i&lt;<span class="nu0">1000</span><span class="br0">&#41;</span> <span class="kw1">and</span> <span class="br0">&#40;</span><span class="kw1">not</span> Terminated<span class="br0">&#41;</span> <span class="kw1">do</span>
<span class="kw1">begin</span>
&nbsp; doSomething<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>и соответственно, если мы не выбросим ссылку на созданный поток, <br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="631608676"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="631608676" 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">th<span class="sy1">:</span><span class="sy3">=</span>TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span><span class="sy1">;</span>
th<span class="sy1">.</span><span class="me1">Resume</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>...мы можем сделать<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="848070777"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="848070777" 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">th<span class="sy1">.</span><span class="me1">Terminate</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div> это примитивный метод, который делает всего лишь Th.terminated := true; и по нашему условию цикл закончится
				   </div>
			   </div><br />
<br />
Пример 2<br />
У нас куча потоков и мы хотим остановить их<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   Делаем то же самое но используем для этого общую переменную. Я специально говорю &quot;общую&quot; а не &quot;глобальную&quot;.<br />
Хотя одно есть разновидность другого. Я очень не рекомендую использовать глобалки в серьезных проектах<br />
Это не страшно, но очень не здорово. При этом глобалку нужно использовать простого типа - boolean, integer, тогда доступ к ней можно осуществлять без механизмов синхронизации.<br />
Хорошим вариантом будет, например, передать в поток УКАЗАТЕЛЬ на переменную.<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="40682254"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="40682254" 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">TMyThread<span class="sy3">=</span><span class="kw1">class</span>
&nbsp; Terminated2<span class="sy1">:</span><span class="sy2">^</span>boolean<span class="sy1">;</span>
&nbsp; <span class="sy1">...</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMyThread<span class="sy1">.</span><span class="me1">Execute</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">while</span> <span class="kw1">not</span> Terminated2<span class="sy2">^</span> <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; <span class="sy1">.....</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>в форме заведем переменную<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="465691722"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="465691722" 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">TForm1<span class="sy3">=</span><span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
&nbsp;<span class="sy1">...</span>
&nbsp; <span class="me1">stopThreads</span><span class="sy1">:</span><span class="kw4">boolean</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
<span class="sy1">...</span>
<span class="me1">th</span> <span class="sy1">:</span><span class="sy3">=</span> TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="sy1">...</span><span class="br0">&#41;</span><span class="sy1">;</span>
th<span class="sy1">.</span><span class="me1">Terminated2</span><span class="sy1">:</span><span class="sy3">=</span><span class="sy2">@</span>stopThread<span class="sy1">;</span>
<span class="sy1">...</span>
<span class="sy1">...</span>
&nbsp;
<span class="me1">stopThread</span> <span class="sy1">:</span><span class="sy3">=</span> <span class="kw2">true</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>и все потоки остановятся
				   </div>
			   </div><br />
<br />
Пример 3<br />
Если чекбокс установлен, то в потоке делать то, а иначе делать сё<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   Понятно, что никакой чекбокс передавать в поток нельзя. Нам нужен не компонент, а само значение. Вот его мы передадим в поток перед стартом<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="992460831"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="992460831" 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">th<span class="sy1">:</span><span class="sy3">=</span>TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="sy1">;</span>
th<span class="sy1">.</span><span class="me1">paramXXX</span> <span class="sy1">:</span><span class="sy3">=</span> checkBox1<span class="sy1">.</span><span class="me1">Checked</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>и используем в работе полученное значение<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="363917736"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="363917736" 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="kw1">procedure</span> TMyThread<span class="sy1">.</span><span class="me1">Execute</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">if</span> paramXXX <span class="kw1">then</span>
&nbsp; &nbsp; Proc1<span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; Proc2<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>мало того. если это значение может меняться в процессе работы потока, вам нужно просто не выбрасывать ссылку на созданный поток ))<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="318352799"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="318352799" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">th <span class="sy1">:</span><span class="sy3">=</span> TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="sy1">...</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="sy1">...</span>
<span class="kw1">procedure</span> TForm1<span class="sy1">.</span><span class="me1">CheckBox1Checked</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span><span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; th<span class="sy1">.</span><span class="me1">paramXXX</span> <span class="sy1">:</span><span class="sy3">=</span> checkBox1<span class="sy1">.</span><span class="me1">Checked</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />
Пример 4<br />
Любимое. Как из потока менять что-то на форме. Синхронизация.<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <br />
Хорошим способом является передача сообщений через SendMessage();<br />
Но тут начнутся проблемы с правильной работой с памятью, когда передаем строки и много другого, и главное - это не кроссплатформенно! Поэтому я обычно выбираю Synchronize. Еще раз подчеркну. Нельзя вызывать формы и их компоненты и еще много чего без синхронизации, т.е. без указания, что эту процедуру можно выполнять только в главном потоке.<br />
Но это значит, что этот поток остановится и будет ждать, когда процедура выполнится. Поэтому выполняйте синхронизацию как можно реже и как можно быстрее.<br />
Как я уже говорил, мы не даем потоку ссылку на форму. Хотите двигать прогресс-бар, - возьмите ссылку на прогресс-бар и  пользуйтесь. Хотите мемо - берите ссылку на мемо. Но помните! Мемо - один из самых тормозных компонентов. 5000 строк - и вся ваша программа 85% времени проводит, добавляя строки в мемо.<br />
Итак, цикл, синхронизация, запись в progressBar. Да еще и не каждый проход цикла, чтобы не молотить зря.<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="121442206"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="121442206" 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">th<span class="sy1">:</span><span class="sy3">=</span>TMyThread<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="sy1">...</span><span class="br0">&#41;</span><span class="sy1">;</span>
th<span class="sy1">.</span><span class="me1">progressBar</span> <span class="sy1">:</span><span class="sy3">=</span> progressBar1<span class="sy1">;</span>
<span class="sy1">...</span>
<span class="kw1">procedure</span> TMyThread<span class="sy1">.</span><span class="me1">ShowProgress</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; progressBar<span class="sy1">.</span><span class="me1">position</span> <span class="sy1">:</span><span class="sy3">=</span> FIndex <span class="kw1">div</span> <span class="nu0">1000</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMyThread<span class="sy1">.</span><span class="me1">Execute</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; FIndex<span class="sy1">:</span><span class="sy3">=</span><span class="nu0">0</span><span class="sy1">;</span>
&nbsp; <span class="kw1">while</span> FIndex &lt; <span class="nu0">100000</span> <span class="kw1">do</span>
&nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; <span class="kw1">if</span> index <span class="kw1">mod</span> <span class="nu0">1000</span> <span class="sy3">=</span> <span class="nu0">0</span> <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; Synchronize<span class="br0">&#40;</span>ShowProgress<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp;<span class="sy1">....</span>
&nbsp; &nbsp; <span class="kw3">inc</span><span class="br0">&#40;</span>FIndex<span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />
upd<br />
тема &quot;Я пишу приложение, которое выкачивает весь интернет по списку из Memo. Скажите как.&quot; настолько замусолена уже<br />
что приложу себе ссылку, чтобы потом легче искать<br />
<a href="https://www.cyberforum.ru/delphi-beginners/thread1441138-page2.html#post7766045">https://www.cyberforum.ru/delp... ost7766045</a></div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/4875.html</guid>
		</item>
		<item>
			<title>Как правильно сделать форму логина</title>
			<link>https://www.cyberforum.ru/blogs/469693/4874.html</link>
			<pubDate>Sun, 13 Aug 2017 05:46:23 GMT</pubDate>
			<description>Как ни странно, но часто создание сценария входа в программу становится довольно сложным...</description>
			<content:encoded><![CDATA[<div>Как ни странно, но часто создание сценария входа в программу становится довольно сложным препятствием при построении архитектуры приложения у молодых программистов. Давайте попробуем сделать хороший пример.<br />
<br />
Итак, сначала должен быть сценарий. Вот он.<br />
Стартует приложение.<br />
Перед показом главной формы мы должны вывести диалог авторизации к кнопками ОК и Отмена<br />
Если в диалоге нажать Отмена, то мы сразу выходим из программы<br />
Если ОК - то нужно проверить логин пароль. Если все правильно - показать главную форму, если нет - опять показать диалог.<br />
<br />
Делать это можно двумя способами - в обработчике OnCreate главной формы, и переопределяя конструктор главной формы<br />
Более правильный вариант - второй. Поэтому рассмотрим его. <br />
Дело в том, что если мы выберем выход из программы, в случае OnCreate главная форма все равно сначала загрузится и только потом мигнет и программа закончится. Нам это не хочется видеть, поэтому - конструктор.<br />
<br />
Итак. Мы создадим главную форму TMainForm и форму логина TLoginForm.<br />
(примечание про AutoCreate <a href="https://www.cyberforum.ru/blogs/469693/blog4873.html">https://www.cyberforum.ru/blog... g4873.html</a>)<br />
LoginForm - два Label два Edit и две TButton с заполненным ModalResult mrOk и mrCancel соответственно. <br />
BorderStyle=bsDialog. Position=poMainFormCenter<br />
<br />
В MainForm переопределяем конструктор и пишем туда... оп! не плодить простыни в коде!<br />
Пишем туда <br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="424450489"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="424450489" 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">inherited</span><span class="sy1">;</span> <span class="co1">// нужно вызвать конструктор предка</span>
CheckLogin<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span> <span class="co1">// а тут будут действия по проверке логина</span></pre></td></tr></table></div></td></tr></tbody></table></div>так же стараемся себя вести и в других местах, выделяя логические блоки в отдельные процедуры и функции<br />
например, сама проверка пароля у нас будет выполняться в функции LoginCorrect(login,pass:string):boolean;<br />
и она ничего вообще не будет знать о форме логина, ибо мало ли откуда к нам придут логин и пароль впоследствии...<br />
<br />
итого:<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="314355041"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="314355041" 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
</pre></td><td class="de1"><pre class="de1"><span class="kw1">unit</span> UMainForm<span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; classes<span class="sy1">,</span> types<span class="sy1">,</span> forms<span class="sy1">,</span> Controls<span class="sy1">,</span> StdCtrls<span class="sy1">,</span> Dialogs<span class="sy1">,</span> SysUtils<span class="sy1">;</span>
&nbsp;
<span class="kw1">type</span>
&nbsp; TMainForm <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
&nbsp; <span class="kw1">private</span>
&nbsp; &nbsp; <span class="kw1">procedure</span> CheckLogin<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">function</span> LoginCorrect<span class="br0">&#40;</span>login<span class="sy1">,</span> pass<span class="sy1">:</span> <span class="kw4">String</span><span class="br0">&#41;</span><span class="sy1">:</span> <span class="kw4">Boolean</span><span class="sy1">;</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; <span class="kw1">constructor</span> Create<span class="br0">&#40;</span>AOwner<span class="sy1">:</span> TComponent<span class="br0">&#41;</span><span class="sy1">;</span> <span class="kw1">override</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">var</span>
&nbsp; MainForm<span class="sy1">:</span> TMainForm<span class="sy1">;</span>
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; ULoginForm<span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="co2">{$R *.dfm}</span>
&nbsp;
<span class="kw1">function</span> TMainForm<span class="sy1">.</span><span class="me1">LoginCorrect</span><span class="br0">&#40;</span>login<span class="sy1">,</span>pass<span class="sy1">:</span><span class="kw4">String</span><span class="br0">&#41;</span><span class="sy1">:</span><span class="kw4">Boolean</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; result <span class="sy1">:</span><span class="sy3">=</span> <span class="kw2">true</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">CheckLogin</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span>
&nbsp; f<span class="sy1">:</span>TLoginForm<span class="sy1">;</span>
&nbsp; r<span class="sy1">:</span>TModalResult<span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; f<span class="sy1">:</span><span class="sy3">=</span>TLoginForm<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">NIL</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; <span class="kw1">repeat</span>
&nbsp; &nbsp; &nbsp; r<span class="sy1">:</span><span class="sy3">=</span>f<span class="sy1">.</span><span class="me1">ShowModal</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> r<span class="sy3">=</span>mrOk <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// придумаем функцию LoginCorrect() которая возвращает нам True или False</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// откуда она берет эти данные, из базы или файла или придумывает сама, нам все равно</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> LoginCorrect<span class="br0">&#40;</span>f<span class="sy1">.</span><span class="me1">eLogin</span><span class="sy1">.</span><span class="me1">text</span><span class="sy1">,</span> f<span class="sy1">.</span><span class="me1">ePassword</span><span class="sy1">.</span><span class="me1">text</span><span class="br0">&#41;</span> <span class="kw1">then</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Break
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">until</span> r<span class="sy3">=</span>mrCancel<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> r<span class="sy3">=</span>mrCancel <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; ShowMessage<span class="br0">&#40;</span><span class="st0">'Отказ от авторизации. Программа завершает свою работу.'</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; Application<span class="sy1">.</span><span class="me1">Terminate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; Abort<span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; <span class="kw1">finally</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">free</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="kw1">constructor</span> TMainForm<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span>AOwner<span class="sy1">:</span> TComponent<span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; <span class="kw1">inherited</span><span class="sy1">;</span>
&nbsp; CheckLogin<span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Кликните здесь для просмотра всего текста</div>
				   <div class="spoiler-body">
					   <div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="964855100"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="964855100" 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="kw1">unit</span> ULoginForm<span class="sy1">;</span>
&nbsp;
<span class="kw1">interface</span>
&nbsp;
<span class="kw1">uses</span>
&nbsp; Windows<span class="sy1">,</span> Messages<span class="sy1">,</span> Forms<span class="sy1">,</span> StdCtrls<span class="sy1">,</span> Classes<span class="sy1">,</span> Controls<span class="sy1">;</span>
&nbsp;
<span class="kw1">type</span>
&nbsp; TLoginForm <span class="sy3">=</span> <span class="kw1">class</span><span class="br0">&#40;</span>TForm<span class="br0">&#41;</span>
&nbsp; &nbsp; eLogin<span class="sy1">:</span> TEdit<span class="sy1">;</span>
&nbsp; &nbsp; ePassword<span class="sy1">:</span> TEdit<span class="sy1">;</span>
&nbsp; &nbsp; bOk<span class="sy1">:</span> TButton<span class="sy1">;</span>
&nbsp; &nbsp; bCancel<span class="sy1">:</span> TButton<span class="sy1">;</span>
&nbsp; <span class="kw1">private</span>
&nbsp; &nbsp; <span class="coMULTI">{ Private declarations }</span>
&nbsp; <span class="kw1">public</span>
&nbsp; &nbsp; <span class="coMULTI">{ Public declarations }</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
&nbsp;
<span class="kw1">implementation</span>
&nbsp;
<span class="co2">{$R *.dfm}</span>
&nbsp;
<span class="kw1">end</span><span class="sy1">.</span></pre></td></tr></table></div></td></tr></tbody></table></div>
				   </div>
			   </div><br />
вот и все<br />
<br />
UPD<br />
Более жизненный сценарий старта программы я привел <a href="https://www.cyberforum.ru/blogs/469693/blog4884.html">здесь</a></div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/4874.html</guid>
		</item>
		<item>
			<title>Создание и использование форм</title>
			<link>https://www.cyberforum.ru/blogs/469693/4873.html</link>
			<pubDate>Sun, 13 Aug 2017 05:09:18 GMT</pubDate>
			<description>Формы это то что придумано для взаимодействия вашей модели данных с пользователем. 
Совсем НЕ для...</description>
			<content:encoded><![CDATA[<div>Формы это то что придумано для взаимодействия вашей модели данных с пользователем.<br />
Совсем НЕ для хранения глобальных переменных, настроек и прочей требухи.<br />
Они должны создаваться в тот момент, когда понадобились, и уничтожаться после использования.<br />
Поэтому первое, что мы должны сделать, создав новую форму, зайти в Project - Options - Forms и удалить ВСЕ формы, кроме главной, из Auto-Create<br />
<br />
Второе.<br />
Если какая-то ваша форма требует данных с главной формы, вы неправильно строите архитектуру!<br />
Никаких &quot;обратных&quot; связей между формами не должно быть.<br />
MainForm uses Form2 и всё. Наоборот - ни-ни.<br />
Возможно, что нужны какие-то общие данные для этой формы. но тогда выносим данные в отдельный юнит и включаем его в uses у обеих форм.<br />
После этого все просто как мычание.<br />
<br />
<div class="codeblock"><table class="delphi"><thead><tr><td colspan="2" id="843279957"  class="head">Delphi</td></tr></thead><tbody><tr class="li1"><td><div id="843279957" 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="kw1">uses</span> USecondForm<span class="sy1">;</span>
<span class="sy1">...</span>
<span class="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">Button1Click</span><span class="br0">&#40;</span>Sender<span class="sy1">:</span><span class="kw4">TObject</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">begin</span>
&nbsp; RunSecondForm<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span>
&nbsp;
<span class="kw1">procedure</span> TMainForm<span class="sy1">.</span><span class="me1">RunSecondForm</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
<span class="kw1">var</span> f<span class="sy1">:</span>TSecondForm<span class="sy1">;</span>
&nbsp; aa<span class="sy1">,</span>bb<span class="sy1">,</span>cc<span class="sy1">....</span>
<span class="kw1">begin</span>
&nbsp; f<span class="sy1">:</span><span class="sy3">=</span>TSecondForm<span class="sy1">.</span><span class="me1">Create</span><span class="br0">&#40;</span><span class="kw1">NIL</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; <span class="kw1">try</span>
&nbsp; &nbsp; <span class="co1">// подготавливаем форму к показу. заполняем ее поля. настраиваем настройки</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">field1</span> <span class="sy1">:</span><span class="sy3">=</span> xxxx<span class="sy1">;</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">field2</span> <span class="sy1">:</span><span class="sy3">=</span> yyyy<span class="sy1">;</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">Init</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="co1">// показываем модально и ждем результата</span>
&nbsp; &nbsp; <span class="kw1">if</span> f<span class="sy1">.</span><span class="me1">ShowModal</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy3">=</span>mrOK <span class="kw1">then</span>
&nbsp; &nbsp; <span class="kw1">begin</span>
&nbsp; &nbsp; &nbsp; <span class="co1">//забираем из полей формы все что нам нужно</span>
&nbsp; &nbsp; &nbsp; aa<span class="sy1">:</span><span class="sy3">=</span>f<span class="sy1">.</span><span class="me1">field5</span><span class="sy1">;</span>
&nbsp; &nbsp; &nbsp; bb<span class="sy1">:</span><span class="sy3">=</span>f<span class="sy1">.</span><span class="me1">field6</span><span class="sy1">;</span>
&nbsp; &nbsp; <span class="kw1">end</span><span class="sy1">;</span>
&nbsp; <span class="kw1">finally</span>
&nbsp; &nbsp; <span class="co1">// и уничтожаем форму</span>
&nbsp; &nbsp; f<span class="sy1">.</span><span class="me1">free</span><span class="sy1">;</span>
&nbsp; <span class="kw1">end</span><span class="sy1">;</span>
<span class="kw1">end</span><span class="sy1">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>99% форм подпадают под этот сценарий</div>

]]></content:encoded>
			<dc:creator>krapotkin</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/469693/4873.html</guid>
		</item>
	</channel>
</rss>
