<?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=5690&amp;type=atom" />
	<updated>2011-04-03T09:46:05Z</updated>
	<generator>PunBB</generator>
	<id>http://forum.script-coding.com/viewtopic.php?id=5690</id>
		<entry>
			<title type="html"><![CDATA[AHK: Определение виртуальных и скан-кодов клавиатуры]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=47330#p47330" />
			<content type="html"><![CDATA[<p>Скрипт определяет виртуальный (vk) и скан-код (sc) клавиши при её нажатии, а также название клавиши по её vk или sc. Полученный код можно скопировать в буфер обмена в виде vkFF или scFF (т. е. в виде, пригодном для использования в AHK-коде для обозначения горячих клавиш) с помощью кнопки &quot;Copy&quot;.</p><p>Когда активно окно скрипта и открыта вкладка &quot;Получить код&quot;, скрипт предотвращает системную обработку нажатий всех клавиш, кроме Alt, Ctrl, Shift и Tab (и некоторых специальных клавиш, например Power), кроме того, переключается статус Num Lock (от этого зависят виртуальные коды цифровой клавиатуры), но не переключается его светодиод. По сочетанию Ctrl + Tab можно осуществить переход между вкладками, Tab — переключение между контролами, Alt + F4 — завершение работы скрипта.<br /></p><div class="codebox"><pre><code>   Menu, Tray, Icon, Shell32.dll, 45

   Height := 165  ; высота клиентской области, не включая заголовки вкладок

   Gui, +AlwaysOnTop
   Gui, Color, DAD6CA
   Gui, Add, Tab2, vTab gTab x0 y0 w200 h185 AltSubmit hwndhTab, Получить код|Клавиша по коду
   Tab = 2
   VarSetCapacity(RECT, 16)
   SendMessage, TCM_GETITEMRECT := 0x130A, 1, &amp;RECT,, ahk_id %hTab%
   TabH := NumGet(RECT, 12, &quot;UInt&quot;)
   GuiControl, Move, Tab, % &quot;x0 y0 w200 h&quot; TabH + Height
   Gui, Add, Text, % &quot;x8 y&quot; TabH + 8 &quot; w183 +&quot; SS_GRAYFRAME := 0x8 &quot; h&quot; Height - 16

   Gui, Font, q5 s12, Verdana
   Gui, Add, Text, vAction x15 yp+7 w170 Center c0033BB, Нажмите клавишу
   Gui, Add, Text, vKey xp yp+35 wp Center Hidden

   Gui, Font, q5 c333333
   Gui, Add, Text, vTextVK xp+8 yp+37 Hidden, vk =
   Gui, Add, Text, vVK xp+35 yp w62 h23 Center Hidden
   Gui, Add, Text, vTextSC xp-35 yp+35 Hidden, sc =
   Gui, Add, Text, vSC xp+35 yp w62 h23 Center Hidden

   Gui, Font, s8
   Gui, Add, Button, vCopyVK gCopy xp+70 yp-35 w50 h22 Hidden, Copy
   Gui, Add, Button, vCopySC gCopy xp yp+33 wp hp Hidden, Copy

   Gui, Tab, 2
   Gui, Add, Text, % &quot;x8 y&quot; TabH + 8 &quot; w183 +&quot; SS_GRAYFRAME &quot; h&quot; Height - 16
   Gui, Add, Text, x15 yp+7 w170 c0033BB
      , Введите код`nв шестнадцатеричном формате без префикса &quot;0x&quot;

   Gui, Font, q5 s11
   Gui, Add, Text, xp yp+58, vk
   Gui, Add, Edit, vEditVK gGetKey xp+25 yp-2 w45 h23 Limit2 Uppercase Center
   Gui, Add, Text, vKeyVK xp+45 yp+2 w105 Center

   Gui, Add, Text, x15 yp+43, sc
   Gui, Add, Edit, vEditSC gGetKey xp+25 yp-2 w45 h23 Limit3 Uppercase Center
   Gui, Add, Text, vKeySC xp+45 yp+2 w105 Center
   Gui, Show, % &quot;w199 h&quot; TabH + Height - 1, Коды клавиш

   hHookKeybd := SetWindowsHookEx()
   OnExit, Exit
   OnMessage(0x6, &quot;WM_ACTIVATE&quot;)
   OnMessage(0x102, &quot;WM_CHAR&quot;)
   Return

Tab:
   If (Tab = 2 &amp;&amp; !hHookKeybd)
      hHookKeybd := SetWindowsHookEx()
   Else if (Tab = 1 &amp;&amp; hHookKeybd)
      DllCall(&quot;UnhookWindowsHookEx&quot;, UInt, hHookKeybd), hHookKeybd := &quot;&quot;
   Return

Copy:
   GuiControlGet, Code,, % SubStr(A_GuiControl, -1)
   StringLower, GuiControl, A_GuiControl
   Clipboard := SubStr(GuiControl, -1) . SubStr(Code, 3)
   Return

GetKey:
   GuiControlGet, Code,, % A_GuiControl
   tipe := SubStr(A_GuiControl, -1)
   Key := RegExReplace( GetKeyName(tipe . Code), &quot;^.&quot;, &quot;$U0&quot; )
   GuiControl,, % &quot;Key&quot; . tipe, % Key
   Return

GuiClose:
   ExitApp

Exit:
   if hHookKeybd
      DllCall(&quot;UnhookWindowsHookEx&quot;, Ptr, hHookKeybd)
   Send {Alt Up}{Shift Up}{Ctrl Up}
   ExitApp

WM_ACTIVATE(wp)
{
   global
   if (wp &amp; 0xFFFF = 0 &amp;&amp; hHookKeybd)
      DllCall(&quot;UnhookWindowsHookEx&quot;, UInt, hHookKeybd), hHookKeybd := &quot;&quot;
   if (wp &amp; 0xFFFF &amp;&amp; Tab = 2 &amp;&amp; !hHookKeybd)
      hHookKeybd := SetWindowsHookEx()
   GuiControl,, Action, % wp &amp; 0xFFFF = 0 ? &quot;Активируйте окно&quot; : &quot;Нажмите клавишу&quot;
}

SetWindowsHookEx()
{
   Return 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)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   static once, WM_KEYDOWN = 0x100, WM_SYSKEYDOWN = 0x104

   vk := NumGet(lParam+0, &quot;UInt&quot;)
   Extended := NumGet(lParam+0, 8, &quot;UInt&quot;) &amp; 1
   sc := (Extended&lt;&lt;8)|NumGet(lParam+0, 4, &quot;UInt&quot;)
   Key := GetKeyName( Format(&quot;vk{1:X}sc{2:X}&quot;, vk, sc) )

   if (wParam = WM_SYSKEYDOWN || wParam = WM_KEYDOWN)
   {
      GuiControl,, Key, % RegExReplace(Key, &quot;^.&quot;, &quot;$U0&quot;)
      GuiControl,, VK, % Format(&quot;{:#x}&quot;, vk)
      GuiControl,, SC, % Format(&quot;{:#x}&quot;, sc)
   }

   if !once
   {
      Controls := &quot;Key|TextVK|VK|TextSC|SC|CopyVK|CopySC&quot;
      Loop, parse, Controls, |
         GuiControl, Show, % A_LoopField
      once = 1
   }

   ;~ if Key Contains Control,Alt,Shift,Tab
      ;~ Return CallNextHookEx(nCode, wParam, lParam)

   if (Key = &quot;F4&quot; &amp;&amp; GetKeyState(&quot;Alt&quot;, &quot;P&quot;))  ; закрытие окна и выход по Alt + F4
      Return CallNextHookEx(nCode, wParam, lParam)

   Return 1
}

CallNextHookEx(nCode, wp, lp)
{
   Return DllCall(&quot;CallNextHookEx&quot;, Ptr, 0, Int, nCode, UInt, wp, UInt, lp)
}

WM_CHAR(wp)
{
   global hBall
   SetWinDelay, 0
   CoordMode, Caret
   WinClose, ahk_id %hBall%
   GuiControlGet, Focus, Focus
   if !InStr(Focus, &quot;Edit&quot;)
      Return

   if wp in 3,8,24,26   ; обработка Ctrl + C, BackSpace, Ctrl + X, Ctrl + Z
      Return

   if wp = 22   ; обработка Ctrl + V
   {
      GuiControlGet, Content,, % Focus
      if !StrLen(String := SubStr(Clipboard, 1, 3 - StrLen(Content)))
      {
         ShowBall(&quot;Буфер обмена не содержит текста.&quot;, &quot;Ошибка!&quot;)
         Return 0
      }
      Loop, parse, String
      {
         Text .= A_LoopField
         if A_LoopField not in 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,A,B,C,D,E,F
         {
            ShowBall(&quot;Буфер обмена содержит недопустимые символы.&quot;
               . &quot;`nДопустимые символы:`n0123456789ABCDEF&quot;, &quot;Ошибка!&quot;)
            Return 0
         }
      }
      Control, EditPaste, % Text, % Focus, Коды клавиш
      Return 0
   }

   Char := Chr(wp)
   if Char not in 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,A,B,C,D,E,F
   {
      ShowBall(&quot;Допустимые символы:`n0123456789ABCDEF&quot;, Char &quot; — недопустимый символ&quot;)
      Return 0
   }
   Return
}

