<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-2370346630241894584</atom:id><lastBuildDate>Fri, 06 Sep 2024 04:07:38 +0000</lastBuildDate><category>Delphi</category><category>Сделай сам</category><category>MSAgent</category><category>Winamp</category><category>web-разработка</category><category>Переезд</category><category>блог</category><category>караоке</category><category>справка</category><title>Статьи о программировании и не только</title><description></description><link>http://ishirko.blogspot.com/</link><managingEditor>noreply@blogger.com (Ivan Shyrko)</managingEditor><generator>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-4495099449947837948</guid><pubDate>Tue, 04 Mar 2008 14:07:00 +0000</pubDate><atom:updated>2008-03-04T06:13:20.527-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Переезд</category><title>Переезд</title><description>Блог переезжает на новый хостинг и будет доступен по адресу &lt;a href=&quot;http://delphiblog.ru/&quot;&gt;http://delphiblog.ru&lt;/a&gt;. Все новые статьи теперь будут публиковаться только там. К существующим статьям будут добавлены исходники примеров. Оставайтесь с нами)</description><link>http://ishirko.blogspot.com/2008/03/blog-post.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-2968151655174084855</guid><pubDate>Tue, 12 Feb 2008 10:24:00 +0000</pubDate><atom:updated>2008-12-08T13:57:33.714-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><title>Поздравьте своих любимых!</title><description>&lt;div align=&quot;justify&quot;&gt;    Господа программисты! Вы на календарь хоть изредка поглядываете? Нет? Так наведите мышкой на часики, которые обычно находятся справа-внизу экрана. Появилась подсказка? Ага… 12 февраля 2008 года (если конечно вы для обхождения триала не переводили дату). Год нам не важен, а вот на число и месяц обратите особое внимание. Скоро будет… нет, 23 февраля тоже скоро будет, но до него еще есть 14 февраля - &lt;strong&gt;День Святого Валентин&lt;/strong&gt;а. Надо бы поздравить свою вторую половинку. Разумеется, вы лучше меня знаете, как это сделать, но, если позволите, я подкину вам небольшое дополнение к поздравлению. Программа-валентинка, простенькая, на Delphi, попалась мне при просмотре форума на &lt;noindex&gt;&lt;a href=&quot;http://delphimaster.ru/&quot; rel=&quot;nofollow&quot;&gt;http://delphimaster.ru&lt;/a&gt;. Автор - &lt;a href=&quot;http://www.delphimaster.ru/cgi-bin/anketa.pl?id=1192068181&quot; rel=&quot;nofollow&quot;&gt;Dmitry S&lt;/a&gt;&lt;/noindex&gt;. Надеюсь, он простит мне маленький пиар его творения. &lt;br/&gt; Сама программа может послужить примером полупрозрачности, проигрывания midi, создания окон, работы с ресурсами.&lt;br/&gt;    На Блоггере файлы размещать нельзя, так что пока я не обзавелся нормальным хостингов (что будет, надеюсь, скоро), файлы буду хранить на народе. Валентинку можете скачать отсюда: &lt;noindex&gt;&lt;a href=&quot;http://ivanfdc.narod.ru/download.html&quot; rel=&quot;nofollow&quot;&gt;http://ivanfdc.narod.ru/download.html&lt;/a&gt;&lt;/noindex&gt; или &lt;noindex&gt;&lt;a href=&quot;http://argi.ru/upload/heart3-w.rar&quot; rel=&quot;nofollow&quot;&gt;http://argi.ru/upload/heart3-w.rar&lt;/a&gt;&lt;/noindex&gt;. 225 КБ. В архиве исходники + сама программа. Текст меняется в модуле &lt;i&gt;WindowMessage.pas&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuTeF-Rlr4wcDN6E0dg87QA3aqLg7rlPa9J5_vVB2q4TZWU1QSUP1pBox1VJbAKqzXCLxMSU6fb30wZAUf45vpz_hFJH9xmQHGCMVDTw3o1gAj4iBjPEaKtxUjUhfOj368zIxL_erx5cY/s400/14+feb.JPG&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5166106335810933954&quot; /&gt;&lt;/div&gt;&lt;br/&gt;</description><link>http://ishirko.blogspot.com/2008/02/blog-post.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuTeF-Rlr4wcDN6E0dg87QA3aqLg7rlPa9J5_vVB2q4TZWU1QSUP1pBox1VJbAKqzXCLxMSU6fb30wZAUf45vpz_hFJH9xmQHGCMVDTw3o1gAj4iBjPEaKtxUjUhfOj368zIxL_erx5cY/s72-c/14+feb.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-4131363643102432043</guid><pubDate>Mon, 28 Jan 2008 10:13:00 +0000</pubDate><atom:updated>2008-01-29T07:08:46.900-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Сделай сам</category><title>Сделай сам: IE и Delphi – вместе веселее!</title><description>&lt;div align=&quot;justify&quot;&gt;&lt;i&gt;    Сегодня мы займёмся самым популярным web-браузером в мире – Internet Explorer&#39;ом. Кто-то обожает эту программу, кто-то терпеть её не может, но, как ни крути, пока что ни один конкурент IE не может приблизиться к нему по возможностям (не считая, конечно, браузеров, построенных на движке IE). Итак, что мы будем делать с IE? Да ничего страшного… Мы просто научимся управлять им так же, как и любым другим окном. Для закрепления полученных знаний сделаем программу для управления IE при помощи горячих клавиш. Для пущего эффекта добавим иконку программы на Системную панель (SysTray). Итак, поехали…&lt;/i&gt;&lt;br/&gt; Первым делом разберёмся с двумя  приёмами программирования, которые мы будем использовать и в последующих статьях данного цикла:&lt;br/&gt;1) Как работать с &quot;горячими&quot; клавишами?&lt;br/&gt;2) Как добавить свой значок на Системную Панель (SysTray, можно узнать по характерным для неё часикам)?&lt;br/&gt;На первый вопрос я уже дал частичный ответ в статье &lt;a href=&quot;http://ishirko.blogspot.com/2007/12/blog-post_17.html&quot;&gt;Сделай сам: &quot;Вскрывалка паролей&quot;&lt;/a&gt;, но нам нужно копнуть немного глубже, а второй вопрос мы ещё вообще не затрагивали.&lt;span class=&quot;fullpost&quot;&gt;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Работа с &quot;горячими&quot; клавишами&lt;/strong&gt;&lt;br/&gt; Для работы с &quot;горячими&quot; клавишами вполне достаточно использования лишь двух функций:&lt;br/&gt;&lt;br/&gt;1) Регистрирует &quot;горячие&quot; клавиши: &lt;br/&gt;BOOL RegisterHotKey(&lt;br/&gt;        HWND hWnd, // этому окну придёт уведомление о нажатии комбинации клавиш&lt;br/&gt;        int id,      // идентификатор &quot;горячих&quot; клавиш&lt;br/&gt;        UINT fsModifiers, // должны ли быть нажаты клавиши Ctrl, Shift, Alt или Win&lt;br/&gt;        UINT vk       // код клавиши, на которую мы будем реагировать&lt;br/&gt;   );&lt;br/&gt;2) Удаляет &quot;горячие&quot; клавиши&lt;br/&gt;BOOL UnregisterHotKey(&lt;br/&gt;        HWND hWnd, // окно, ассоциированное с &quot;горячими&quot; клавишами&lt;br/&gt;        int id  // идентификатор &quot;горячих&quot; клавиш &lt;br/&gt;   );&lt;br/&gt;&lt;br/&gt;   Всё бы ничего, да вот при работе с &quot;горячими&quot; клавишами из DLL (динамически подключаемой библиотеки) могут возникнуть проблемы с идентификаторами. Чтобы этого избежать следует использовать функцию GlobalAddAtom, которая возвратит нам уникальный идентификатор (атом) требуемого формата. После завершения работы с &quot;горячими&quot; клавишами атом нужно удалить при помощи функции GlobalDeleteAtom. Работу с атомами мы рассмотрим в одной из следующих статей, где будем использовать DLL.&lt;br/&gt;Помещение своей иконки в SysTray&lt;br/&gt; Бывают такие программы, которые постоянно должны быть активны в системе. Они довольно часто помещают свой значок на Системную панель, чтобы не надоедать пользователю присутствием своего окна и в то же время оставить возможность &quot;достучаться&quot; до программы. Для управления иконкой на Системной панели используется функция &lt;br/&gt;Shell_NotifyIcon(dwMessage: DWORD; lpData: PNotifyIconData): BOOL;&lt;br/&gt;&lt;i&gt;dwMessage&lt;/i&gt; – сообщение, которое мы посылаем Панели задач, может принимать следующие значения: &lt;i&gt;N&lt;/i&gt;&lt;i&gt;IM_ADD&lt;/i&gt; – добавить новую иконку, &lt;i&gt;NIM_DELETE&lt;/i&gt; – удалить иконку, &lt;i&gt;NIM_MODIFY&lt;/i&gt; – изменить иконку.&lt;br/&gt;&lt;i&gt;lpData&lt;/i&gt; – указатель на структуру NotifyIconData, которая состоит из следующих полей:&lt;br/&gt;&lt;i&gt;cbSize&lt;/i&gt;: DWORD;&lt;br/&gt;&lt;i&gt;Wnd&lt;/i&gt;: HWND;&lt;br/&gt;&lt;i&gt;uID&lt;/i&gt;: UINT;&lt;br/&gt;&lt;i&gt;uFlags&lt;/i&gt;: UINT;&lt;br/&gt;&lt;i&gt;uCallbackMessage&lt;/i&gt;: UINT;&lt;br/&gt;&lt;i&gt;hIcon&lt;/i&gt;: HICON;&lt;br/&gt;&lt;i&gt;szTip&lt;/i&gt;: array [0..63] of AnsiChar;&lt;br/&gt;Пояснения:&lt;br/&gt;&lt;i&gt;cbSize&lt;/i&gt; – размер структуры;&lt;br/&gt;&lt;i&gt;Wnd&lt;/i&gt; – идентификатор окна, которое будет получать сообщения, ассоциированные с иконкой;&lt;br/&gt;&lt;i&gt;uID&lt;/i&gt; – идентификатор иконки, который мы сами ей назначаем;&lt;br/&gt;&lt;i&gt;uFlags&lt;/i&gt; – комбинация из трёх флагов, которая обозначает, какие поля структуры мы хотим заполнить: NIF_ICON (хотим заполнить поле hIcon), NIF_MESSAGE (поле uCallbackMessage), NIF_TIP (поле szTip).&lt;br/&gt;&lt;i&gt;uCallbackMessage&lt;/i&gt; – определяемый нами идентификатор сообщения, ассоциированного с иконкой;&lt;br/&gt;&lt;i&gt;hIcon&lt;/i&gt; – идентификатор иконки;&lt;br/&gt;&lt;i&gt;szTip&lt;/i&gt; – текст подсказки к иконке, которая появляется при наведении на неё курсора мышки.&lt;br/&gt; Пример использования функции Shell_NotifyIcon вы найдёте в коде нашей сегодняшней программы.&lt;br/&gt;&lt;br/&gt; Настала пора приступить к созданию программы. Она будет выполнять две полезные функции:&lt;br/&gt;1) Закрытие всех окон IE;&lt;br/&gt;2) Переход &quot;Вперёд\Назад&quot; в коллекции некоторых объектов. Всё дело в том, что часто при просмотре какого-либо форума или галереи картинок, ссылки имеют вид &quot;http://anysite/forum.php?page=2&quot;. Т.е мы находимся на второй странице форума. Если мы заменим цифру на &#39;1&#39;, то попадём на предыдущую страницу, на &#39;3&#39; – на следующую. Примерно по такому принципу мы организуем Переход &quot;Вперёд\Назад&quot;.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Закрытие всех окон IE&lt;/strong&gt;&lt;br/&gt;Предлагаю два способа реализации функции закрытия всех окон IE.&lt;br/&gt;&lt;strong&gt;&lt;i&gt;Способ I&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;Последовательно ищем окна Internet Explorer&#39;a и закрываем их: &lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; CloseAllIE_1;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    ie: HWND;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    //ищем окно IE&lt;br/&gt;    ie := FindWindow(&#39;IEFrame&#39;, &lt;strong&gt;nil&lt;/strong&gt;);&lt;br/&gt;    //пока найдено окно IE…&lt;br/&gt;    &lt;strong&gt;while&lt;/strong&gt; (ie&lt;&gt;0) &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;      &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;          //…закрываем его&lt;br/&gt;          postmessage(ie, WM_CLOSE, 0, 0);&lt;br/&gt;          //ищем следующее&lt;br/&gt;          ie := FindWindow(&#39;IEFrame&#39;, &lt;strong&gt;nil&lt;/strong&gt;);&lt;br/&gt;      &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;&lt;i&gt;&lt;strong&gt;Способ II&lt;/strong&gt;&lt;/i&gt;&lt;br/&gt;Перебираем все родительские окна в системе и, если увидели окно IE, то закрываем его. Таким образом, мы совершаем только один проход по окнам, а значит, работает этот способ намного быстрее предыдущего.&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; CloseAllIE_2;&lt;br/&gt;  //эта функция будет применяться к каждому окну&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt;CloseIE (Wnd: HWND): &lt;strong&gt;boolean&lt;/strong&gt;; &lt;strong&gt;stdcall&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;      winclass: array [0..255] &lt;strong&gt;of&lt;/strong&gt; char;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;      //получаем класс окна&lt;br/&gt;      GetClassName (Wnd, WinClass, sizeof(WinClass));&lt;br/&gt;      //если у нас окно IE, то закрываем его&lt;br/&gt;      &lt;strong&gt;if&lt;/strong&gt; (WinClass=&#39;IEFrame&#39;) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;        PostMessage (Wnd, WM_CLOSE, 0, 0);&lt;br/&gt;      //принимаем следующее окно&lt;br/&gt;      CloseIE := true;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  //перебираем все родительские окна, указывая, &lt;br/&gt;  //какой функцией будем их обрабатывать&lt;br/&gt;    EnumWindows(@CloseIE, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Переход &quot;Вперёд\Назад&quot;&lt;/strong&gt;&lt;br/&gt; Разделим нашу задачу на три составляющие:&lt;br/&gt;1) Получить адрес (URL) текущей странички IE;&lt;br/&gt;2) Увеличить (уменьшить) последнее число адреса на единицу;&lt;br/&gt;3) Записать изменённый адрес в окно IE и заставить браузер перейти по нему.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;&lt;i&gt;Пункт 1: получить адрес текущей странички&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;Окно IE, как и любое порядочное окно, содержит множество дочерних окон (всякие там кнопочки, поля ввода, надписи и т.д.). В одном из таких окон содержится URL странички. После недолгого изучения иерархии окон в IE при помощи специальной программы, добраться до адреса совсем несложно. Следующая функция возвращает идентификатор поля ввода (класс &#39;Edit&#39;), в котором содержится URL:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; FindEdit(var h:hwnd):boolean;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    wclass: array[0..255] &lt;strong&gt;of&lt;/strong&gt; char;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    //получаем идентификатор и класс &quot;верхнего&quot; окна&lt;br/&gt;    h := getforegroundwindow;&lt;br/&gt;    getclassname(h, wclass, sizeof(wclass));&lt;br/&gt;    //если это окно IE, то &quot;распутываем&quot; иерархию дочерних окон&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (wclass=&#39;IEFrame&#39;) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        h := findwindowex(h, 0, &#39;WorkerA&#39;, &lt;strong&gt;nil&lt;/strong&gt;);&lt;br/&gt;        h := findwindowex(h, 0, &#39;ReBarWindow32&#39;, &lt;strong&gt;nil&lt;/strong&gt;);&lt;br/&gt;        h := findwindowex(h, 0, &#39;ComboBoxEx32&#39;, &lt;strong&gt;nil&lt;/strong&gt;);&lt;br/&gt;        h := findwindowex(h, 0, &#39;ComboBox&#39;, &lt;strong&gt;nil&lt;/strong&gt;);&lt;br/&gt;        h := findwindowex(h, 0, &#39;Edit&#39;, &lt;strong&gt;nil&lt;/strong&gt;);&lt;br/&gt;        result := true;&lt;br/&gt;    &lt;strong&gt;end else&lt;/strong&gt;&lt;br/&gt;        result := false;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;После того, как мы добрались до поля ввода, в котором хранится адрес странички, извлечём его при помощи следующей функции:&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; GetText(WindowHandle: hwnd): String;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    txtLength: Integer;&lt;br/&gt;    buffer: String;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  //Узнаём длину текста&lt;br/&gt;    TxtLength := SendMessage(WindowHandle, WM_GETTEXTLENGTH, 0, 0);&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (txtlength&gt;0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        txtlength := txtlength + 1;&lt;br/&gt;        setlength (buffer, txtlength);&lt;br/&gt;        //записываем текст окна в buffer&lt;br/&gt;        sendmessage(WindowHandle, wm_gettext, txtlength, longint(@buffer[1]));&lt;br/&gt;        result := buffer;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt; &lt;strong&gt;else&lt;/strong&gt; result := &#39;&#39;;&lt;br/&gt;end;&lt;br/&gt;&lt;br/&gt;Таким образом, чтобы узнать текущий адрес в IE, достаточно применить эти две функции:&lt;br/&gt;…&lt;br/&gt;FindEdit(h);&lt;br/&gt;Adress := GetText(h);&lt;br/&gt;…&lt;br/&gt;&lt;strong&gt;&lt;i&gt;Пункт 2: Увеличить (уменьшить) последнее число адреса на единицу&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;Здесь нам потребуется только умение оперировать со строками и знание основ арифметики.&lt;br/&gt;//увеличение последнего числа в строке s&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; IncURL(s:string): String;&lt;br/&gt;&lt;strong&gt;const&lt;/strong&gt;&lt;br/&gt;    num = [&#39;0&#39;..&#39;9&#39;];&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    i,  j, cnt: word;&lt;br/&gt;    plus, ch: byte;&lt;br/&gt;    code: integer;&lt;br/&gt;    s1: string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    i := length(s);&lt;br/&gt;    plus := 0;&lt;br/&gt;    //ищем первую цифру с конца&lt;br/&gt;    &lt;strong&gt;while&lt;/strong&gt; (i&gt;0) &lt;strong&gt;and&lt;/strong&gt; &lt;strong&gt;not&lt;/strong&gt;(s[i] &lt;strong&gt;in&lt;/strong&gt; num) &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;        dec(i);&lt;br/&gt;    //если нашли…&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (i&lt;&gt;0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        //считаем количество девяток, которыми кончается число&lt;br/&gt;        cnt := 0;&lt;br/&gt;        &lt;strong&gt;while&lt;/strong&gt; (i&gt;0) and (s[i]=&#39;9&#39;) do&lt;br/&gt;        &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;            dec(i);&lt;br/&gt;            inc(cnt);&lt;br/&gt;        &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;        &lt;strong&gt;if&lt;/strong&gt; (i=0) &lt;strong&gt;or not&lt;/strong&gt;( s[i] &lt;strong&gt;in&lt;/strong&gt; num) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;        &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;            ch := 0;&lt;br/&gt;          {если число сплошь состоит из девяток, то мы должны первой цифрой    сделать &#39;1&#39; и заменить все девятки на нули}&lt;br/&gt;            &lt;strong&gt;if&lt;/strong&gt; &lt;strong&gt;not&lt;/strong&gt;(s[i] &lt;strong&gt;in&lt;/strong&gt; num) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;                plus := 1;&lt;br/&gt;        &lt;strong&gt;end else&lt;/strong&gt;&lt;br/&gt;            val(s[i], ch, code);&lt;br/&gt;        inc(ch);&lt;br/&gt;        str(ch, s1);&lt;br/&gt;        &lt;strong&gt;if&lt;/strong&gt; (cnt&gt;0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;            //заменяем последние девятки на нули&lt;br/&gt;            &lt;strong&gt;for&lt;/strong&gt; j := 1 &lt;strong&gt;to&lt;/strong&gt; cnt &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;                s1 := s1 + &#39;0&#39;;&lt;br/&gt;        //составляем итоговую строку&lt;br/&gt;        s := copy(s, 1, i-1+plus)+s1+copy(s, i+cnt+1, length(s)-i-cnt);&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    result := s;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//уменьшение последнего числа в строке s&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; DecURL(s:string):string;&lt;br/&gt;&lt;strong&gt;const&lt;/strong&gt;&lt;br/&gt;    num = [&#39;0&#39;..&#39;9&#39;];&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    i, j, cnt: word;&lt;br/&gt;    minus, ch: byte;&lt;br/&gt;    code: integer;&lt;br/&gt;    s1: string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    i := length(s);&lt;br/&gt;    minus := 0;&lt;br/&gt;    //ищем последнюю цифру в строке&lt;br/&gt;    &lt;strong&gt;while&lt;/strong&gt; (i&gt;0) &lt;strong&gt;and not&lt;/strong&gt; (s[i] in num) do&lt;br/&gt;        dec(i);&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (i&lt;&gt;0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        cnt := 0;&lt;br/&gt;        //считаем количество нулей&lt;br/&gt;        &lt;strong&gt;while&lt;/strong&gt; (i&gt;0) &lt;strong&gt;and&lt;/strong&gt;(s[i]=&#39;0&#39;) do&lt;br/&gt;        &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;            dec(i);&lt;br/&gt;            inc(cnt);&lt;br/&gt;        &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;        &lt;strong&gt;if&lt;/strong&gt; (i&gt;0) &lt;strong&gt;and&lt;/strong&gt; (s[i] &lt;strong&gt;in&lt;/strong&gt; num) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;        &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;            val(s[i],ch,code);&lt;br/&gt;            dec(ch);&lt;br/&gt;            &lt;strong&gt;if&lt;/strong&gt; (ch=0) &lt;strong&gt;and&lt;/strong&gt; (i&gt;0)&lt;strong&gt; and no&lt;/strong&gt;t(s[i-1] &lt;strong&gt;in&lt;/strong&gt; num) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;                s1 := &#39;&#39;&lt;br/&gt;            &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;                str(ch, s1);&lt;br/&gt;            &lt;strong&gt;if&lt;/strong&gt; (cnt&gt;0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;                //заменяем последние нули на девятки&lt;br/&gt;                &lt;strong&gt;for&lt;/strong&gt; j := 1 &lt;strong&gt;to&lt;/strong&gt; cnt &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;                    s1 := s1 + &#39;9&#39;;&lt;br/&gt;            //составляем итоговый URL&lt;br/&gt;            s := copy(s, 1, i-1-minus) + s1 + copy(s, i+cnt+1, length(s)-i-cnt);&lt;br/&gt;        &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    result := s;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;&lt;i&gt;&lt;strong&gt;Пункт 3: записать изменённый адрес в окно IE и заставить браузер перейти по нему.&lt;/strong&gt;&lt;/i&gt;&lt;br/&gt;Для выполнения третьей части задачи нужно просто послать полю ввода два сообщения:&lt;br/&gt;…&lt;br/&gt;//&quot;вводим&quot; изменённый адрес&lt;br/&gt;SendMessage(h, WM_SETTEXT, 0, longint(Pchar(s)));&lt;br/&gt;//&quot;нажимаем&quot; клавишу &quot;Ввод&quot; (Enter)&lt;br/&gt;SendMessage(h, WM_KEYDOWN, VK_RETURN, 0);&lt;br/&gt;…&lt;br/&gt;&lt;br/&gt;Теперь соберём эти три пункта в нужные нам процедуры:&lt;br/&gt;//переход &quot;Вперёд&quot;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; NextPage;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    s: String;&lt;br/&gt;    h: HWnd;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; FindEdit(h) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        //получаем URL&lt;br/&gt;        s := gettext(h);&lt;br/&gt;        delete(s, length(s), 1);&lt;br/&gt;        //увеличиваем последнее число на единицу&lt;br/&gt;        s := IncURL(s);&lt;br/&gt;        //записываем новый URL&lt;br/&gt;        SendMessage(h, WM_SETTEXT, 0, longint(Pchar(s)));&lt;br/&gt;        //нажимаем клавишу &quot;Ввод&quot;&lt;br/&gt;        SendMessage(h, WM_KEYDOWN, VK_RETURN, 0);&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//переход &quot;Вперёд&quot;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; PrevPage;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    s: String;&lt;br/&gt;    h: HWnd;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; FindEdit(h) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        s := string(gettext(h));&lt;br/&gt;        delete(s, length(s), 1);&lt;br/&gt;        s := DecURL(s);&lt;br/&gt;        SendMessage(h, WM_SETTEXT, 0, longint(Pchar(s)));&lt;br/&gt;        SendMessage(h, WM_KEYDOWN, VK_RETURN, 0);&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Все основные процедуры нашей программы готовы, теперь настало время сделать для них оболочку. Создайте новый проект и поместите на форму один-единственный компонент – &lt;i&gt;PopupMenu1:TPopupMenu1&lt;/i&gt;. В нём должен быть один пункт – &quot;Выход&quot;. Процедура при выборе этого пункта:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.ExitClick(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    //завершаем работу программы&lt;br/&gt;    halt;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt; Добавьте к списку подключаемых модулей (раздел Uses) модуль ShellApi. Объявите константу&lt;br/&gt; &lt;br/&gt;&lt;strong&gt;const&lt;/strong&gt;&lt;br/&gt;    WM_ICONTRAY = wm_user + 1;&lt;br/&gt;&lt;br/&gt;Этим мы определили сообщение, которое будем получать от иконки в SysTray. &lt;br/&gt;В раздел Private добавьте три строчки:&lt;br/&gt;&lt;br/&gt;  //информация о нашей иконке&lt;br/&gt;  TrayIconData: TNotifyIconData;&lt;br/&gt;  //эта процедура будет обрабатывать поступающие от иконки сообщения&lt;br/&gt;  &lt;strong&gt;procedure&lt;/strong&gt; TrayMessage &lt;strong&gt;(var&lt;/strong&gt; Msg: TMessage); &lt;strong&gt;message&lt;/strong&gt; WM_ICONTRAY;&lt;br/&gt;  //процедура обработки нажатия &quot;горячих&quot; клавиш&lt;br/&gt;  &lt;strong&gt;procedure&lt;/strong&gt; hotykey(&lt;strong&gt;var&lt;/strong&gt; msg:TWMHotkey); &lt;strong&gt;message&lt;/strong&gt; WM_HOTKEY;&lt;br/&gt;&lt;br/&gt;Запишите процедуру для события OnCreate формы:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.FormCreate(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    //заполняем информацию об иконке&lt;br/&gt;    &lt;strong&gt;with&lt;/strong&gt; TrayIconData &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        cbSize := SizeOf(TrayIconData);&lt;br/&gt;        Wnd := Handle;&lt;br/&gt;        uID := 0;&lt;br/&gt;        uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;&lt;br/&gt;        uCallbackMessage := WM_ICONTRAY;&lt;br/&gt;        hIcon := application.icon.handle;&lt;br/&gt;        szTip := &#39;My TrayIcon!&#39;;&lt;br/&gt;  &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    //добавляем иконку в SysTray&lt;br/&gt;    Shell_NotifyIcon(NIM_ADD, @TrayIconData);&lt;br/&gt;    //регистрируем &quot;горячие&quot; клавиши Alt+P&lt;br/&gt;    RegisterHotKey(handle, 1,.MOD_Alt, 80);&lt;br/&gt;  //регистрируем &quot;горячие&quot; клавиши Alt+Q&lt;br/&gt;    RegisterHotKey(handle, 2,.MOD_Alt, 81);&lt;br/&gt;  //регистрируем &quot;горячие&quot; клавиши Alt+R&lt;br/&gt;    RegisterHotKey(handle, 3,.MOD_Alt, 82);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Теперь процедура при уничтожении формы:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.FormDestroy(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    //удаляем иконку&lt;br/&gt;    ShellApi.Shell_NotifyIcon(NIM_DELETE, @TrayIconData);&lt;br/&gt;    //удаляем &quot;горячие&quot; клавиши&lt;br/&gt;    UnRegisterHotKey(handle, 1);&lt;br/&gt;    UnRegisterHotKey(handle, 2);&lt;br/&gt;    UnRegisterHotKey(handle, 3);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//обработка сообщений от иконки&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.TrayMessage(&lt;strong&gt;var&lt;/strong&gt; Msg: TMessage);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    p: TPoint;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;case&lt;/strong&gt; Msg.lParam &lt;strong&gt;of&lt;/strong&gt;&lt;br/&gt;      //если нажата правая кнопка мыши,&lt;br/&gt;        WM_RBUTTONDown, WM_RBUTTONDBLCLK:&lt;br/&gt;        &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;            SetForegroundWindow(handle);&lt;br/&gt;            GetCursorPos(p);&lt;br/&gt;            //то показываем наше меню в текущей позиции курсора&lt;br/&gt;            popupmenu1.Popup(p.x,p.y);&lt;br/&gt;        &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//нажатие на &quot;горячие&quot; клавиши&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.hotykey(&lt;strong&gt;var&lt;/strong&gt; msg:TWMHotkey);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    n: Integer;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    n := msg.HotKey;&lt;br/&gt;      //если нажали Alt+P, то закрываем все окна IE&lt;br/&gt;      &lt;strong&gt;if&lt;/strong&gt; (n=1) then CloseAllIE_2;&lt;br/&gt;      &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;          //если нажали Alt+Q, то переход &quot;Вперёд&quot;&lt;br/&gt;          &lt;strong&gt;if&lt;/strong&gt; (n=2) &lt;strong&gt;then&lt;/strong&gt; NextPage&lt;br/&gt;          &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;              //если нажали Alt+R, то переход &quot;Назад&quot;&lt;br/&gt;              &lt;strong&gt;if&lt;/strong&gt; (n=3) then PrevPage;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt; На этом создание программы, которая расширяет функциональность браузера Internet Explorer, завершено. Мы научились:&lt;br/&gt;1) работать с &quot;горячими&quot; клавишами;&lt;br/&gt;2) помещать иконку на Системную панель;&lt;br/&gt;3) работать с сообщениями и окнами.&lt;br/&gt;На сегодня всё.&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;i&gt;&lt;strong&gt;&lt;span style=&quot;color:#333333;&quot;&gt;Иван Ширко&lt;/span&gt;&lt;br/&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/strong&gt;&lt;/i&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2008/01/ie-delphi.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-147560667264374624</guid><pubDate>Wed, 09 Jan 2008 08:39:00 +0000</pubDate><atom:updated>2008-12-08T13:57:33.979-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Сделай сам</category><title>Сделай сам: управление автозагрузкой</title><description>&lt;div align=&quot;justify&quot;&gt;    Продолжаем серию &quot;Сделай сам&quot;, посвящённую практическому применению Delphi. На этот раз мы поговорим о такой важной составляющей жизни нашего компьютера, как автозагрузка. При загрузке Windows могут запускаться самые разные приложения: от системной панели (вы её можете узнать по характерным для неё часам) до программы оптимизации реестра.&lt;br/&gt;    Все мы любим устанавливать новые программы. А некоторые из них, дабы мы с ними никогда не расставались, втихую прописывают себя в автозагрузку. Вот и получается, что со временем Windows загружается всё дольше и дольше. А всё потому, что с ней за компанию запускаются различные &quot;удобняшки&quot;, антивирусы (а иногда и их анти-сородичи) и т.п.&lt;br/&gt;    Вывод из всего вышесказанного: время от времени нужно проводить &quot;зачистку&quot; в автозагрузке. Продвинутыми пользователями это делается при помощи редактора реестра и Блокнота, а все остальные используют специальные программы. Давайте посмотрим, что нам предлагает Windows для управления автозагрузкой. После недолгих поисков была найдена программа MsConfig (лежит она в каталоге …\Windows\System). MsConfig позволяет просматривать список файлов, запускающихся вместе с Windows и удалять элементы из автозагрузки с возможностью восстановления. Программа обрабатывает файл Win.ini, папку &quot;Автозагрузка&quot; и следующие ключи реестра: &lt;em&gt;HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run&lt;/em&gt;, &lt;em&gt;HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run&lt;/em&gt; и &lt;em&gt;HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices&lt;/em&gt;.&lt;br/&gt;Теперь, когда есть с чем сравнить, сделаем свою программу для управления автозагрузкой. Вот что наше творение будет уметь делать к концу статьи:&lt;br/&gt;1) Всё, что умеет MsConfig, за исключением восстановления удалённых из автозагрузки файлов;&lt;br/&gt;2) Добавлять новые файлы в автозагрузку и изменять пути к существующим;&lt;br/&gt;3) Обрабатывать большее количество ключей реестра, чем MsConfig. &lt;/div&gt;&lt;span class=&quot;fullpost&quot;&gt;&lt;div align=&quot;justify&quot;&gt;&lt;br/&gt;Теперь немного теоретических сведений:&lt;br/&gt;1) В Win.ini есть два параметра: Load и Run. Все файлы, имена которых записаны в этих параметрах через пробел, будут загружаться при старте Windows. А значит, в именах файлов не должно быть пробелов. Этого легко добиться при помощи функции sysutils.ExtractShortPathName (filename).&lt;br/&gt;2) В реестре есть &quot;автозагрузочные&quot; ключи с одинаковыми названиями: Run и RunOnce. Одна пара находится в разделе &lt;em&gt;HKEY_LOCAL_MACHINE&lt;/em&gt;, а другая – в &lt;em&gt;HKEY_CURRENT_USER&lt;/em&gt;. В связи с этим, в нашей программе будем осуществлять переход между разделами при помощи двух компонентов &lt;em&gt;TradioButton&lt;/em&gt; (см. рис. 1). &lt;/div&gt;&lt;br/&gt;&lt;br/&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5153405622080073474&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimTBaReXo-xMpm0ZvKgLcxJK6pN2CgFUvu3rhWllbbpfyA_ONtUDAL8pYra3_pLn8GdO51oz0FbU4LuZPG4PhFqiO0ZyH7DNYJTdf4Nka2ont0j4frydJTIgOFgLdtWgfpc_n_IKzKuqE/s400/Pic1.jpg&quot; border=&quot;0&quot; /&gt; &lt;p align=&quot;justify&quot;&gt;&lt;br/&gt;Создайте в Delphi новый проект и поместите на форму &lt;em&gt;PageControl1:TpageControl&lt;/em&gt;. Затем на этот компонент поместите &lt;em&gt;ListView1:TlistView&lt;/em&gt;. После этого на форму поместите следующие компоненты: &lt;em&gt;ToolBar1:TtoolBar, ImageList1:TimageList, OpenDialog1:TopenDialog, RadioButton1:TradioButton и RadioButton2:TradioButton&lt;/em&gt;. Теперь выделите &lt;em&gt;PageControl1&lt;/em&gt; и нажмите правую клавишу мыши. Из появившегося меню выберите пункт &lt;em&gt;New Page&lt;/em&gt;. После этого на компоненте должна появиться новая страница. Создайте, таким образом, ещё четыре страницы и дайте каждой название (свойство &lt;em&gt;Caption&lt;/em&gt;): 1 – Run, 2 – RunOnce, 3 – RunServices, 4 – RunServicesOnce, 5 – Win.ini. Каждая страница будет отвечать за определённый ключ реестра, либо за файл Win.ini. Теперь выделите &lt;em&gt;ListView1&lt;/em&gt; и, при помощи свойства &lt;em&gt;Columns&lt;/em&gt;, создайте две колонки с названиями (свойство &lt;em&gt;Caption&lt;/em&gt;) &lt;em&gt;Имя&lt;/em&gt; и &lt;em&gt;Путь&lt;/em&gt; соответственно, также для каждой колонки установите свойству &lt;em&gt;Autosize&lt;/em&gt; значение &lt;em&gt;True&lt;/em&gt;. После этого измените значения свойства &lt;em&gt;ViewStyle&lt;/em&gt; на &lt;em&gt;vsReport&lt;/em&gt;. Затем сделайте активным компонент &lt;em&gt;ToolBar1&lt;/em&gt; и создайте на нём четыре кнопки. Для каждой свойству &lt;em&gt;ShowHint&lt;/em&gt; (показывать подсказку) установите значение true (истина), а в свойство &lt;em&gt;Hint&lt;/em&gt; запишите эти самые подсказки, которые будут появляться при наведении указателя мыши на ту или иную кнопку: 1 – Добавить файл, 2 – Изменить путь, 3 – Удалить файл, 4 – Автозагрузка. На кнопки, при помощи &lt;em&gt;ImageList1&lt;/em&gt;, можно поместить иконки (см. рисунок 1). Чтобы сделать это, выполните следующие действия: кликните двойным щелчком по компоненту &lt;em&gt;ImageList1&lt;/em&gt;, при помощи кнопки “Add…” добавьте в компонент нужные значки (каждый значок будет помещён под своим номером), выделите компонент &lt;em&gt;ToolBar1&lt;/em&gt; и в свойстве &lt;em&gt;Images&lt;/em&gt; выберите компонент &lt;em&gt;ImageList1&lt;/em&gt;. После этого нужно в свойстве &lt;em&gt;ImageIndex&lt;/em&gt; каждой кнопки выбрать номер понравившегося значка. Теперь приведите вашу форму к виду, подобному на форму, изображённую на рисунке 1.&lt;br/&gt;На этом внешнее оформление программы завершено, а значит, пора заняться непосредственно программированием. Для начала в разделе &lt;em&gt;Uses&lt;/em&gt; подключите два модуля: &lt;em&gt;Registry&lt;/em&gt; (для работы с реестром) и &lt;em&gt;IniFiles&lt;/em&gt; (для работы с Ini-файлами). После этого нужно объявить несколько глобальных переменных:&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;  …&lt;br/&gt;  ActIndex: Integer; //индекс активной страницы&lt;br/&gt;  Appini: TIniFile; //для работы с Ini-файлами&lt;br/&gt;  key: Cardinal; //текущий ключ реестра&lt;br/&gt;  path: String; //путь к файлу&lt;br/&gt;  reg: TRegistry; //для работы с реестром&lt;br/&gt;  i: Integer; //используется в циклах&lt;br/&gt;  pathfile: String;&lt;br/&gt;  Value, Load, Run: TStringList; //списки файлов автозагрузки&lt;br/&gt;  ListItem:TListItem; //для работы с компонентом ListView1&lt;br/&gt;&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Затем запишите процедуру, которая будет из строки извлекать пути к файлам, разделённые пробелами, и помещает их в список. Позже эта процедура будет востребована.&lt;/p&gt;&lt;strong&gt;procedure&lt;/strong&gt; ExtractFilenames(s: String;FileNames: String;qw: TStrings);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  {если найдены два пробела, то удаляем один из них}&lt;br/&gt;  i := pos(&#39; &#39;, filenames);&lt;br/&gt;&lt;strong&gt;  while&lt;/strong&gt; (i &amp;lt;&amp;gt; 0) &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;  begin&lt;/strong&gt;&lt;br/&gt;    delete(filenames, i, 1);&lt;br/&gt;    i := pos(&#39; &#39;, filenames);&lt;br/&gt;&lt;strong&gt;  end&lt;/strong&gt;;&lt;br/&gt;  i := pos(&#39; &#39;, filenames);&lt;br/&gt;  {добавляем в список qw все файлы из строки}&lt;br/&gt;&lt;strong&gt;  while&lt;/strong&gt; (i&lt;&gt;0) &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;  begin&lt;/strong&gt;&lt;br/&gt;    qw.Add(copy(Filenames, 1, i-1));&lt;br/&gt;    delete(filenames, 1, i);&lt;br/&gt;    i := pos(&#39; &#39;, filenames);&lt;br/&gt;&lt;strong&gt;  end&lt;/strong&gt;;&lt;br/&gt;  qw.Add(filenames);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Для обработки события OnShow компонента TabSheet1 (мы её назвали &quot;Run&quot;) запишите следующую процедуру:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.TabSheet1Show(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  //очищаем ListView1&lt;br/&gt;  ListView1.Items.Clear;&lt;br/&gt;  //создаём объект для работы с реестром&lt;br/&gt;  reg := TRegistry.Create;&lt;br/&gt;  //будем работать в ключе хранящемся в переменной Key&lt;br/&gt;  reg.RootKey := Key;&lt;br/&gt;  {открываем ключ, в котором содержатся имена файлов загружаемых при каждом старте Windows и записываем эти в ListBox1}&lt;br/&gt;  reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\Run&#39;, False);&lt;br/&gt;  reg.GetValueNames(value);&lt;br/&gt;&lt;strong&gt;  for&lt;/strong&gt; i := 0 &lt;strong&gt;to&lt;/strong&gt; value.Count-1 &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    with&lt;/strong&gt; ListView1 do&lt;br/&gt;&lt;strong&gt;    begin&lt;/strong&gt;&lt;br/&gt;      ListItem := Items.Add;&lt;br/&gt;      ListItem.Caption :=Value.Strings[i];&lt;br/&gt;      ListItem.SubItems.Add(reg.ReadString(Value.Strings[i]));&lt;br/&gt;&lt;strong&gt;    end&lt;/strong&gt;;&lt;br/&gt;  //освобождаем память, выделенную под объект reg&lt;br/&gt;  reg.Free;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Процедура события OnShow компонента TabSheet2:&lt;br/&gt;Всё то же самое, только открываем другой ключ реестра:&lt;br/&gt;...&lt;br/&gt;  reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunOnce&#39;, False);&lt;br/&gt;...&lt;br/&gt;Обработка события OnShow компонента TabSheet3:&lt;br/&gt;То же, что и в предыдущих процедурах, но открываем ключ реестра, в котором хранятся имена сервисов, которые запускаются вместе с Windows:&lt;br/&gt;...&lt;br/&gt;  reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunServices&#39;, False);&lt;br/&gt;...&lt;br/&gt;Обработка события OnShow компонента TabSheet4:&lt;br/&gt;Открываем ключ реестра, в котором хранятся имена сервисов, которые запустятся только один раз при ближайшей перезагрузки Windows:&lt;br/&gt;...&lt;br/&gt;  reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunServicesOnce&#39;, False);&lt;br/&gt;...&lt;br/&gt;&lt;br/&gt;Процедура обработки события OnShow компонента TabSheet5:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.TabSheet5Show(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  ListView1.Items.Clear;&lt;br/&gt;  load.Clear;&lt;br/&gt;  run.Clear;&lt;br/&gt;  //получаем доступ к файлу Win.ini&lt;br/&gt;  AppIni := TIniFile.Create(&#39;Win.INI&#39;);&lt;br/&gt;  //читаем пути к файлам из строки Load&lt;br/&gt;  path := appini.ReadString(&#39;windows&#39;, &#39;Load&#39;, &#39;&#39;);&lt;br/&gt;  //удаляем все ведущие пробелы&lt;br/&gt;&lt;strong&gt;  while&lt;/strong&gt; (path[1]= &#39; &#39;) &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;    delete(path, 1, 1);&lt;br/&gt;  //записываем пути к файлам в список Load&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; (path &lt;&gt; &#39;&#39;) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;  ExtractFileNames(&#39;Load&#39;, path, Load);&lt;br/&gt;  {теперь всё это повторяем со строкой “Run” и записываем их в список Run}&lt;br/&gt;  path := appini.ReadString(&#39;windows&#39;,&#39;Run&#39;, &#39;error&#39;);&lt;br/&gt;&lt;strong&gt;  while&lt;/strong&gt; (pos(&#39; &#39;, path) = 1) &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;    delete(path, 1, 1);&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; (path &lt;&gt; &#39;&#39;) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;  ExtractFileNames(&#39;Run&#39;,path,Run);&lt;br/&gt;  AppIni.Free;&lt;br/&gt;  {отображаем пути ко всем файлам из списков Run и Load в ListView1}&lt;br/&gt;&lt;strong&gt;  for&lt;/strong&gt; i:=0 &lt;strong&gt;to&lt;/strong&gt; Load.Count-1 &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    with&lt;/strong&gt; ListView1 &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    begin&lt;/strong&gt; &lt;br/&gt;      ListItem := Items.Add;&lt;br/&gt;      ListItem.Caption :=&#39;Load&#39;;&lt;br/&gt;      ListItem.SubItems.Add(Load.Strings[i]);&lt;br/&gt;&lt;strong&gt;    end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;  for&lt;/strong&gt; i:=0 &lt;strong&gt;to&lt;/strong&gt; Run.Count-1 &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    with&lt;/strong&gt; ListView1 &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    begin&lt;/strong&gt;&lt;br/&gt;      ListItem := Items.Add;&lt;br/&gt;      ListItem.Caption :=&#39;Run&#39;;&lt;br/&gt;      ListItem.SubItems.Add(Run.Strings[i]);&lt;br/&gt;&lt;strong&gt;    end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Обработка события OnClick компонента RadioButton1:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.RadioButton1Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  {если текущий ключ не HKEY_LOCAL_MACHINE, то делаем его активным и, если нужно, обновляем информацию в ListBox1}&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; Key&lt;&gt;windows.HKEY_LOCAL_MACHINE &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;  begin&lt;/strong&gt;&lt;br/&gt;    key := Windows.HKEY_LOCAL_MACHINE;&lt;br/&gt;&lt;strong&gt;    if&lt;/strong&gt; PageControl1.ActivePageIndex&lt;2&gt;&lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;      PageControl1.ActivePage.OnShow(self);&lt;br/&gt;&lt;strong&gt;  end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Обработка события OnClick компонента RadioButton1:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.RadioButton2Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  {если текущий ключ не HKEY_CURRENT_USER, то делаем его активным и, если нужно, обновляем информацию в ListBox1}&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; Key&lt;&gt;windows.HKEY_CURRENT_USER &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;  begin&lt;/strong&gt;&lt;br/&gt;    key := Windows.HKEY_CURRENT_USER;&lt;br/&gt;&lt;strong&gt;if&lt;/strong&gt; PageControl1.ActivePageIndex&amp;lt;2&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;  end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;После этого создайте новую форму и поместите на неё кнопку Tbutton, и два компонента TradioButton (рис. 2).&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5153405321432362738&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYQTX1J-_RjsRCT2jSHg3hHDcZwxhh_FkgxDs6pih99VFY-BfPBJul7sy6lUZ1SmwTQ6cLtDF_1hmSbnxcD0V2hbcJuq4uq_asMgx8RPynBQnwuhPJwyUNfhFNZfP0zfggRHfCJRZDrCc/s400/Pic2.jpg&quot; border=&quot;0&quot; /&gt;Запишите обработку события нажатия на кнопку:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm2.Button1Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;  FName: String;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  {преобразуем имя выбранного файла в краткий формат}&lt;br/&gt;  FName := sysutils.ExtractShortPathName(form1.opendialog1.filename);&lt;br/&gt;  {записываем в выбранную константу имя файла после пробела, также отображаем добавленный файл в окне нашей программы}&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; form2.RadioButton1.Checked &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    path := &#39;Load&#39;&lt;br/&gt;&lt;strong&gt;  else &lt;/strong&gt; path:=&#39;Run&#39;;&lt;br/&gt;  AppIni := TIniFile.Create(&#39;Win.INI&#39;);&lt;br/&gt;  AppIni.writeString(&#39;windows&#39;, path, appini.readstring(&#39;windows&#39;, path, &#39;&#39;) + &#39; &#39; + FName);&lt;br/&gt;  AppIni.Free;&lt;br/&gt;&lt;strong&gt;  with&lt;/strong&gt; form1.ListView1 &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;  begin&lt;/strong&gt;&lt;br/&gt;    ListItem := Items.Add;&lt;br/&gt;    ListItem.Caption := path;&lt;br/&gt;    ListItem.SubItems.Add(FName);&lt;br/&gt;&lt;strong&gt;  end&lt;/strong&gt;;&lt;br/&gt;  form2.hide;&lt;br/&gt;  form1.show;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Теперь запишите обработку нажатия кнопки New, при помощи которой можно добавить новый файл в автозагрузку:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.ToolButton1Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  {если выбран файл, который нужно добавить, то продолжаем}&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; OpenDialog1.Execute &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;  {если активна страница с ключами реестра то добавляем файл в реестр, иначе – в Win.ini}&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; PageControl1.ActivePageIndex&amp;lt;4&gt;&lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;  begin&lt;/strong&gt;&lt;br/&gt;    reg := Tregistry.Create;&lt;br/&gt;&lt;strong&gt;    if&lt;/strong&gt; PageControl1.ActivePageIndex&amp;lt;2&lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;      reg.RootKey:=key&lt;br/&gt;&lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;      reg.RootKey:=windows.HKEY_LOCAL_MACHINE;&lt;br/&gt;&lt;strong&gt;    case&lt;/strong&gt; PageControl1.ActivePageIndex &lt;strong&gt;of&lt;/strong&gt;&lt;br/&gt;      0: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\Run&#39;, False);&lt;br/&gt;      1: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunOnce&#39;, False);&lt;br/&gt;      2: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunServices&#39;, False);&lt;br/&gt;      3: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunServicesOnce&#39;, False);&lt;br/&gt;&lt;strong&gt;    end&lt;/strong&gt;;&lt;br/&gt;    //просим ввести имя константы для нового файла&lt;br/&gt;    path:=inputbox(&#39;Введите имя константы&#39;, &#39;&#39;, Extractfilename OpenDialog1.filename));&lt;br/&gt;    {если имя не введено, то вместо него записываем имя добавляемого файла}&lt;br/&gt;&lt;strong&gt;    if&lt;/strong&gt; path=&#39;&#39; &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;      path := Extractfilename(OpenDialog1.filename);&lt;br/&gt;    pathfile := ExtractShortPathName(OpenDialog1.filename);&lt;br/&gt;    reg.WriteString(path, pathfile);&lt;br/&gt;    reg.CloseKey;&lt;br/&gt;    reg.Free;&lt;br/&gt;&lt;strong&gt;    with&lt;/strong&gt; ListView1 &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    begin&lt;/strong&gt;&lt;br/&gt;      ListItem := Items.Add;&lt;br/&gt;      ListItem.Caption :=path;&lt;br/&gt;      ListItem.SubItems.Add(pathfile);&lt;br/&gt;&lt;strong&gt;    end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;  end&lt;/strong&gt; &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;  {если нужно добавить файл в Win.ini, то вызываем форму 2}&lt;br/&gt;  form2.show;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Нажатие кнопки &quot;Изменить&quot;:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.ToolButton2Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;  Temp: String;&lt;br/&gt;  Results: String;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  {если выбран новый файл для константы, то продолжаем}&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; ListView1.ItemFocused.Selected &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    if&lt;/strong&gt; opendialog1.Execute &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    begin&lt;/strong&gt;&lt;br/&gt;      {получаем индекс активной константы}&lt;br/&gt;      ActIndex := ListView1.ItemFocused.Index;&lt;br/&gt;      {преобразовываем имя выбранного файла в короткий формат}&lt;br/&gt;      results := ExtractShortPathName(OpenDialog1.filename);&lt;br/&gt;      {теперь записываем в константу новый файл}&lt;br/&gt;&lt;strong&gt;      if&lt;/strong&gt; PageControl1.ActivePageIndex&amp;lt;4 &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;      begin&lt;/strong&gt;&lt;br/&gt;        reg := TRegistry.Create;&lt;br/&gt;&lt;strong&gt;        if&lt;/strong&gt; PageControl1.ActivePageIndex&amp;lt;2 &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;          reg.RootKey := key&lt;br/&gt;&lt;strong&gt;        else&lt;/strong&gt;&lt;br/&gt;          reg.RootKey:=windows.HKEY_LOCAL_MACHINE;&lt;br/&gt;&lt;strong&gt;        case&lt;/strong&gt; PageControl1.ActivePageIndex &lt;strong&gt;of&lt;/strong&gt;&lt;br/&gt;          0: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\Run&#39;, False);&lt;br/&gt;          1: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunOnce&#39;, False);&lt;br/&gt;          2: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunServices&#39;, False);&lt;br/&gt;          3: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunServicesOnce&#39;, False);&lt;br/&gt;&lt;strong&gt;        end&lt;/strong&gt;;&lt;br/&gt;        reg.WriteString(listview1.Items.Item[ActIndex].Caption,results);&lt;br/&gt;        reg.CloseKey;&lt;br/&gt;        reg.Free;&lt;br/&gt;&lt;strong&gt;      end&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;&lt;/strong&gt;&lt;strong&gt;      else&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;      begin&lt;/strong&gt;&lt;br/&gt;        AppIni:=TIniFile.Create(&#39;Win.INI&#39;);&lt;br/&gt;        path := appini.readstring(&#39;windows&#39;,listview1.Items.Item[ActIndex].Caption,&#39;error&#39;);&lt;br/&gt;        temp := ListView1.Items.Item[actindex].SubItems.Strings[0];&lt;br/&gt;        i := pos(temp,path);&lt;br/&gt;&lt;strong&gt;        if&lt;/strong&gt; i&lt;&gt;0 &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;        begin&lt;/strong&gt;&lt;br/&gt;          delete(path, i, length(temp));&lt;br/&gt;          path := path + &#39; &#39; + results;&lt;br/&gt;          appini.writeString(&#39;windows&#39;,listview1.Items.Item[ActIndex].Caption, path);&lt;br/&gt;          AppIni.Free;&lt;br/&gt;&lt;strong&gt;        end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;      end&lt;/strong&gt;;&lt;br/&gt;      ListView1.Items.Item[actindex].SubItems.Strings[0] := Results;&lt;br/&gt;&lt;strong&gt;    end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Нажатие кнопки &quot;Удалить&quot;:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.ToolButton3Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;  temp: String;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  {если пользователь уверен в своём решении, то удаляем выбранный файл из автозагрузки}&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; ListView1.ItemFocused.Selected &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    if&lt;/strong&gt; messagedlg(&#39;Вы уверены?&#39;, mtConfirmation, [mbYes,mbNo], 0) = mryes &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    begin&lt;/strong&gt;&lt;br/&gt;      ActIndex := ListView1.ItemFocused.Index;&lt;br/&gt;&lt;strong&gt;      if&lt;/strong&gt; PageControl1.ActivePageIndex&amp;lt;4 &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;      begin&lt;/strong&gt;&lt;br/&gt;        reg:=Tregistry.Create;&lt;br/&gt;&lt;strong&gt;        if&lt;/strong&gt; PageControl1.ActivePageIndex&amp;lt;2 &lt;strong&gt;then&lt;/strong&gt; reg.RootKey:=key&lt;br/&gt;&lt;strong&gt;        else&lt;/strong&gt;&lt;br/&gt;          reg.RootKey:=windows.HKEY_LOCAL_MACHINE;&lt;br/&gt;&lt;strong&gt;        case&lt;/strong&gt; PageControl1.ActivePageIndex &lt;strong&gt;of&lt;/strong&gt;&lt;br/&gt;          0: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\Run&#39;, False);&lt;br/&gt;          1: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunOnce&#39;, False);&lt;br/&gt;          2: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunServices&#39;, False);&lt;br/&gt;          3: reg.OpenKey(&#39;Software\Microsoft\Windows\CurrentVersion\RunServicesOnce&#39;, False);&lt;br/&gt;&lt;strong&gt;        end&lt;/strong&gt;;&lt;br/&gt;      reg.DeleteValue(listview1.Items.Item[ActIndex].Caption);&lt;br/&gt;      reg.CloseKey;&lt;br/&gt;      reg.Free;&lt;br/&gt;&lt;strong&gt;    end&lt;/strong&gt; &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;    begin&lt;/strong&gt;&lt;br/&gt;      AppIni := TIniFile.Create(&#39;Win.INI&#39;);&lt;br/&gt;      path := AppIni.readstring(&#39;windows&#39;, listview1.Items.Item[ActIndex].Caption, &#39;error&#39;);&lt;br/&gt;      temp := ListView1.Items.Item[actindex].SubItems.Strings[0];&lt;br/&gt;      i := pos(temp,path);&lt;br/&gt;&lt;strong&gt;      if&lt;/strong&gt; (i&amp;lt;&amp;gt;0) &lt;strong&gt;then&lt;/strong&gt; &lt;br/&gt;&lt;strong&gt;      begin&lt;/strong&gt;&lt;br/&gt;        delete(path,i,length(temp));&lt;br/&gt;        appini.writeString(&#39;windows&#39;,listview1.Items.Item[ActIndex].Caption, path);&lt;br/&gt;        AppIni.Free;&lt;br/&gt;&lt;strong&gt;      end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;    end&lt;/strong&gt;;&lt;br/&gt;    ListView1.Items.Item[actindex].Delete;&lt;br/&gt;&lt;strong&gt;  end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Нажатие на кнопку &quot;Автозагрузка&quot;:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.ToolButton4Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;  Auto: String;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  reg:=TRegistry.Create(windows.key_Read);&lt;br/&gt;  reg.RootKey:=HKEY_USERS;&lt;br/&gt;  reg.OpenKey(&#39;.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders&#39;, False);&lt;br/&gt;  {читаем из реестра путь к папке &quot;Автозагрузка&quot; и открываем её}&lt;br/&gt;  Auto:=&#39;Explorer &#39;+reg.ReadString(&#39;Startup&#39;);&lt;br/&gt;  reg.Free;&lt;br/&gt;  winexec(pchar(Auto),SW_ShowNormal);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Теперь добавим в программу пару штрихов.&lt;br/&gt;Выделите компонент &lt;em&gt;ListView1&lt;/em&gt; и для события &lt;em&gt;OnDblClick&lt;/em&gt; (при двойном щелчке мышью) выберите процедуру &lt;em&gt;ToolButton2Click&lt;/em&gt;, а для события &lt;em&gt;OnKeyDown&lt;/em&gt; (при нажатии клавиши) запишите следующее:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.ListView1KeyDown(Sender: TObject; var Key: Word;&lt;br/&gt;Shift: TShiftState);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;  if&lt;/strong&gt; key=VK_DELETE &lt;strong&gt;then&lt;/strong&gt; form1.ToolButton3.OnClick(self);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;    В итоге, при нажатии кнопки Delete, выбранный файл будет удалён, а при двойном щелчке мыши будет предложено заменить этот файл другим.&lt;br/&gt;    Вот и всё. Предложения по поводу тем следующих статей этого цикла присылайте мне на e-mail.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;&lt;em&gt;&lt;span&gt;Иван Ширко&lt;br/&gt;&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2008/01/blog-post.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimTBaReXo-xMpm0ZvKgLcxJK6pN2CgFUvu3rhWllbbpfyA_ONtUDAL8pYra3_pLn8GdO51oz0FbU4LuZPG4PhFqiO0ZyH7DNYJTdf4Nka2ont0j4frydJTIgOFgLdtWgfpc_n_IKzKuqE/s72-c/Pic1.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-2009113460590601620</guid><pubDate>Mon, 17 Dec 2007 10:57:00 +0000</pubDate><atom:updated>2008-12-08T13:57:34.000-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Сделай сам</category><title>Сделай сам: &quot;Вскрывалка паролей&quot;</title><description>&lt;div align=&quot;justify&quot;&gt;&lt;span&gt;Каждому пользователю ПК время от времени приходится вводить пароли: для установки программы, для соединения с интернетом, для получения почты и т.д. Как правило, при вводе пароля, вместо нормальных символов появляются звёздочки (&#39;*&#39;). Делается такая конспирация не только для сокрытия пароля от посторонних глаз, но и для того, чтобы злоумышленник, получивший доступ к компьютеру, не мог узнать пароли, сохранённые в системе. Но, как известно, нет совершенной защиты, поэтому теперь можно найти много программ для извлечения паролей&lt;span&gt;  &lt;/span&gt;из-под &quot;звёздочек&quot;. Некоторые программы могут показывать пароль в отдельном окошке, другие же неким чудесным образом заставляют превратиться &quot;звёздочки&quot; в нормальные символы. В данной статье мы рассмотрим процесс создания программы, которая умеет &quot;выковыривать&quot; пароли двумя вышеописанными способами.&lt;/span&gt;&lt;br/&gt;&lt;/div&gt;&lt;p align=&quot;justify&quot;&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;Вначале немного теории. Windows, судя по названию, это &quot;сборище&quot; окон. Каждое окно обычно содержит другие окна, т.е. является родителем для некоторых других окон (эти &quot;другие окна&quot; называют дочерними). Для нашей программы нам достаточно знать, что то поле, куда мы вводим пароли является хоть и маленьким, но окном. А значит, как и любое порядочное окно, оно имеет параметр &quot;текст окна&quot; и умеет принимать\отсылать сообщения. Именно на данных весьма полезных свойствах полей ввода основаны программы для извлечения паролей из-под &quot;звёздочек&quot;. &lt;/span&gt;&lt;/p&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;Итак, способ первый для &quot;вскрытия&quot; паролей: нужно просто узнать текст окна, содержащего пароль. Вот и всё, никаких сложностей. Правда, работать данный способ будет только в Win9x&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и, возможно, в &lt;span lang=&quot;EN-US&quot;&gt;WinMe&lt;/span&gt;. Осталось только написать функцию для получения текста произвольного окна:&lt;p p=&quot;&quot; p=&quot;&quot; p=&quot;&quot;&gt;&lt;span class=&quot;fullpost&quot;&gt;&lt;strong&gt;&lt;span&gt;Function&lt;/span&gt;&lt;/strong&gt;&lt;span&gt; GetText(WindowHandle: hwnd):&lt;strong&gt;string&lt;/strong&gt;;&lt;/span&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;var&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;txtLength : integer;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;buffer: &lt;strong&gt;string&lt;/strong&gt;;&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;Узнаём&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;длину&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;текста&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;TxtLength := SendMessage(WindowHandle, WM_GETTEXTLENGTH, 0, 0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;strong&gt;if&lt;/strong&gt; txtlength&amp;gt;0 &lt;strong&gt;then&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt; &lt;/span&gt;txtlength := txtlength + 1;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt; &lt;/span&gt;setlength (buffer, txtlength);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;//&lt;/span&gt;&lt;span&gt;записываем&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;текст&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;окна&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;в&lt;/span&gt;&lt;span&gt; buffer&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt; &lt;/span&gt;sendmessage(WindowHandle, wm_gettext, txtlength, longint(@buffer[1]));&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt; &lt;/span&gt;result := buffer;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;strong&gt;end&lt;/strong&gt; &lt;strong&gt;else&lt;/strong&gt; result:=&#39;&#39;;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;end&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;&lt;br/&gt;&lt;p align=&quot;justify&quot;&gt;&lt;span&gt;Теперь, если мы вызовем эту функцию, записав в параметр идентификатор поля ввода пароля, то она возвратит нам сам пароль. Как узнать идентификатор нужного окна будет рассказано далее. А сейчас поговорим о втором способе извлечения пароля. Только в данном способе мы не запишем пароль в какую-либо переменную, а заставим поле ввода отобразить вместо звёздочек нормальные символы. Для этого нужно послать ему сообщение &lt;span&gt;EM_SETPASSWORDCHAR&lt;/span&gt;. Вообще, это сообщение используется и для того, чтобы нормальный текст заменить каким-либо символом (обычно используются звёздочки). Далее приведена процедура, которая не просто показывает нормальный текст вместо звёздочек, но, если у выбранного поля ввода текст не зашифрован, то мы заменяем его звёздочками. Т.е., если для поля ввода пароля применить эту процедуру, то появятся нормальные символы, а если для того же поля повторить операцию, то текст опять превратится в звёздочки.&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;Procedure&lt;/strong&gt; ShowPass(h:hwnd);&lt;br/&gt;&lt;p&gt;&lt;span&gt;var&lt;/span&gt;&lt;/p&gt;ch:integer;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;i:integer;&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;&lt;span&gt;begin&lt;/span&gt;&lt;/strong&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;//узнаём, закодирован ли текст&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;ch:=SendMessage(h, EM_GETPASSWORDCHAR, 0, 0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;//если закодирован, то раскодируем текст, иначе кодируем звёздочками&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;if&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; ch&amp;gt;0 &lt;strong&gt;then&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;i:=0&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;strong&gt;else&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;i:=ord(&#39;*&#39;);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;SendMessage(h, EM_SETPASSWORDCHAR, i, 0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;end&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;Теперь можно приступить к созданию самой программы, но перед этим нужно оговорить принципы её функционирования:&lt;/span&gt;&lt;br/&gt;&lt;p align=&quot;justify&quot;&gt;&lt;span&gt;&lt;span&gt;–&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;пользователь должен как-то указать программе, какой именно пароль он хочет &quot;вскрыть&quot;. Наиболее удобным для юзера способом мне представляется следующий: пользователь наводит курсор мышки на поле ввода с нужным паролем, нажимает определённую комбинацию клавиш и получает взамен &quot;звёздочек&quot; нормальный пароль.&lt;/span&gt;&lt;/p&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span&gt;&lt;span&gt;–&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;сделаем функцию копирования паролей в буфер обмена (этого нет в подобных программах!). &lt;span lang=&quot;EN-US&quot;&gt;Windows&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;не позволяет просто взять и скопировать пароль, поэтому будем делать так:&lt;/span&gt;&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;1)&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;Заменяем &quot;звёздочки&quot; на обычные символы;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;2)&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;Выделяем весь текст в поле ввода;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;3)&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;Копируем выделенный текст в буфер обмена;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;4)&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;Обратно маскируем пароль&lt;span&gt; &lt;/span&gt;&quot;звёздочками.&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;p align=&quot;justify&quot;&gt;&lt;span&gt;Теперь запускаем &lt;span lang=&quot;EN-US&quot;&gt;Delphi&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и делаем формочку, взяв за образец &lt;strong&gt;рис.1&lt;/strong&gt;.&lt;br/&gt;&lt;/span&gt;&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8xsBFNHLPJijUmrl06-3pKzuk6Suhqsmv9r62hyt9oXM2LCmgEmNH3BXAWip0n5aac5abTe-90oXbOdhH4FQ7Vp2ImKTQ1AFQbkUYCaiqKYsy-6nT_eDnmbW074ObmcBLbQADKQDBYEU/s400/Pic1.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5144905916161027794&quot; /&gt;&lt;br/&gt;&lt;span&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;В свойстве формы &lt;span lang=&quot;EN-US&quot;&gt;FormStyle&lt;/span&gt; установите константу &lt;span lang=&quot;EN-US&quot;&gt;fsStayOnTop&lt;/span&gt;, чтобы окно нашей программы находилось поверх остальных. Запишите функцию &lt;span lang=&quot;EN-US&quot;&gt;GetText &lt;/span&gt;и процедуру &lt;span lang=&quot;EN-US&quot;&gt;ShowPass (&lt;/span&gt;см. выше). В разделе &lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;Var&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;/strong&gt;нужно объявить несколько глобальных переменных:&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;em&gt;p:&lt;/em&gt;&lt;em&gt;&lt;span lang=&quot;EN-US&quot;&gt;TP&lt;/span&gt;oint;&lt;/em&gt;&lt;br/&gt;&lt;p&gt;&lt;em&gt;&lt;span lang=&quot;EN-US&quot;&gt;h:HWND;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;em&gt;&lt;span lang=&quot;EN-US&quot;&gt;ch:Integer;&lt;/span&gt;&lt;/em&gt;&lt;br/&gt;&lt;p&gt;&lt;em&gt;&lt;span lang=&quot;EN-US&quot;&gt;s:&lt;strong&gt;String&lt;/strong&gt;;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;span&gt;Процедура обработки нажатия на кнопку &quot;Показать\Спрятать пароль&quot;:&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;procedure&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; TForm1.Button1Click(Sender: TObject);&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;begin&lt;/span&gt;&lt;/strong&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;узнаём&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;координаты&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;курсора&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;мыши&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;getcursorpos(p);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;//получаем идентификатор окна, находящегося под курсором мыши&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;h:=windowfrompoint(p);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;//прячем\показываем пароль&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;ShowPass(h);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;перерисовываем&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;окно&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;InvalidateRect(h, nil, true);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;end&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;Данная процедура позволяет маскировать\демаскировать текст почти любого поля ввода.&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;Процедура обработки нажатия на кнопку &quot;Скопировать пароль&quot;:&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;procedure&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; TForm1.Button2Click(Sender: TObject);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;begin&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;узнаём&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;координаты&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;курсора&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;мыши&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;getcursorpos(p);&lt;/span&gt;&lt;/p&gt;&lt;span&gt;//получаем идентификатор окна, находящегося под курсором мыши&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;h:=windowfrompoint(p);&lt;/span&gt;&lt;/p&gt;&lt;span&gt;//каким символом замаскирован текст в данном окне?&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;ch:=SendMessage(h, EM_GETPASSWORDCHAR, 0, 0);&lt;/span&gt;&lt;/p&gt;&lt;span&gt;//если пароль замаскирован, то показываем его в нормальном виде&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;if&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; ch&amp;gt;0 &lt;strong&gt;then&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;SendMessage(h, EM_SETPASSWORDCHAR, 0, 0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;//выделяем весь текст&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;SendMessage(h, EM_SETSEL, 0, -1);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;//копируем выделенный текст&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;SendMessage(h, WM_COPY, 0, 0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;//если мы &quot;вскрывали&quot; пароль, то опять маскируем его&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;if&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; ch&amp;gt;0 &lt;strong&gt;then&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;SendMessage(h,EM_SETPASSWORDCHAR, ch, 0);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;перерисовываем&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;окно&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;InvalidateRect(h, nil, true);&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;&lt;span&gt;end&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;&lt;br/&gt;Процедура обработки нажатия на кнопку &quot;Показать пароль в отдельном окне&quot;:&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;procedure&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; TForm1.Button3Click(Sender: TObject);&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;begin&lt;/span&gt;&lt;/strong&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;узнаём&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;координаты&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;курсора&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;мыши&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;getcursorpos(p);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;//получаем идентификатор окна, находящегося под курсором мыши&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;h:=windowfrompoint(p);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;получаем&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;текст&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;окна&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;s:=gettext(h);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;//если текст не является пустой строкой, то показываем его пользователю&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;if&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; s&amp;lt;&amp;gt;&#39;&#39; &lt;strong&gt;then&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;setforegroundwindow(form1.handle);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;showmessage(s);&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;end&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;С помощью данной процедуры (работает она только в &lt;span lang=&quot;EN-US&quot;&gt;Win&lt;/span&gt;9&lt;span lang=&quot;EN-US&quot;&gt;x&lt;/span&gt;) можно узнать не только пароль, скрытый под &quot;звёздочками&quot;, но и текст практически любого стандартного элемента управления &lt;span lang=&quot;EN-US&quot;&gt;Windows&lt;/span&gt;: поля ввода, кнопки, флажка (&lt;span lang=&quot;EN-US&quot;&gt;checkbox&lt;/span&gt;) и др. Напомню, что текст копируется в буфер обмена, работа с которым рассматривается в №7 за 2002 год в статье &quot;Работа с буфером обмена в &lt;span lang=&quot;EN-US&quot;&gt;Delphi&quot;&lt;/span&gt;.&lt;/span&gt;&lt;br/&gt;&lt;/div&gt;&lt;p align=&quot;justify&quot;&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;В принципе программа уже готова к эксплуатации. Но для удобства пользователя сделаем, как и собирались, поддержку &quot;горячих клавиш&quot;. Для этого мы воспользуемся функцией&lt;/span&gt;&lt;/p&gt;&lt;span&gt;RegisterHotKey(&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;HWND hWnd, // этому окну придёт уведомление о нажатии &lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;комбинации клавиш&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;int id,&lt;span&gt;           &lt;/span&gt;// идентификатор &quot;горячих клавиш&quot;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;UINT fsModifiers,&lt;span&gt;   &lt;/span&gt;// должны ли быть нажаты клавиши &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Ctrl&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Shift&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span&gt;или &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Alt&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;UINT vk &lt;span&gt;     &lt;/span&gt;// код клавиши, на которую мы будем реагировать&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Для события &lt;span lang=&quot;EN-US&quot;&gt;OnCreate&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;формы запишите процедуру:&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;procedure&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; TForm1.FormCreate(Sender: TObject);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;begin&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;span&gt;//регистрируем сочетание &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Shift&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Alt&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;F&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;If&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;strong&gt;not&lt;/strong&gt; RegisterHotkey&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;         &lt;/span&gt;(Handle, 1, MOD_ALT &lt;strong&gt;or&lt;/strong&gt; MOD_SHIFT, VK_F9) &lt;strong&gt;Then&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ShowMessage(&#39;Нельзя использовать данное сочетание клавиш!&#39;);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;регистрируем&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;сочетание&lt;/span&gt;&lt;span&gt; &lt;span lang=&quot;EN-US&quot;&gt;Shift+Alt+F8&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;If&lt;/strong&gt; &lt;strong&gt;not&lt;/strong&gt; RegisterHotkey&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;         &lt;/span&gt;(Handle, 2, MOD_ALT &lt;strong&gt;or&lt;/strong&gt; MOD_SHIFT, VK_F8) &lt;strong&gt;Then&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ShowMessage(&#39;Нельзя использовать данное сочетание клавиш!&#39;);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//&lt;/span&gt;&lt;span&gt;регистрируем&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;сочетание&lt;/span&gt;&lt;span&gt; &lt;span lang=&quot;EN-US&quot;&gt;Shift+Alt+F7&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;If&lt;/strong&gt; &lt;strong&gt;not&lt;/strong&gt; RegisterHotkey&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;        &lt;/span&gt;(Handle, 3, MOD_ALT &lt;strong&gt;or&lt;/strong&gt; MOD_SHIFT, VK_F7) &lt;strong&gt;Then&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ShowMessage(&#39;Нельзя использовать данное сочетание клавиш!&#39;);&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;&lt;span&gt;end&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;;&lt;br/&gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Теперь в секции &lt;strong&gt;&lt;em&gt;&lt;span lang=&quot;EN-US&quot;&gt;Private&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;объявите процедуру, которая будет реагировать на нажатие комбинаций клавиш:&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;Procedure&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; WMHotkey( Var msg: TWMHotkey ); message WM_HOTKEY;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;   &lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;А вот и сама процедура:&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;Procedure&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt; TForm1.WMHotkey( Var msg: TWMHotkey );&lt;/span&gt;&lt;/p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;begin&lt;/span&gt;&lt;/strong&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;case&lt;/strong&gt; msg.hotkey &lt;strong&gt;of&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;//если нажато Shift+Alt+F9, то копируем пароль&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;  &lt;/span&gt;1:&lt;strong&gt;begin&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;getcursorpos(p);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;h:=windowfrompoint(p);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;ch:=SendMessage(h,EM_GETPASSWORDCHAR,0,0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;&lt;strong&gt;if&lt;/strong&gt; ch&amp;gt;0 &lt;strong&gt;then&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;       &lt;/span&gt;SendMessage(h,EM_SETPASSWORDCHAR,0,0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;SendMessage(h,EM_SETSEL,0,-1);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;SendMessage(h,WM_COPY,0,0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;&lt;strong&gt;if&lt;/strong&gt; ch&amp;gt;0 &lt;strong&gt;then&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;   &lt;/span&gt;SendMessage(h,EM_SETPASSWORDCHAR,ch,0);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;InvalidateRect(h,nil,true);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;//если нажато &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Shift&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Alt&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;F&lt;/span&gt;&lt;span&gt;8, то прячем\показываем пароль пароль&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;2:&lt;strong&gt;begin&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;/span&gt;getcursorpos(p);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;/span&gt;h:=windowfrompoint(p);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;/span&gt;ShowPass(h);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;/span&gt;InvalidateRect(h,nil,true);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;span&gt;end&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;//если нажато &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Shift&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Alt&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;F&lt;/span&gt;&lt;span&gt;9, то показываем пароль в отдельном окне&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;3:&lt;strong&gt;begin&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;/span&gt;getcursorpos(p);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;/span&gt;h:=windowfrompoint(p);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;/span&gt;s:=gettext(h);&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt; &lt;br/&gt;     &lt;/span&gt;&lt;strong&gt;if&lt;/strong&gt; s&amp;lt;&amp;gt;&#39;&#39; &lt;strong&gt;then&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;/span&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;        &lt;/span&gt;setforegroundwindow(form1.handle);&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;        &lt;/span&gt;showmessage(s);&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;        &lt;/span&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;     &lt;/span&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/span&gt;&lt;/p&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/span&gt;&lt;br/&gt;&lt;p&gt;&lt;strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;end&lt;/span&gt;&lt;/strong&gt;&lt;span lang=&quot;EN-US&quot;&gt;;&lt;/span&gt;&lt;/p&gt;&lt;div align=&quot;justify&quot;&gt;&lt;span&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;span&gt;      &lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Вот&lt;span&gt; &lt;/span&gt;и&lt;span&gt; &lt;/span&gt;всё&lt;span lang=&quot;EN-US&quot;&gt;. &lt;/span&gt;Осталось только откомпилировать программу, которая по своим возможностям превосходит все виденные мною аналоги. Правда, интерфейс у неё хромает, но это уже не совсем из области программирования.&lt;/span&gt;&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;&lt;span lang=&quot;EN-US&quot;&gt;P&lt;/span&gt;. &lt;span lang=&quot;EN-US&quot;&gt;S&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;Разумеется, данную программу нельзя применять ни в каких деструктивных целях.&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;/span&gt;&lt;strong&gt;&lt;i&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;Иван Ширко&lt;/span&gt;&lt;br/&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/strong&gt;&lt;span&gt;&lt;span&gt;&lt;br/&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2007/12/blog-post_17.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8xsBFNHLPJijUmrl06-3pKzuk6Suhqsmv9r62hyt9oXM2LCmgEmNH3BXAWip0n5aac5abTe-90oXbOdhH4FQ7Vp2ImKTQ1AFQbkUYCaiqKYsy-6nT_eDnmbW074ObmcBLbQADKQDBYEU/s72-c/Pic1.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-6562066103107703538</guid><pubDate>Tue, 11 Dec 2007 12:32:00 +0000</pubDate><atom:updated>2008-01-09T01:52:46.736-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">блог</category><title>&quot;Читать дальше&quot; в блоге или Экономим трафик читателей</title><description>&lt;div align=&quot;justify&quot;&gt;После добавления очередной статьи в блог я заметил, что главная страница при загрузке &quot;съела&quot; почти метр трафика, что не есть хорошо. Поэтому, предварительно покопавшись в справке Блоггера, принялся редактировать шаблон блога. В итоге, при загрузке страницы со списком статей, будь то главная страница или архив, отображается только часть поста. А чтобы прочитать понравившийся пост полностью достаточно перейти по ссылке &quot;Читать дальше&gt;&gt;&quot;.&lt;br/&gt;      Сделать это оказалось совсем несложно. Достаточно внести в шаблон блога следующие изменения:&lt;br/&gt;Добавьте (например после тега стилевой блок, который, в зависимости от типа страницы (полностью пост или список постов) установит полное либо частичное отображение поста:&lt;pre&gt;&lt;br /&gt;&amp;lt;style&amp;gt;&lt;br /&gt;  &amp;lt;b:if cond=&#39;data:blog.pageType == &quot;item&quot;&#39;&amp;gt;&lt;br /&gt;    span.fullpost {display:inline;}&lt;br /&gt;  &amp;lt;b:else/&amp;gt;&lt;br /&gt;    span.fullpost {display:none;}&lt;br /&gt;  &amp;lt;/b:if&amp;gt;&lt;br /&gt;&amp;lt;style&amp;gt;&lt;/pre&gt;&lt;br/&gt;После тега &amp;lt;data:post body=&quot;&quot;&amp;gt; поместите код, который покажет ссылку на пост целиком:&lt;pre&gt;&lt;code&gt;&amp;lt;b:if cond=&#39;data:blog.pageType != &quot;item&quot;&#39;&amp;gt;&amp;lt;br /&amp;gt;&lt;br/&gt;   &amp;lt;a expr:href=&#39;data:post.url&#39;&amp;gt;Читать дальше&gt;&gt;!&amp;lt;/a&amp;gt;&lt;br/&gt;&amp;lt;/b:if&amp;gt;&lt;/code&gt;&lt;/pre&gt;Теперь осталось оформить неотображаемую часть каждого поста тегом &amp;lt;span class=&quot;fullpost&quot;&amp;gt;&amp;lt;/span&amp;gt;. Пример: &lt;br/&gt;Это начало поста &amp;lt;span class=&quot;fullpost&quot;&amp;gt; а вот и продолжение&amp;lt;/span&amp;gt;. В итоге, чтобы прочитать такой пост целиком, придется щелкнуть по такой вот ссылке:&lt;/div&gt;&lt;span class=&quot;fullpost&quot;&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2007/12/blog-post_11.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-2944826268369995553</guid><pubDate>Mon, 10 Dec 2007 09:13:00 +0000</pubDate><atom:updated>2008-12-08T13:57:34.123-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><title>Двойная буферизация или Анимация без мерцания</title><description>&lt;div align=&quot;justify&quot;&gt;     Все мы с упоением в детстве смотрели мультики, да и сейчас иногда, щёлкая каналы, с ностальгией в душе останавливаемся посмотреть на рисованных персонажей, живущих своею жизнью.&lt;br/&gt;      Что же представляет из себя анимация? Да просто сменяющие одна другую картинки. И чем быстрее и плавнее меняется изображение, тем лучше выглядит анимация. Возможностей современного компьютера вполне достаточно, чтобы обеспечить нормальное отображение любой анимации. Но в играх анимация формируется динамически, так что любая задержка отображения картинок может вызвать мерцание. Чтобы этого избежать используют различные алгоритмы вывода изображения на экран. Давайте рассмотрим простой способ, с помощью которого можно делать динамические анимации, отлично отображающиеся даже на слабых компьютерах. &lt;br/&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;      Итак, разберём самый простой случай, когда нам нужно двигать простую фигуру (например, круг) по одноцветному фону. Реализовать это можно разными способами.  Можно, например, действовать напрямую: нарисовать поверх фона круг и через некоторый промежуток времени заливать всю картинку цветом фона, после чего рисовать круг со смещёнными координатами.  В итоге мы получим вполне движущуюся фигуру, но вот мерцание будет всё портить. Решение напрашивается само собой: нужно заливать не весь холст цветом фона, а только ту область, из которой нам нужно стереть изображение круга. В данном случае достаточно просто нарисовать цветом фона такой же круг, но у которого цвет равен цвету фона, что приведёт к стиранию начального круга.&lt;br/&gt; А теперь представим, что у нас по одноцветному фону движется уже сложное изображение. Здесь уже не удастся пиксель в пиксель затереть это изображение, так что придётся обводить его некоторой простой областью (например, прямоугольником) и закрашивать её. &lt;br/&gt;     Всё это, конечно, хорошо, но описанные случаи не представляют из себя особой практической ценности и используется разве что в учебных целях. Так что усложним ситуацию: пусть сложное изображение движется по сложному фону. Закрашивать тут не имеет смысла, так что нужно придумывать что-нибудь новенькое. Вот тут мы и подошли к методу двойной буферизации. Этот метод использовался и используется в играх, программах с графическим интерфейсом, да и просто в стандартных компонентах операционных систем. Как следует из названия, метод двойной буферизации предполагает наличие двух буферов. Один нужен для хранения перемещаемого изображения, а другой для хранения той области фона, в которую мы собираемся прорисовать это изображение. То есть последовательность действий примерно такая:&lt;br/&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;сохраняем область фона в буфер;&lt;br/&gt;&lt;/li&gt;&lt;li&gt;прорисовываем на фоне в этой области перемещаемое изображение;&lt;br/&gt;&lt;/li&gt;&lt;li&gt;через некоторое время восстанавливаем участок фона, вычисляем новые координаты и переходим к пункту 1.&lt;br/&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div align=&quot;justify&quot;&gt;     Давайте рассмотрим реализацию этого алгоритма на Delphi. В данном примере по сложному фону будет летать по круговой траектории  самолётик &lt;span class=&quot;fullpost&quot;&gt; (рис.1).&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkWF0rx2lipjUszvR_NoPni7NnYHKMEUB-oGmqV8zSWGtIpuaolVL9hTvLMPnvGr5k0TrURHgQRG9Oz7SGZLQabjcR3Ri0zI7Wk3fv2O4cTga5X0TXeUWCsKfcsOm9hvwHXnDo-11JPMk/s400/pic1.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5142273366970094802&quot; /&gt;&lt;/div&gt;&lt;br/&gt;Вначале нужно объявить несколько констант и переменных:&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;strong&gt;const&lt;/strong&gt;&lt;br/&gt;   //координаты центра окружности&lt;br/&gt;    xc = 200;&lt;br/&gt;    yc = 200;&lt;br/&gt;    //приращение угла&lt;br/&gt;    dl = 0.05;&lt;br/&gt;    //радиус окружности&lt;br/&gt;    R=100;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    //для хранения изображений&lt;br/&gt;    sam, buf: TBitmap;&lt;br/&gt;    BufRct: TRect;&lt;br/&gt;    l: real;&lt;br/&gt;    x, y:integer;&lt;br/&gt;    w, h:integer;&lt;br/&gt;&lt;br/&gt;Действия при запуске программы:&lt;br/&gt;&lt;br/&gt;  //создаём объекты для хранения изображений&lt;br/&gt;   Buf:=TBitmap.Create;&lt;br/&gt;   Sam:=TBitmap.Create;&lt;br/&gt;   //делаем фон самолётика прозрачным&lt;br/&gt;   Sam.Transparent:=true;&lt;br/&gt;   //загружаем изображение самолётика&lt;br/&gt;   Sam.LoadFromFile(&#39;sam.bmp&#39;);&lt;br/&gt;   //устанавливаем размеры буфера такими же, как у самолётика&lt;br/&gt;   w := Sam.Width;&lt;br/&gt;   h := Sam.Height;&lt;br/&gt;   Buf.Width:=w;&lt;br/&gt;   Buf.Height:=h;&lt;br/&gt;   //начальный угол&lt;br/&gt;   l := 0;&lt;br/&gt;   //начальные координаты&lt;br/&gt;   x := round(xc+R*cos(l));&lt;br/&gt;   y := round(yc+R*sin(l));&lt;br/&gt;   //сохраняем участок фона&lt;br/&gt;   BufRct := Bounds(x,y,w,h);&lt;br/&gt;   Buf.Canvas.CopyRect(Buf.Canvas.ClipRect,Image1.Canvas,BufRct);&lt;br/&gt;   //рисуем самолётик&lt;br/&gt;   Image1.Canvas.Draw(x,y,sam);&lt;br/&gt;   //запускаем таймер&lt;br/&gt;   Timer1.Enabled := true;&lt;br/&gt;&lt;br/&gt;Теперь через небольшой промежуток времени выполняем процедуру:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Timer1Timer(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;   //восстанавливаем участок фона&lt;br/&gt;   Image1.Canvas.Draw(x,y,buf);&lt;br/&gt;   //увеличиваем угол&lt;br/&gt;   l := l + dl;&lt;br/&gt;   //если самолёт сделал круг, то отнимаем от угла 2 пи&lt;br/&gt;   &lt;strong&gt;if&lt;/strong&gt; (l&gt;2*pi) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;      l := l - 2*pi;&lt;br/&gt;   //высчитываем координаты по новому углу&lt;br/&gt;   x := round(xc+R*cos(l));&lt;br/&gt;   y := round(yc+R*sin(l));&lt;br/&gt;   //сохраняем участок фона в буфер&lt;br/&gt;   BufRct := Bounds(x,y,w,h);&lt;br/&gt;   Buf.Canvas.CopyRect(Buf.Canvas.ClipRect,Image1.Canvas,BufRct);&lt;br/&gt;   //рисуем самолётик&lt;br/&gt;   Image1.Canvas.Draw(x,y,sam);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;     Разумеется, этот алгоритм можно перенести и на случай движения изображения по движущемуся фону, достаточно лишь математически учесть изменение положения фона. Метод двойной буферизации применяют также и для неподвижных объектов, например, для отображения какой-нибудь анимации (флаг развевается на ветру), т.е. после каждого кадра анимации мы восстанавливаем фон, чтобы исключить наложение кадров друг на друга.&lt;br/&gt;     Как видим, метод двойной буферизации достаточно легко реализовать, но несмотря на это он показывает очень хорошие результаты. И правильное использование описанного алгоритма делает программу с простой анимацией более эффектной и профессиональной без особых  усилий программиста.&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;strong&gt;&lt;i&gt;&lt;span&gt;Иван Ширко&lt;/span&gt;&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;&lt;a href=&quot;http://www.blogger.com/ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2007/12/blog-post.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkWF0rx2lipjUszvR_NoPni7NnYHKMEUB-oGmqV8zSWGtIpuaolVL9hTvLMPnvGr5k0TrURHgQRG9Oz7SGZLQabjcR3Ri0zI7Wk3fv2O4cTga5X0TXeUWCsKfcsOm9hvwHXnDo-11JPMk/s72-c/pic1.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-5589850080784129302</guid><pubDate>Wed, 05 Dec 2007 11:22:00 +0000</pubDate><atom:updated>2008-12-08T13:57:34.667-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><title>Мультимедиа под контролем или Функция mciSendString</title><description>    В данной статье рассматривается функция mciSendString, которая находится в библиотеке winmm.dll. Эта функция может подавать команды любому MCI (Media Control Interface) устройству (поддерживаемое системой мультимедиа устройство: WAV, MIDI, CDAudio, Video и т.п.). &lt;br/&gt;Вот её синтаксис:&lt;br/&gt;&lt;i&gt;MCIERROR mciSendString(&lt;br/&gt;      LPCTSTR lpszCommand, &lt;br/&gt;      LPTSTR lpszReturnString, &lt;br/&gt;      UINT cchReturn, &lt;br/&gt;      HANDLE hwndCallback &lt;br/&gt;   );&lt;/i&gt;&lt;br/&gt;lpszCommand – команда;&lt;br/&gt;lpszReturnString – строка результата;&lt;br/&gt;cchReturn – размер в символах строки результата;&lt;br/&gt;hwndCallback – окно отзыва (используется только при установленном в первом параметре флага &quot;notify&quot;).&lt;br/&gt;     Все дальнейшие примеры будут написаны на  Delphi, но их перевод на другие языки, я думаю, не составит особого труда. &lt;br/&gt;     Теперь условимся с параметрами функция mciSendString в последующих примерах:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;HwndCallback: будет принимать значение 0;&lt;br/&gt;&lt;/li&gt;&lt;li&gt;CchReturn: будет принимать значение 64 (в MSDN написано, что это максимальная длина ошибки, которая может быть возвращена параметром lpszReturnString);&lt;br/&gt;&lt;/li&gt;&lt;li&gt;LpszReturnString: в этом параметре будем использовать переменную sbReturn: array [1..64] of char;&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;     Пришло время перейти к самому главному параметру функции – lpszCommand. Эта команда составляется при помощи специальных операторов, часть которых рассматривается далее.&lt;br/&gt;&lt;span class=&quot;fullpost&quot;&gt;&lt;br/&gt;&lt;strong&gt;Open&lt;/strong&gt;&lt;br/&gt; Эта команда поддерживается всеми устройствами. Она служит для инициализации устройства. Синтаксис команды:&lt;br/&gt;&lt;i&gt;&#39;open lpszDeviceID lpszOpenFlags lpszFlags&#39;&lt;/i&gt;&lt;br/&gt;Параметры:&lt;br/&gt;&lt;i&gt;LpszDeviceID&lt;/i&gt; – идентификатор одного из устройств (или его псевдоним), прописанных в разделе [MCI] файла System.ini или в реестре. Может указывать также на драйвер. Например: cdaudio, sequencer, waveaudio, MyDriver.drv.&lt;br/&gt;&lt;i&gt;LpszOpenFlags&lt;/i&gt; – флаг, определяющий дополнительные параметры инициализации устройства. Я не буду приводить весь список значений этого параметра для каждого устройства, а упомяну лишь значение &quot;alias device_alias type device_type&quot;, которое открывает устройство типа device_type под псевдонимом device_alias. &lt;br/&gt;&lt;i&gt;LpszFlags&lt;/i&gt; – может принимать одно из следующих значений:&lt;br/&gt;&lt;ol&gt;&lt;li&gt;Test – служит для определения возможности выполнения команды, при этом сама команда устройству не отправляется.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Wait – при этом флаге управление программе передаётся только после выполнения команды.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Notify – при этом флаге программа получит специальное сообщение, при помощи которого сможет узнать о завершении выполнения команды, а управление передаётся без промедления.&lt;br/&gt;&lt;/li&gt;&lt;/ol&gt;Пример:&lt;br/&gt;&lt;i&gt;mciSendString(&#39;open d:\Sound.wav type waveaudio alias MyWave wait&#39;, nil, 0, 0); &lt;/i&gt;- связывает устройство &lt;i&gt;WaveAudio&lt;/i&gt; под псевдонимом &lt;i&gt;MyWave&lt;/i&gt; с файлом &lt;i&gt;d:\Sound.wav&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Play&lt;/strong&gt;&lt;br/&gt; Эта команда запускает проигрывание для одного из следующих устройств: CD audio, digital-video, MIDI sequencer, videodisc, VCR, и waveform-audio. &lt;br/&gt;Синтаксис команды:&lt;br/&gt;&lt;i&gt;&#39;play lpszDeviceID lpszPlayFlags lpszFlags&#39;&lt;/i&gt;&lt;br/&gt;Параметры:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;LpszDeviceID&lt;/i&gt; – идентификатор одного из устройств (или его псевдоним), прописанных в разделе [MCI] файла System.ini. Например: cdaudio, sequencer, waveaudio, avivideo.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;LpszPlayFlags&lt;/i&gt; – флаг, определяющий тип проигрывания устройства. В Таблице 1 приведён список значений этого параметра для каждого устройства, а в Таблице 2 даны пояснения для этих значений.&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3VxOv1xLfCyDH8SvXm7hSl4LjhyDb1FU0EgvpD2xa0fxLtyFrolZY-vddjbMob_HiCBYEaJoZL1wFpg3ZiyXW3BLum_7-iDrxc6kh5Rd01fEXsokgnJ93byViPmNyZwJd7VCsp1GKTz4/s400/tab1.GIF&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5140458184941786290&quot; /&gt;&lt;br/&gt;&lt;br/&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTRyrujNaOZAj-wdiO1NSA4yDbyvbp2jL4xrJmUPvF0YyVJ2X3yrjBePEVy9dKJu8Nkb5426RvFWh0x0UnCP93E9NItKFpb9C8JOsVyDdmjmjv5H1f96XV1AKMhKxO3d4e3kYe38xBaJc/s400/tab2.GIF&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5140458184941786306&quot; /&gt;&lt;br/&gt;&lt;br/&gt;Пример:&lt;br/&gt;&lt;i&gt;mciSendString(&#39;play cdaudio&#39;, nil, 0, 0);&lt;/i&gt; - музыкальный компакт-диск начинает проигрываться либо с начала, либо с позиции, зафиксированной командой &quot;Пауза&quot;.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;br/&gt; Данная команда служит для определения различных параметров. Параметров много, поэтому все их приводить не буду. Остановлюсь лишь на командах для музыкальных компакт-дисков. &lt;br/&gt;&lt;ul&gt;&lt;li&gt;c&lt;i&gt;daudio type track number&lt;/i&gt; – для определения типа дорожки с номером number&lt;br/&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;current track &lt;/i&gt;– для определения номера текущей композиции length – для определения длины диска  length track number – для определения длины композиции с номером number media present – для определения наличия диска в CD-ROM mode – для определения состояния проигрывания: &lt;i&gt;playing, stopped, paused, open, not ready, parked, recording или seeking&lt;/i&gt;.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;number of tracks&lt;/i&gt; – для определения количества дорожек на диске position – для определения текущей позиции диска position track number – для определения начальной позиции дорожки с номером number ready – возвращает истину, если устройство может принимать другие команды start position – начальная позиция диска&lt;br/&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;time format&lt;/i&gt; – формат времени, используемый в данной сессии работы с устройством.&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br/&gt;     На этом закончим с теорией и перейдём к практике. Напишем при помощи функции mciSendString проигрыватель музыкальных компакт-дисков. Конечно, мы рассмотрели не все команды, которые нам понадобятся, но, я думаю, что проблем не возникнет, т.к. остальные команды достаточно просты в употреблении.&lt;br/&gt; Создайте в Delphi новый проект и приведите форму к нужному виду (см. рис.1).&lt;br/&gt;&lt;br/&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2mQLyocLjz0uTPfln4mo_WTBD-gkd72lTOI3R-Mf9DDkYxInxrihMFc56CWATW5QoTwti8qYGUab-NBklCdbxZJbdezw_X7-eHhx9h7NZXKksdYVUOhbXw5YnD-WQLbD1ed8m_73Rsc0/s400/pic1.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5140458180646818978&quot; /&gt;&lt;br/&gt;&lt;br/&gt;Для этого понадобятся следующие компоненты: TLabel (5 штук), TButton (7 штук), TListBox, TTrackBar и TTimer. К списку модулей добавьте &lt;i&gt;MMSystem&lt;/i&gt;. Теперь объявите две глобальные переменные:&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    sbReturn: &lt;strong&gt;array&lt;/strong&gt; [1..64] &lt;strong&gt;of&lt;/strong&gt; char; //для возвращаемых значений&lt;br/&gt;    com: pchar; //посылаемая команда&lt;br/&gt;&lt;br/&gt;После этого можно писать функции для управления проигрыванием:&lt;br/&gt;//переход к дорожке с номером Track&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; gototrack(Track: integer);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    com:pchar;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    //установка формата времени в &quot;Дорожка:Минуты:Секунды:Фреймы&quot;&lt;br/&gt;    com:=&#39;set cdaudio time format tmsf&#39;;&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    //начинаем проигрывание дорожки Track&lt;br/&gt;    com:=pchar(&#39;play cdaudio from &#39;+inttostr(Track));&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    //устанавливаем формат времени в миллисекунды&lt;br/&gt;    com:=&#39;set cdaudio time format ms&#39;;&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//получение номера текущей композиции&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; GetCurrentTrack:byte;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    com:pchar;&lt;br/&gt;    st:string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    result := 0;&lt;br/&gt;    com := &#39;status cdaudio current track wait&#39;;&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (mciSendString(com, @sbReturn, 64, 0) &lt;&gt; 0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;        exit;&lt;br/&gt;    st := trim(sbReturn);&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (length(st) &gt; 0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;        result := strtoint(st);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//количество композиций на диске&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; GetTracksCnt: integer;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;   st:string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;   result := 0;&lt;br/&gt;   com := &#39;status cdaudio number of tracks wait&#39;;&lt;br/&gt;  &lt;strong&gt; if&lt;/strong&gt; (mciSendString(com, @sbReturn, 64, 0) &lt;&gt; 0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;      exit;&lt;br/&gt;   st := trim(sbreturn);&lt;br/&gt;   &lt;strong&gt;if&lt;/strong&gt; (length(st) &gt; 0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;      result := strtoint(st);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//переход к следующей композиции&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; NextTrack;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;   cur:integer;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    cur:=GetCurrentTrack;&lt;br/&gt;    //если текущая композиция – последняя, то переходим к первой&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (cur &lt;&gt;then&lt;br/&gt;        GoToTrack(cur+1)&lt;br/&gt;    &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;        GoToTrack(1);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//переход к предыдущей композиции&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; PrevTrack;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    cur:integer;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    cur := getcurrentTrack;&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (cur &gt; 1)&lt;strong&gt; then&lt;/strong&gt;&lt;br/&gt;        GoToTrack(cur-1)&lt;br/&gt;    //если текущая композиция – первая, то переходим к последней  &lt;br/&gt;    &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;        GoToTrack(GetTracksCnt);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//длина композиции&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; GetTrackLength(Track: integer): string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    com := pchar(&#39;status cdaudio length track &#39;+inttostr(Track)+&#39; wait&#39;);&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    result := trim(sbReturn);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//длина диска&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; GetCDLength:string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    com := pchar(&#39;status cdaudio length wait&#39;);&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    result := trim(sbReturn);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//статус проигрывания&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; GetStatus:string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    com := &#39;status cdaudio mode wait&#39;;&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    result := trim(sbReturn);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//есть ли диск&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; IsCDReady:string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    com := &#39;status cdaudio ready wait&#39;;&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    result := trim(sbReturn);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//Начать проигрывание&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; PlayCD;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    mciSendString(&#39;play cdaudio&#39;, @sbReturn, 64, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//Пауза&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; PauseCD;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    mciSendString(&#39;pause cdaudio wait&#39;, @sbReturn, 64, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//Остановить проигрывание&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; StopCD;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    mciSendString(&#39;stop cdaudio wait&#39;, @sbReturn, 64, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//начальная позиция композиции&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; GetTrackPos(Track:word): string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    com := pchar(&#39;status cdaudio position track &#39;+inttostr(Track)+&#39; wait&#39;);&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    result := trim(sbReturn);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//текущая позиция диска&lt;br/&gt;&lt;strong&gt;function&lt;/strong&gt; GetCDPos: string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    com := pchar(&#39;status cdaudio position wait&#39;);&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    result := trim(sbReturn);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;А теперь напишем обработчики различных событий для компонентов:&lt;br/&gt;//инициализируем устройство при загрузке&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.FormCreate(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    mciSendString(&#39;open cdaudio&#39;, @sbReturn, 64, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//при выходе закрываем устройство&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.FormDestroy(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    mciSendString(&#39;close cdaudio wait&#39;, @sbReturn, 64, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;{при появлении формы записываем&lt;br/&gt; в ListBox список композиций}&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.FormShow(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;   i: word;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;for&lt;/strong&gt; i := 1 &lt;strong&gt;to&lt;/strong&gt; GetTracksCnt &lt;strong&gt;do&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        Listbox1.Items.Add(inttostr(i)+&#39;  &#39;+GetTrackLength(i));&lt;br/&gt;    &lt;strong&gt;end;&lt;br/&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//кнопка Play&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button1Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    PlayCD;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//кнопка Pause&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button2Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    PauseCD;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//кнопка Stop&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button3Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    StopCD;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//кнопка Next (следующая композиция)&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button4Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    NextTrack;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//кнопка Prev (переход к предыдущей композиции)&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button5Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    PrevTrack;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//процедура для таймера, повторяющаяся каждую секунду&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Timer1Timer(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    cur, i: word;&lt;br/&gt;    st: string;&lt;br/&gt;    cnt: byte;&lt;br/&gt;    hour: word;&lt;br/&gt;    min, sec: byte;&lt;br/&gt;    t: integer;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    //выводим состояние проигрывания&lt;br/&gt;    label5.Caption:=&#39;Состояние: &#39;+GetStatus;&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (GetStatus &lt;&gt;&#39;playing&#39;) &lt;strong&gt;and&lt;/strong&gt;&lt;br/&gt;            (GetStatus&lt;&gt;&#39;stopped&#39;) &lt;strong&gt;and&lt;/strong&gt;&lt;br/&gt;            (GetStatus&lt;&gt;&#39;paused&#39;) &lt;strong&gt;then&lt;/strong&gt; exit;&lt;br/&gt;    //устанавливаем формат времени в миллисекунды&lt;br/&gt;    com:=&#39;set cdaudio time format ms wait&#39;;&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    cur:=GetCurrentTrack;&lt;br/&gt;    //выделяем в списке композиций текущую&lt;br/&gt;    ListBox1.ItemIndex:=cur-1;&lt;br/&gt;    {выводим формат времени, эти строки только для примера, т.к. мы сами недавно   установили формат в миллисекунды}&lt;br/&gt;    com:=&#39;status cdaudio time format wait&#39;;&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    //выводим информацию информацию&lt;br/&gt;    label2.Caption:=&#39;Формат времени: &#39;+trim(sbReturn);&lt;br/&gt;    label3.Caption:=&#39;Начальная позиция: &#39;+GetTrackPos(cur);&lt;br/&gt;    label4.Caption:=&#39;Текущая позиция: &#39;+GetCDPos;&lt;br/&gt;    {устанавливаем ползунок TrackBar&#39;a в нужную позицию, соответствующую текущему   положению проигрываемой композиции}&lt;br/&gt;    TrackBar1.Max:=strtoint(GetTrackLength(cur)) div 1000;&lt;br/&gt;    t:=strtoint(GetCDPos)-strtoint(GetTrackPos(cur));&lt;br/&gt;    t:=t &lt;strong&gt;div&lt;/strong&gt; 1000;&lt;br/&gt;    TrackBar1.Position:=t;&lt;br/&gt;    hour:=t &lt;strong&gt;div&lt;/strong&gt; 3600;&lt;br/&gt;    t:=t &lt;strong&gt;mod&lt;/strong&gt; 3600;&lt;br/&gt;    min:=t &lt;strong&gt;div&lt;/strong&gt; 60;&lt;br/&gt;    t:=t &lt;strong&gt;mod&lt;/strong&gt; 60;&lt;br/&gt;    sec:=t;&lt;br/&gt;    st:=format(&#39;%d:%d&#39;,[min,sec]);&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (hour &gt; 0) &lt;strong&gt;then&lt;/strong&gt; &lt;br/&gt;      st:=inttostr(hour)+&#39;:&#39;+st;&lt;br/&gt;    //выводим время проигрывания текущей композиции&lt;br/&gt;    label1.Caption:=st;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//при двойном щелчке по композиции из списка начинаем её проигрывание&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.ListBox1DblClick(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    GoToTrack(ListBox1.ItemIndex+1);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//перемотка композиции на 5 секунд вперёд&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button6Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    t: integer;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    t := strtoint(GetCDPos)+5000;&lt;br/&gt;    StopCD; &lt;br/&gt;    com := pchar(&#39;seek cdaudio to &#39;+inttostr(t)+&#39; wait&#39;);&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    PlayCD;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;//перемотка композиции на 5 секунд назад&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button7Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    t: integer;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    t := strtoint(GetCDPos)-5000;&lt;br/&gt;    StopCD;&lt;br/&gt;    com := pchar(&#39;seek cdaudio to &#39;+inttostr(t)+&#39; wait&#39;);&lt;br/&gt;    mciSendString(com, @sbReturn, 64, 0);&lt;br/&gt;    PlayCD;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;    Вот и готов CD-проигрыватель, написанный на достаточно низком уровне при помощи, в принципе, всего одной функции, вынесенной в заглавие статьи. Вот такая вот функция! А ведь она может не только с музыкальным компакт-диском управляться: не следует забывать и про видеодиски, устройства записи и проигрывания мультимедиа и т.п. &lt;br/&gt;Конечно, в CD-проигрывателе почти отсутствует контроль ошибок, и некоторые участки кода можно оптимизировать, но свою функцию эта программа в данной статье выполняет: демонстрирует применение функции &lt;i&gt;mciSendString&lt;/i&gt; для различных задач.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;&lt;i&gt;&lt;span&gt;Иван Ширко&lt;/span&gt;&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2007/12/mcisendstring.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3VxOv1xLfCyDH8SvXm7hSl4LjhyDb1FU0EgvpD2xa0fxLtyFrolZY-vddjbMob_HiCBYEaJoZL1wFpg3ZiyXW3BLum_7-iDrxc6kh5Rd01fEXsokgnJ93byViPmNyZwJd7VCsp1GKTz4/s72-c/tab1.GIF" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-6566009490781890802</guid><pubDate>Mon, 03 Dec 2007 10:09:00 +0000</pubDate><atom:updated>2008-12-08T13:57:35.026-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">MSAgent</category><title>Microsoft Agent. Часть II</title><description>В &lt;a href=&quot;http://ishirko.blogspot.com/2007/11/microsoft-agent-i.html&quot;&gt;прошлой части&lt;/a&gt; мы научились применять технологию Microsoft Agent в web-страничках. В этот раз мы будем работать с Delphi. Убедитесь, что установлены все необходимые компоненты (&lt;a href=&quot;http://ishirko.blogspot.com/2007/11/microsoft-agent-i.html&quot;&gt;см. первую часть&lt;/a&gt;) и можно отправляться в увлекательное путешествие по миру MsAgent.&lt;br/&gt;Запустите Delphi и в меню &quot;Component&quot; выберите пункт &quot;Import ActiveX Control…&quot;. В появившемся диалоговом окне нужно выделить строку &quot;Microsoft Agent Control…&quot; и нажать кнопку &quot;Install&quot;. Далее произойдёт стандартный процесс установки нового компонента. После окончания инсталляции создайте новое приложение и поместите на форму полученный компонент –  Agent1:TAgent (он должен находиться на закладке ActiveX).&lt;br/&gt;Вот этот вот почти «ноль-ноль-семь» будет помогать нам создавать приложения, которые будут работать с технологией MsAgent. Начнём с небольшого примера, с маленького костяка, который можно будет использовать при разработке более сложных программ.&lt;span class=&quot;fullpost&quot;&gt;&lt;br/&gt;Установите свойству Connected компонента Agent1 значение True, затем объявите две глобальные переменные:&lt;br/&gt;&lt;strong&gt;Var&lt;/strong&gt;&lt;br/&gt;&lt;span&gt;   //для хранения персонажа&lt;/span&gt;&lt;br/&gt;      Character: IAgentCtlCharacterEx;&lt;br/&gt;  &lt;span&gt;//для получения состояния персонажа&lt;/span&gt;&lt;br/&gt;      Request: IAgentCtlRequest;&lt;br/&gt;&lt;br/&gt;  Для события OnCreate формы запишите процедуру:&lt;br/&gt;  &lt;strong&gt;procedure&lt;/strong&gt; TForm1.FormCreate(Sender: TObject);&lt;br/&gt;  &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;   &lt;span&gt; &lt;span&gt;//загружаем персонаж «Джин»&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;      Request := Agent1.Characters.Load(&#39;genie&#39;, &#39;genie.acs&#39;);&lt;br/&gt;    &lt;span&gt;//получаем объект персонажа Джин&lt;/span&gt;&lt;br/&gt;      Character := Agent1.Characters.Character(&#39;genie&#39;)as IAgentCtlCharacterEx;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//Джин появляется&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;      Request := Character.Show(False);&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//Джин здоровается и вкратце рассказывает о себе&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    Request := Character.Speak(&#39;Здравствуйте! &#39;+Сharacter.Description, EmptyParam);&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//Джин играет анимацию «Greet»&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;      Request:=Character.Play(&#39;Greet&#39;);&lt;br/&gt;  &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;При закрытии формы нужно выгрузить персонаж:&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.FormClose(Sender: TObject; &lt;strong&gt;var&lt;/strong&gt; Action: TCloseAction);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    Agent1.Characters.Unload(‘genie’);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt; Если запустить эту программу, то вместе с формой появится Джин, который поздоровается и на несколько секунд застынет в приветственном поклоне. Теперь будем дополнять данный пример.&lt;br/&gt; Как уже упоминалось в первой части, персонажи умеют проигрывать различные анимации, при этом для каждого персонажа могут определяться свои анимации. Поэтому иногда требуется получить все допустимые анимации для персонажа, что и делает следующая процедура:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; GetAgentAnim(st: TStrings);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    AnEnum: IEnumVariant;&lt;br/&gt;    flag: Cardinal;&lt;br/&gt;    V: OleVariant;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;&lt;span&gt;  &lt;span&gt;//получаем интерфейс анимаций агента&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    AnEnum := (Character.AnimationNames.Enum) as IEnumVariant;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//Сбрасываем указатель списка на начало&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    AnEnum.Reset;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//перебираем все анимации и добавляем их в наш список&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    &lt;strong&gt;repeat&lt;/strong&gt;&lt;br/&gt;        AnEnum.Next(1, V, flag);&lt;br/&gt;        &lt;strong&gt;if&lt;/strong&gt; (VarToStr(V) &lt;&gt; &#39;&#39;) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;            st.Add(V);&lt;br/&gt;    &lt;strong&gt;until&lt;/strong&gt; (flag = 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt; Давайте проверим работоспособность данной процедуры. Добавьте на форму кнопку Button1 и список ListBox1. Дайте заголовок кнопке «Список анимаций» и запишите процедуру обработки её нажатия:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button1Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    GetAgentAnim(ListBox1.Items);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Данная процедура записывает список анимаций загруженного персонажа в компонент &lt;i&gt;ListBox1&lt;/i&gt;. А теперь сделаем так, чтобы при двойном щелчке мышкой по ListBox’у Джин проигрывал выбранную анимацию:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.ListBox1DblClick(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    Request := Character.Play(ListBox1.Items[ListBox1.ItemIndex]);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt; Теперь посмотрим, зачем нам переменная Request (её мы объявили как глобальную). Именно она служит для синхронизации действий персонажа (либо персонажей, если их несколько). Интерфейс IAgentCtlRequest имеет одно очень полезное свойство – Status. В зависимости от состояния запроса, который в данный момент выполняет персонаж, это свойство принимает следующие значения:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Status | &lt;/strong&gt;&lt;strong&gt;Пояснения&lt;/strong&gt;&lt;br/&gt;  0             Запрос успешно выполнен&lt;br/&gt;  1             Запрос «провалился»&lt;br/&gt;  2             Запрос не выполняется, т.к. ждёт завершения обработки других запросов&lt;br/&gt;  3             Запрос прерван&lt;br/&gt;  4             Запрос обрабатывается&lt;br/&gt;&lt;br/&gt;На основе этой таблички легко написать процедуру, которая будет дожидаться выполнения всех запросов к персонажу, а затем вернёт программе управление:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; WaitFor(Request:IAgentCtlRequest);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;      &lt;strong&gt;repeat&lt;/strong&gt;&lt;br/&gt;          Application.ProcessMessages;&lt;br/&gt;          Status := Request.Status;&lt;br/&gt;      &lt;strong&gt;until&lt;/strong&gt; (Request.Status &lt;&gt; 2) and (Request.Status &lt;&gt; 4);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Для примера добавьте на форму кнопку «Пример WaitFor»:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button3Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;  &lt;span&gt;&lt;span&gt;//Джин произносит фразу&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    Request := Character.Speak(&#39;Доброе утро&#39;, EmptyParam);&lt;br/&gt;    &lt;strong&gt;&lt;span&gt;&lt;span&gt;{waitfor(Request);}&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;br/&gt;  &lt;span&gt;&lt;span&gt;//Показываем сообщение&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    ShowMessage(&#39;Всё&#39;);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;Если нажать на кнопку, то Джин начнёт говорить и сразу же появится сообщение. А если снять комментарии со строки waitfor(Request);, то сообщение появится только после того, как Джин закончит говорить.&lt;br/&gt; А сейчас «научим» Джина вслух произносить текущее время. Для этого ему нельзя подсунуть строку типа «21 час 44 минуты 32 секунды», эту строку он произнесёт так: «двадцать один час, сорок четвёртого минуты, тридцать второго секунды». В связи с этим, Джину нужно полностью «разжевать», что именно он должен произносить. Так что будем давать ему такую строку: «21 час, 44 минуты, 30 две секунды». Т.е. число, стоящее в женском роде (32 секунды),  разделяем на составляющие (30 две секунды).&lt;br/&gt; Добавьте на форму очередную кнопку «Сколько времени?» и запишите следующую процедуру:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button1Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;    buf, str: string;&lt;br/&gt;    Hour, Min, Sec, Msec: Word;&lt;br/&gt;    Hours, Mins, Secs: string;&lt;br/&gt;    hs, ms, ss: string;&lt;br/&gt;    DT: TDateTime;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;    hs := &#39;&#39;;&lt;br/&gt;    ms := &#39;&#39;;&lt;br/&gt;    ss := &#39;&#39;;&lt;br/&gt;   &lt;span&gt; &lt;span&gt;//узнаём текущее время&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    DT := Now;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//разбиваем его на составляющие&lt;/span&gt;&lt;/span&gt; &lt;br/&gt;    DecodeTime(DT, Hour, Min, Sec, MSec);&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//смотрим, какое окончание должно быть у слова «час»&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    &lt;strong&gt;case&lt;/strong&gt; hour &lt;strong&gt;of&lt;/strong&gt;&lt;br/&gt;        2..4, 22, 23: hs := &#39;а&#39;;&lt;br/&gt;        0, 5..20: hs := &#39;ов&#39;;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//окончание слова «минута»&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    &lt;strong&gt;case&lt;/strong&gt; min &lt;strong&gt;of&lt;/strong&gt;&lt;br/&gt;        1, 21, 31, 41, 51: ms := &#39;а&#39;;&lt;br/&gt;        2..4, 22..24, 32..34, 42..44, 52..54: ms := &#39;ы&#39;;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;   &lt;span&gt; &lt;span&gt;//окончание слова «секунда»&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    &lt;strong&gt;case&lt;/strong&gt; sec &lt;strong&gt;of&lt;/strong&gt;&lt;br/&gt;        1, 21, 31, 41, 51: ss := &#39;а&#39;;&lt;br/&gt;        2..4, 22..24, 32..34, 42..44, 52..54: ss := &#39;ы&#39;;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//часы не будем преобразовывать, т.к. слово «час» мужского рода&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    hours := inttostr(hour);&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//при необходимости разбиваем минуты на слова&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    mins := inttostr(min);&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (mins[length(mins)] = &#39;1&#39;) &lt;strong&gt;and&lt;/strong&gt; (min &lt;&gt; 11) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        &lt;strong&gt;if&lt;/strong&gt; (min &gt; 10) &lt;strong&gt;then&lt;/strong&gt; buf := mins[1] + &#39;0 &#39;&lt;br/&gt;        &lt;strong&gt;else&lt;/strong&gt; buf:=&#39;&#39;;&lt;br/&gt;        mins := buf + &#39;одна&#39;;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        &lt;strong&gt;if&lt;/strong&gt; (mins[length(mins)]=&#39;2&#39;) &lt;strong&gt;and&lt;/strong&gt; (min&lt;&gt;12) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;        &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;            &lt;strong&gt;if&lt;/strong&gt; (min&gt;10) &lt;strong&gt;then&lt;/strong&gt; buf:=mins[1]+&#39;0 &#39;&lt;br/&gt;            &lt;strong&gt;else&lt;/strong&gt; buf:=&#39;&#39;;&lt;br/&gt;            mins := buf + &#39;две&#39;;&lt;br/&gt;        &lt;strong&gt;end&lt;br/&gt;    end&lt;/strong&gt;;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//при необходимости разбиваем секунды на слова&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    secs := inttostr(sec);&lt;br/&gt;    &lt;strong&gt;if&lt;/strong&gt; (secs[length(secs)]=&#39;1&#39;) &lt;strong&gt;and&lt;/strong&gt; (sec&lt;&gt;11) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        &lt;strong&gt;if&lt;/strong&gt; (sec&gt;10) &lt;strong&gt;then&lt;/strong&gt; buf := secs[1] + &#39;0 &#39;&lt;br/&gt;        &lt;strong&gt;else&lt;/strong&gt; buf := &#39;&#39;;&lt;br/&gt;        secs := buf + &#39;одна&#39;;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;else&lt;/strong&gt;&lt;br/&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;        &lt;strong&gt;if&lt;/strong&gt; (secs[length(secs)]=&#39;2&#39;)  &lt;strong&gt;and&lt;/strong&gt;(sec&lt;&gt;12) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;        &lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;            &lt;strong&gt;if&lt;/strong&gt; (sec&gt;10)&lt;strong&gt; then&lt;/strong&gt; buf := secs[1] + &#39;0 &#39;&lt;br/&gt;            &lt;strong&gt;else&lt;/strong&gt; buf:=&#39;&#39;;&lt;br/&gt;            secs := buf + &#39;две&#39;;&lt;br/&gt;        &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    &lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//составляем строку, которую должен произнести Джин&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    str := hours + &#39; час&#39; + hs+ &#39;, &#39; + mins + &#39; минут&#39; + ms + &#39;, &#39; + secs + &#39; секунд&#39; + ss;&lt;br/&gt;    &lt;span&gt;&lt;span&gt;//Джин произносит строку str, а над ним отображается текущее время (рис.1)&lt;/span&gt;&lt;/span&gt;&lt;br/&gt;    Request := Character.Speak(&#39;\Pit=18400\\Spd=100\\Map=&quot;&#39;+str+&#39;&quot;=&quot;&#39;+timetostr(DT)+&#39;&quot;\&#39;,EmptyParam);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoebkOGEpgvCC3pu75fqLfvzqufZbW7X89tFD_V60z_XoiKMcDckjEtMkGQc5OnqQIVe_QMWv6ng-KYKoJErp1ar3khhy6-ozLVVYMZi0kR2rkeKEn6WOQWZ72KtxQYdoK_GRQbY-AmxM/s400/Pic_1.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5139689884012008562&quot; /&gt;&lt;br/&gt;&lt;br/&gt; Напоследок рассмотрим некоторые параметры голосового движка. На один компьютер можно установить поддержку нескольких языков. Чтобы переключаться между ними, нужно изменять параметр персонажа LanguageID. В таблице приведены идентификаторы к некоторым языкам. Символ «$» означает, что число представлено в шестнадцатеричной системе счисления.               &lt;br/&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN0Z8gR555cS29XJWhFmBL2_PIl71M-SjKDppTIfA7T5Tgm3VFPJ6TVfn86qCtaQhZ6s8cLogohp4AbBbC3DcCfX-BzYKigLNmuR6z3P4ekCjYsTW8vPxd7jMRF0kO9w_KlKibJnE3TqI/s400/tab1.gif&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5139690064400635010&quot; /&gt;&lt;br/&gt;&lt;br/&gt;&lt;i&gt;Пример: Character.LanguageID := $409;&lt;/i&gt; – переключаемся на английский язык.&lt;br/&gt; Ещё можно изменять сам голос. Для этого есть свойство TTSModeID.  Ниже приведён список голосов для русского и английского языков.&lt;br/&gt;&lt;span&gt;&lt;br/&gt;&lt;/span&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU8ETHGg5PO3gBdMNhwjrbp3Vi1_7FGDJhGMRwPq-Azp35AysqimhXJJdV-V2D_WVrrni5lWhduBdMCP8ZW4Ia40ru8yQyFaflxO4gZ_ur9dFMv9QF_aZfEmp9kSdRO0utb1ecXuvn80w/s400/tab2.gif&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5139690219019457682&quot; /&gt;&lt;span&gt;&lt;br/&gt;&lt;/span&gt;&lt;br/&gt;Пример: &lt;br/&gt;&lt;i&gt;Сharacter.TTSModeID:=&#39;{06377F80-D48E-11d1-B17B-0020AFED142E}&#39;;&lt;/i&gt; –&lt;br/&gt;устанавливает женский голос для русского языка. Так что можете поиздеваться над Джином, заставляя его разговаривать женским голосом. &lt;br/&gt; На сегодня всё, в следующей части мы научимся управлять Джином при помощи голосовых команд.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;&lt;i&gt;&lt;span&gt;&lt;span&gt;Иван Ширко&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;br/&gt;&lt;/a&gt;&lt;/span&gt;&lt;br/&gt;</description><link>http://ishirko.blogspot.com/2007/12/microsoft-agent-ii.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoebkOGEpgvCC3pu75fqLfvzqufZbW7X89tFD_V60z_XoiKMcDckjEtMkGQc5OnqQIVe_QMWv6ng-KYKoJErp1ar3khhy6-ozLVVYMZi0kR2rkeKEn6WOQWZ72KtxQYdoK_GRQbY-AmxM/s72-c/Pic_1.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-5699379702224686161</guid><pubDate>Fri, 30 Nov 2007 18:52:00 +0000</pubDate><atom:updated>2007-12-07T01:19:16.532-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">web-разработка</category><title>Джентльменский набор web-разработчика</title><description>Сейчас огромное количество людей имеет доступ к интернету. И многим пользователям в один прекрасный день приходит в голову мысль о создании собственного представительства в этой необъятной сети. Тогда пользователь при помощи HTML-редактора создаёт свою домашнюю страничку. Через некоторое время, если энтузиазм не закончится, происходит переход на более мощную программу для редактирования web-страниц, в которой переделывается первоначальная версия сайта. Большинство на этом этапе останавливаются, но некоторые пользователи пытаются улучшить свой сайт и через некоторое время натыкаются  на проблемы, которые HTML, даже динамический, решить не в состоянии. А значит, настало время переходить на скриптовые web-языки программирования. И вот тут-то и возникает проблема отладки скриптов. Конечно, можно закачивать их на сервер и тестировать в самых, что ни на есть реальных условиях. Но, как известно, программы без ошибок сразу не пишутся, поэтому закачивать на сервер свои скрипты придётся не один и даже не десять раз. Так что к затратам на интернет добавятся и временные затраты. Поэтому web-разработчики устанавливают себе локальные web-серверы, которые позволяют безо всякого интернета запускать различные скрипты.&lt;br /&gt;         Самым популярным web-сервером на сегодняшний день является Apache. Но не каждый, даже продвинутый пользователь сможет корректно настроить его и подключить все необходимые модули. К тому же для установки потребуется скачать более 10 Мб, а интернет – удовольствие не бесплатное.&lt;br /&gt;         В связи с вышеизложенным хочу обратить внимание начинающих, да и не только начинающих, web-разработчиков на пакет «Джентльменский набор web-разработчика», или коротко &amp;shy;– Денвер. Данный пакет включает в себя весь комплекс программ, необходимый для комфортной и эффективной отладки любых сайтов. Вот состав базового комплекта:&lt;br /&gt;1. Сам web-сервер Apache;&lt;br /&gt;2. PHP;&lt;br /&gt;3. MySQL;&lt;br /&gt;4. phpMyAdmin – панель   управления   базой  данных MySQL;&lt;br /&gt;5. Perl (без модулей);&lt;br /&gt;6. Отладочная &quot;заглушка&quot; для sendmail. То есть, если скрипт отправляет письмо, то оно не отправляется, а записывается в текстовый файл.&lt;br /&gt;И вот этот базовый комплект занимает чуть больше 2 Мб! Давайте посчитаем, сколько всё это должно занимать места при обычной установке всех этих приложений:&lt;br /&gt;·        Apache » 4 Мб;&lt;br /&gt;·        PHP4 » 5,5 Мб;&lt;br /&gt;·        ActivePerl » 8,5 Мб;&lt;br /&gt;·        MySQL » 12,5 Мб.&lt;br /&gt;·        PhpMyAdmin » 1 Мб.&lt;br /&gt;Итого: »31,5 MB. Правда, обычно PHP и Perl вместе не используются, так что можно отнять мегабайт  семь, но всё равно цифра получается довольно впечатляющей, особенно на фоне качества наших телефонных линий. Как же удалось уместить всё это в двух мегабайтах? Во-первых, были удалены редко используемые компоненты и документация. Также, за ненадобностью были удалены инструкции установки и всякие истории развития продуктов. После чего всё это упаковали очень мощным архиватором – 7-zip. Конечно, если вам вдруг понадобится документация или дополнительные модули, то их можно найти в разнообразных расширениях. Вот так вот практически без потери функциональности  размер дистрибутива сокращён в десятки раз. Но сокращение размера, на мой взгляд, не самое главное достоинство Денвера.&lt;span class=&quot;fullpost&quot;&gt; Основное преимущество этого джентльменского набора в очень лёгкой и быстрой установке и настройке всех модулей. Нужно просто запустить программу установки и после нескольких несложных шагов (выбор папки, способ запуска сервера и т.п.) Apache полностью настроен и готов к работе. При этом Денвер ничего не записывает в реестр, никаких новых файлов в системных директориях у вас тоже не появится. Более того, можно даже просто переместить Денвер в другой каталог и он всё равно будет нормально функционировать.&lt;br /&gt;         Ну а теперь пара слов о работе Денвера. При запуске создаётся виртуальный локальный диск, например, Z: (созданием виртуальных дисков в Windows занимается утилита subst), который ассоциируется с каталогом Денвера. Затем последовательно запускаются все программы. После завершения работы восстанавливаются прежние настройки системы. Особенно меня порадовала поддержка Денвером виртуальных хостов, т.е. когда на одном компьютере ведётся работа с несколькими локальными сайтами. Для добавления нового хоста нужно просто в соответствующем каталоге создать новую папку, перезапустить сервер и всё! Денвер сам сконфигурирует Apache и внесёт необходимые изменения в файл …\Windows\hosts. Для тех же, кто любит вручную копаться в различных параметрах, все комментарии в настроечных файлах переведены на великий и могучий и, главное, понятный русский язык. Ну и напоследок хочу сказать, что авторы Денвера активно сотрудничают с пользователями и, учитывая их вопросы и предложения, постоянно развивают свой джентльменский набор.&lt;br /&gt;         Скачать Денвер можно отсюда: &lt;a href=&quot;http://dklab.ru/chicken/web/dis/Base/&quot;&gt;http://dklab.ru/chicken/web/dis/Base/&lt;/a&gt;. А на самом сайте &lt;a href=&quot;http://dklab.ru/&quot;&gt;http://dklab.ru/&lt;/a&gt; можно найти много интересного про Денвер в частности и про создание динамических сайтов вообще.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color:#666666;&quot;&gt;&lt;strong&gt;&lt;em&gt;Иван Ширко&lt;br /&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2007/11/web.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-5334278068152507478</guid><pubDate>Thu, 29 Nov 2007 08:29:00 +0000</pubDate><atom:updated>2008-12-08T13:57:35.408-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Winamp</category><category domain="http://www.blogger.com/atom/ns#">Сделай сам</category><title>Сделай сам: Управление Winamp</title><description>&lt;div align=&quot;justify&quot;&gt;В этот раз мы поговорим об управлении популярнейшим аудио-плеером, имя которому – Winamp. Благодаря своей нулевой цене, поддержке скинов и, что самое главное, плагинов, Winamp установлен на огромном количестве ПК. И этим программным шедевром Nullsoft, оказывается, можно довольно легко управлять программно. В связи с этим, большинство soft-каталогов не обходится без пары-тройки программ управления Winamp’ом. Давайте рассмотрим, что же происходит в недрах таких программ.&lt;br/&gt;&lt;/div&gt;Winamp поддерживает большое количество сообщений, которые можно послать его окну при помощи функции&lt;br/&gt;SendMessage(&lt;br/&gt;HWND:hWnd, &lt;span&gt;// идентификатор окна&lt;/span&gt;&lt;br/&gt;Msg:Integer, &lt;span&gt;// посылаемое сообщение&lt;/span&gt;&lt;br/&gt;WParam:Integer, &lt;span&gt;// первый параметр сообщения&lt;/span&gt;&lt;br/&gt;LParam:Integer &lt;span&gt;// второй параметр сообщения&lt;/span&gt;&lt;br/&gt;);&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;Winamp поддерживает два основных типа сообщения (параметр Msg):&lt;br/&gt;– &lt;em&gt;WM_COMMAND&lt;/em&gt;: служит только для подачи определённых команд Winamp’у (Play, Stop, Next, Close и т.д.);&lt;br/&gt;– &lt;em&gt;WM_USER&lt;/em&gt;: используется не только для выполнения определённых действий, но и для определения различной информации (версия, текущая композиция, количество композиций и т.д.).&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5138183051801039650&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFhkKr3dGrt5Hc-iBRHBNvu7JHHGSMEOxdzpCnnN48lTloCkkurbcDD-QE4p6RYQIpP-cBpAmRLiyO7cElyV77-u3_kBCuxyK9FN0TJ6A9IQSblUs2puApQ4X23KLdfBhFiX6LNby2ssM/s400/table1.GIF&quot; border=&quot;0&quot; /&gt; &lt;br/&gt;В таблице1 приведены основные константы для первого параметра сообщения WM_COMMAND. Для их использования запишите процедуру:&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; WinampCommand(Command:Integer);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;&lt;span&gt;//поиск окна Winamp’a&lt;/span&gt;&lt;br/&gt;WinampHWND := findwindow(&#39;Winamp v1.x&#39;,nil);&lt;br/&gt;&lt;span&gt;//если поиск успешен,то посылаем сообщение&lt;/span&gt;&lt;br/&gt;&lt;strong&gt;if&lt;/strong&gt; (WinampHWND &lt;&gt; 0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;SendMessage(WinampHWND, WM_Сommand, Command, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;Теперь для подачи сообщения типа WM_COMMAND нужно выбрать из таблицы понравившуюся константу и передать её в качестве параметра процедуре WinampCommand. Пример:&lt;br/&gt;&lt;em&gt;WinampCommand(40044);&lt;/em&gt; – переход к предыдущей композиции.&lt;span class=&quot;fullpost&quot;&gt;&lt;br/&gt;&lt;div div=&quot;&quot;&gt;&lt;br/&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5138181303749350146&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7QwtbNgb68fhfmgkSNfS8_3uMhQyjutLwAWGoT7VL5C1JsoO0ap8oIV4nC5KYXQpSBevlmzLLKBDBGc1N6pb7HG2Q52OmGyuqXuPbkrEW8AwB5n0RGDkLGLB2JrM6EgUfpCvs6b9K9ww/s400/table1.GIF&quot; border=&quot;0&quot; /&gt; В Таблице2 перечислены основные константы для сообщений WM_USER. Для их использования запишите следующую функцию:&lt;br/&gt;&lt;strong&gt;Function&lt;/strong&gt; WinampUser(data: Integer, id: Integer):integer;&lt;br/&gt;&lt;strong&gt;begin&lt;br/&gt;&lt;/strong&gt;WinampHWND := findwindow(&#39;Winamp v1.x&#39;, &lt;strong&gt;nil&lt;/strong&gt;);&lt;br/&gt;&lt;strong&gt;if&lt;/strong&gt; (WinampHWND &lt;&gt; 0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;result := SendMessage(WinampHWND, WM_USER, data, id)&lt;br/&gt;&lt;strong&gt;else&lt;/strong&gt; result := -1;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;Пример: &lt;em&gt;WinampUser(1, 105);&lt;/em&gt; – возвращает длину текущей композиции в секундах.&lt;br/&gt;&lt;/div&gt;&lt;div&gt;Итак, управлять Winamp’ом мы научились, осталось только воплотить наши навыки в небольшую программу. &lt;/div&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5138183854959924018&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3KDP3KvESKW1Cyn3tkVjJXBoBNZ60U73NEq6pezQukOkjvn_aofT5wlfVJeWAotUZOM0t1B9I7VYyBLOjZDVgYPr95pufCbZzKvotc6nmQFqHggdoajN-OSqgDWEkONcTVJEQlvV4O9I/s400/pic1.jpg&quot; border=&quot;0&quot; /&gt; &lt;div&gt;&lt;strong&gt;unit&lt;/strong&gt; Unit1;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;interface&lt;/strong&gt;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;uses&lt;/strong&gt;&lt;br/&gt;Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Registry,&lt;br/&gt;StdCtrls;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;br/&gt;TForm1 = &lt;strong&gt;class&lt;/strong&gt;(TForm)&lt;br/&gt;Button1: TButton;&lt;br/&gt;Button2: TButton;&lt;br/&gt;Button3: TButton;&lt;br/&gt;Button4: TButton;&lt;br/&gt;Button5: TButton;&lt;br/&gt;Button6: TButton;&lt;br/&gt;Button7: TButton;&lt;br/&gt;Button8: TButton;&lt;br/&gt;Button9: TButton;&lt;br/&gt;Button10: TButton;&lt;br/&gt;Button11: TButton;&lt;br/&gt;Button12: TButton;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button1Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button2Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button3Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button4Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button5Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button6Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button7Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button8Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button9Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button10Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button11Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; Button12Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;private&lt;/strong&gt;&lt;br/&gt;{ Private declarations }&lt;br/&gt;&lt;strong&gt;public&lt;/strong&gt;&lt;br/&gt;{ Public declarations }&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;Form1: TForm1;&lt;br/&gt;reg:TRegistry;&lt;br/&gt;WinampHWND:hwnd;&lt;br/&gt;&lt;strong&gt;implementation&lt;/strong&gt;&lt;br/&gt;&lt;br/&gt;{$R *.DFM}&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Function&lt;/strong&gt; WinampUser(data: Integer; id: Integer):integer;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampHWND := findwindow(&#39;Winamp v1.x&#39;, nil);&lt;br/&gt;&lt;strong&gt;if&lt;/strong&gt; (WinampHWND &lt;&gt; 0) &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;result := SendMessage(WinampHWND, WM_USER, data,id)&lt;br/&gt;&lt;strong&gt;else&lt;/strong&gt; result := -1;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; WinampCommand(Command:Integer);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampHWND := findwindow(&#39;Winamp v1.x&#39;,nil);&lt;br/&gt;&lt;strong&gt;if&lt;/strong&gt; WinampHWND&lt;&gt;0 &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;SendMessage(WinampHWND, messages.WM_command, Command, 0);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;span&gt;//Запуск Winamp’а&lt;/span&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; StartWinamp;&lt;br/&gt;&lt;strong&gt;var&lt;/strong&gt;&lt;br/&gt;WinampExe:string;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;reg := TRegistry.create;&lt;br/&gt;reg.RootKey:=Windows.HKEY_LOCAL_MACHINE;&lt;br/&gt;reg.OpenKey(&#39;Software\CLASSES\Winamp.File\shell\open\command&#39;, False);&lt;br/&gt;WinampExe := reg.ReadString(&#39;&#39;);&lt;br/&gt;reg.Free;&lt;br/&gt;&lt;strong&gt;if&lt;/strong&gt; WinampExe&lt;&gt;&#39;&#39; &lt;strong&gt;then&lt;/strong&gt;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampExe:=copy(WinampExe, 2, length(WinampExe)-7);&lt;br/&gt;WinExec(pchar(WinampExe), SW_SHOWNORMAL);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; Play;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40045);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; Stop;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40047);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; Pause;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40046);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; NextTrack;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40048);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; PrevTrack;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40044);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;span&gt;{передвинуть текущую позицию на 5 секунд вперёд}&lt;/span&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; FastForward5Sec;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40148);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;span&gt;{передвинуть текущую позицию на 5 секунд назад}&lt;br/&gt;&lt;/span&gt;&lt;strong&gt;Procedure&lt;/strong&gt; FastRewind5Sec;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40144);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;span&gt;//перезагрузить Winamp&lt;/span&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; RestartWinamp;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampUser(0, 135);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; CloseWinamp;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40001);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; RepeatMode;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40022);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Procedure&lt;/strong&gt; SuffleMode;&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;WinampCommand(40023);&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button1Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;StartWinamp;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button2Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;Play;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button3Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;Stop;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button4Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;Pause;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure &lt;/strong&gt;TForm1.Button5Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;NextTrack;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button6Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;PrevTrack;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button7Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;CloseWinamp;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button8Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;FastForward5Sec;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button9Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;FastRewind5Sec;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button10Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;RestartWinamp;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button11Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;RepeatMode;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;&lt;br/&gt;&lt;strong&gt;procedure&lt;/strong&gt; TForm1.Button12Click(Sender: TObject);&lt;br/&gt;&lt;strong&gt;begin&lt;/strong&gt;&lt;br/&gt;SuffleMode;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;;&lt;br/&gt;&lt;strong&gt;end&lt;/strong&gt;.&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;Разумеется, это только прототип. В одной из следующих статей мы обязательно превратим программу в плагин для Winamp’а и добавим поддержку горячих клавиш. На сегодня всё.&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;span&gt;&lt;strong&gt;&lt;em&gt;&lt;span&gt;Иван Ширко&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt; &lt;/div&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/div&gt;</description><link>http://ishirko.blogspot.com/2007/11/winamp.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFhkKr3dGrt5Hc-iBRHBNvu7JHHGSMEOxdzpCnnN48lTloCkkurbcDD-QE4p6RYQIpP-cBpAmRLiyO7cElyV77-u3_kBCuxyK9FN0TJ6A9IQSblUs2puApQ4X23KLdfBhFiX6LNby2ssM/s72-c/table1.GIF" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-4475910432207582069</guid><pubDate>Wed, 28 Nov 2007 13:58:00 +0000</pubDate><atom:updated>2007-12-07T01:25:53.513-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">справка</category><title>Создание справочной системы</title><description>&lt;br/&gt;Всё! Завершено гениальное творение не менее гениального программиста. Программное детище проверено, отлажено и перепроверено. Все найденные друзьями-тестерами &quot;баги&quot; благополучно устранены. А значит, пришло время распространить программу среди пользователей, которые раньше как-то умудрялись без неё обходиться... И вдруг понимаешь, что, несмотря на интуитивно-понятный интерфейс, в мире обязательно найдутся не интуитивно-понятливые &quot;юзеры&quot;, которые не смогут насладиться всеми функциями данного произведения искусства, а то и вовсе (о, ужас!) удалят программу БЕЗВОЗВРАТНО. Смахнув со лба капли холодного пота и преисполнившись жалостью к таким &quot;юзерам&quot;, всерьёз задумываешься о сопроводительной документации. На ум сразу же приходят мысли о файле &quot;readme.txt&quot; или о небольшой html-страничке, но тут же отметаются: в солидном проекте всё должно  быть солидно. Так что придётся делать общепринятый файл *.hlp, который будет гордо называться &quot;справочной системой&quot;. Как создавать файлы такого формата рассказывает данная статья.&lt;br/&gt;Прежде всего, нам понадобится программа Microsoft Help Workshop. Найти её можно по адресу &lt;a href=&quot;http://download.microsoft.com/download/0/a/9/0a939ef6-e31c-430f-a3df-dfae7960d564/htmlhelp.exe&quot;&gt;http://download.microsoft.com/download/0/a/9/0a939ef6-e31c-430f-a3df-dfae7960d564/htmlhelp.exe&lt;/a&gt;, также она распространяется вместе с популярными средами программирования (Delphi, VC++). Помимо этой &quot;софтины&quot;, нам потребуется текстовый процессор для создания файла в формате RTF (rich-text format), Word от всё той же Microsoft вполне подойдёт.&lt;br/&gt;Теперь можно приступить к процессу создания справочной системы, который состоит из трёх важных составляющих:&lt;br/&gt;– подготовка RTF-файла;&lt;br/&gt;– создание и компилирование файлов справочной системы;&lt;br/&gt;– создание содержания справки.&lt;span class=&quot;fullpost&quot;&gt;&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;center&quot;&gt;&lt;strong&gt;&lt;span&gt;Создание RTF-файла&lt;/span&gt;&lt;/strong&gt;&lt;br/&gt;&lt;/div&gt;&lt;strong&gt;&lt;i&gt;Оформление разделов&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;Как известно, справка обычно разбивается на разделы. В RTF-файле каждый раздел должен начинаться заголовком и заканчиваться символом &quot;разрыв страницы&quot; (&quot;Вставка\Разрыв...&quot;). Кроме этого, раздел должен содержать уникальный идентификатор. Для его установки поместите текстовый курсор перед первым символом заголовка и из меню &quot;Вставка&quot; выберите пункт &quot;Сноска...&quot;. В появившемся диалоговом окне (рис.1) в разделе нумерация установите радиокнопку в положение &quot;Другая&quot; и введите символ диеза (&#39;#&#39;). После нажатия на кнопку &quot;OK&quot;, Word предложит ввести текст сноски, что и необходимо сделать. Следует заметить, что если текст сноски начинается с префикса IDH_, то во время компиляции справочной системы будет проверена корректность всех ссылок данного раздела. &lt;br/&gt;&lt;i&gt;&lt;strong&gt;Ссылки на другие разделы&lt;/strong&gt;&lt;/i&gt;&lt;br/&gt;Для связывания разных разделов используются слова-ссылки, при нажатии на которые осуществляется переход к нужной ветке справки. Для того, чтобы сделать слово ссылкой, нужно выделить его и подчеркнуть двойной линией (&quot;Формат\Шрифт\Подчёркивание/Двойное&quot;). После этого, сразу за словом-ссылкой, требуется поместить идентификатор нужного раздела (текст сноски). При запуске справки ссылка будет выделена цветом и одинарным подчёркиванием.&lt;br/&gt;&lt;i&gt;&lt;strong&gt;Комментарии&lt;/strong&gt;&lt;/i&gt;&lt;br/&gt;В документе можно использовать не только ссылки на другие разделы, но и ссылки на комментарии (например, для объяснения какого-нибудь заумного термина). Во время работы справочной системы такие ссылки выделяются цветом и подчёркиванием пунктирной линией, при нажатии на них появляется вплывающее окно с текстом комментария. В RTF-файле комментарии оформляются так же, как и разделы, но они не должны начинаться с заголовка. Ссылку на комментарий нужно подчеркнуть одной линией и сразу за ней написать его идентификатор скрытым текстом.&lt;br/&gt;&lt;strong&gt;&lt;i&gt;Ключевые слова и поиск по разделам&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;Для каждого раздела справки можно создать список ключевых слов. Для этого нужно перед заголовком раздела установить сноску K, а в текст сноски нужно записать все ключевые слова, разделив их точкой с запятой. При работе справочной системы ключевые слова всех разделов будут отображены в закладке &quot;Указатель&quot;. Рядом с ней находится закладка &quot;Поиск&quot;, в которой осуществляется поиск по справке. Для того, чтобы включить возможность поиска по какому-либо разделу, нужно перед его заголовком поставить сноску $, текстом которой должно служить название раздела в поисковой системе.&lt;br/&gt;&lt;i&gt;&lt;strong&gt;Вставка графики&lt;/strong&gt;&lt;/i&gt;&lt;br/&gt;Для вставки картинки в раздел, достаточно просто поместить её туда в Word&#39;e (&quot;Вставка\Рисунок&quot;).&lt;br/&gt; &lt;br/&gt;&lt;div align=&quot;center&quot;&gt;&lt;strong&gt;&lt;span&gt;Создание файла справочной системы&lt;/span&gt;&lt;/strong&gt;&lt;br/&gt;&lt;/div&gt; Теперь, когда RTF-файл набран, можно приступить к созданию справки на основе этого файла. Запустите программу Microsoft Help Workshop и создайте новый проект, выбрав пункт меню &quot;File\New/Help Project&quot;. В правой части окна программы нажмите на кнопку &quot;Files...&quot; и в появившемся диалоговом окне при помощи кнопки &quot;Add&quot; добавьте к проекту RTF-файл. Теперь пройдёмся по опциям справочной системы (кнопка &quot;Options...&quot;).&lt;br/&gt; &lt;strong&gt;&lt;i&gt;General&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt; Эта закладка содержит основные настройки справки:&lt;br/&gt; &lt;i&gt;Default topic&lt;/i&gt; – идентификатор основного раздела справки. Этот раздел появляется при запуске справочной системы (если она не имеет содержания) и в случае, если пользователь нажал на ссылку на несуществующий раздел.&lt;br/&gt; &lt;i&gt;Help title&lt;/i&gt; – заголовок справки, который отображается на заголовке окна.&lt;br/&gt; &lt;i&gt;Copyright information&lt;/i&gt; – текст, отображаемый в диалоговом окне &quot;Версия&quot; и текст, который автоматически добавляется при печати и копировании справки (подпись).&lt;br/&gt; &lt;strong&gt;Сompression&lt;/strong&gt;&lt;br/&gt; Здесь находятся настройки сжатия справочной системы.&lt;br/&gt; &lt;i&gt;None&lt;/i&gt; – не использовать сжатие.&lt;br/&gt; &lt;i&gt;Maximum&lt;/i&gt; – максимальное сжатие (дольше компилируется, но занимает меньше места на диске).&lt;br/&gt; &lt;i&gt;Custom&lt;/i&gt; – позволяет выбрать алгоритмы сжатия справочной системы.&lt;br/&gt;&lt;strong&gt;&lt;i&gt;Files&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt; Файлы, составляющие справочную систему.&lt;br/&gt; &lt;i&gt;Help File&lt;/i&gt; – имя файла справки (*.hlp);&lt;br/&gt; &lt;i&gt;Log File&lt;/i&gt; – имя log-файла (отчёт о компиляции справочной системы);&lt;br/&gt; &lt;i&gt;Rich Text Format (RTF) files&lt;/i&gt; – RTF-файлы (*.rtf);&lt;br/&gt; &lt;i&gt;Contents file&lt;/i&gt; – содержание справочной системы (*.cnt);&lt;br/&gt; &lt;strong&gt;FTS (full-text search)&lt;/strong&gt;&lt;br/&gt; Настройки поисковой системы справки.&lt;br/&gt; &lt;i&gt;Generate full text search index&lt;/i&gt; – генерировать содержание поиска по справке. Если этот параметр выбран, то при компиляции справочной системы сгенерируется файл имя_справки.fts, который нужен для текстового поиска. Как правило, этот файл занимает намного больше места на диске, чем сама справка (*.hlp).&lt;br/&gt;Теперь осталось сделать содержание для нашей справочной системы.&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;center&quot;&gt;&lt;strong&gt;&lt;span&gt;Создание содержания&lt;/span&gt;&lt;/strong&gt;&lt;br/&gt;&lt;/div&gt; Выберите &quot;File\New/Help Contents&quot; и введите имя и заголовок содержания. При помощи кнопок &quot;Add Above&quot; (&quot;Добавить над&quot;) и &quot;Add Below&quot; (&quot;Добавить под&quot;) создайте нужные папки (Heading) и пункты содержания (Topic). При добавлении пункта, введите его название в поле &quot;Title&quot;, в &quot;Topic ID&quot; – идентификатор раздела справки, на который ссылается этот пункт, в &quot;Help File&quot; – имя файла справки, в котором находится этот раздел. Кнопки &quot;Move Right&quot; и &quot;Move Left&quot; служат для изменения иерархии пунктов. После сохранения содержания, откройте проект справки (*.hpj),  нажмите на кнопку &quot;Options&quot;, активизируйте закладку &quot;Files&quot; и в поле &quot;Contents file&quot; введите имя файла содержания либо выберите его при помощи кнопки &quot;Browse&quot;. Откомпилируйте проект.&lt;br/&gt; На этом создание полноценной справочной системы завершено. Наш маленький, но очень гордый &quot;хелп&quot; имеет удобное содержание и мощную поисковую систему, содержит как текстовую, так и графическую информацию, и даже подписывается при цитировании и распечатке! &lt;br/&gt;&lt;br/&gt;&lt;strong&gt;&lt;i&gt;&lt;span&gt;Иван Ширко&lt;/span&gt;&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2007/11/blog-post_28.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-6067036114424957522</guid><pubDate>Wed, 28 Nov 2007 12:00:00 +0000</pubDate><atom:updated>2007-12-07T01:27:16.046-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">караоке</category><title>Караоке в домашних условиях</title><description>Бывают в жизни моменты, когда душа требует песни, притом собственного исполнения. Но обеспечить себе достойное музыкальное сопровождение могут далеко не все, да и слова не всегда вспоминаются в нужный момент. А если и слова знаешь и можешь примерно в тему побренчать на гитаре, то в минуты особого веселья бывает трудновато перемещать непослушные пальцы по грифу в поисках нужного аккорда… Все эти проблемы решает караоке: музыка играет без твоего участия, слова перед глазами, к тому же показывается, когда эти слова нужно петь. Караоке можно организовать по-разному: начиная с сопровождающего оркестра с бегающими перед носом людьми с плакатами с текстом и заканчивая крутым музыкальным автоматов, который даст почувствовать себя талантливым певцом даже при полном отсутствии музыкального слуха. Мы же рассмотрим реализацию караоке на домашнем компьютере в виде специальных программ. Сейчас песни-караоке наиболее часто встречаются в виде файлов *.kar, но бывают, разумеется, и альтернативные форматы. Например, довольно популярным является формат *.st3.&lt;span class=&quot;fullpost&quot;&gt;&lt;br/&gt;&lt;span&gt;&lt;strong&gt;vanBasco&#39;s Karaoke Player&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt; Эта программа для проигрывания караоке, несмотря на свою нулевую стоимость и маленький размер, обладает довольно большими возможностями. Присутствуют все основные возможности хорошего аудио-плеера: управление проигрыванием (пауза, перемотка и т.п.), работа с playlist&#39;ами, анализатор спектра. Кроме этого есть и &quot;навороты&quot;: притягивание окон (как в Winamp&#39;e), управление скоростью воспроизведения, преобразование караоке в midi-файл, есть даже виртуальное пианино… Правда, программа умеет проигрывать только файлы форматов *.kar и *.mid, но проблему воспроизведения других караошек можно решить при помощи специальных программ-преобразователей. Скачать этот плеер можно здесь: &lt;a href=&quot;http://www.vanbasco.com/&quot;&gt;www.vanBasco.com&lt;/a&gt; (796 кБ).&lt;br/&gt;&lt;span&gt;&lt;strong&gt;Karakan&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt; Этот пакет состоит из двух бесплатных программ:&lt;br/&gt;1) KPlay – служит для воспроизведения караошек в формате *.kar. В отличие от vanBasco&#39;s KarPlayer, это очень простенький проигрыватель, который делает только свою основную функцию. В принципе, довольно удобный. На мой взгляд, отображение слов песни у него реализовано даже лучше, чем у вышеописанного конкурента, но возможность перемотки караошки была бы, конечно, не лишней.&lt;br/&gt;2) Karakan – а это уже редактор караошек, точнее не редактор, а создатель, т.к. редактирование готовых *.kar не поддерживается. Караошки создаются на основе midi-файлов, а текст и разметка песни вводятся в формате STF (Song Text Format). С этим форматом легко разобраться после прочтения его описания в системе помощи программы, но всё же создание караоке здесь напоминает создание HTML-документа в Блокноте. Как говорится, дело вкуса, но некая автоматизация всё же не помешала бы… &lt;br/&gt;&quot;Весит&quot; этот пакет 540 кБ – &lt;a href=&quot;http://www.geocities.com/takawadanl/karakan.html&quot;&gt;www.geocities.com/takawadanl/karakan.html&lt;/a&gt;&lt;br/&gt;&lt;span&gt;&lt;strong&gt;VocalJam&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt; Эта программа не похожа на предыдущие. Нет, здесь тоже играет музыка, и нужные слова появляются в нужный момент на экране. И дело даже не в том, что за полную версию программы надо платить, нет… VocalJam не просто даёт возможность спеть какую-нибудь песню, но она может ещё и научить петь и даже выслушать певца, а потом выставить ему оценку за исполнение. Разумеется, никакого сложного анализа пения пользователя не происходит: баллы ставятся лишь за попадание в такт музыке и за правильность высоты пения. Конечно, не очень приятно от компьютера получать нелестные отзывы о своих певческих способностях, поэтому можно в настройках программы отключить вывод всяких комментариев, а оставить одни баллы.  Только не забудьте оставить вылючённой для записи все громкости, кроме микрофона, иначе за ваше пение будет приниматься музыка. В демо-версии программы также есть поддержка &quot;скинов&quot; интерфейса, анализатор частот и даже нотная интерпретация песни. Также имеется немаленькая (несколько десятков) подборка популярных композиций, а если понадобится ещё, то зайдите на сайт программы – &lt;a href=&quot;http://www.vocaljam.narod.ru/&quot;&gt;www.VocalJam.narod.ru&lt;/a&gt;. Идея VocalJam хорошая, но мне программа показалась скорее любительской, чем профессиональной разработкой. Демо-версия VocalJam занимает 7.7 МБ.&lt;br/&gt; Когда мне попалась на глаза ещё одна программа для проигрывания караоке – &lt;span&gt;RealOrche&lt;/span&gt; – то я понял, что что-то здесь не так. Дело в том, что это практически программы близнецы: одинаковый интерфейс, примерно одинаковые возможности, VocalJam даже не запускается вместе с RealOrche, считая её своей копией, и наоборот! Либо работают над программами одни и те же люди, либо плагиат налицо. На мой взгляд RealOrche выглядит намного профессиональней, чем VocalJam, но если хочется петь русские песни, то придётся выбрать вторую программу, ведь она &quot;сделана в России&quot;. Кстати, RealOrche умеет не только проигрывать все популярные форматы караошек, но и редактировать их. Скачать RealOrche можно на сайте программы: &lt;a href=&quot;http://www.realorche.com.br/&quot;&gt;www.realorche.com.br&lt;/a&gt;, размер, в зависимости от версии, 4-5 МБ.&lt;br/&gt;Где взять караошки?&lt;br/&gt; В большом количестве песни в виде караоке можно найти на www.karaoke.ru. Но если этого окажется мало, то загляните сюда: &lt;a href=&quot;http://www.parkov6.narod.ru/&quot;&gt;www.parkov6.narod.ru&lt;/a&gt; (иностранные песни) и &lt;a href=&quot;http://www.parkov7.narod.ru/&quot;&gt;www.parkov7.narod.ru&lt;/a&gt; (русские песни). &lt;br/&gt;Ну что ж, остаётся только пожелать приятных вам песнопений и терпения вашим соседям.&lt;br/&gt;&lt;span&gt;&lt;strong&gt;&lt;span&gt;&lt;i&gt;&lt;span style=&quot;color:#999999;&quot;&gt;Иван Ширко&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br/&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/span&gt;</description><link>http://ishirko.blogspot.com/2007/11/blog-post.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2370346630241894584.post-7467934792889628540</guid><pubDate>Wed, 28 Nov 2007 09:54:00 +0000</pubDate><atom:updated>2008-12-08T13:57:35.655-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">MSAgent</category><title>Microsoft Agent. Часть I</title><description>&lt;div align=&quot;justify&quot;&gt;Microsoft, несмотря на всю льющуюся на них критику, постоянно предоставляет разработчикам новые возможности. Несколько лет назад появилась очень интересная технология – Microsoft Agent. Где можно было наблюдать её применение? Например, в популярном переводчике Magic Gooddy. Основной &quot;фишкой&quot; данной программы является утёнок Gooddy, который свободно может говорить на русском и английском языках. Более того, этот утёнок может ещё и &quot;понимать&quot; некоторые голосовые команды, произнесённые в микрофон. У Gooddy, ко всему прочему, всё время меняется настроение: если долго не пользоваться его услугами, то он начинает грустить, а при переводе он выглядит самым счастливым утёнком в мире. Этот утёнок со всеми его возможностями является наглядным примером применения технологии MsAgent.&lt;br/&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt; Вот таким вступлением я открыл небольшую серию статей, посвящённых Microsoft Agent. В первой части мы рассмотрим аспекты использования MsAgent в web-страницах. Представьте себе, сидите вы в интернете, открываете некую web-страничку, а тут из лампы вылазит Джин из мультфильма &quot;Аладдин&quot; и начинает что-нибудь вам рассказывать. А если вы вдруг наведёте курсор мыши на какую-нибудь гиперссылку, то Джин подлетит к ней и доходчиво объяснит, куда вы попадёте, нажав на ссылку… Здорово? Вот приблизительно такую страничку мы и сотворим в данной статье.&lt;span class=&quot;fullpost&quot;&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt; Теперь самое время установить MsAgent. Для этого нужно отправиться на страницу &lt;a href=&quot;http://www.microsoft.com/msagent/downloads/user.asp&quot;&gt;http://www.microsoft.com/msagent/&lt;/a&gt; и скачать оттуда следующие файлы:&lt;br/&gt;1) Сам Microsoft Agent – &lt;a href=&quot;http://activex.microsoft.com/activex/controls/agent2/MSagent.exe&quot;&gt;http://activex.microsoft.com/activex/controls/agent2/MSagent.exe&lt;/a&gt; (395 кб), обязательно;&lt;br/&gt;2) Перевод на русский язык различных диалогов, надписей и т.п. – &lt;a href=&quot;http://activex.microsoft.com/activex/controls/agent2/AgtX0419.exe&quot;&gt;http://activex.microsoft.com/activex/controls/agent2/AgtX0419.exe&lt;/a&gt; (128 кб), необязательно;&lt;br/&gt;3) один из персонажей (например, Джин из мультфильма &quot;Аладдин&quot;) – &lt;a href=&quot;http://download.microsoft.com/download/0/0/c/00cde5f8-321d-4325-baae-eb27f1bde85f/Genie.exe&quot;&gt;http://download.microsoft.com/download/0/0/c/00cde5f8-321d-4325-baae-eb27f1bde85f/Genie.exe&lt;/a&gt; (1.6 Mb), необязательно, можно работать и с другим персонажем;&lt;br/&gt;4) компонент для произношения текстов (для русского языка) – &lt;a href=&quot;http://activex.microsoft.com/activex/controls/agent2/lhttsrur.exe&quot;&gt;http://activex.microsoft.com/activex/controls/agent2/lhttsrur.exe&lt;/a&gt; (2.9 Mb), необязательно;&lt;br/&gt;5) Поддержка SAPI (нужна для произношения текстов, в Win2000 должна быть установлена изначально) – &lt;a href=&quot;http://activex.microsoft.com/activex/controls/sapi/spchapi.exe&quot;&gt;http://activex.microsoft.com/activex/controls/sapi/spchapi.exe&lt;/a&gt; (824 кб), необязательно.&lt;br/&gt;  После установки всех этих компонентов можно приступать к разработке приложений, использующих технологию MsAgent. Начнём мы, как уже было сказано, с web-страниц. Сразу замечу, что MsAgent накладывает некоторые ограничения на пользователя:&lt;br/&gt;– MsAgent не будет работать ни в одном web-браузере, кроме Internet Explorer (разработчик ведь Microsoft). Версия IE должна быть не ниже, чем 3.02;&lt;br/&gt;– у посетителя должно быть установлено необходимое программное обеспечение (его мы уже скачали).&lt;br/&gt;Теперь сделаем маленькую пробную страничку. Откройте самый продвинутый HTML-редактор с названием Блокнот (некоторым он известен как NotePad). Запишите в нём следующие строки:&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&amp;lt;html&amp;gt;&lt;br/&gt;&amp;lt;head&amp;gt;&lt;br/&gt; &amp;lt;title&amp;gt;Microsoft Agent&amp;lt;/title&amp;gt;&lt;br/&gt; &amp;lt;Object ID=&quot;Agent&quot; Width=0 Height=0&lt;br/&gt; ClassID=&quot;CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F&quot;&lt;br/&gt; CodeBase=&quot;#VERSION=2,0,0,0&quot;&amp;gt;&lt;br/&gt; &amp;lt;/Object&amp;gt;&lt;br/&gt; &amp;lt;script language=javascript&amp;gt;&lt;br/&gt; &amp;lt;!--&lt;br/&gt;  var Genie;&lt;br/&gt;  function LoadAgent()&lt;br/&gt;   {&lt;br/&gt;    Agent.Characters.Load (&quot;Genie&quot;, &quot;Genie.acs&quot;);&lt;br/&gt;    Genie = Agent.Characters.Character(&quot;Genie&quot;);&lt;br/&gt;    Genie.Show();&lt;br/&gt;//А здесь можно написать другие команды&lt;br/&gt;   }&lt;br/&gt;  function UnLoadAgent()&lt;br/&gt;   { Agent.Characters.Unload(&quot;Genie&quot;);}&lt;br/&gt; //--&amp;gt;&lt;br/&gt; &amp;lt;/script&amp;gt;&lt;br/&gt;&amp;lt;/head&amp;gt;&lt;br/&gt;&amp;lt;body&lt;br/&gt; onload=&quot;LoadAgent()&quot;&lt;br/&gt; onunload=&quot;UnLoadAgent()&quot;&amp;gt;&lt;br/&gt;&amp;lt;html&amp;gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;Теперь сохраните данный код в файл *.html и откройте полученную страничку при помощи Internet Explorer. После загрузки страницы из дыма появится Джин, поприветствует вас поклоном и произнесёт на русском языке приветственную фразу.  Давайте посмотрим, как мы добились такого результата.&lt;br/&gt; В тэге &amp;lt;object&amp;gt; мы подключили к нашей странице объект AGENT, который предоставит нам все возможности технологии MsAgent. После этого на языке JavaScript записали две функции – LoadAgent и UnLoadAgent. А затем в тэге  указали, что эти функции должны вызываться при загрузке и закрытии страницы соответственно. После строчек&lt;br/&gt;&lt;/div&gt;…&lt;br/&gt;Agent.Characters.Load (&quot;Genie&quot;, &quot;Genie.acs&quot;);&lt;br/&gt;Genie = Agent.Characters.Character(&quot;Genie&quot;);&lt;br/&gt;…&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;мы можем &quot;давать команды&quot;  Джину: Genie.Show; Genie.Play;  Genie.Speak; и т.д. Давайте рассмотрим некоторые команды более подробно:&lt;br/&gt;Команда Пояснения&lt;br/&gt;Show Служит для появления персонажа на экране&lt;br/&gt;Hide Скрывает персонажа&lt;br/&gt;MoveTo(X, Y) Перемещает персонажа в точку с координатами (X; Y), координаты задаются в пикселях &lt;br/&gt;Play(&quot;Имя анимации&quot;); Проигрывает заданную анимацию.&lt;br/&gt;GestureAt(X, Y) Персонаж указывает рукой в точку с координатами (X; Y)&lt;br/&gt;Think(&quot;Мысль&quot;) Персонаж &quot;думает Мысль&quot;, т.е. звука нет, но над персонажем появляется текст Мысли.&lt;br/&gt;Speak(&quot;Фраза&quot;) Персонаж произносит Фразу. &lt;br/&gt;&lt;/div&gt;&lt;br/&gt;Вот несколько анимаций для персонажа &quot;Джин&quot;:&lt;br/&gt;&lt;br/&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju5pMB9Itj_3rLRUDZtRw51Yi59PzJZ2h7_YsOc8gzAG00OAxNft2EB_cdyYOyHbHg4Kg5UoC0nV90lPeeQx6V7NvEy1vP5pDMol3xlisFYcG-SwQ-0poVJe1KQORwYXUKHyIjcjs8_po/s1600-h/2003140201.jpg&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju5pMB9Itj_3rLRUDZtRw51Yi59PzJZ2h7_YsOc8gzAG00OAxNft2EB_cdyYOyHbHg4Kg5UoC0nV90lPeeQx6V7NvEy1vP5pDMol3xlisFYcG-SwQ-0poVJe1KQORwYXUKHyIjcjs8_po/s320/2003140201.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5137837358473319138&quot; /&gt;&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Пример: Genie.Play(&quot;Write&quot;);&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;MsAgent позволяет управлять даже голосом персонажа. Делается это при помощи специальных тэгов, которые нужно добавлять к произносимой фразе:&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Тэг Значения и описание&lt;br/&gt;\Chr=&quot;значение&quot;\  Изменяет голос персонажа:&lt;br/&gt;&quot;Normal&quot; (по умолчанию) – нормальный голос&lt;br/&gt;&quot;Monotone&quot; – монотонный голос&lt;br/&gt;&quot;Whisper&quot; – шёпот&lt;br/&gt;\Emp\ На следующем за тэгом слове делается ударение&lt;br/&gt;\Map=&quot;spokentext&quot;=&quot;balloontext&quot;\ &lt;br/&gt; Персонаж вслух произносит строку &quot;spokentext&quot;, а над ним отображается строка &quot;balloontext&quot;. Т.е. персонаж как бы думает одно, а говорит совершенно другое.&lt;br/&gt;\Pau=значение\&lt;br/&gt; Делает паузу, которая длится &quot;значение&quot; миллисекунд&lt;br/&gt;\Pit=значение\&lt;br/&gt; Устанавливает частоту произношения в Герцах&lt;br/&gt;\Rst\ Устанавливает все параметры в исходное состояние&lt;br/&gt;\Spd=значение\ Устанавливает скорость произношения текста в &quot;словах в минуту&quot; &lt;br/&gt;\Vol=значение\ Устанавливает громкость произношения текста (от 0 до 65535)&lt;br/&gt;&lt;br/&gt;Пример для JavaScript: Genie.Speak(&quot;\\chr=\&quot;Whisper\&quot;\\\\Pit=18400\\\\Spd=100\\Привет!&quot;);&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt; С помощью представленных команд можно создать довольно эффектную и интерактивную страничку. Про другие команды и свойства мы поговорим в следующей части, когда перейдём к Delphi, а пока рассмотрим несколько аспектов использования MsAgent в web-страничках. Предположим, вы поместили страничку в интернете. Тогда её могут просматривать три вида пользователей:&lt;br/&gt;&lt;/div&gt;1) С браузером Internet Explorer и установленной MsAgent;&lt;br/&gt;2) С браузером Internet Explorer без установленной MsAgent;&lt;br/&gt;3) С другим браузером.&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt;Именно эти три случая мы должны обрабатывать в нашей страничке. Сделать это не так и сложно. Вначале запишем функцию HaveAgent, которая будет определять, установлены ли компоненты MsAgent в системе:&lt;br/&gt;&lt;/div&gt;Function HaveAgent()&lt;br/&gt;     Dim agent&lt;br/&gt;     HaveAgent = False&lt;br/&gt;     On Error Resume Next&lt;br/&gt;     Set agent = CreateObject(&quot;Agent.Control.1&quot;)&lt;br/&gt;     HaveAgent = IsObject(agent)&lt;br/&gt;End Function&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt; Теперь на основе этой функции можно написать шаблон странички, которая будет предусматривать все возможные варианты:&lt;br/&gt;&lt;/div&gt;&lt;pre&gt;&amp;lt;SCRIPT LANGUAGE=VBSCRIPT&amp;gt;&lt;br/&gt; If HaveAgent() Then&lt;br/&gt;  document.write &quot;&amp;lt;H2 align=center&amp;gt;MsAgent найден&amp;lt;/H2&amp;gt;&quot;&lt;br/&gt; Else&lt;br/&gt;&#39;Microsoft Agent control was not found.&lt;br/&gt;  document.write &quot;&amp;lt;H2 align=center&amp;gt; MsAgent не найден&amp;lt;/H2&amp;gt;&quot;&lt;br/&gt; End If&lt;br/&gt; Function HaveAgent()&lt;br/&gt;  Dim agent&lt;br/&gt;  HaveAgent = False&lt;br/&gt;  On Error Resume Next&lt;br/&gt;  Set agent = CreateObject(&quot;Agent.Control.1&quot;)&lt;br/&gt;  HaveAgent = IsObject(agent)&lt;br/&gt; End Function&lt;br/&gt;&amp;lt;/SCRIPT&amp;gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;div align=&quot;justify&quot;&gt; Вот и всё! По этому небольшому шаблону можно писать web-странички с использованием MsAgent, которые будут корректно отображаться во всех браузерах.  Для примера я создал страничку, которую можно найти по адресу &lt;a href=&quot;http://www.agentsample.narod.ru/&quot;&gt;http://www.agentsample.narod.ru/&lt;/a&gt;&lt;br/&gt;&lt;/div&gt;&lt;div align=&quot;justify&quot;&gt;На этом мы заканчиваем рассмотрение использования технологии Microsoft Agent в web-страничках. В &lt;a href=&quot;http://ishirko.blogspot.com/2007/12/microsoft-agent-ii.html&quot;&gt;следующей части&lt;/a&gt; мы перейдём к Delphi.&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;strong&gt;&lt;i&gt;&lt;span&gt;Иван Ширко&lt;/span&gt;&lt;/i&gt;&lt;/strong&gt;&lt;br/&gt;&lt;a href=&quot;mailto:ishyrko@gmail.com&quot;&gt;ishyrko@gmail.com&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;</description><link>http://ishirko.blogspot.com/2007/11/microsoft-agent-i.html</link><author>noreply@blogger.com (Ivan Shyrko)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju5pMB9Itj_3rLRUDZtRw51Yi59PzJZ2h7_YsOc8gzAG00OAxNft2EB_cdyYOyHbHg4Kg5UoC0nV90lPeeQx6V7NvEy1vP5pDMol3xlisFYcG-SwQ-0poVJe1KQORwYXUKHyIjcjs8_po/s72-c/2003140201.jpg" height="72" width="72"/><thr:total>0</thr:total></item></channel></rss>