<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Delphi блог Димаса &#187; Статьи</title>
	<atom:link href="http://parsers.info/cat/stati/feed/" rel="self" type="application/rss+xml" />
	<link>http://parsers.info</link>
	<description>Delphi, программы, парсеры, статьи, исходники</description>
	<lastBuildDate>Wed, 07 Jul 2010 11:27:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Изменение размеров буфера консольного окна</title>
		<link>http://parsers.info/2010/01/getconsolescreenbufferinfo-setconsolescreenbuffersize/</link>
		<comments>http://parsers.info/2010/01/getconsolescreenbufferinfo-setconsolescreenbuffersize/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 17:20:32 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[delphi]]></category>
		<category><![CDATA[Кодинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[winapi]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=541</guid>
		<description><![CDATA[Привет! Это второй пост, который был потерян когда-то в июле в связи с переездом на другой хостинг. Речь пойдёт о так называемом Screen Buffer. Консольное окно само по себе имеет определенные размеры, обычно 24 на 80 символов. Также справа есть полоса прокрутки, с помощью неё можно увидеть то, что вышло за рамки экрана, так как [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://parsers.info/wp-content/uploads/2010/01/cmd.png" alt="SetConsoleScreenBufferSize: изменение размеров буфера консольного окна" title="Изменение размеров буфера консольного окна" width="182" height="286" class="alignleft size-full wp-image-543" />Привет! Это второй пост, который был потерян когда-то в июле в связи с переездом на другой хостинг.<br />
Речь пойдёт о так называемом <strong>Screen Buffer</strong>.<br />
Консольное окно само по себе имеет определенные размеры, обычно 24 на 80 символов.<br />
<span id="more-541"></span><br />
Также справа есть полоса прокрутки, с помощью неё можно увидеть то, что вышло за рамки экрана, так как когда мы всё пишем и пишем, например с помощью <em>процедуры writeln</em>, доходим до строки номер 24 и пишем дальше, то всё сдвигается. Или когда с помощью <strong>api функции SetConsoleCursorPosition</strong> или через <em>GotoXY</em> из <a href="http://parsers.info/2009/04/modul-crt-dlya-delphi-2/">модуля crt для delphi </a>ставим курсор на место, расположенное ниже досягаемого нами пространства.<br />
Всё, что можно увидеть с помощью прокрутки, и есть Screen Buffer.</p>
<p>Чтобы поменять его размеры, нужно познакомиться с ним поближе.</p>
<h3>Что нам о нём известно?</h3>
<p>Его размеры можно получить с помощью api функции <strong>GetConsoleScreenBufferInfo</strong>, вот её синтаксис:</p>
<pre name="code" class="delphi">function GetConsoleScreenBufferInfo(hConsoleOutput: THandle; var lpConsoleScreenBufferInfo: TConsoleScreenBufferInfo): BOOL;</pre>
<p>По порядку:<br />
<strong>hConsoleOutput: THandle</strong> &#8211; handle вывода консольного окна, его нам вернёт api функция <strong>GetStdHandle</strong> с параметром <strong>STD_OUTPUT_HANDLE</strong>;<br />
<strong>lpConsoleScreenBufferInfo: TConsoleScreenBufferInfo</strong> &#8211; сюда передаём объект типа TConsoleScreenBufferInfo</p>
<p>Структура <strong>CONSOLE_SCREEN_BUFFER_INFO</strong>, она же TConsoleScreenBufferInfo, она же _CONSOLE_SCREEN_BUFFER_INFO:</p>
<pre name="code" class="delphi">
  _CONSOLE_SCREEN_BUFFER_INFO = packed record
    dwSize: TCoord;
    dwCursorPosition: TCoord;
    wAttributes: Word;
    srWindow: TSmallRect;
    dwMaximumWindowSize: TCoord;
  end;
</pre>
<p>Функция GetConsoleScreenBufferInfo её нам заполнила, что мы получили:<br />
<strong>dwSize: TCoord</strong> &#8211; размер буфера, вот он! (по умолчанию 80 на 300 символов)<br />
<strong>dwCursorPosition: TCoord</strong> &#8211; положение курсора, тоже полезно, вполне заменит паскалевские <strong>WhereX</strong> и <strong>WhereY</strong>, они также реализованы в моём <a href="http://parsers.info/2009/04/modul-crt-dlya-delphi-2/">модуле crt</a><br />
<strong>wAttributes: Word</strong> &#8211; не экспериментировал с этим, вроде цвета<br />
<strong>srWindow: TSmallRect</strong> &#8211; тоже не экспериментировал, по msdn это координаты окна, уточни какого и напиши в комментарии, ок?<br />
<strong>dwMaximumWindowSize: TCoord</strong> &#8211; максимальный размер буфера, в символах, естественно.</p>
<h3>Меняем размер Screen Buffer</h3>
<p>Ну и кульминация, <strong>функция SetConsoleScreenBufferSize</strong>:</p>
<pre name="code" class="delphi">SetConsoleScreenBufferSize(hConsoleOutput: THandle; dwSize: TCoord): BOOL;</pre>
<p>Передаём тот же handle вывода, и структуру TCoord с нужным нам размером.</p>
<h3>Как же без примера?</h3>
<pre name="code" class="delphi">
const
  NewSize: TCoord = (x: 80; y: 10000);

...
  SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), NewSize);
</pre>
<p>Здесь размер буфера окна стал 80 на 10000.</p>
<p><em>Постовой:</em><br />
А тем временем Zdez Bil Ya в своём <a href="http://avtuh.ru">добром-добром блоге</a> пишет про delphi и пароли в qip.</p>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2010/01/getconsolescreenbufferinfo-setconsolescreenbuffersize/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Функция copy или восстанавливаем пароль icq после заражения вирусом Piggy.</title>
		<link>http://parsers.info/2010/01/function-copy-ili-vosstanavlivaem-parol-icq-posle-zarazheniya-virusom-piggy/</link>
		<comments>http://parsers.info/2010/01/function-copy-ili-vosstanavlivaem-parol-icq-posle-zarazheniya-virusom-piggy/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 15:28:41 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[delphi]]></category>
		<category><![CDATA[Кодинг]]></category>
		<category><![CDATA[Новости]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[icq]]></category>
		<category><![CDATA[парсер]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=518</guid>
		<description><![CDATA[Привет, ты наверняка уже наслышан о недавно появившемся вирусе Piggy. Если не в курсе, буду краток: он использует принцип спама по цепочке. Вот тебе приходит ссылка от человека, мол, flash игра прикольная. Ты пишешь, мол, ага, знаем, спам. И тебе в ответ: нет, мол, не спам, ага. Качаешь, так как немного пьян, и с твоим [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://parsers.info/wp-content/uploads/2010/01/pig.jpg"><img src="http://parsers.info/wp-content/uploads/2010/01/pig.jpg" alt="" title="Получаем пароль после действия вируса piggy" width="369" height="229" class="aligncenter size-full wp-image-519" /></a></p>
<p>Привет, ты наверняка уже наслышан о недавно появившемся<em> вирусе Piggy</em>. Если не в курсе, буду краток: он использует принцип спама по цепочке.<br />
Вот тебе приходит ссылка от человека, мол, flash игра прикольная. Ты пишешь, мол, ага, знаем, спам. И тебе в ответ: нет, мол, не спам, ага. Качаешь, так как немного пьян, и с твоим номером происходит то же самое: пароль меняется, а эта программа висит некоторое время как icq-бот и предлагает твоим друзьям, которые в контакт-листе, скачать себя. Реагирует на слова &laquo;бот&raquo;, &laquo;спам&raquo; и прочие по-разному, отвечает, даже меняет статус на &laquo;печатает&#8230;&raquo;. Некоторые индивиды окрестили этот вирус как вирус с &laquo;искуственным интеллектом&raquo;, так как сейчас такое &#8211; большая редкость.<span id="more-518"></span><br />
Думаю, со временем такие боты-болтуны захватят этот мир.</p>
<p>Ну что, если такое случилось, то есть возможность вернуть пароль. Автор программы, видимо, ставил эксперимент <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  На хабре появилось сообщение о том, как вернуть пароль: piggy меняет также информацию о пользователе, там теперь можно найти 80 цифр в двоичной системе &#8211; 0 или 1.<br />
Например, 01011001100101101010010110100001001100000101101000010110110001011011000101101000 это 57606886. Можно не пытаться переводить в десятичную систему, там просто шифр.<br />
Вот статья &#8211; <a href="http://habrahabr.ru/blogs/infosecurity/81172/" rel="nofollow">link</a></p>
<p>А вот шифр, который уже разлетелся по интернетам:</p>
<pre>0100110010: 1
0101100000: 2
0101100010: 3
0101100100: 4
0101100110: 5
0101101000: 6
0101101010: 7
0101101100: 8
0101101110: 9
0100110000: 0
</pre>
<p>Символы идут подряд, без пробелов.</p>
<p>Итак, суть сегодняшнего поста.</p>
<p><strong>Функция copy</strong><br />
Призвана получить часть строки из целой. Синтаксис:</p>
<pre name="code" class="delphi">function Copy(S; Index, Count: Integer): string;</pre>
<p>S &#8211; строка или массив, а в нашем случае строка. Index &#8211; с какого символа брать кусок (первый символ это первый символ, а не нулевой), Count это, очевидно, количество.<br />
Это конец теории, далее только код и ссылки на скачку.</p>
<p><strong>Введём массив значений</strong></p>
<pre name="code" class="delphi">
const
  csymbs:array[0..9] of string=('0100110000', '0100110010',
                                '0101100000', '0101100010',
                                '0101100100', '0101100110',
                                '0101101000', '0101101010',
                                '0101101100', '0101101110' );
</pre>
<p>Начиная с нуля. Таким приёмом пользуются, чтобы, например, брать имена месяцев из массива.</p>
<p>Теперь получим по шифру его значение. <strong>Сначала для одного символа.</strong></p>
<pre name="code" class="delphi">
function checksymbol(c: string): string;
var
  i:integer;
begin
  result:='n'; // на случай чего-то не того
  for i:=0 to 9 do
    if csymbs[i]=c then Result:=IntToStr(i);
end;
</pre>
<p>Очевидно, мы передадим нашей функции строки из восьми символов.</p>
<p><strong>А теперь общую функцию</strong><br />
Простой цикл, плюс функция copy.</p>
<pre name="code" class="delphi">
function decode(c: string):string;
var
  i:integer;
begin
  for i:=0 to 7 do
    result:=result+checksymbol(copy(c, i*10+1, 10));
end;
</pre>
<p>Само приложение я сделал консольным, использовал модули windows, sysutils и clipbrd. Хоть и консольное, но получилось 368Кб.<br />
<strong>Как оно работает:</strong> копируем в буфер обмена шифр, запускаем программу и получаем результат.</p>
<p><strong><a href="http://parsers.info/pub/hellopiggy/hellopiggy.exe">Скачать парсер пароля <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </a><br />
<a href="http://parsers.info/pub/hellopiggy/hellopiggy.dpr">Скачать исходник</a></strong></p>
<p>(c) crystalbit, <a href="http://parsers.info">http://parsers.info</a></p>
<p>Теперь немного ссылок:</p>
<ul>
<li/>статья по теме на блоге программиста &#8211; <a href="http://eax.me/icq-virus-h1n1-piggy/">link</a><br />
В этой статье я нашел картинку:<br />
<img src="http://eax.me/files/2010/01/piggy-grab.png" alt="piggy :)" /><br />
По ней можно видеть действие вируса.</p>
<li/>и, в качестве постового, я хочу, чтобы ты обратил внимание на <a href="http://greenkaktus.wordpress.com">блог зелёного кактуса</a>, где он выкладывает вкусности интернета.</ul>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2010/01/function-copy-ili-vosstanavlivaem-parol-icq-posle-zarazheniya-virusom-piggy/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>WinSock: HTTP-запрос с помощью блокирующего сокета</title>
		<link>http://parsers.info/2010/01/winsock-http-zapros-s-pomoshhyu-blokiruyushhego-soketa/</link>
		<comments>http://parsers.info/2010/01/winsock-http-zapros-s-pomoshhyu-blokiruyushhego-soketa/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 15:25:35 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[delphi]]></category>
		<category><![CDATA[Кодинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[winsock]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=508</guid>
		<description><![CDATA[Сегодня хочу начать цикл заметок о winsock. Около года назад я этим заинтересовался, потом незаслуженно забыл и забросил. WinSock &#8211; достаточно мощный инструмент, основа всех основ. Если ты пишешь программу на чистом api, тебе важен конечный размер программы или работаешь с хитрым протоколом, то сокеты просто незаменимы. В этой заметке рассмотрим, как открыть сокет и [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://parsers.info/wp-content/uploads/2010/01/winsock.png" alt="Синхронный сокет winsock. GET запрос" title="HTTP-запрос с помощью блокирующего (синхронного) сокета." width="348" height="144" class="aligncenter size-full wp-image-509" /></p>
<p>Сегодня хочу начать цикл заметок о winsock. Около года назад я этим заинтересовался, потом незаслуженно забыл и забросил.<br />
<strong>WinSock</strong> &#8211; достаточно мощный инструмент, основа всех основ. Если ты пишешь программу на чистом api, тебе важен конечный размер программы или работаешь с хитрым протоколом, то сокеты просто незаменимы. В этой заметке рассмотрим, как открыть сокет и послать GET запрос серверу.<br />
<span id="more-508"></span></p>
<h3>Типы сокетов</h3>
<p>Вкратце. Есть сокеты <strong>синхронные</strong>, с ними работать удобнее. Программа (поток) будет ждать, пока запрос посылается, или же ждать ответа. Такие сокеты также называются <strong>блокирующими</strong>, и речь сегодня пойдёт о них.<br />
Второй тип &#8211; <strong>асинхронные</strong> или <strong>неблокирующие</strong> сокеты. Из названия вполне очевидно, что, посылая запрос, мы не будем ничего ждать. Нам достаточно будет или иногда проверять состояние, или назначить событие, в разных версиях winsock существует две возможные тактики. Также массив асинхронных сокетов вполне заменяет многопоточность.</p>
<h3>Инициализируем winsock</h3>
<p>Сперва подключим модуль <strong>winsock</strong>. Теперь нам необходимо инициализировать winsock, для этого нам потребуется функция WSAStartup. Я использую её следующим образом:</p>
<pre name="code" class="delphi">
  if WSAStartup(MAKEWORD(2,2), WSAData1)<>0 then begin
    writeln('WinSock error');
    readln;
    Exit;
  end;
</pre>
<p>MAKEWORD(2,2) &#8211; просто константа, точнее возвращает константу, можешь писать $101. WSAData1 &#8211; структура типа TWSAData. Не забудь объявить такую <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Как ты уже заметил, в случае успешной инициализации функция возвращает 0, иначе ошибка. Структура TWSAData (WSAData) и коды ошибок есть в msdn, не будем углубляться в голую теорию.<br />
Еще замечу, что я пишу консольное приложение, пусть writeln и readln не смущают читателя.</p>
<h3>Создадим сокет</h3>
<p>Сокет &#8211; как красиво звучит. А это всего лишь число, эх. <strong>Socket1:TSocket</strong>, <strong>Socket1:integer</strong> &#8211; так надо объявить (TSocket сам по себе integer). Создаём функцией <strong>Socket</strong>:</p>
<pre name="code" class="delphi">
  Socket1:=Socket(AF_INET,SOCK_STREAM,0);
  if Socket1=INVALID_SOCKET then begin
    writeln('socket error');
    readln;
    Exit;
  end;
</pre>
<p>Всё достаточно ясно, примем как есть, нудной теорией займёмся как-нибудь потом.</p>
<h3>Устанавливаем соединение.</h3>
<p>Сокет &#8211; это тебе не Indy или Synapse, здесь запрос делается только после установления соединения (мы сейчас про TCP, UDP не будем затрагивать). Как же нам установить соединение? Объявим следующую переменную: <strong>SockAddr1:TSockAddr;</strong>. Это структура, в ней укажем протокол, адрес сервера и порт:</p>
<pre name="code" class="delphi">
  SockAddr1.sin_family:=AF_INET;
  SockAddr1.sin_addr.S_addr:=inet_addr(PChar('62.109.19.221'));
  SockAddr1.sin_port:=htons(80);
</pre>
<p>Таким образом мы можем указать только ip-адрес. Получению dns будет посвящён отдельный пост. IP-адрес я указал своего блога <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Теперь <strong>функция connect</strong>:</p>
<pre name="code" class="delphi">
  if Connect(Socket1,SockAddr1,SizeOf(SockAddr1))<>0 then begin
    writeln('connection error #',WSAGetLastError);
    readln;
    exit;
  end;
</pre>
<p><strong>WSAGetLastError</strong> выполняет функции, аналогичные GetLastError, то есть возвращает код ошибки winsock.<br />
Если нет никаких ошибок, то на данный момент мы уже подключены к серверу.</p>
<h3>Send &#8211; посылаем запрос</h3>
<p>Объявим две переменных:</p>
<pre name="code" class="delphi">
  Buffer1:string;
  Buffer2:array[1..1024] of char;
</pre>
<p>В одной будем формировать запрос, в другую будем порциями писать ответ сервера.</p>
<p>Сначала, конечно, надо сформировать запрос. Если ты хотя бы поверхностно знаком с http протоколом, то это не составит труда:</p>
<pre name="code" class="delphi">
  Buffer1:='GET / HTTP/1.1'#13#10+
           'host: parsers.info'#13#10+
           'Connection: close'#13#10+
           #13#10;
</pre>
<p>А теперь можно и послать этот запрос:</p>
<pre name="code" class="delphi">
  if send(Socket1,Buffer1[1],Length(Buffer1),0)=SOCKET_ERROR then begin
    writeln('socket error #',WSAGetLastError);
    readln;
    exit;
  end;
</pre>
<p>Спасибо <em>A.Truhin</em> за замечание, код выше исправлен, и теперь проверяется возвращаемое значение функции send. Она возвращает количество переданных байт, а в случае ошибки -1, то есть SOCKET_ERROR.<br />
Мы передали начало буфера и его длину. Так как наш сокет блокирующий, то всё, что написано после send, будет выполнено после того, как пройдёт запрос. А после этого нам предстоит ждать ответа <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Reсv &#8211; получаем ответ</h3>
<p>Мы знаем, что ответ должен быть, так как мы работаем с http протоколом. Поэтому сразу претендуем на ответ от сервера. Наш помощник &#8211; <strong>функция recv</strong>.</p>
<pre name="code" class="delphi">
  repeat
    FillChar(Buffer2,SizeOf(Buffer2),0);
    d:=recv(Socket1,Buffer2,SizeOf(Buffer2),0);
    for i:=1 to d do write(Buffer2[i]);
  until d<=0;
</pre>
<p>Небольшое пояснение. Recv читает из буфера сокета, в который он получает ответ. То есть мы ждём ответа, а потом читаем из буфера сокета. Если мы не прочитаем, то данные там и останутся, и при следующем вызове recv мы их и получим. Функция recv возвращает нам количество полученных байт, если это ноль, то всё, больше ничего нет. Моё цикл просто выводит на экран ответ сервера, он содержит тело ответа и html-код моего сайта.</p>
<h3>Закроем сокет и подведём итог.</h3>
<pre name="code" class="delphi">
if CloseSocket(Socket1)<>0 then
  writeln('error closing socket');
</pre>
<p>Итог: <em>winsock - это просто!</em><br />
<a href="http://parsers.info/pub/httpget.dpr">Скачать исходник!</a><br />
И в заключение хочу отметить, что вес нашей программы всего 17Кб! Неплохо для работы с интернетом? <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>(c) crystalbit, <a href="http://parsers.info">http://parsers.info</a><br />
Подпишись на <a href="http://feeds.feedburner.com/parsers">RSS ленту</a>, и я обещаю тебе много интересного материала по сокетам!</p>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2010/01/winsock-http-zapros-s-pomoshhyu-blokiruyushhego-soketa/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Парсим csv и tsv файлы в delphi</title>
		<link>http://parsers.info/2010/01/parsim-csv-i-tsv-v-delphi/</link>
		<comments>http://parsers.info/2010/01/parsim-csv-i-tsv-v-delphi/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 10:31:50 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[delphi]]></category>
		<category><![CDATA[Кодинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[csv]]></category>
		<category><![CDATA[tsv]]></category>
		<category><![CDATA[парсинг]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=505</guid>
		<description><![CDATA[Читая иностранные блоги, наткнулся на пост, в котором поднимается проблема парсинга и отображения в TStringGrid tsv файлов (tab-separated values &#8211; значения, разделенные символом табуляции, англ.). В таких файлах элементы в строках разделены знаком табуляции (девятым символом). Также не хочется забывать про не менее популярный формат csv &#8211; comma-separated values &#8211; в нём элементы разделены запятой. [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://parsers.info/wp-content/uploads/2010/01/parsingcsv.png" alt="Парсинг csv на delphi" title="Парсим csv и tsv на delphi" width="252" height="131" class="aligncenter size-full wp-image-504" /><br />
Читая иностранные блоги, наткнулся на пост, в котором поднимается проблема <em>парсинга и отображения</em> в TStringGrid <strong>tsv файлов</strong> (tab-separated values &#8211; значения, разделенные символом табуляции, англ.). В таких файлах элементы в строках разделены знаком табуляции (девятым символом). Также не хочется забывать про не менее популярный <strong>формат csv</strong> &#8211; comma-separated values &#8211; в нём элементы разделены запятой. Стоит сказать, что программы для работы с таблицами просто обязаны читать эти два формата.<br />
<span id="more-505"></span></p>
<h3>[Матчасть]</h3>
<p>Как оказалось, delphi нам уже всё подготовил. Мы будем использовать два объекта <strong>TStringList</strong> и, очевидно, <strong>TStringGrid</strong>.<br />
У объекта TStringList есть свойство <strong>Delimiter</strong> (разделитель &#8211; англ.). А сам TStringList по сути своей &#8211; массив строк.<br />
<strong>DelimitedText</strong> &#8211; string. Строка, присвоенная DelimitedText, разобьётся, согласно Delimiter, и у нас становится TStringList с элементами строки. Впрочем, тот же explode на php.<br />
<strong>QuoteChar</strong> &#8211; это свойство нам сегодня не пригодится, но упомянуть стоит. Например, у нас есть строка <i>&laquo;delimiter&raquo;;&raquo;delimitedtext&raquo;;&raquo;quotechar&raquo;;&raquo;tstringlist&raquo;</i>. Элементы в ней не только разделены точкой с запятой, но еще и заключены в кавычки. В этом случае Delimiter ставим как <b>;</b>, а QuoteChar как <b>&laquo;</b>. И легким движением руки мы получаем список из ключевых слов данного поста <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Хотел сначала написать, что функция explode на php так не может (ха-ха), а потом прочитал, что там есть готовая функция fgetcsv, Нагайченко Максим написал об этом <a href="http://nagaychenko.com/blog/2009/11/28/парсинг-csv-файлов/">в посте на своём блоге</a>.</p>
<h3>Готовим TStringGrid</h3>
<p>Для будущей загрузки таблицы, в Object Inspector я изначально поставил <em>ColCount=1</em>, а <em>FixedCols</em> и <em>FixedRows</em> обратил в ноль.</p>
<h3>Парсим csv</h3>
<p>Допустим, у нас есть таблица <em>c:\table.csv</em>, которую нам предстоит загрузить в TStringGrid.<br />
Наши действия: каждую строку построчно разбиваем на элементы с помощью вышеописанных свойств и вставляем в TStringGrid.<br />
В примере я использовал второй TStringList для открытия файла. Для больших таблиц также неплохо будет использование стандартного построчного получения файла, перешедшего из паскаля (AssignFile, Reset, ReadLn), но сегодня акцент не на этом.</p>
<p>Код:</p>
<pre name="code" class="delphi">
procedure TForm1.Button1Click(Sender: TObject);
var
  sdata, srow: TStrings;
  i:integer;
begin
  sdata:=TStringList.Create;
  srow:=TStringList.Create;
  sdata.Delimiter:=',';
  sdata.LoadFromFile('c:\table.csv');
  StringGrid1.RowCount:=sdata.Count;
  for i:=0 to sdata.Count-1 do begin
    srow.DelimitedText:=sdata[i];
    if srow.Count>StringGrid1.ColCount then
      StringGrid1.ColCount:=srow.Count;
    StringGrid1.Rows[i].Assign(srow);
  end;
  srow.Free;
  sdata.Free;
end;
</pre>
<p>Небольшие пояснения: в sdata загружаем файл, строки из sdata по очереди парсим в srow, который каждый раз присваиваем следующей строке TStringGrid.</p>
<h3>Про tsv и прочее</h3>
<p>Для парсинга tsv свойству Delimiter нужно присвоить значение табуляции. Это девятый символ, #9, chr(9) &#8211; так можно записать. Согласно википедии, csv и tsv объединяет формат dsv &#8211; delimiter-separated values, собственно его мы сегодня и отпарсили.</p>
<p>(c) crystalbit, <a href="http://parsers.info">http://parsers.info</a><br />
<a href="feeds.feedburner.com/parsers" rel="nofollow">RSS поток</a> &#8211; будь в курсе!</p>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2010/01/parsim-csv-i-tsv-v-delphi/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Перечисление всех компонентов на форме</title>
		<link>http://parsers.info/2009/12/perechislenie-vsex-komponentov-na-forme/</link>
		<comments>http://parsers.info/2009/12/perechislenie-vsex-komponentov-na-forme/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 15:40:12 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[delphi]]></category>
		<category><![CDATA[Кодинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[sender]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=452</guid>
		<description><![CDATA[Сегодня рассмотрим вопрос о том, как перечислить все компоненты на форме. Например, как очистить все TEdit одним циклом, как изменить надписи на всех TLabel, как нажать все TButton В заметке про создание кнопок с использованием TImage я уже испольовал данный приём, теперь рассмотрим подробнее. 0. Матчасть У объекта TForm (а также других, на которых можно [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://parsers.info/wp-content/uploads/2009/12/perkomp.png"><img src="http://parsers.info/wp-content/uploads/2009/12/perkomp.png" alt="" title="Перечисление компонентов в delphi. Очистка всех TEdit" width="277" height="174" class="aligncenter size-full wp-image-451" /></a></p>
<p>Сегодня рассмотрим вопрос о том, как перечислить все компоненты на форме. Например, как очистить все TEdit одним циклом, как изменить надписи на всех TLabel, как нажать все TButton <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
В заметке про <a href="http://parsers.info/2009/12/sender-sozdayom-svoj-stil-knopok/">создание кнопок с использованием TImage</a> я уже испольовал данный приём, теперь рассмотрим подробнее.<br />
<span id="more-452"></span></p>
<h3>0. Матчасть</h3>
<p>У объекта TForm (а также других, на которых можно поставить, например, кнопку) есть массив <strong>Components</strong>. Очевидно, так мы можем обращаться ко всем объектам на форме.<br />
Количество объектов &#8211; свойство <strong>ComponentCount</strong>. Первый объект имеет индекс 0, последний ComponentCount-1.</p>
<h3>1. Просто перечислим имена компонентов</h3>
<p>Запишем в Memo, другой наглядной реализации в голову не пришло</p>
<pre name="code" class="delphi">
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do
    Memo1.Lines.Add(Components[i].Name);
end;
</pre>
<p>Теперь в Memo1 у нас имена всех компонентов.</p>
<h3>2. Конкретизируем задачу</h3>
<p>Будем использовать <a href="http://parsers.info/2009/12/operatory-as-i-is-delphi/">операторы is и as</a>, тут без них никак:</p>
<pre name="code" class="delphi">
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do
    if Components[i] is TLabel then
	  Memo1.Lines.Add((Components[i] as TLabel).Caption);
end;
</pre>
<p>Вот так просто мы получили все надписи на объектах TLabel. Теперь давай сделаем их невидимыми &#8211; пусть никто не прочитает <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre name="code" class="delphi">
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do
    if Components[i] is TLabel then
	  (Components[i] as TLabel).Visible:=False;
end;
</pre>
<h3>3. Итог</h3>
<p>Теперь мы крутые, и нам не нужно прописывать:</p>
<pre name="code" class="delphi">
Label1.Visible:=False;
Label2.Visible:=False;
...
</pre>
<p>Наконец, хочу сделать картинку к этому посту в моём <a href="http://parsers.info">delphi блоге</a>. Я поставил на форму в случайном порядке несколько TLabel и TEdit, поставил кнопку, по нажатию на которую написал:</p>
<pre name="code" class="delphi">
procedure TForm1.Button1Click(Sender: TObject);
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do
    if Components[i] is TLabel then
	    (Components[i] as TLabel).Caption:='http://parsers.info'
    else if Components[i] is TEdit then
      (Components[i] as TEdit).Text:='crystalbit';
end;
</pre>
<p>Запустил, нажал на неё. А результат смотри в начале этого поста <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>5. Замечание</h3>
<p>Если используешь фреймы на форме, то этот механизм может не сработать.<br />
Спасибо Алексею Тимохину</p>
<h3>6. Вариант с рекурсией от JayDi</h3>
<p>Подходит для фреймов</p>
<pre name="code" class="delphi">
procedure FillChildComponentsList(const SourceComponent: TComponent;
  var ChildsList: TList);
var
  I: Integer;
begin
  //рекурсивный поиск дочерних компонентов
  for I := 0 to SourceComponent.ComponentCount - 1 do
  begin
    ChildsList.Add(SourceComponent.Components[I]);
    FillChildComponentsList(SourceComponent.Components[I], ChildsList);
  end;
end;  

procedure Tf_TestFrameComponents.Button_TestComponentsClick(Sender: TObject);
var
  FoundedComponentsList: TList;
  I: Integer;
  Comp: TComponent;
begin
  //получение списка компонетов
  FoundedComponentsList := TList.Create;
  FillChildComponentsList(Self, FoundedComponentsList);  

  //смена текста у всех лейблов
  for I := 0 to FoundedComponentsList.Count - 1 do
  begin
    Comp := FoundedComponentsList[I];
    if Comp is TLabel then
    begin
      (Comp as TLabel).Caption := 'Its work!';
    end;
  end;  

  FreeAndNil(FoundedComponentsList);
end;
</pre>
<p>(c) crystalbit, <a href="http://parsers.info">http://parsers.info</a><br />
а еще на блоге есть <a href="http://feeds.feedburner.com/parsers" rel="nofollow">rss-лента</a>!</p>
<p>P.S. сколько у меня мусора в метках, надо этим заняться</p>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2009/12/perechislenie-vsex-komponentov-na-forme/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Sender: немного практики, или создаём свой стиль кнопок.</title>
		<link>http://parsers.info/2009/12/sender-sozdayom-svoj-stil-knopok/</link>
		<comments>http://parsers.info/2009/12/sender-sozdayom-svoj-stil-knopok/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 19:54:23 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[delphi]]></category>
		<category><![CDATA[Кодинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[sender]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=442</guid>
		<description><![CDATA[Полтора года назад писал такую статью на одном форуме, на блоге этого нет. В связи с тем, что на этой неделе поднял тему использования Sender: TObject и операторов as и is, распишу всё заново здесь и сейчас Мы используем TImage, столько TImage, сколько нужно кнопок. Подготовка У наших кнопок будет три состояния &#8211; нажата, не [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://parsers.info/wp-content/uploads/2009/12/button.jpg" alt="Создаём свои кнопки, используя TImage и параметр Sender. На delphi" title="Создаём свои кнопки, используя TImage и параметр Sender. На delphi" width="199" height="214" class="size-full wp-image-443" /><br />
Полтора года назад писал такую статью на одном форуме, на блоге этого нет. В связи с тем, что на этой неделе поднял тему использования <a href="http://parsers.info/2009/12/parametr-sender-v-obrabotchikax-sobytij-event-handlers-na-delphi/">Sender: TObject</a> и операторов <a href="http://parsers.info/2009/12/operatory-as-i-is-delphi/">as и is</a>, распишу всё заново здесь и сейчас <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
<span id="more-442"></span><br />
Мы используем TImage, столько TImage, сколько нужно кнопок.</p>
<h3>Подготовка</h3>
<p>У наших кнопок будет три состояния &#8211; нажата, не нажата, активна (наведена мышь).<br />
Заранее подготовь три картинки, для трёх этих состояний, и помести в папку программы.<br />
Создадим константы с именами наших картинок:</p>
<pre name="code" class="delphi">
const
  IM_DOWN: string='down.bmp';
  IM_MAIN:  string='main.bmp';
  IM_HOVER: string='hover.bmp';
</pre>
<p>Ии, нам надо их менять, подготовимся:</p>
<pre name="code" class="delphi">
procedure SetState(btn:TImage;vstate:string);
var
  vfile:string;
begin
  vfile:=ExtractFilePath(ParamStr(0))+vstate;
  try
    btn.Picture.LoadFromFile(vfile);
  except
  end;
end;
</pre>
<p>Здесь мы передаём функции имя файла картинки (из созданных констант) и указание на TImage, с которым нужно такое сотворить.</p>
<p>Так-с, поставим теперь на форму Image1, создадим ему следующие обработчики событий:</p>
<pre name="code" class="delphi">
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  SetState(Image1,IM_HOVER);
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  SetState(Image1,IM_MAIN);
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  SetState(Image1,IM_DOWN);
end;
</pre>
<p>Тут всё понятно (надеюсь): при нажатии, отжатии, наведении мышью. А как быть, когда мышь уходит?</p>
<pre name="code" class="delphi">
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  SetState(Image1,IM_MAIN);
end;
</pre>
<p>Да, с одним TImage работает на ура. Только вот мерцает при движении мышью, это плохо, так ведь?</p>
<p>Тогда добавим еще четыре константы:</p>
<pre name="code" class="delphi">
const
  BS_UP=1001;         //последнее событие было mouseup
  BS_DOWN=1002;       //последнее событие было mousedown
  BS_HOVER=1003;      //последнее событие было mousemove
  BS_FORM=1004;  //мышь двигается по форме
</pre>
<p>Куда мы будем их присваивать? Неверно, к <strong>свойству tag</strong> у TImage, оно зарезервировано специально для таких пожарных случаев.</p>
<p>Сразу приведу модифицированный код:</p>
<pre name="code" class="delphi">
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if Image1.Tag<>BS_HOVER then
    SetState(Image1,IM_HOVER);
  Image1.Tag:=BS_HOVER;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Image1.Tag<>BS_UP then
    SetState(Image1,IM_MAIN);
  Image1.Tag:=BS_UP;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Image1.Tag<>BS_DOWN then
    SetState(Image1,IM_DOWN);
  Image1.Tag:=BS_DOWN;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if Image1.Tag<>BS_FORM then
    SetState(Image1,IM_MAIN);
  Image1.Tag:=BS_FORM;
end;
</pre>
<h3>Обобщение</h3>
<p>Вот и настал тот момент&#8230; когда нам надо переходить от одного Image1 к любому TImage, на котором произошло событие. Если ты читал мой блог, то уже знаешь, что надо заменить Image1 на (Sender as TImage) во всех обработчиках событий у Image1.</p>
<p>А что делать при движении мышью по форме? Точно, надо перебрать все компоненты TImage на форме, полезный, кстати, навык:</p>
<pre name="code" class="delphi">
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do begin
    if Components[i] is TImage then begin
      if (Components[i] as TImage).Tag<>BS_FORM then
        SetState((Components[i] as TImage),IM_MAIN);
     (Components[i] as TImage).Tag:=BS_FORM;
    end;
  end;
end;
</pre>
<p>Вроде всё чисто и ясно, могу про это потом отдельный пост написать.</p>
<p>Ну и назначим события при старте формы:</p>
<pre name="code" class="delphi">
procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
begin
  for i:=0 to ComponentCount-1 do begin
    if Components[i] is TImage then begin
      (Components[i] as TImage).OnMouseDown:=Image1MouseDown;
      (Components[i] as TImage).OnMouseUp:=Image1MouseUp;
      (Components[i] as TImage).OnMouseMove:=Image1MouseMove;
    end;
  end;
end;
</pre>
<h3>Итог</h3>
<p>Теперь, сколько бы мы TImage не создали в проекте, столько у нас и будет кнопок <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<hr/>
<img src="http://parsers.info/wp-content/uploads/2009/12/11.PNG" alt="Свой стиль кнопок на delphi" title="Свой стиль кнопок на delphi" width="386" height="162" class="aligncenter size-full wp-image-444" /><br />
А вы знали, что google &#8211; хиппи? Особенно рано утром <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
<hr/>
(c) crystalbit, <a href="http://parsers.info">http://parsers.info</a></p>
<p>Ах, вот проектик &#8211; <strong><a href="http://parsers.info/pub/TImageButtons.rar">скачать</a></strong><br />
А вот rss лента &#8211; <strong><a href="http://feeds.feedburner.com/parsers/">подписаться</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2009/12/sender-sozdayom-svoj-stil-knopok/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Операторы as и is или &#171;английский язык произошел от дельфи&#187;.</title>
		<link>http://parsers.info/2009/12/operatory-as-i-is-delphi/</link>
		<comments>http://parsers.info/2009/12/operatory-as-i-is-delphi/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 14:34:41 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[delphi]]></category>
		<category><![CDATA[Кодинг]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[sender]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=434</guid>
		<description><![CDATA[Про Sender: TObject я недавно рассказал. Согласись, что использовать Sender без таких операторов как is и as не очень кавайно. Конечно, для определенных целей они даже не требуются, а вот кое-где уже не обойтись. Ты-то про них знаешь всё, а вот остальным сейчас расскажу. 1. As Да, я в названии не опечатался. Когда я использую [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://parsers.info/wp-content/uploads/2009/12/is.jpg" alt="Использование операторов is и as вместе с параметром Sender." title="Использование операторов is и as вместе с параметром Sender." width="349" height="277" class="aligncenter size-full wp-image-435" /><br />
Про <a href="http://parsers.info/2009/12/parametr-sender-v-obrabotchikax-sobytij-event-handlers-na-delphi/">Sender: TObject</a> я недавно рассказал. Согласись, что использовать <strong>Sender</strong> без таких операторов как <strong>is и as</strong> не очень кавайно. Конечно, для определенных целей они даже не требуются, а вот кое-где уже не обойтись.<br />
Ты-то про них знаешь всё, а вот остальным сейчас расскажу.<br />
<span id="more-434"></span></p>
<h3>1. As</h3>
<p>Да, я в названии не опечатался. Когда я использую <strong>as и is</strong>, мне кажется, что я пишу сочинение на английском на свободную тему &#8211; даже получаются правильно построенные предложения <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
<em>Оператор as</em> &#8211; я бы его перевёл как &laquo;использовать как&raquo;.<br />
Примерчик: при нажатии на кнопку, написать на ней &laquo;нажато&raquo;. Пускай мы не знаем, какая кнопка нажата, так как наше событие вызывают несколько кнопок.</p>
<pre name="code" class="delphi">
procedure TForm1.Button1Click(Sender: TObject);
begin
  (Sender as TButton).Caption:='нажато';
end;
</pre>
<p>Мы используем <em>Sender типа TObject как TButton</em>, потому что мы заранее знаем, что это кнопка. Почему бы просто не написать <em>Sender.Caption</em>? Вот если у вызвавшего события компонента не будет такого свойства, то не имеет смысла. Впрочем, ошибка появится уже на этапе компиляции.<br />
Можно и так:</p>
<pre name="code" class="delphi">
procedure TForm1.Button1Click(Sender: TObject);
var
  vb: TButton;
begin
  vb:=Sender as TButton;
  vb.Caption:='нажато';
end;
</pre>
<p>Подводя итог, после as пишем тип, за который мы хотим принимать объект.</p>
<h3>2. Is</h3>
<p>А как нам быть, если мы не знаем, какого типа объект вызвал наш метод? Допутим, мы поставили еще и <em>Label1 (TLabel)</em> и на <em>OnDblClick</em> присвоили наш Button1Click. <strong>Sender as TButton</strong> &#8211; так для TLabel не получится. В runtime появится ошибка &laquo;<em>invalid class typecas</em>t&raquo;.<br />
Ну что,</p>
<pre name="code" class="delphi">
procedure TForm1.Button1Click(Sender: TObject);
begin
  if (Sender is TButton) then
    (Sender as TButton).Caption:='нажато';
  if (Sender is TLabel) then
    (Sender as TLabel).Caption:='дважды нажато';
end;
</pre>
<p>Вот и всё, нет ошибки. Если говорить по матчасти, <em>(Sender is TButton)</em> возвращает true или false.</p>
<p>В ближайшем будущем хочется привести один замечательный пример, подпишись на <a href="http://feeds.feedburner.com/parsers/" rel="nofollow">rss ленту</a> и узнаешь первым <img src='http://parsers.info/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>А я сегодня сдал зачёт по экологии)</p>
<p>(c) crystalbit, <a href="http://parsers.info">http://parsers.info</a></p>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2009/12/operatory-as-i-is-delphi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Несколько причин, почему люди не оставляют комментарии в блоге.</title>
		<link>http://parsers.info/2009/12/neskolko-prichin-pochemu-lyudi-ne-ostavlyayut-kommentarii-v-bloge/</link>
		<comments>http://parsers.info/2009/12/neskolko-prichin-pochemu-lyudi-ne-ostavlyayut-kommentarii-v-bloge/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 16:31:21 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[SEO, SMO]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[SMO]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=429</guid>
		<description><![CDATA[Привет, читатель! Поздравляю с начавшейся наконец зимой! Сегодня рассмотрим вопрос, который относится скорее к SEO &#8211; почему человек, зашедший на блог, не оставляет комментарий. Пускай ему даже есть что добавить. ME Liz Strauss на своём блоге (источник) в 2006 году опросила своих читателей и сформулировала 10 и одну причину: Твой пост достаточно полон, и сложно [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://parsers.info/wp-content/uploads/2009/12/kkkd.jpg" alt="Почему не комментируют блог? Скандалы, интриги, расследования" title="Почему не комментируют блог? Скандалы, интриги, расследования" width="312" height="275" class="aligncenter size-full wp-image-430" /><br />
Привет, читатель! Поздравляю с начавшейся наконец зимой!<br />
Сегодня рассмотрим вопрос, который относится скорее к SEO &#8211; почему человек, зашедший на блог, не оставляет комментарий. Пускай ему даже есть что добавить.<br />
<span id="more-429"></span><br />
ME Liz Strauss на своём блоге (<a href="http://www.successful-blog.com/1/10-reasons-readers-dont-leave-comments/" rel="nofollow">источник</a>) в 2006 году опросила своих читателей и сформулировала 10 и одну причину:</p>
<ol>
<li/>Твой <strong>пост достаточно полон</strong>, и сложно что-то написать, кроме как &laquo;хорошая работа&raquo;. Я считаю это глупым, читаю пост и иду дальше.
<li/>В посте <strong>я узнал что-то новое, мне нужно это обдумать</strong>, даже перед тем, как сформулировать вопрос. Аналогично предыдущему, не хочу ставить себя в глупое положение. Прохожу мимо.
<li/>Я готов написать комментарий, но замечаю, что ты <strong>ответил только некоторым близким знакомым</strong>. Я не хочу быть высмеянным на публике.
<li/>Люди, комментирующие твои посты, любят <strong>ругаться</strong>, а я &#8211; нет. Я не уверен в своей храбрости сражаться с толпой.
<li/>Ты <strong>редко отвечаешь на комментарии</strong>. Поэтому просто нет смысла писать еще один.
<li/>Ты относишься к комментаторам, как к <strong>глупым.</strong> Я не настолько глуп, чтобы писать в твоём блоге.
<li/>Мне реально понравился твой пост и весь блог, но <strong>я очень устал или занят своими делами</strong>. Я отпишу в следующий раз, как буду проходить мимо.
<li/>Твои посты заканчиваются общим вопросом, типа &laquo;Что ты думаешь про теорию большого взрыва?&raquo;. <strong>Вопрос слишком объемен</strong>, у меня просто нет времени на него ответить. Мне неудобно писать более короткий ответ.
<li/>Между мной и моим комментарием стена в виде <strong>авторизации</strong>. У меня и так много паролей, и мне не очень хочется добавить еще один в мой список.
<li/>Контент <strong>недостаточно свежий и интересный</strong>. Я читал об этом на дестке других блогов. Если комментировать, то расписывать всё заново.
<li/>Пост носит <strong>негативный характер</strong>. Это отпугивает.
</ol>
<p>Блоггер с ником Xager тоже поднимал эту тему в мае.<br />
Почему многие блоги кажутся неживыми? Он приводит следующие причины:</p>
<ol>
<li/><strong>Комментировать некому.</strong> Надо подниматься в топ <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />
<li/><strong>Материал не интересен, автор не интересен, блог не интересный.</strong> Надо брать пример с успешных людей в таком случае.
<li/><strong>Непонятно.</strong> Совсем.
<li/><strong>Нечего добавить.</strong> Смотри первую причину в предыдущем обзоре.
<li/><strong>Ты не отвечаешь на комментарии</strong>, зачем тогда комментировать?
<li/><strong>У вас ГС.</strong> Не знаю, что это такое) Xager, о приди и оставь комментарий!
<li/><strong>Ты грубый.</strong> Плохой.
<li/><strong>Нет смысла из SEO соображений.</strong> Если стоит nofollow, а может еще и noindex, т<br />
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2009/12/neskolko-prichin-pochemu-lyudi-ne-ostavlyayut-kommentarii-v-bloge/feed/</wfw:commentRss>
		<slash:comments>53</slash:comments>
		</item>
		<item>
		<title>Параметр Sender в обработчиках событий (event handlers) на delphi.</title>
		<link>http://parsers.info/2009/12/parametr-sender-v-obrabotchikax-sobytij-event-handlers-na-delphi/</link>
		<comments>http://parsers.info/2009/12/parametr-sender-v-obrabotchikax-sobytij-event-handlers-na-delphi/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 14:45:03 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[delphi]]></category>
		<category><![CDATA[Кодинг]]></category>
		<category><![CDATA[Переведённое]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[sender]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=424</guid>
		<description><![CDATA[Всем привет. Димон, особенно тебе, рад что ты ссылку запомнил! Итак, сегодня я хочу рассказать про так часто мелькающее перед нашими глазами Sender: TObject. Точнее, своими словами я рассказывать не буду, а переведу с английского доступным языком, копирайт смотри в конце поста, как обычно. Давным-давно, в царстве delphi Жил-был объект по имени Sender [Обработчики событий [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://parsers.info/wp-content/uploads/2009/12/3947976663_3f139c016e.jpg" alt="Sender: TObject на delphi - всё о нём" title="Sender: TObject на delphi - всё о нём" width="500" height="333" class="aligncenter size-full wp-image-422" /><br />
Всем привет. Димон, особенно тебе, рад что ты ссылку запомнил!<br />
Итак, сегодня я хочу рассказать про так часто мелькающее перед нашими глазами <strong>Sender: TObject</strong>.</p>
<p>Точнее, своими словами я рассказывать не буду, а переведу с английского доступным языком, копирайт смотри в конце поста, как обычно.<br />
<span id="more-424"></span><br />
<em>Давным-давно, в царстве delphi<br />
Жил-был объект по имени Sender</em></p>
<h2>[Обработчики событий и Sender]</h2>
<p>Посмотрим на обработчик события OnClick кнопки Button1:</p>
<pre name="code" class="delphi">
procedure TForm1.Button1Click(Sender: TObject) ;
begin
  ...
end;
</pre>
<p>Метод Button1Click указывает на объект <strong>Sender</strong> типа <strong>TObject</strong>. Каждый обработчик в delphi обязательно имеет параметр <strong>Sender</strong>. Функция <strong>Button1Click</strong> вызывается для события <strong>OnClick</strong> каждый раз, когда нажимается кнопка.</p>
<p>Параметр <strong>Sender</strong> ссылается на компонент, который вызвал метод. Если ты нажмёшь на <strong>Button1</strong>, выполнится метод Button1Click. А ссылка или указатель на объект Button1 передастся в параметре <strong>Sender</strong>.</p>
<h2>[На практике]</h2>
<p>Правильное использование <strong>параметра Sender</strong> может придать неимоверную гибкость нашему коду. Параметр <strong>Sender</strong> даёт нам знать, какой компонент возбудил наше событие. (возбудил событие &#8211; запомню) Это облегчает использование одного обработчика для двух разных компонентов.</p>
<p>Например, мы хотим, чтобы кнопка и пункт меню выполняли одну и ту же функцию. Люди усомнятся в твоей ориентации, если ты напишешь одно событие дважды.</p>
<p>Для того, чтобы сделать вышеизложенное в Delphi, нужно следующее:</p>
<ul>
<li/>Напиши обработчик события для первого объекта (почему бы не на кнопку в SpeedBar&#8217;е?)
<li/>Выдели еще объекты, а может и несколько объектов (почему бы не MenuItem1, а?)
<li/>В Object Inspector найди Events
<li/>Рядом с нужным событием выбери в списке уже созданный обработчик (Delphi предложит все совместимые функции на форме)
</ul>
<p>Вот мы с тобой и создали единственный метод, который обрабатывает <strong>события OnClick</strong> на кнопке и пункте меню. Теперь нам только и остаётся, что различать, какой компонент вызвал наш метод. К примеру, у тебя мог получиться такой код:</p>
<pre name="code" class="delphi">
procedure TForm1.Button1Click(Sender: TObject) ;
begin
  {общий код для пункта меню и кнопки}
  ...
  {а вот и разделение труда:}
  if Sender = Button1 then
   ShowMessage('Button1 клац!')
  else if Sender = MenuItem1 then
   ShowMessage('MenuItem1 клац!')
  else
   ShowMessage('??? клац!') ;
end;
</pre>
<p>В общих чертах, мы сравниваем <strong>Sender</strong> с компонентом.</p>
<p><u>Замечание</u>:<br />
Второй else в конструкции if-then-else для тех случаев, когда событие вызвано не Button1 и не MenuItem1. Но кто же еще мог вызвать наш метод? Попробуй так, поставь только еще и Button2:</p>
<pre name="code" class="delphi">
procedure TForm1.Button2Click(Sender: TObject) ;
begin
   Button1Click(Button2) ;
   {будет сообщение '??? клац!'}
end;
</pre>
<p>(c) Delphi Programming &#8211; <a href="http://delphi.about.com" rel="nofollow">http://delphi.about.com</a><br />
(c) crystalbit &#8211; <a href="http://parsers.info">http://parsers.info</a></p>
<p>В следующей части данной статьи рассказывается про такие операторы, как as и is, скоро появится у меня на блоге.<br />
Подпишись на <a href="http://feeds.feedburner.com/parsers/" rel="nofollow">rss ленту</a>, чтобы не упустить момент;)</p>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2009/12/parametr-sender-v-obrabotchikax-sobytij-event-handlers-na-delphi/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Жизнь без условий (Life without ‘if’s)</title>
		<link>http://parsers.info/2009/12/zhizn-bez-uslovij-life-without-%e2%80%98if%e2%80%99s/</link>
		<comments>http://parsers.info/2009/12/zhizn-bez-uslovij-life-without-%e2%80%98if%e2%80%99s/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 18:00:19 +0000</pubDate>
		<dc:creator>crystalbit</dc:creator>
				<category><![CDATA[Переведённое]]></category>
		<category><![CDATA[Статьи]]></category>
		<category><![CDATA[if]]></category>

		<guid isPermaLink="false">http://parsers.info/?p=415</guid>
		<description><![CDATA[Привет, хорошая погода. Сегодня решил перевести пост одного коллеги по блогосфере, копирайт в конце. Прошла ужасная неделя! После того, как я освободился от работы с WPF, мне пришлось сконцентрироваться на исправлении мерзких багов и добавлении требуемых фич в &#171;только что законченный&#187; проект, который мы писали с шестью другими разработчиками. Я чувствовал себя виноватым, так как [...]]]></description>
			<content:encoded><![CDATA[<p>Привет, хорошая погода. Сегодня решил перевести пост одного коллеги по блогосфере, копирайт в конце.<br />
<img src="http://parsers.info/wp-content/uploads/2009/12/noif.jpg" alt="Жизнь без условий." title="Жизнь без условий." width="360" height="359" class="aligncenter size-full wp-image-416" /><br />
<span id="more-415"></span><br />
Прошла ужасная неделя! После того, как я освободился от работы с <A href="http://www.sysgen.fi/blog/archives/wpf-rules">WPF</A>, мне пришлось сконцентрироваться на исправлении мерзких багов и добавлении требуемых фич в &laquo;только что законченный&raquo; проект, который мы писали с шестью другими разработчиками. Я чувствовал себя виноватым, так как всё, что я мог сделать на прошлой неделе, ограничивалось добавлением новых строк кода и <strong>условий if</strong> в этот код, который мои коллеги и так разукрасили миллионами <strong>if&#8217;</strong>ов. Иногда я успеваю сделать многострочный нарост кода до компактного, порою в одну строку. Это спасает мой день. На прошлой неделе таких дней не было. </p>
<p>Каждое условие, которое мы пишем, делает всю нашу будущую жизнь всё более печальной. Чем больше у нас <strong>if</strong>, тем тяжелее понимать код и оказывать его поддержку. Если логическая основа не умещается в один экран, ощущаешь, что твой коллега, которому придётся с этим работать, не только не поймёт твои идеи, а сделает еще хуже, добавив <strong>еще if</strong>.</p>
<p> Мир был бы лучше <strong>без условий if</strong> &#8211; знакомо это чувство? Когда ты пишешь очередной <strong>if</strong>, твой код становится зависимым от случая. Иногда ты даже не уверен, какая именно ветка кода будет на самом деле выполнена. Если посмотреть с другой стороны, алгоритм без условий &#8211; необходимый, обязательный, он выполняется только так, как ты запрограммировал. Самый ущербный <strong>if</strong> &#8211; тот if, который ты пишешь &laquo;на всякий случай&raquo;, когда не можешь представить ситуацию, которая будет при выполнении кода.</p>
<p>Существует много религий, но современный люди считают, что всё предопределено &#8211; Богу не нужны условия. Будучи простым смертным, я восхищаюсь тем, что не знаю ничего заранее и, таким образом, должен быть готов к различным ситуациям, при различных условиях. Но есть и уже известные нам вещи, основываясь на которых, мы должны осмыслить мир вокруг нас и выразить его в нашем коде настолько чисто и ясно, насколько это возможно. Но если ты хочешь скрыть смысл кода, то пиши столько условий, сколько можешь!</p>
<p> А давай посмотрим на пример? Это реальный код, который я нашел в одном проекте несколько лет назад. Основываясь на данном значении суммы, он считает контрольную цифру Финского банка (Finnish bank reference number):</p>
<p><img src="http://www.sysgen.fi/blog/images/CheckDigit_a.png" /></p>
<p> Не зная о существовании данной процедуры, я набросал свою версию:</p>
<p><img src="http://www.sysgen.fi/blog/images/CheckDigit_b.png" /></p>
<p>Чувак, никаких условий! Если быть точным, одно условие не делает здесь большого различия, и первая строчка кода показывает, что автор CheckDigit_a не осмыслил весь смысл до этого расчета. В конце кода отнюдь не судьба определяет значение суммы, равное 10, а может и нет. Это вполне может быть посчитано и, какое бы ни было значение, оно всегда не условно. То есть, однажды передав функции значение, мы имеем конкретный результат, вытекающий из неё. Тут нет места сомнениям, никаких условий!</p>
<p> Вот мы и дошли до сути дела: использование оператора <strong>if</strong> вполне адекватно и даже необходимо, когда условия действительно непредвиденные, то есть их вводит пользователь, мы получаем из базы данных и т.п. В противном случае, ты должен оставить один <strong>if</strong> и прикинуть, существует ли возможность поступить иначе.</p>
<p>В связи с тем, что мы никак не можем жить без условий <strong>if,</strong> я хочу предложить следующую вещь. Чтобы общее количество <strong>операторов if</strong> оставалось наименьшим, программисты должны платить штраф за каждый написанный ими <strong>if</strong>. Если хочешь не уйти в минус и получить хоть что-то после рабочего дня, помни следующее:</p>
<ul>
<li/>используй арифметику, функции для работы со строками, символами и т.п. везде, где это возможно!
<li/>пытайся уменьшить количество вложенных <strong>if</strong>, анализируя свои условия. Когда ситуация становится сложна для понимания, используй карандаш, клочок бумаги и таблицы истинности. Этот метод может помочь объединить несколько операторов <strong>if</strong> в один и, что вполне возможно, найти ветку, которая никогда не выполнится;
<li/>используй оператор <strong>?:</strong> при простых условиях. Логически он эквивалентен <strong>if</strong>, но очень компактен. Так легче представлять конструкцию как один логический блок, в то время как if делает конструкцию размытой;
<li/>используй оператор switch вместо if .. else if, где это возможно;
<li/>не вздумай использовать if как заплатку! Бывает, что кажется простым решением добавить всего один маленький if, но, анализируя код глубже, можно найти действительно верное решение проблемы.
</ul>
<p>Если в проекте наблюдается постоянно растущее количество операторов <strong>if</strong>, там наверняка закрадётся ошибка в самом начале. Использование <strong>switch</strong> может быть забыто, или не учтены все возможные ситуации. Или дизайн может оказаться слишком сложным, так и не достигнув цели: ты хотел крошечный файл, а получился швейцарский нож.</p>
<p>&laquo;Хороший план &#8211; половина работы&raquo; (“Well planned is half done”) — гласит известное высказывание, которое можно интерпретировать как &laquo;Плохо спланированное требует всё больше условий <strong>if</strong>&laquo;. Когда твой код раздувается от количества условий, всё еще возможно сохранить большую часть работы, меняя структуру приложения. На практике такое вряд ли возможно, кто-то признает недочёт в начальном дизайне, поэтому всё, что останется делать, это учиться на своих ошибках. Пытаться избавиться от этого проекта, быть мудрее при работе над следующим, если такой предвидится.</p>
<p>(c) Heikki Valkonen (aka Hex), <a href="http://www.sysgen.fi">http://www.sysgen.fi</a><br />
(c) crystalbit, <a href="http://parsers.info">http://parsers.info</a> &#8211; перевод с английского (translation)</p>
<p>Вот я и перевёл статью горячего финского парня <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Хотя сам в Финляндии никогда не был, да и за границей тоже. Один раз отдыхал в Крыму &#8211; разве это настоящий туризм? Вот туры в Египет, <a href="http://www.tourskidki.ru/countrys/1011/795/1664.html">туры в Мармарис</a> (Турция) &#8211; это да <img src='http://parsers.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://parsers.info/2009/12/zhizn-bez-uslovij-life-without-%e2%80%98if%e2%80%99s/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