ShowBall(Text, Title=&quot;&quot;)
{
   global
   WinClose, ahk_id %hBall%
   hBall := TrackToolTip(Text, A_CaretX+1, A_CaretY+15, Title)
   SetTimer, BallDestroy, -2000
   Return

BallDestroy:
   WinClose, ahk_id %hBall%
   Return
}</code></pre></div><p>Скрипт осуществляет перехват нажатий клавиш посредством установки <a href="http://forum.script-coding.com/viewtopic.php?id=6350">клавиатурного хука</a>. Его <a href="http://script-coding.com/AutoHotkey/RegisterCallback.html">callback-функция</a> <a href="http://msdn.microsoft.com/en-us/library/ms644985%28VS.85%29.aspx">LowLevelKeyboardProc</a> при каждом клавиатурном событии получает описывающие его парметры, из которых можно извлечь vk и sc нажатых клавиш, после чего можно получить их название с помощью команды <em>GetKeyName</em>.<br />Спасибо <strong>YMP</strong> за <a href="http://forum.script-coding.com/viewtopic.php?pid=47289#p47289">помощь</a> при создании скрипта.<br /><a href="http://forum.script-coding.com/viewtopic.php?id=5686">Тема для обсуждения на форуме</a>.</p>]]></content>
			<author>
				<name><![CDATA[teadrinker]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=24515</uri>
			</author>
			<updated>2011-04-03T09:46:05Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=47330#p47330</id>
		</entry>
</feed>
