<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; AHK: Определение символов, посылаемых с клавиатуры]]></title>
	<link rel="self" href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=5697&amp;type=atom" />
	<updated>2012-04-30T18:30:34Z</updated>
	<generator>PunBB</generator>
	<id>http://forum.script-coding.com/viewtopic.php?id=5697</id>
		<entry>
			<title type="html"><![CDATA[Re: AHK: Определение символов, посылаемых с клавиатуры]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=59856#p59856" />
			<content type="html"><![CDATA[<p>Код исправлен для поддержки AHK_L x64.</p>]]></content>
			<author>
				<name><![CDATA[teadrinker]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=24515</uri>
			</author>
			<updated>2012-04-30T18:30:34Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=59856#p59856</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[AHK: Определение символов, посылаемых с клавиатуры]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=47396#p47396" />
			<content type="html"><![CDATA[<p>Требует AHK_L.<br />Скрипт определяет символы, посылаемые с клавиатуры окнам других приложений и показывает их в своём окне.<br /></p><div class="codebox"><pre><code>   SetBatchLines, -1
   Gui, Add, Edit, x0 y0 w200 h100 ReadOnly hwndhEdit
   Gui, Show, w200 h100 NA
   OnExit, Exit
   hHookKeybd := DllCall(&quot;SetWindowsHookEx&quot; . (A_IsUnicode ? &quot;W&quot; : &quot;A&quot;)
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback(&quot;LowLevelKeyboardProc&quot;, &quot;Fast&quot;)
      , Ptr, DllCall(&quot;GetModuleHandle&quot;, UInt, 0, Ptr)
      , UInt, 0, Ptr)
   OnExit, Exit
   Return

GuiClose:
   ExitApp

Exit:
   DllCall(&quot;UnhookWindowsHookEx&quot;, Ptr, hHookKeybd)
   ExitApp

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   global
   Critical

   if (wParam = 0x100)   ; WM_KEYDOWN = 0x100
   {
      vk := NumGet(lParam+0, &quot;UInt&quot;)
      sc := NumGet(lParam+0, 4, &quot;UInt&quot;)
      SetTimer, ShowChar, -10
   }
   Return DllCall(&quot;CallNextHookEx&quot;, Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)

ShowChar:
   Char := GetCharOfKey(vk, sc)
   Control, EditPaste, % Char,, ahk_id %hEdit%
   Return
}

GetCharOfKey(vk, sc)
{
   ThreadID := DllCall(&quot;GetWindowThreadProcessId&quot;, UInt, WinExist(&quot;A&quot;), UInt, 0)
   InputLocaleID := DllCall(&quot;GetKeyboardLayout&quot;, UInt, ThreadID)
   VarSetCapacity(KeyState, 256)

   DllCall(&quot;AttachThreadInput&quot;, UInt, ThreadID
                              , UInt, DllCall(&quot;GetCurrentThreadId&quot;)
                              , UInt, 1)

   DllCall(&quot;GetKeyboardState&quot;, UInt, &amp;KeyState)

   VarSetCapacity(Buffer, 2)
   A_IsUnicode ? DllCall(&quot;ToUnicodeEx&quot;
                  , UInt, vk, UInt, sc
                  , UInt, &amp;KeyState, Str, Buffer
                  , Int, 1, UInt, 0, UInt, InputLocaleID) : DllCall(&quot;ToAsciiEx&quot;
                                                               , UInt, vk, UInt, sc
                                                               , UInt, &amp;KeyState, Str, Buffer
                                                               , UInt, 0, UInt, InputLocaleID)
   Return Buffer
}</code></pre></div><p>Для перехвата клавиатурных событий скрипт устанавливает <a href="http://msdn.microsoft.com/en-us/library/ms644990%28VS.85%29.aspx">хук</a>, callback-функция которого (<a href="http://msdn.microsoft.com/en-us/library/ms644985%28VS.85%29.aspx">LowLevelKeyboardProc</a>) определяет виртуальный и скан-код нажатой клавиши. После этого мы выходим из обработчика событий, чтобы не создавать задержки, и остальные действия будем выполнять асинхронно в подпрограмме таймера.</p><p>Теперь для определения символа, посланного нажатой клавишей, нужно узнать текущую раскладку клавиатуры в активном окне (ф-ция <a href="http://msdn.microsoft.com/en-us/library/ms646296%28VS.85%29.aspx">GetKeyboardLayout</a>) и статусы клавиш Shift и Caps Lock. Ф-ция <a href="http://msdn.microsoft.com/en-us/library/ms646299%28VS.85%29.aspx">GetKeyboardState</a> делает снимок состояний всех виртуальных клавиш и помещает его в буфер. Чтобы иметь возможность сделать такой снимок для другого потока, нужно предварительно вызвать <a href="http://msdn.microsoft.com/en-us/library/ms681956%28VS.85%29.aspx">AttachThreadInput</a>.</p><p>Сейчас у нас есть все данные, нужные для определения символа. В Unicode-версии AHK это делается с помщью ф-ции <a href="http://msdn.microsoft.com/en-us/library/ms646322%28VS.85%29.aspx">ToUnicodeEx</a>, в ANSI-версии — посредством <a href="http://msdn.microsoft.com/en-us/library/ms646318%28VS.85%29.aspx">ToAsciiEx</a>. Скрипт сам определит нужный вариант по значению переменной <a href="http://www.autohotkey.net/~Lexikos/AutoHotkey_L/docs/#vars">A_IsUnicode</a>.</p>]]></content>
			<author>
				<name><![CDATA[teadrinker]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=24515</uri>
			</author>
			<updated>2011-04-05T15:15:05Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=47396#p47396</id>
		</entry>
</feed>
