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

<channel>
	<title>Малинников.ru &#187; WinAPI</title>
	<atom:link href="http://malinnikov.ru/tag/winapi/feed/" rel="self" type="application/rss+xml" />
	<link>http://malinnikov.ru</link>
	<description>Абсолютно неофициальная страница Павла Малинникова</description>
	<lastBuildDate>Sun, 20 May 2012 01:05:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Каретка, как индикатор текущей раскладки</title>
		<link>http://malinnikov.ru/karetka-kak-indikator-tekushhej-raskladki/</link>
		<comments>http://malinnikov.ru/karetka-kak-indikator-tekushhej-raskladki/#comments</comments>
		<pubDate>Tue, 12 May 2009 20:13:38 +0000</pubDate>
		<dc:creator>Павел Малинников</dc:creator>
				<category><![CDATA[Разработка ПО]]></category>
		<category><![CDATA[WinAPI]]></category>

		<guid isPermaLink="false">http://malinnikov.ru/?p=1235</guid>
		<description><![CDATA[Есть хорошая тема, показывать текущую раскладку цветом каретки. Каретка&#160;— это та мигающая палочка, из которой вылезает текст, если что. А курсор — это мышиный указатель. По крайней мере, в терминах ресурсов Windows. Но для пользователей и она в большинстве случаев — курсор.

Например, для русской раскладки можно было бы использовать красный цвет каретки, а для английского [...]]]></description>
			<content:encoded><![CDATA[<p>Есть хорошая тема, показывать текущую раскладку цветом каретки. <em>Каретка&nbsp;— это та мигающая палочка, из которой вылезает текст, если что. А курсор — это мышиный указатель. По крайней мере, в терминах ресурсов Windows. Но для пользователей и она в большинстве случаев — курсор.<br />
</em></p>
<p>Например, для русской раскладки можно было бы использовать красный цвет каретки, а для английского — чёрный.</p>
<p><img align="center" src="http://malinnikov.ru/wp-content/uploads/word/051209_2013_1.png" alt="" /></p>
<p>Я впервые прочитал о таком способе индикации на сайте <noindex><a href="http://artgorbunov.ru/bb/ui/cursor/" class="extlink">Артёма Горбунова</a></noindex> а Илья Бирман <noindex><a href="http://ilyabirman.ru/meanwhile/2009/05/11/1/" class="extlink">тут рассказывает</a></noindex> о своей реализации этой идеи на Маке.</p>
<p>Ну конечно, я примерил идею на винду. Что мы имеем в смысле её реализации средствами WinAPI? <span id="more-1235"></span>Виндоус умеет создавать 3 типа кареток: линию (горизонтальную и вертикальную), блок и пользовательский битмап. Созданная каретка рисуется инвертированным цветом фона, точнее not (bgcolor xor bgcolor).</p>
<p><img src="http://malinnikov.ru/wp-content/uploads/word/051209_2013_2.png" alt="" align="left" />Первое, что приходит в голову, это старый добрый хук на смену раскладки и последующее создание каретки нужного цвета от имени текущего приложения. Но не тут-то было. Это вопрос, который приоткрывает завесу того борделя, который творится в написании приложений третьими (а также вторыми и даже первыми) разработчиками. Word, например, должен как-то рисовать мигающую палку на пол-экрана, когда кто-нибудь захочет сделать масштаб 400% и шрифт 72 размера. Он не пользуется системной функцией отображения каретки, он сам рисует свои палки, а каретку стыдливо прячет. Я нагло внедрился к нему в процесс и просто попросил показать каретку, он этого явно не ожидал и на клиентской части окна стал появляться нестёртый мусор.</p>
<p>Редакторы, сделанные на Java, вообще чихать хотели на системную каретку и настройку частоты её мигания. Они рисуют там что-то свое, мигающее по собственному таймеру. Список можно продолжать. Чего стоят одни браузеры со своими элементами формы и собственным видением единственно православной каретки.</p>
<p>Так что CreateCaret от имени приложения не годится, потому что неизвестно, какую каретку создавать. Может у приложения вот такая каретка в виде бабочки, как узнать хандлу этого битмапа? Нет, промышленное решение из этого не получится, один гнусный хакинг. Хотя (вроде бы) <noindex><a href="http://www.amlpages.com/Rus/download.htm" class="extlink">Aml Maple</a></noindex> умеет красить карету в разные цвета, но я не проверял.</p>
<p>Я думал и об окне, плавающем рядом с кареткой, но такой подход может вызвать у многих пользователей эпилепсию. Ещё неплохая, по-моему, мысль, рисовать прямо на захученном окне средствами GDI, только приложение после переключения всё равно нарисует своё барахло, а чтобы постоянно перерисовывать каретку нужным цветом нужно в адресном пространстве каждого процесса оставлять дополнительный поток, что ли — вот приложения обрадуются!</p>
<p>Ну хорошо, давайте подумаем. Задача состоит в том, чтобы не косить глаза в угол монитора, а по виду самой каретки определить текущий язык.</p>
<p>Предусмотреть все варианты отображения кареток в разных приложениях условно нереально. Что остается? </p>
<p><span style="font-size:14pt"><em>Частота мерцания!</em></span></p>
<p>Переключаюсь я на русский язык, начинает быстро мигать. В английском — медленно. Ну настраивать можно, кому как нравится, понятно. Собрался печатать — он быстро молотит — ага, переключиться надо. Не хуже красного цвета, на мой взгляд, по отношению полезность/сложность реализации.</p>
<p>Частота мерцания курсора — это законный параметр винды, в панели управления:</p>
<p><img align="center" src="http://malinnikov.ru/wp-content/uploads/word/051209_2013_3.png" alt="" width="408" height="452" /></p>
<p>Управляется функциями SetCaretBlinkTime, GetCaretBlinkTime.</p>
<p>Итак: делаю службу, которая загружает длл с хуком для события на переключение раскладки. А в hook-функции написано, к примеру:</p>
<div class="codecolorer-container cpp " style="overflow:auto;white-space:nowrap;width:100%;height:500px"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="cpp codecolorer" style="font-family: Courier New, monospace">LRESULT CALLBACK hookProc <span class="br0">&#40;</span><span class="kw4">int</span> nCode, WPARAM wParam, LPARAM lParam<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>nCode <span class="sy1">&gt;=</span> <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>nCode <span class="sy1">==</span> HSHELL_LANGUAGE<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LANGID inputLang <span class="sy1">=</span> LOWORD <span class="br0">&#40;</span>lParam<span class="br0">&#41;</span><span class="sy4">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">char</span> szLocaleData <span class="br0">&#91;</span><span class="nu0">255</span><span class="br0">&#93;</span><span class="sy4">;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GetLocaleInfo <span class="br0">&#40;</span>inputLang, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;LOCALE_SENGLANGUAGE, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;szLocaleData, <span class="kw3">sizeof</span> <span class="br0">&#40;</span>szLocaleData<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy4">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>_tcscmp <span class="br0">&#40;</span>szLocaleData, _T<span class="br0">&#40;</span><span class="st0">&quot;Russian&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetCaretBlinkTime <span class="br0">&#40;</span><span class="nu0">200</span><span class="br0">&#41;</span><span class="sy4">;</span> <span class="co1">// ну к примеру</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SetCaretBlinkTime <span class="br0">&#40;</span><span class="nu0">1000</span><span class="br0">&#41;</span><span class="sy4">;</span> <span class="co1">// к примеру</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>CallNextHookEx <span class="br0">&#40;</span>g_hHook, nCode, wParam, lParam<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy4">;</span><br />
<span class="br0">&#125;</span></div></td></tr></tbody></table></div>
<p>И я в какой-то момент так этой идеей загорелся, что даже сделал действующую модель. Кто желает, может взять здесь.</p>
<p><span style="font-size:14pt"><strong><a href='http://malinnikov.ru/wp-content/uploads/2009/05/blink.zip'>blink.zip (90 Кб)</a></strong></span></p>
<p>В архиве 4 файла:</p>
<table border="1" cellpadding="3px">
<tr>
<td>blink.exe</td>
<td>служба</td>
</tr>
<tr>
<td>blink.dll</td>
<td>длл-ка с хуком</td>
</tr>
<tr>
<td>install.bat</td>
<td>регистрирует и стартует службу(должен лежать и запускаться из той же папки, где лежит blink.exe)</td>
</tr>
<tr>
<td>uninstall.bat</td>
<td>останавливает и удаляет службу</td>
</tr>
</table>
<p>Ничего в реестр не пишется, ведётся лог в темповой папке.</p>
<p>Для установки нужно запустить install.bat. Для удаления uninstall.bat. Это оригинально. Как и предупреждение о том, что я, как и все разработчики, снимаю с себя всякую ответственность за вашу карму и возможные стихийные бедствия, источником которых (как вы можете подумать) может стать это ПО. Могу добавить, что работает все стабильно (у меня дома и на работе на 2-х машинах). Софтина делает то же, что и апплет панели управления, не больше. </p>
<p>После удаления службы вы всегда можете в панели управления установить обратно свою частоту мерцания курсора. Пробовал в W2k, XP.  (upd: попробовал в Висте — не работает, может быть, займусь этим).</p>
<p>Но! Во многих прогах частота мерцания каретки не изменяется из-за описанных выше причин. Некоторые окна нуждаются в деактивации/активации, чтобы изменения частоты вступили в силу. В настоящих виндюшных эдит-боксах все без проблем, в визуал студии тоже, в общем, хотите — посмотрите.</p>
<p>И в заключение на тему индикации текущей раскладки:</p>
<p><span style="font-size:14pt"><strong>ЭТО ВСЁ ВООБЩЕ НЕ НУЖНО, ПОКА ЕСТЬ PUNTO SWITCHER<br />
</strong></span></p>
<p>Спасибо за внимание.</p>
<p>UPD:</p>
<p>Посмотрел Маплю. Всё ясно. Создаёт каретку и показывает её. В ворде такое же поведение, как я наблюдал (остаётся мусор):<br />
<img src="http://malinnikov.ru/wp-content/uploads/2009/05/maplja.jpg" alt="maplja" title="maplja" width="600" height="479" class="aligncenter size-full wp-image-1256" /></p>
<p>Java-проги тоже игнорируют её. Это не годится. Это вина не Мапли, просто надо думать дальше.</p>
]]></content:encoded>
			<wfw:commentRss>http://malinnikov.ru/karetka-kak-indikator-tekushhej-raskladki/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>GetLastError</title>
		<link>http://malinnikov.ru/getlasterror/</link>
		<comments>http://malinnikov.ru/getlasterror/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 16:17:33 +0000</pubDate>
		<dc:creator>Павел Малинников</dc:creator>
				<category><![CDATA[Наблюдения]]></category>
		<category><![CDATA[Разработка ПО]]></category>
		<category><![CDATA[WinAPI]]></category>

		<guid isPermaLink="false">http://malinnikov.ru/?p=767</guid>
		<description><![CDATA[Пришлось мне как-то несколько раз подряд по просьбе товарищей запускать Error Lookup и смотреть, что означает код ошибки из Win API. Поэтому я решил вытащить сразу все коды с описанием в один файл.
Кто интересуется кодом, может посмотреть в подробностях, хотя там ничего военного нету. А неожиданность вот в чём. У кого-нибудь есть предположения о смысле [...]]]></description>
			<content:encoded><![CDATA[<p>Пришлось мне как-то несколько раз подряд по просьбе товарищей запускать Error Lookup и смотреть, что означает код ошибки из Win API. Поэтому я решил вытащить сразу все коды с описанием в <a href="http://malinnikov.ru/wp-content/uploads/2009/03/winapi_error_list.txt">один файл</a>.</p>
<p>Кто интересуется кодом, может посмотреть в подробностях, хотя там ничего военного нету. А неожиданность вот в чём. У кого-нибудь есть предположения о смысле таких ошибок, как:</p>
<blockquote>
<table style="height: 106px; width: 100%;" border="0" align="center">
<tbody>
<tr>
<td valign="top">5090:	Испания<br />
5091:	Дания<br />
5092:	Швеция<br />
5093:	Норвегия<br />
5094:	Германия</td>
<td valign="top">5095:	Австралия<br />
5096:	Япония<br />
5097:	Корея<br />
5098:	Китай (КНР)<br />
5099:	Тайвань</td>
<td valign="top">5100:	Азия<br />
5101:	Португалия<br />
5102:	Финляндия<br />
5103:	Арабский<br />
5104:	Иврит</td>
</tr>
</tbody>
</table>
</blockquote>
<p>Я, было, подумал, что это языки, но страны не все. Да и «Азия» как-то не очень вписывается. К тому же есть отдельные функции перечисления региональных установок. А это коды именно ошибок.</p>
<blockquote><p>4385:	Воскресенье, 4386:	Понедельник, 4387:	Вторник, 4388:	Среда, 4389:	Четверг</p></blockquote>
<p>— А где пятница и суббота?</p>
<p>Кто-нибудь сталкивался с такими сообщениями об ошибках?</p>
<p><span id="more-767"></span><br />
Вот как я сгенерил файлик:</p>
<div class="codecolorer-container cpp " style="overflow:auto;white-space:nowrap;width:100%"><table cellspacing="0" cellpadding="0"><tbody><tr><td class="line-numbers"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br /></div></td><td><div class="cpp codecolorer" style="font-family: Courier New, monospace">CString GetSysErrorDescr<span class="br0">&#40;</span>DWORD dwLastErr<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LPVOID lpMsgBuf<span class="sy4">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>FormatMessage<span class="br0">&#40;</span>FORMAT_MESSAGE_ALLOCATE_BUFFER <span class="sy3">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FORMAT_MESSAGE_FROM_SYSTEM <span class="sy3">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FORMAT_MESSAGE_IGNORE_INSERTS,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">NULL</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwLastErr,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span>LPTSTR<span class="br0">&#41;</span> <span class="sy3">&amp;</span>lpMsgBuf,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="sy1">==</span> <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> _T<span class="br0">&#40;</span><span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="sy4">;</span><br />
<br />
&nbsp; &nbsp; CString sErr <span class="br0">&#40;</span><span class="br0">&#40;</span>LPTSTR<span class="br0">&#41;</span> lpMsgBuf<span class="br0">&#41;</span><span class="sy4">;</span><br />
&nbsp; &nbsp; LocalFree <span class="br0">&#40;</span>lpMsgBuf<span class="br0">&#41;</span><span class="sy4">;</span><br />
<br />
&nbsp; &nbsp; sErr.<span class="me1">TrimRight</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy4">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">return</span> sErr<span class="sy4">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> DumpErrDescr<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">FILE</span> <span class="sy2">*</span> f <span class="sy1">=</span> _tfopen <span class="br0">&#40;</span>_T<span class="br0">&#40;</span><span class="st0">&quot;log.log&quot;</span><span class="br0">&#41;</span>, _T<span class="br0">&#40;</span><span class="st0">&quot;a&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy4">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span>DWORD i <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> i <span class="sy1">&lt;</span> <span class="nu0">100000</span><span class="sy4">;</span> i<span class="sy2">++</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CString err <span class="sy1">=</span> GetSysErrorDescr<span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="sy4">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>err <span class="sy3">!</span><span class="sy1">=</span> _T<span class="br0">&#40;</span><span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _ftprintf <span class="br0">&#40;</span>f, _T<span class="br0">&#40;</span><span class="st0">&quot;%d:<span class="es1">\t</span>%s<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span>, i, err<span class="br0">&#41;</span><span class="sy4">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; <span class="kw3">fclose</span> <span class="br0">&#40;</span>f<span class="br0">&#41;</span><span class="sy4">;</span><br />
<span class="br0">&#125;</span></div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss>http://malinnikov.ru/getlasterror/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

