1 (изменено: teadrinker, 2011-04-03 23:04:38)

Тема: AHK: Определение виртуальных и сканкодов клавиатуры

Давно хотел написать удобный скрипт для определения виртуальных и сканкодов, ибо тот, что есть в Коллекции, довольно убог.

Скрипт определяет виртуальный (vk) и сканкод (sc) клавиши при её нажатии, а также название клавиши по её vk или sc. Полученный код можно скопировать в буфер обмена в виде vkFF или scFF (т. е. в виде, пригодном для использования в AHK-коде для обозначения горячих клавиш) с помощью кнопки "Copy".

Когда активно окно скрипта и открыта вкладка "Получить код", скрипт предотвращает системную обработку нажатий всех клавиш, кроме Alt, Ctrl, Shift и Tab, кроме того, переключается статус Num Lock (от этого зависят виртуальные коды цифровой клавиатуры), но не переключается его светодиод. По сочетанию Ctrl + Tab можно осуществить переход между вкладками, Tab — переключение между контролами, Alt + F4 — завершение работы скрипта.

   Menu, Tray, Icon, Shell32.dll, 45

; клавиши дополнительной клавиатуры и Pause, sc которых ф-ция MapVirtualKey не определяет
   ScVk := "45,13|11D,A3|135,6F|136,A1|137,2C|138,A5|145,90|147,24|148,26|149,21|"
         . "14B,25|14D,27|14F,23|150,28|151,22|152,2D|153,2E|15B,5B|15C,5C|15D,5D"

; клавиши мыши и их vk, а также Ctrl+Break и Clear
   KeysVK := "LButton,1|RButton,2|Ctrl+Break,3|MButton,4|XButton1,5|XButton2,6|"
           . "Clear,c|Shift,10|Ctrl,11|Alt,12"

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

   Gui, Color, DAD6CA
   Gui, Add, Tab2, vTab gTab x0 y0 w200 h185 AltSubmit hwndhTab, Получить код|Клавиша по коду
   Tab = 2
   VarSetCapacity(RECT, 16)
   SendMessage, TCM_GETITEMRECT := 0x130A, 1, &RECT,, ahk_id %hTab%
   TabH := NumGet(RECT, 12)
   GuiControl, Move, Tab, % "x0 y0 w200 h" TabH + Height
   Gui, Add, Text, % "x8 y" TabH + 8 " w183 +" SS_GRAYFRAME := 0x8 " h" 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, % "x8 y" TabH + 8 " w183 +" SS_GRAYFRAME " h" Height - 16
   Gui, Add, Text, x15 yp+7 w170 c0033BB
      , Введите код`nв шестнадцатеричном формате без префикса "0x"

   Gui, Font, q5 s11
   Gui, Add, Text, xp yp+58, vk
   Gui, Add, Edit, vEditVK gGetKey xp+25 yp-2 w45 h23 Limit3 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, % "w199 h" TabH + Height - 1, Коды клавиш

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

Tab:                            ; whenever the user switches to a new tab, the output variable will
   If (Tab = 2 && !hHookKeybd)  ; be set to the previously selected tab number in the case of AltSubmit.
      hHookKeybd := SetWindowsHookEx()
   Else if (Tab = 1 && hHookKeybd)
      DllCall("UnhookWindowsHookEx", UInt, hHookKeybd), hHookKeybd := ""
   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
   Code := RegExReplace(Code, "^0+")
   Code := "0x" . Code
   SetFormat, IntegerFast, H
   if A_GuiControl = EditVK
   {
      if (Code > 0xA5 && Code < 0xBA)
         Key := "", IsKey := 1

      Loop, parse, KeysVK, |
      {
         if (Substr(Code, 3) = RegExReplace(A_LoopField, ".*,(.*)", "$1"))
         {
            Key := RegExReplace(A_LoopField, "(.*),.*", "$1")
            IsKey = 1
            Break
         }
      }

      if !IsKey
      {
         Loop, parse, ScVk, |
         {
            if (Code = "0x" . RegExReplace(A_LoopField, ".*,(.*)", "$1"))
            {
               Code := RegExReplace(A_LoopField, "(.*),.*", "0x$1")
               IsCode = 1
               Break
            }
         }
         if !IsCode
            Code := DllCall("MapVirtualKey", UInt, Code, UInt, MAPVK_VK_TO_VSC := 0)
      }
   }
   else if (Code = 0x56 || Code > 0x1FF)
      Key := "", IsKey := 1

   if !IsKey
      Key := GetKeyNameText(Code)

   Key := RegExReplace(Key, "(.*)Windows", "$1Win")
   GuiControl,, % "Key" SubStr(A_GuiControl, -1), % Key
   Key := IsKey := IsCode := ""
   Return

GuiClose:
   ExitApp

Exit:
   if hHookKeybd
      DllCall("UnhookWindowsHookEx", UInt, hHookKeybd)
   ExitApp

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

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx"
            , Int, WH_KEYBOARD_LL := 13
            , UInt, RegisterCallback("LowLevelKeyboardProc", "Fast")
            , UInt, DllCall("GetModuleHandle", UInt, 0)
            , UInt, 0)
}

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

   Critical
   SetFormat, IntegerFast, H
   vk := NumGet(lParam+0)
   Extended := NumGet(lParam+0, 8) & 1
   sc := (Extended<<8)|NumGet(lParam+0, 4)
   sc := sc = 0x136 ? 0x36 : sc
   Key := GetKeyNameText(sc)

   if (wParam = WM_SYSKEYDOWN || wParam = WM_KEYDOWN)
   {
      GuiControl,, Key, % Key
      GuiControl,, VK, % vk
      GuiControl,, SC, % sc
   }

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

   if Key Contains Ctrl,Alt,Shift,Tab
      Return CallNextHookEx(nCode, wParam, lParam)

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

   Return nCode < 0 ? CallNextHookEx(nCode, wParam, lParam) : 1
}

CallNextHookEx(nCode, wp, lp)
{
   Return DllCall("CallNextHookEx", UInt, 0, Int, nCode, UInt, wp, UInt, lp)
}

GetKeyNameText(sc)
{
   VarSetCapacity(Key, A_IsUnicode ? 32 : 16)
   DllCall("GetKeyNameText", UInt, sc<<16, Str, Key, UInt, 16)
   if Key in Shift,Ctrl,Alt
      Key := "Left " . Key
   Return Key
}

WM_CHAR(wp, lp)
{
   global hBall
   SetWinDelay, 0
   CoordMode, Caret
   WinClose, ahk_id %hBall%
   GuiControlGet, Focus, Focus
   if !InStr(Focus, "Edit")
      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("Буфер обмена не содержит текста.", "Ошибка!")
         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("Буфер обмена содержит недопустимые символы."
               . "`nДопустимые символы:`n0123456789ABCDEF", "Ошибка!")
            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("Допустимые символы:`n0123456789ABCDEF", Char " — недопустимый символ")
      Return 0
   }
   Return
}

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

BallDestroy:
   WinClose, ahk_id %hBall%
   Return
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; BalloonTip — это ToolTip с хвостиком
   ; h_icon — 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon.

   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON|TTS_CLOSE
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   VarSetCapacity(TOOLINFO, 40)
   NumPut(40, TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)       ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, 36)

   A_DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, 500         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1042,, x|(y<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW

   DetectHiddenWindows, % A_DHW
   Return hWnd
}

Скрипт осуществляет перехват нажатий клавиш посредством установки клавиатурного хука. Его callback-функция LowLevelKeyboardProc при каждом клавиатурном событии получает описывающме его парметры, из которых можно извлечь vk и sc нажатых клавиш, после чего можно получить их название с помощью функции GetKeyNameText.

Протестируйте, у всех ли хорошо работает. Конструктивная критика приветствуется.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

2 (изменено: ilya20069, 2011-04-02 00:02:58)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Машина Acer Extensa 4220
Со всей клавиатурой работает нормально (Даже перебил программу Mkey)
Показывает, но не предотвращает срабатывание спец. кнопок которые включают/выключают WiFi/Bluetooth.
Кнопка Power также срабатывает.

3

Re: AHK: Определение виртуальных и сканкодов клавиатуры

ilya20069 пишет:

Показывает, но не предотвращает срабатывание спец. кнопок которые включают/выключают WiFi/Bluetooth.
Кнопка Power также срабатывает.

Значит, система их не видит, наверное. Или не может предотвратить их срабатывание.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

4 (изменено: ilya20069, 2011-04-02 00:26:17)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Ну дык, ежу понятно что не видит или не может . Я просто указал недочеты. А то давно хочу повесить на кнопку Power какой нибудь веселый скрипт вместо выключения)

Кстати когда я вешал на эти спец. кнопки скрипты, родное назначение глушилось. А настройки кнопки Power в системе есть - Экран => Заставка => Питание => Дополнительно => Кнопки питания - раз можно изменить функцию значит система все-таки видит.

5

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Отличная программка получилась. Глюков пока не заметил. Но не все названия клавиш полностью умещаются, получается "Page Dow", "Scroll L". И ещё заметил, что в шестнадцатеричных числах в AHK_L буквы в верхнем регистре, а в AHK в нижнем. Числа вроде 0xa как-то не очень смотрятся.

6

Re: AHK: Определение виртуальных и сканкодов клавиатуры

YMP пишет:

Но не все названия клавиш полностью умещаются, получается "Page Dow", "Scroll L".

Странно, у меня так:

   http://s53.radikal.ru/i140/1104/cd/2db275098ee2.png

Правда, на обычном AHK не пробовал, у меня нету его.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

7 (изменено: YMP, 2011-04-02 07:35:38)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Сейчас уточнил: обрезает только на AHK_Lw. Видимо, дело в этом:

VarSetCapacity(Key, 15)

Маловато места для имени в Юникоде. А размер буфера в GetKeyNameText почему-то указан как 50 символов.

У меня заголовок окна не полностью виден, а как "Коды клави..." и дальше уже кнопки идут. Может, изменить его на "Коды клавиш"? Тогда влезает, да и понятнее вроде.

8

Re: AHK: Определение виртуальных и сканкодов клавиатуры

YMP пишет:

Маловато места для имени в Юникоде.

Кстати, а почему? Ведь кодировка в Utf-8 до 128 символа соответствует ASCII, вроде?

YMP пишет:

Может, изменить его на "Коды клавиш"?

Можно.

YMP пишет:

И ещё заметил, что в шестнадцатеричных числах в AHK_L буквы в верхнем регистре, а в AHK в нижнем. Числа вроде 0xa как-то не очень смотрятся.

А стоит ли ориентироваться на AHK-Basic? Ведь он перестал обновляться. Я буду пропагандировать переход на AHK_L, там и массивы появились, и поддержка COM.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

9

Re: AHK: Определение виртуальных и сканкодов клавиатуры

teadrinker пишет:

Кстати, а почему? Ведь кодировка в Utf-8 до 128 символа соответствует ASCII, вроде?

Да, но API-функции с UTF-8 не работают, только с UTF-16. Да и сам AHK_Lw все строки в памяти держит в UTF-16. При загрузке скрипта происходит перекодирование из UTF-8 в UTF-16.

teadrinker пишет:

А стоит ли ориентироваться на Pure_AHK? Ведь он перестал обновляться. Я буду пропагандировать переход на AHK_L, там и массивы появились, и поддержка COM

Ну тогда, думаю, надо предупреждать, для какой версии разработан скрипт. Ещё много народу пользуется старым.

10 (изменено: teadrinker, 2011-04-03 23:04:23)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

YMP пишет:

Да, но API-функции с UTF-8 не работают, только с UTF-16. Да и сам AHK_Lw все строки в памяти держит в UTF-16. При загрузке скрипта происходит перекодирование из UTF-8 в UTF-16.

Ага, ясно, спасибо.
Последний вариант, под AHK_La и AHK_Lw. Будет работать и под AHK-Basic, но с менее красивыми шрифтами.

   Menu, Tray, Icon, Shell32.dll, 45

; клавиши дополнительной клавиатуры и Pause, sc которых ф-ция MapVirtualKey не определяет
   ScVk := "45,13|11D,A3|135,6F|136,A1|137,2C|138,A5|145,90|147,24|148,26|149,21|"
         . "14B,25|14D,27|14F,23|150,28|151,22|152,2D|153,2E|15B,5B|15C,5C|15D,5D"

; клавиши мыши и их vk, а также Ctrl+Break и Clear
   KeysVK := "LButton,1|RButton,2|Ctrl+Break,3|MButton,4|XButton1,5|XButton2,6|"
           . "Clear,c|Shift,10|Ctrl,11|Alt,12"

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

   Gui, Color, DAD6CA
   Gui, Add, Tab2, vTab gTab x0 y0 w200 h185 AltSubmit hwndhTab, Получить код|Клавиша по коду
   Tab = 2
   VarSetCapacity(RECT, 16)
   SendMessage, TCM_GETITEMRECT := 0x130A, 1, &RECT,, ahk_id %hTab%
   TabH := NumGet(RECT, 12)
   GuiControl, Move, Tab, % "x0 y0 w200 h" TabH + Height
   Gui, Add, Text, % "x8 y" TabH + 8 " w183 +" SS_GRAYFRAME := 0x8 " h" 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, % "x8 y" TabH + 8 " w183 +" SS_GRAYFRAME " h" Height - 16
   Gui, Add, Text, x15 yp+7 w170 c0033BB
      , Введите код`nв шестнадцатеричном формате без префикса "0x"

   Gui, Font, q5 s11
   Gui, Add, Text, xp yp+58, vk
   Gui, Add, Edit, vEditVK gGetKey xp+25 yp-2 w45 h23 Limit3 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, % "w199 h" TabH + Height - 1, Коды клавиш

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

Tab:                            ; whenever the user switches to a new tab, the output variable will
   If (Tab = 2 && !hHookKeybd)  ; be set to the previously selected tab number in the case of AltSubmit.
      hHookKeybd := SetWindowsHookEx()
   Else if (Tab = 1 && hHookKeybd)
      DllCall("UnhookWindowsHookEx", UInt, hHookKeybd), hHookKeybd := ""
   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
   Code := RegExReplace(Code, "^0+")
   Code := "0x" . Code
   SetFormat, IntegerFast, H
   if A_GuiControl = EditVK
   {
      if (Code > 0xA5 && Code < 0xBA)
         Key := "", IsKey := 1

      Loop, parse, KeysVK, |
      {
         if (Substr(Code, 3) = RegExReplace(A_LoopField, ".*,(.*)", "$1"))
         {
            Key := RegExReplace(A_LoopField, "(.*),.*", "$1")
            IsKey = 1
            Break
         }
      }

      if !IsKey
      {
         Loop, parse, ScVk, |
         {
            if (Code = "0x" . RegExReplace(A_LoopField, ".*,(.*)", "$1"))
            {
               Code := RegExReplace(A_LoopField, "(.*),.*", "0x$1")
               IsCode = 1
               Break
            }
         }
         if !IsCode
            Code := DllCall("MapVirtualKey", UInt, Code, UInt, MAPVK_VK_TO_VSC := 0)
      }
   }
   else if (Code = 0x56 || Code > 0x1FF)
      Key := "", IsKey := 1

   if !IsKey
      Key := GetKeyNameText(Code)

   Key := RegExReplace(Key, "(.*)Windows", "$1Win")
   GuiControl,, % "Key" SubStr(A_GuiControl, -1), % Key
   Key := IsKey := IsCode := ""
   Return

GuiClose:
   ExitApp

Exit:
   if hHookKeybd
      DllCall("UnhookWindowsHookEx", UInt, hHookKeybd)
   ExitApp

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

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx"
            , Int, WH_KEYBOARD_LL := 13
            , UInt, RegisterCallback("LowLevelKeyboardProc", "Fast")
            , UInt, DllCall("GetModuleHandle", UInt, 0)
            , UInt, 0)
}

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

   Critical
   SetFormat, IntegerFast, H
   vk := NumGet(lParam+0)
   Extended := NumGet(lParam+0, 8) & 1
   sc := (Extended<<8)|NumGet(lParam+0, 4)
   sc := sc = 0x136 ? 0x36 : sc
   Key := GetKeyNameText(sc)

   if (wParam = WM_SYSKEYDOWN || wParam = WM_KEYDOWN)
   {
      GuiControl,, Key, % Key
      GuiControl,, VK, % vk
      GuiControl,, SC, % sc
   }

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

   if Key Contains Ctrl,Alt,Shift,Tab
      Return CallNextHookEx(nCode, wParam, lParam)

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

   Return nCode < 0 ? CallNextHookEx(nCode, wParam, lParam) : 1
}

CallNextHookEx(nCode, wp, lp)
{
   Return DllCall("CallNextHookEx", UInt, 0, Int, nCode, UInt, wp, UInt, lp)
}

GetKeyNameText(sc)
{
   VarSetCapacity(Key, A_IsUnicode ? 32 : 16)
   DllCall("GetKeyNameText", UInt, sc<<16, Str, Key, UInt, 16)
   if Key in Shift,Ctrl,Alt
      Key := "Left " . Key
   Return Key
}

WM_CHAR(wp, lp)
{
   global hBall
   SetWinDelay, 0
   CoordMode, Caret
   WinClose, ahk_id %hBall%
   GuiControlGet, Focus, Focus
   if !InStr(Focus, "Edit")
      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("Буфер обмена не содержит текста.", "Ошибка!")
         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("Буфер обмена содержит недопустимые символы."
               . "`nДопустимые символы:`n0123456789ABCDEF", "Ошибка!")
            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("Допустимые символы:`n0123456789ABCDEF", Char " — недопустимый символ")
      Return 0
   }
   Return
}

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

BallDestroy:
   WinClose, ahk_id %hBall%
   Return
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; BalloonTip — это ToolTip с хвостиком
   ; h_icon — 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon.

   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON|TTS_CLOSE
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   VarSetCapacity(TOOLINFO, 40)
   NumPut(40, TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)       ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, 36)

   A_DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, 500         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1042,, x|(y<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW

   DetectHiddenWindows, % A_DHW
   Return hWnd
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

11

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Сейчас не обрезает. Но вообще вызов GetKeyNameText у тебя некорректный. Размер буфера ей нужно указывать в символах, а у тебя в байтах, т.е. для AHK_Lw указанный размер в два раза больше реального.

12

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Вот, блин! Вот так, что ли, правильно будет для обоих вариантов?

VarSetCapacity(Key, A_IsUnicode ? 32 : 16)
DllCall("GetKeyNameText", UInt, sc<<16, Str, Key, UInt, 16)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

13

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Да, так правильно. Кстати, переменная Whith у тебя нигде не используется. Вообще-то и написано неправильно, надо Width.

14

Re: AHK: Определение виртуальных и сканкодов клавиатуры

YMP пишет:

Да, так правильно.

Или нет? Ведь

cchSize [in]

    Type: int

    The maximum length, in characters, of the key name, including the terminating null character.

А VarSetCapacity:

Specify for RequestedCapacity the length of string that the variable should be able to hold after the adjustment. This length does not include the internal zero terminator.

Значит, по идее, правильнее будет:

VarSetCapacity(Key, A_IsUnicode ? 32 : 16)
DllCall("GetKeyNameText", UInt, sc<<16, Str, Key, UInt, 17)

Хотя, наверное, не страшно, если буфер будет меньше выделенной вместимости.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

15

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Я обычно не принимаю в расчёт этот internal zero terminator. Строго говоря, как устроены переменные в АНК — это его внутреннее дело. Тем более, что в ANSI-версии это один нулевой байт, а в юникодной должно быть два байта. И в последнем случае RequestedCapacity — это не length of string, поскольку указывается всё равно в байтах, а не в символах. В общем, мне кажется, что лучше полагаться на то, что явно запрошено.

16 (изменено: teadrinker, 2011-04-03 23:03:58)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Последний вариант, исправлен маленький баг.

   Menu, Tray, Icon, Shell32.dll, 45

; клавиши дополнительной клавиатуры и Pause, sc которых ф-ция MapVirtualKey не определяет
   ScVk := "45,13|11D,A3|135,6F|136,A1|137,2C|138,A5|145,90|147,24|148,26|149,21|"
         . "14B,25|14D,27|14F,23|150,28|151,22|152,2D|153,2E|15B,5B|15C,5C|15D,5D"

; клавиши мыши и их vk, а также Ctrl+Break и Clear
   KeysVK := "LButton,1|RButton,2|Ctrl+Break,3|MButton,4|XButton1,5|XButton2,6|"
           . "Clear,c|Shift,10|Ctrl,11|Alt,12"

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

   Gui, Color, DAD6CA
   Gui, Add, Tab2, vTab gTab x0 y0 w200 h185 AltSubmit hwndhTab, Получить код|Клавиша по коду
   Tab = 2
   VarSetCapacity(RECT, 16)
   SendMessage, TCM_GETITEMRECT := 0x130A, 1, &RECT,, ahk_id %hTab%
   TabH := NumGet(RECT, 12)
   GuiControl, Move, Tab, % "x0 y0 w200 h" TabH + Height
   Gui, Add, Text, % "x8 y" TabH + 8 " w183 +" SS_GRAYFRAME := 0x8 " h" 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, % "x8 y" TabH + 8 " w183 +" SS_GRAYFRAME " h" Height - 16
   Gui, Add, Text, x15 yp+7 w170 c0033BB
      , Введите код`nв шестнадцатеричном формате без префикса "0x"

   Gui, Font, q5 s11
   Gui, Add, Text, xp yp+58, vk
   Gui, Add, Edit, vEditVK gGetKey xp+25 yp-2 w45 h23 Limit3 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, % "w199 h" TabH + Height - 1, Коды клавиш

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

Tab:                            ; whenever the user switches to a new tab, the output variable will
   If (Tab = 2 && !hHookKeybd)  ; be set to the previously selected tab number in the case of AltSubmit.
      hHookKeybd := SetWindowsHookEx()
   Else if (Tab = 1 && hHookKeybd)
      DllCall("UnhookWindowsHookEx", UInt, hHookKeybd), hHookKeybd := ""
   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
   Code := RegExReplace(Code, "^0+")
   Code := "0x" . Code
   SetFormat, IntegerFast, H
   if A_GuiControl = EditVK
   {
      if (Code > 0xA5 && Code < 0xBA)
         Key := "", IsKey := 1

      Loop, parse, KeysVK, |
      {
         if (Substr(Code, 3) = RegExReplace(A_LoopField, ".*,(.*)", "$1"))
         {
            Key := RegExReplace(A_LoopField, "(.*),.*", "$1")
            IsKey = 1
            Break
         }
      }

      if !IsKey
      {
         Loop, parse, ScVk, |
         {
            if (Code = "0x" . RegExReplace(A_LoopField, ".*,(.*)", "$1"))
            {
               Code := RegExReplace(A_LoopField, "(.*),.*", "0x$1")
               IsCode = 1
               Break
            }
         }
         if !IsCode
            Code := DllCall("MapVirtualKey", UInt, Code, UInt, MAPVK_VK_TO_VSC := 0)
      }
   }
   else if (Code = 0x56 || Code > 0x1FF)
      Key := "", IsKey := 1

   if !IsKey
      Key := GetKeyNameText(Code)

   Key := RegExReplace(Key, "(.*)Windows", "$1Win")
   GuiControl,, % "Key" SubStr(A_GuiControl, -1), % Key
   Key := IsKey := IsCode := ""
   Return

GuiClose:
   ExitApp

Exit:
   if hHookKeybd
      DllCall("UnhookWindowsHookEx", UInt, hHookKeybd)
   ExitApp

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

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx"
            , Int, WH_KEYBOARD_LL := 13
            , UInt, RegisterCallback("LowLevelKeyboardProc", "Fast")
            , UInt, DllCall("GetModuleHandle", UInt, 0)
            , UInt, 0)
}

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

   Critical
   SetFormat, IntegerFast, H
   vk := NumGet(lParam+0)
   Extended := NumGet(lParam+0, 8) & 1
   sc := (Extended<<8)|NumGet(lParam+0, 4)
   sc := sc = 0x136 ? 0x36 : sc
   Key := GetKeyNameText(sc)

   if (wParam = WM_SYSKEYDOWN || wParam = WM_KEYDOWN)
   {
      GuiControl,, Key, % Key
      GuiControl,, VK, % vk
      GuiControl,, SC, % sc
   }

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

   if Key Contains Ctrl,Alt,Shift,Tab
      Return CallNextHookEx(nCode, wParam, lParam)

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

   Return nCode < 0 ? CallNextHookEx(nCode, wParam, lParam) : 1
}

CallNextHookEx(nCode, wp, lp)
{
   Return DllCall("CallNextHookEx", UInt, 0, Int, nCode, UInt, wp, UInt, lp)
}

GetKeyNameText(sc)
{
   VarSetCapacity(Key, A_IsUnicode ? 32 : 16)
   DllCall("GetKeyNameText", UInt, sc<<16, Str, Key, UInt, 16)
   if Key in Shift,Ctrl,Alt
      Key := "Left " . Key
   Return Key
}

WM_CHAR(wp, lp)
{
   global hBall
   SetWinDelay, 0
   CoordMode, Caret
   WinClose, ahk_id %hBall%
   GuiControlGet, Focus, Focus
   if !InStr(Focus, "Edit")
      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("Буфер обмена не содержит текста.", "Ошибка!")
         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("Буфер обмена содержит недопустимые символы."
               . "`nДопустимые символы:`n0123456789ABCDEF", "Ошибка!")
            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("Допустимые символы:`n0123456789ABCDEF", Char " — недопустимый символ")
      Return 0
   }
   Return
}

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

BallDestroy:
   WinClose, ahk_id %hBall%
   Return
}

BalloonTip(x, y, sText, sTitle = "", h_icon = 0)
{
   ; BalloonTip — это ToolTip с хвостиком
   ; h_icon — 1:Info, 2: Warning, 3: Error, n > 3: предполагается hIcon.

   TTS_NOPREFIX := 2, TTS_ALWAYSTIP := 1, TTS_BALLOON := 0x40, TTS_CLOSE := 0x80

   hWnd := DllCall("CreateWindowEx", UInt, WS_EX_TOPMOST := 8
                                   , Str, "tooltips_class32", Str, ""
                                   , UInt, TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON|TTS_CLOSE
                                   , Int, 0, Int, 0, Int, 0, Int, 0
                                   , UInt, 0, UInt, 0, UInt, 0, UInt, 0)
   VarSetCapacity(TOOLINFO, 40)
   NumPut(40, TOOLINFO)
   NumPut(0x20, TOOLINFO, 4)       ; TTF_TRACK = 0x20
   NumPut(&sText, TOOLINFO, 36)

   A_DHW := A_DetectHiddenWindows
   DetectHiddenWindows, On
   WinWait, ahk_id %hWnd%

   SendMessage, 1048,, 500         ; TTM_SETMAXTIPWIDTH
   SendMessage, 1028,, &TOOLINFO   ; TTM_ADDTOOL
   SendMessage, 1042,, x|(y<<16)   ; TTM_TRACKPOSITION
   SendMessage, 1041, 1, &TOOLINFO ; TTM_TRACKACTIVATE
   SendMessage, 1056 + (A_IsUnicode ? 1 : 0), h_icon, &sTitle      ; TTM_SETTITLEA и TTM_SETTITLEW
   SendMessage, 1036 + (A_IsUnicode ? 45 : 0),, &TOOLINFO     ; TTM_UPDATETIPTEXTA и TTM_UPDATETIPTEXTW

   DetectHiddenWindows, % A_DHW
   Return hWnd
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

17 (изменено: teadrinker, 2011-04-03 23:06:15)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Чёрт, ещё нашёлся!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

18

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Аналогичный скрипт, создаёт окно, в котором отображается скан-код клавиши, а так же копирует этот скан-код в буфер обмена.

Скрипт мне дал друг, а где он его нашел - мне не известно...

#persistent
SetFormat, Integer, Hex
Gui +ToolWindow -SysMenu +AlwaysOnTop
Gui, Font, s14 Bold, Arial
Gui, Add, Text, w100 h33 vSC 0x201 +Border, {SC000}
Gui, Show,, % "// ScanCode //////////"
Loop 9
  OnMessage( 255+A_Index, "ScanCode" ) ; 0x100 to 0x108
Return
ScanCode( wParam, lParam ) {
 Clipboard := "SC" SubStr((((lParam>>16) & 0xFF)+0xF000),-2)
 GuiControl,, SC, %Clipboard%
}
return

19

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Не очень хорошо работает.
Например, для клавиши Left сканкод 0x14B, а он определяет 0x04B, что соответствует Num 4.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

20

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Скорее всего нашел тут.

21

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Как сделать, чтобы было при запуске окно скрипта поверх всего? Пробовал так:

WinSet, AlwaysOnTop, On, ahk_class AutoHotkeyGUI

- не помогло.

22

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Перед строчкой Gui, Color, DAD6CA добавь Gui, +AlwaysOnTop:

   ...
   Gui, +AlwaysOnTop
   Gui, Color, DAD6CA
   ...
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

23

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Помогло , спасибо.

24

Re: AHK: Определение виртуальных и сканкодов клавиатуры

К сожалению не работает как задумано на win7 x64:
http://savepic.su/912023m.png

25

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Нужно определить, почему не вычисляется TabH в 19 строке. Можно попробовать заменить

TabH := NumGet(RECT, 12)

на

TabH := NumGet(RECT, 12, "UInt")

В крайнем случае подставить подходящее значение вручную.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

26

Re: AHK: Определение виртуальных и сканкодов клавиатуры

После замены на

TabH := NumGet(RECT, 12, "UInt")

TabH вычисляется верно.

27

Re: AHK: Определение виртуальных и сканкодов клавиатуры

А, раньше просто "UInt" было по умолчанию, теперь "UPtr", в Win64 UPtr равно 32 битам, а UInt — 16.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

28

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Ой, то есть в Win64 UPtr равно 64 битам, а UInt — 32.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

29

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Смысл этой программы в том, что она определяет коды даже для тех клавиш, которые не всегда верно определяются с помощью клавиатурного хука, а кроме того, "гасит" существующие в данный момент в системе горячие клавиши, чтобы вместо определения их кодов не выполнялись их обработчики. Для того, чтобы определять названия клавиш по уже имеющемуся виртуальному коду, данная программа не нужна, достаточно воспользоваться GetKeyName(Key).

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

30 (изменено: Irbis, 2012-08-08 17:00:20)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Почему-то GetKeyVK() возвращает вирт.код только букв, которые есть в текущей  раскладке клавиатуры. В данном примере это видно, если переключить раскладку, а потом нажать "OK":

SetFormat, IntegerFast, h
MsgBox % "En - " GetKeyVK("W") "`n" "Ru - " GetKeyVK("Ц")
MsgBox % "En - " GetKeyVK("W") "`n" "Ru - " GetKeyVK("Ц")

GetKeySC() ведет себя точно так же. И как получить вирт. или скан-код для буквы "Q", к примеру, если текущая раскладка - русская?
(Имеется в виду, штатными средствами, не изобретая велосипед)

31

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Определить раскладку, если русская — переключить.

SetFormat, IntegerFast, H
VarSetCapacity(List, A_PtrSize*2)
DllCall("GetKeyboardLayoutList", Int, 2, Ptr, &List)
Locale1 := NumGet(List)
b := SubStr(Locale2 := NumGet(List, A_PtrSize), -3) = 0409
En := b ? Locale2 : Locale1
Ru := b ? Locale1 : Locale2

ThreadID := DllCall("GetWindowThreadProcessId", Ptr, WinExist("A"), UInt, 0, Ptr)
if DllCall("GetKeyboardLayout", Ptr, ThreadID, Ptr) = Ru
   SendMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, En,, A

MsgBox, % GetKeyVK("Q")

Потом можно переключить обратно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

32

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Результат нулевой, к сожалению. (В прямом смысле - MsgBox выдает 0x0, замена на "Q" на "Й" - работает...)

33

Re: AHK: Определение виртуальных и сканкодов клавиатуры

К сожалению, не могу протестировать данный код — у меня при любой раскладке "Q" определяется, а "Й" — нет. Возможно, следует добавить небольшую паузу:

SetFormat, IntegerFast, H
VarSetCapacity(List, A_PtrSize*2)
DllCall("GetKeyboardLayoutList", Int, 2, Ptr, &List)
Locale1 := NumGet(List)
b := SubStr(Locale2 := NumGet(List, A_PtrSize), -3) = 0409
En := b ? Locale2 : Locale1
Ru := b ? Locale1 : Locale2

ThreadID := DllCall("GetWindowThreadProcessId", Ptr, WinExist("A"), UInt, 0, Ptr)
if DllCall("GetKeyboardLayout", Ptr, ThreadID, Ptr) = Ru
{
   SendMessage, WM_INPUTLANGCHANGEREQUEST := 0x50,, En,, A
   Sleep, 100
}

MsgBox, % GetKeyVK("Q")
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

34

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Irbis пишет:

И как получить вирт. или скан-код для буквы "Q", к примеру, если текущая раскладка - русская?

Текущая раскладка чего? Здесь имеет значение раскладка окна скрипта, а не активного окна на экране. В вашем примере с MsgBox переключение работает, потому что MsgBox — тоже окно скрипта.

35

Re: AHK: Определение виртуальных и сканкодов клавиатуры

YMP, это и имелось в виду, для этого и вызывается MsgBox, чтоб переключить раскладку окна скрипта. Вот и имеется целью получить сканкод или вирт.код, не зависящий от текущей раскладки.

36 (изменено: YMP, 2012-08-09 09:45:16)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Можно проверять, что возвращает GetKeyVK() и переключать раскладку при необходимости. Если раскладки две, то так, например:

MsgBox, % GetVK("Q") "`n" GetVK("Й")

GetVK(Name)
{
    Prev := A_FormatInteger
    SetFormat, Integer, H
    if !(vk := GetKeyVK(Name)) {
        DetectHiddenWindows, On
        hWnd := WinExist(A_ScriptFullPath " - AutoHotkey")
        PostMessage, 0x50, 2,,, ahk_id %hWnd%
        Sleep, -1
        vk := GetKeyVK(Name)
        PostMessage, 0x50, 2,,, ahk_id %hWnd%
        Sleep, -1
        DetectHiddenWindows, Off
    }
    SetFormat, Integer, %Prev%
    return vk
}

37 (изменено: Irbis, 2012-08-09 16:30:10)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

DetectHiddenWindows, On !
Вот чего мне не хватило, чтоб практически аналогичный скрипт выдал такой же результат. Правда, я посчитал, что получение id скрипта таким способом излишне, раз есть встроенные переменные.
Но, как ни странно, даже A_ScriptHwnd не работает без DetectHiddenWindows. В общем, вместо

        hWnd := WinExist(A_ScriptFullPath " - AutoHotkey")
        PostMessage, 0x50, 2,,, ahk_id %hWnd%
        Sleep, -1

у меня просто

SendMessage, 0x50, 2,,, ahk_id %A_ScriptHwnd%

И еще, мне не совсем понятен смысл расчетов в процедуре GetVK() в HEX формате, ведь MsBox выводит десятичное значение (81, а не 0x51)?
Тогда уж SetFormat лучше поставить перед MsgBox в основном коде.

38

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Я просто был не в курсе, что уже есть A_ScriptHwnd.
WM_INPUTLANGCHANGEREQUEST, согласно MSDN, положено постить, а не сендить, так что я просто сделал, как положено.

MsgBox в моём коде у меня выводит в хексе, т.е. 0x51, так что не совсем понял ваш вопрос.

39

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Копирую и запускаю скрипт "As Is", вот что выдает AHK_L:
http://savepic.org/2450817.jpg

40

Re: AHK: Определение виртуальных и сканкодов клавиатуры

А у меня вот что:

---------------------------
DC08090E0801025B.AHK
---------------------------
0x51
0x51
---------------------------
ОК   
---------------------------

Одинаково на ANSI, Unicode, x64. Версия 1.1.08.00.

41

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Подозреваю, что дело может быть в этом:

1.1.08.00 - July 14, 2012

Breaking changes:

Changed return x to preserve formatting of numeric strings; it is now equivalent to return (x).

42 (изменено: Irbis, 2012-08-09 23:34:27)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Действительно, на "испытательной" машине была версия AHK_L 1.1.07.00. После обновления показания стали идентичны.
Хотя я тут прикинул... Ведь мне всего-то надо, чтобы из хоткея, полученного по команде Gui, Add, Hotkey, vHotkeyName получить его вирт.код, с сохранением модификаторов, разумеется.
Такое сужение поля (минус кириллица, минус строчные буквы ) не могло не сказаться на коде:

SetFormat, Integer, H
MsgBox % GetVK("^!Q") "`n" GetVK("+#Numpad9")
return

GetVK(HK)
{
   return RegExReplace(HK, "\w") "vk" Substr(StrLen(Name := RegExReplace(HK, "\W")) = 1 ? Asc(Name) : GetKeyVK(Name),3)
}

43

Re: AHK: Определение виртуальных и сканкодов клавиатуры

А как быть с такими комбинациями, как "^+-" или "^+]"?

44 (изменено: Irbis, 2012-08-10 23:46:44)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

YMP пишет:

А как быть с такими комбинациями, как "^+-" или "^+]"?

Легко

SetFormat, Integer, H
No_No_No_mr_YMP := True
Gui, Add, Hotkey, vChosenHotkey, ^+A
Gui, Show
return

#IF No_No_No_mr_YMP
*vkC0::
*vkDB::
*vkDD::
*vkBD::
*vkBB::
*vkBC::
*vkBE::
*vkBF::
*vkDC:: return
#IF

GuiClose:
No_No_No_mr_YMP := False
Gui, Submit
MsgBox % GetVK(ChosenHotkey)
ExitApp
 
GetVK(HK)
{
   return RegExReplace(HK, "\w") "vk" Substr(StrLen(Name := RegExReplace(HK, "\W")) = 1 ? Asc(Name) : GetKeyVK(Name),3)
}

Конечно, это шутка. А вот корректный (я надеюсь) код:

SetFormat, Integer, H
Gui, Add, Hotkey, vChosenHotkey, ^[
Gui, Add, CheckBox, gWin, WIN
Gui, Show
return

Win:
Win := !Win ? "#" : ""
return

GuiClose:
Gui, Submit
ChosenHotkey := Win ChosenHotkey
MsgBox % GetVK(ChosenHotkey)
ExitApp
 
return
 
GetVK(HK)
{
   return RegExReplace(HK, "[^+!\^#]") "vk" Substr(StrLen(Name := RegExReplace(HK, "[\^+!#]")) = 1 
                       && Asc(Name) > 0x40 && Asc(Name) < 0x5B ? Asc(Name) : GetKeyVK(Name),3)
}

45

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Irbis
Работает.

Кстати, ведь есть кнопки, у которых вирткоды совпадают — стрелки, Page Up/Down и иже с ними: обычные и их двойники на цифровой клавиатурке.

46

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Действительно, при выключенном NumLock'е такой эффект имеет место быть.
К счастью, меня это пока не очень волнует; как вариант - можно работать со сканкодами.

47

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Прикрутил Ваш код к своему скрипту, но вот есть вопрос. Надо чтоб при активации окна хук (перехват) включался только если он был включен непосредственно перед деактивацией, потому как по текущему табу не получится в моём случае. Может в какой то переменной содержится включен перехват или нет?

WM_ACTIVATE(wp)
{
global
if (wp & 0xFFFF = 0 && hHookKeybd)
    DllCall("UnhookWindowsHookEx", UInt, hHookKeybd), hHookKeybd := ""
   if (wp & 0xFFFF && Tab = 2 && !hHookKeybd)
    hHookKeybd := SetWindowsHookEx()
GuiControl,, Action, % wp & 0xFFFF = 0 ? "..." : "Кнопка"                 ;  %
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

48

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Не очень понял суть задачи, но в моём скрипте можно судить о том, включен ли перехват, по содержанию переменной hHookKeybd. Если она не пуста — перехват включен.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

49

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Вот спасибо! Сделал так


WM_ACTIVATE(wp)
{
global
if (wp & 0xFFFF = 0 && hHookKeybd)
{
PrevHookKeybd = %hHookKeybd%
DllCall("UnhookWindowsHookEx", UInt, hHookKeybd), hHookKeybd := ""
Return	
}
if PrevHookKeybd > 0
{
PrevHookKeybd = 0
hHookKeybd := SetWindowsHookEx()
Return
}
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

50

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Оффтоп, кросспостинг, расстрелять.

51

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Подскажите пожалуйста, каким образом эти команды
Код (AutoHotKey):
OnMessage(0x6, "WM_ACTIVATE")
 OnMessage(0x102, "WM_CHAR")

могут создавать такую проблему http://forum.script-coding.com/viewtopic.php?id=7563
Если их закомментировать, то всё в порядке.!?

удалил OnMessage(0x102, "WM_CHAR"), всё нормально стало. Правда так и непонял что это такое

Подскажите ещё пожалуйста, как мне добавить в ваш код, определение кнопок джойстика.

Gui, Add, Edit, vJoy w222
Gui, Show 
GetKeyState, joy_buttons, %JoystickNumber%JoyButtons
Loop
{
Loop, %joy_buttons%
{
GetKeyState, joy%a_index%, %JoystickNumber%joy%a_index%
if joy%a_index% = D
buttons_down = %JoystickNumber%Joy%a_index%
}
GuiControl, , Joy, %buttons_down%
Continue
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

52

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Про джойстик не подскажу за неимением оного.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

53

Re: AHK: Определение виртуальных и сканкодов клавиатуры

teadrinker пишет:

Про джойстик не подскажу за неимением оного.

Я так понял что просто хук на джойстик поставить нельзя, а вот как запустить этот цикл (или вообще любой другой) в вашем коде, чтобы в это же время обрабатывались также и все остальные кнопки, как это есть сейчас.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

54 (изменено: serzh82saratov, 2012-10-22 04:48:46)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Помогите пожалуйста нубу сообразить, как-бы мне тут сделать, чтоб при нажатиях Ctrl, Alt, Shift, Win ставились соответствующие чекбоксы?
Т.е. нажал Ctrl+Alt+1 - отметились чекбоксы и выплыл код единицы, нажал после этого просто 2 - чекбоксы опустели, выплыл код двойки.

	
#SingleInstance force
	Menu, Tray, Icon, Shell32.dll, 45
	KeysVK := "LButton,1|RButton,2|Ctrl+Break,3|MButton,4|XButton1,5|XButton2,6|"
			. "Clear,c|Shift,10|Ctrl,11|Alt,12|Browser_Back,a6"
	Gui, Color, B0C4DE
	Gui, Font, q5 s10, Verdana
	Gui, Add, Text, vKey Center x5 y5 w325
	Gui, Add, Edit, ReadOnly vVK -Background x5 yp+35 w260 h33 Center
	Gui, Add, Button, gCopyVK vCopyVK xp+265 h33 w60, Copy
	Gui, Add, CheckBox, xs+20 ys+182 w60 h40  vAlt, Alt
	Gui, Add, CheckBox, xp+60 yp w70 h40  vCtrl, Ctrl
	Gui, Add, CheckBox, xp+70 yp w80 h40  vShift, Shift
	Gui, Add, CheckBox, xp+80 yp w70 h40  vWIN, Win
	Gui, Show,  h225 w335, KeyCodeXBMC
	hHookKeybd := SetWindowsHookEx()
	OnExit, Exit
	OnMessage(0x6, "WM_ACTIVATE")
	Return

WM_ACTIVATE(wp)
{
	global
 if (wp & 0xFFFF = 0 && hHookKeybd)
	{
		PrevHookKeybd = %hHookKeybd%
		DllCall("UnhookWindowsHookEx", UInt, hHookKeybd), hHookKeybd := ""
		Return	
	}
 if PrevHookKeybd > 0
	{
		PrevHookKeybd = 0
		hHookKeybd := SetWindowsHookEx()
		Return
	}
}
SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx"
            , Int, WH_KEYBOARD_LL := 13
            , UInt, RegisterCallback("LowLevelKeyboardProc", "Fast")
            , UInt, DllCall("GetModuleHandle", UInt, 0)
            , UInt, 0)
}

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

   Critical
   SetFormat, IntegerFast, H
   vk := NumGet(lParam+0)
   Extended := NumGet(lParam+0, 8) & 1
   StringReplace, vk2, vk, 0x, vk
   KeyName := GetKeyName(vk2)
   StringReplace, vk, vk, 0x

   if (wParam = WM_SYSKEYDOWN || wParam = WM_KEYDOWN)
   {
      GuiControl,, Key, %KeyName%
      GuiControl,, VK, %vk%
   }

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

   if Key Contains Ctrl,Alt,Shift,Tab
      Return CallNextHookEx(nCode, wParam, lParam)

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

   Return nCode < 0 ? CallNextHookEx(nCode, wParam, lParam) : 1
}
   
CallNextHookEx(nCode, wp, lp)
{
   Return DllCall("CallNextHookEx", UInt, 0, Int, nCode, UInt, wp, UInt, lp)
}
	
CopyVK:
	Gui Submit, NoHide
	clipboard = %VK%
	GuiControl,, CopyVK, OK
	SLEEP 500
	GuiControl,, CopyVK, Copy
	Return
	
GuiClose:
   ExitApp

Exit:
   if hHookKeybd
      DllCall("UnhookWindowsHookEx", UInt, hHookKeybd)
   ExitApp

   
/* 
  if vk in A0,A1,A2,A3,A4,A5,5B

   GuiControl, , Shift, 0
   GuiControl, , Win, 0
   GuiControl, , Alt, 0
   GuiControl, , Ctrl, 0
   
   GuiControl, , Shift, 1
   GuiControl, , Win, 1
   GuiControl, , Alt, 1
   GuiControl, , Ctrl, 1
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

55

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Помогите пожалуйста нубу сообразить, как-бы мне тут сделать, чтоб при нажатиях Ctrl, Alt, Shift, Win ставились соответствующие чекбоксы?
Т.е. нажал Ctrl+Alt+1 - отметились чекбоксы и выплыл код единицы, нажал после этого просто 2 - чекбоксы опустели, выплыл код двойки.

Как вариант видимо надо как-то сделать, чтоб  при нажатии Ctrl, Alt, Shift, Win не было вызова LowLevelKeyboardProc, и просто установить хоткеи.
Вообщем полная каша, пните в нужном направлении, а то котелок не варит

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

56

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov пишет:

Вообщем полная каша

Это точно. Моя функция LowLevelKeyboardProc() не является универсальной, она предназначена только для моего скрипта и не годится для того, чтобы её бездумно вставлять куда угодно. Для решения твоей не вполне для меня ясной задачи нужен какой-то другой вариант, и какой именно, не смогу подсказать за незнанием глобальной цели твоего скрипта. Предлагаю для начала разобраться с принципами работы клавиатурного хука, а уже затем использовать его в своих программах.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

57 (изменено: serzh82saratov, 2012-10-23 01:25:11)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Для решения твоей не вполне для меня ясной задачи нужен какой-то другой вариант

Задачка распространённая,  скрипт "принимает" нажатия кнопок в том числе и вместе с нажатиями модификаторов, и записывает в память. Потом пользователь на записанные кнопки через GUI этого-же скрипта назначает выполнение нужных задач.

Предлагаю для начала разобраться с принципами работы клавиатурного хука

Да разобратся то очень хочется, но неможется.

а уже затем использовать его в своих программах

Такова печальная участь быдлокодера 

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

58

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Предлагаю для начала разобраться с принципами работы клавиатурного хука

Так понимаю, что где-то здесь "оно" начинается...


SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx"
            , Int, WH_KEYBOARD_LL := 13
            , UInt, RegisterCallback("LowLevelKeyboardProc", "Fast")
            , UInt, DllCall("GetModuleHandle", UInt, 0)
            , UInt, 0)
}

Но тут мне ни строки, не ясно. Конечно с десяток раз перечитал DllCall и RegisterCallback, но увы ничего не понял.
Тут без наставника не обойтись...

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

59 (изменено: Александр_, 2012-10-23 02:40:04)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov пишет:

Но тут мне ни строки, не ясно. Конечно с десяток раз перечитал DllCall и RegisterCallback, но увы ничего не понял.

Это потому, что данный код использует не столько возможности AHK, сколько возможности WinAPI- вот её и нужно изучать. Про хуки написано очень много, но с наскока в них не разобраться. Я начинал с книги Румянцева "Азбука программирования в Win32 API" и всячески её рекомендую. Конкретно про хуки хорошая статья на RSDN, но скорее всего будет просто не понятно о чём речь.

60

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Спасибо за совет. Т.е. после вдумчивого* прочтения, можно переходить к изучению статьи на RSDN?
Если выводы я сделать несмогу, то скорее всего и не дано?

* насколько это возможно неокрепшим мозгом дилетанта

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

61

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Ну и с этой темой не помешает ознакомиться.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

62

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov пишет:

Т.е. после вдумчивого* прочтения, можно переходить к изучению статьи на RSDN?

Книга написана так, что особо вдумываться не придётся. БОльшая часть книги это перевод документации с последующим примером. Соответственно и всю книгу тоже читать не придётся, но она пригодится как справочник. На самом деле "критическая" часть это часть между "предисловием" и главой "UNICODE", не включая эти главы, в этих 20-ти страницах описана реальная структура Windows-программы. Нужно знать что понимают под "сообщением" или "потоком" и уметь вызывать API-функции по их описанию.

serzh82saratov пишет:

Если выводы я сделать несмогу, то скорее всего и не дано?

Любой кто смог закончить школу, сможет научиться программировать, это определённо не сложная профессия.

63 (изменено: serzh82saratov, 2012-10-23 14:24:37)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

teadrinker пишет:

Ну и с этой темой не помешает ознакомиться.

То что надо.

   
#Persistent
   OnExit, Exit
   hHookKeybd := DllCall("SetWindowsHookEx"
      , Int, WH_KEYBOARD_LL := 13
      , UInt, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , UInt, DllCall("GetModuleHandle", UInt, 0)
      , UInt, 0)
   Return
 
Exit:
   DllCall("UnhookWindowsHookEx", UInt, hHookKeybd)
   ExitApp
 
LowLevelKeyboardProc(nCode, wParam, lParam)
{
   Critical
   SetFormat, Integer, H
   ToolTip, % wParam . "| vkCode: " . NumGet(lParam+0, 0) . " scCode: " . NumGet(lParam+0, 4)
      . " Extended: " . NumGet(lParam+0, 8) & 1 . " Time: " . NumGet(lParam+0, 12)
   Return DllCall("CallNextHookEx", UInt, 0, Int, nCode, UInt, wParam, UInt, lParam)
}

Подскажите, как сделать чтоб клавиатурные нажатия не проходили в систему, т.е. чтоб винда не реагировала на нажатия. Так и не пойму что их перехватывает.

Так понимаю что этот код можно использовать как базу, и к нему уже что то "лепить" если хочется что то добавить.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

64 (изменено: serzh82saratov, 2012-10-24 00:46:35)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Александр_ пишет:
serzh82saratov пишет:

Т.е. после вдумчивого* прочтения, можно переходить к изучению статьи на RSDN?

Книга написана так, что особо вдумываться не придётся. БОльшая часть книги это перевод документации с последующим примером. Соответственно и всю книгу тоже читать не придётся, но она пригодится как справочник. На самом деле "критическая" часть это часть между "предисловием" и главой "UNICODE", не включая эти главы, в этих 20-ти страницах описана реальная структура Windows-программы. Нужно знать что понимают под "сообщением" или "потоком" и уметь вызывать API-функции по их описанию.

Спасибо что по полочкам разложили. Статья на RSDN тоже очень познавательная, и хорошо переваримаемая.
-----------------
По сабжу так понял, что просто нужно внутри функции делать проверку нужных кнопок по GetKeyState или по VK и wParam. И при нажатии соответствующих выполнять отметку чекбоксов и далее рекурсию функции, или возврат...

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

65

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov спасибо за скрипт, а то я купил себе клавиатурку для просмотра фильмов (аля пульт) и было очень сложно узнать скан-коды.
А то что проскакивает код в систему это верно, но после определения кода - всё ОК.
Это раньше запускало плеер -

#Persistent
vkB5::
send {s}
return

Вопрос - можно отловить нажатие на Fn и ей подобные клавиши или это клавиатурный аппаратный модификатор?

"На каждое действие есть равная ему противодействующая критика." Постулат Харриссона
OS Windows 7 x64
AHK 1.1.30.01

66 (изменено: serzh82saratov, 2012-12-16 23:35:41)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Indomito пишет:

serzh82saratov спасибо за скрипт, а то я купил себе клавиатурку для просмотра фильмов (аля пульт) и было очень сложно узнать скан-коды.
А то что проскакивает код в систему это верно, но после определения кода - всё ОК.

Думаю вы ошиблись, и вам к teadrinker.
По счёт кнопки Fn, сам бы хотел знать.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

67

Re: AHK: Определение виртуальных и сканкодов клавиатуры

У меня, к сожалению, нет на клавиатуре этой кнопки.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

68

Re: AHK: Определение виртуальных и сканкодов клавиатуры

В вин7 есть на виртуальной. Коды остальных кнопок с неё определяются.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

69

Re: AHK: Определение виртуальных и сканкодов клавиатуры

teadrinker пишет:

У меня, к сожалению, нет на клавиатуре этой кнопки.

думаю не поможет и её наличие, т.к. она ни какой код не выдаёт, хотя всё бывает.....

"На каждое действие есть равная ему противодействующая критика." Постулат Харриссона
OS Windows 7 x64
AHK 1.1.30.01

70

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov пишет:

В вин7 есть на виртуальной. Коды остальных кнопок с неё определяются.

А у меня она почему-то не работает.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

71

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Отзыв по скрипту опубликованному в первом посте:
1. Помимо перечисленных

teadrinker пишет:

Когда активно окно скрипта и открыта вкладка "Получить код", скрипт предотвращает системную обработку нажатий всех клавиш, кроме Alt, Ctrl, Shift и Tab

А также Sleep (у меня на клавиатуре среди мультимедийных кнопок есть и такая).

В коде я также увидел это:

; клавиши мыши и их vk, а также Ctrl+Break и Clear
   KeysVK := "LButton,1|RButton,2|Ctrl+Break,3|MButton,4|XButton1,5|XButton2,6|"
           . "Clear,c|Shift,10|Ctrl,11|Alt,12"

у меня скрипт никак не реагирует на нажатие любых клавиш на мышке.

teadrinker пишет:

Протестируйте, у всех ли хорошо работает. Конструктивная критика приветствуется.

А ещё при нажатии media клавиш на клавиатуре - у некоторых показываются латинские буквы (как иллюстрация только что нажатой кнопки), т.к. у них сканкоды состоят из 3-ёх символов (после 0x), и последние два - точно такие как у тех латинских букв (у них не 3 а 2 символа после 0х).

Ещё бы историю нажатий прикрутить и было бы вообще замечательно.

72

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Drugoy пишет:

у меня скрипт никак не реагирует на нажатие любых клавиш на мышке.

Да, всё правильно. Там можно определить мышиные клавиши по коду, а наоборот нет. Не стал добавлять эту возможность, поскольку нет особого смысла указывать код вместо их реального названия.

Drugoy пишет:

А ещё при нажатии media клавиш на клавиатуре - у некоторых показываются латинские буквы

Будет время, попробую пофиксить эту проблему, но у меня, правда, клавиатура без медиа-клавиш.

Drugoy пишет:

Ещё бы историю нажатий прикрутить и было бы вообще замечательно.

Не знаю, по-моему данный скрипт не имеет смысла использовать для этой цели. Я его запускаю, только когда нужно узнать конкретный код, и сразу закрываю, какая там может быть история нажатий?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

73 (изменено: vlad1986, 2017-12-06 18:43:50)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Drugoy пишет:

А ещё при нажатии media клавиш на клавиатуре - у некоторых показываются латинские буквы

Подтверждаю. Некоторые определяются, как буквы. А есть мультимедийные клавиши, которые вообще никак не определяются.

74

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Когда создавался скрипт, у меня не было клавиатуры с мультимедийными клавишами, попозже подправлю.

vlad1986 пишет:

А есть мультимедийные клавиши, которые вообще никак не определяются.

Значит это чисто аппаратные клавиши, они не будут определяться. У меня из мультимедийных определяются только Volume_Mute, Volume_Up и  Volume_Down.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

75 (изменено: vlad1986, 2017-12-06 23:30:26)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

teadrinker пишет:

У меня из мультимедийных определяются только Volume_Mute, Volume_Up и  Volume_Down

Так же правильно определяются Media_Next, Media_Prev, Media_Play_Pause.

По поводу тех, что не определились вообще никак, на фотографии, это то, что находится на F4 (вкл\выкл микрофон) и F6 (запрашивает пароль для учетной записи).

http://i102.fastpic.ru/thumb/2017/1206/88/8d88e35553da736338ebff9046ee4c88.jpeg

76

Re: AHK: Определение виртуальных и сканкодов клавиатуры

А какие как буквы определяются?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

77 (изменено: vlad1986, 2017-12-08 17:40:10)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

F7 (поиск) определяется, как F (vk46).
F8 (Открывает Мой Компьютер) определяется, как E (vk45).
F9 (Печать) определяется, как P (vk50).

78 (изменено: serzh82saratov, 2017-12-08 12:01:18)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Так это просто они посылают сочетания клавиш Ctrl+F, Win+E, Ctrl+P, можете в ахкспай проверить. ММ клавиши тут не причём.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

79 (изменено: vlad1986, 2017-12-08 17:39:56)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov

А, точно. Значит придется танцевать с бубном, чтобы их идентифицировать.

80

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Если их сканкод не определяется можно пробовать через HID.

81

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Зачем HID? Не проще на vk хоткей сделать и просто скан проверить? Но я таких случаев не видел.

Ещё в таких случаях бывает что нажатие не физическое, и если не интересуют их эмулированные, то через GetKeyState(Key, "P") проверить.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

82

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Я так понял, что у vlad1986 сканкод клавиш не определяется.

83

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Так а HID что будет узнавать?

С GetKeySC я поспешил, но можно создать два хоткея ^sc19 и ^vk50, если сработает с vk50, то скан не определился.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

84

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov пишет:

Так а HID что будет узнавать?

Как я понимаю, попытается отлавливать ввод через Raw Input Api.

If your key or mouse button is not detectable by the Key History screen, one of the following might help:

    Reconfigure the software that came with your mouse or keyboard (sometimes accessible in the Control Panel or Start Menu) to have the "mystery key" send some other keystroke. Such a keystroke can then be defined as a hotkey in a script. For example, if you configure a mystery key to send Control+F1, you can then indirectly make that key as a hotkey by using ^F1:: in a script.

    Try AHKHID. You can also try searching the forum for a keywords like RawInput*, USB HID or AHKHID.

    The following is a last resort and generally should be attempted only in desperation. This is because the chance of success is low and it may cause unwanted side-effects that are difficult to undo:
    Disable or remove any extra software that came with your keyboard or mouse or change its driver to a more standard one such as the one built into the OS. This assumes there is such a driver for your particular keyboard or mouse and that you can live without the features provided by its custom driver and software.

https://autohotkey.com/docs/KeyList.htm#SpecialKeys

85

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Такая клава у меня на работе, поэтому я еще не имел возможности посмотреть, что показывает AHKSpy и еще не проверял правильные ли показываются сканкоды. Проверю и отпишусь завтра (в воскресенье)

86

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Malcev пишет:

Как я понимаю, попытается отлавливать ввод через Raw Input Api.

Так когда отловит, что смотреть?

vlad1986 пишет:

посмотреть, что показывает AHKSpy

Посмотрите ещё нет ли в первой строке "Not a physical press".

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

87

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov пишет:

Так когда отловит, что смотреть?

Не знаю. На практике данный метод использовать не приходилось.

88 (изменено: vlad1986, 2017-12-10 10:39:57)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Проблему свою понял -- наличие клавиши Fn на клавиатуре, хотя это не ноутбук.  Предварительный забег по гуглу показал, что ее средствами  Autohotkey не оседлать и даже просто не выключить. Комбинация Fn+num не работает, а отключать Fn через Биос или реестр нет возможности т.к это не домашний комп.

serzh82saratov пишет:

Посмотрите ещё нет ли в первой строке "Not a physical press".

Эту надпись показывает на всех мультимедийных клавишах, даже на тех, которые определяются правильно, например Volume_Mutte.

89

Re: AHK: Определение виртуальных и сканкодов клавиатуры

vlad1986 пишет:

Эту надпись показывает на всех мультимедийных клавишах, даже на тех, которые определяются правильно, например Volume_Mutte.

Это я знаю, на Ctrl+P показывает?

vlad1986 пишет:

Проблему свою понял -- наличие клавиши Fn на клавиатуре

Так речь же про то чтобы повесить хоткей на Ctrl+P, удостоверившись в том что она вызвана именно по F9, а не по Ctrl+P...

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

90

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov пишет:

Это я знаю, на Ctrl+P показывает?

Да, я это и имел в виду, что проверил все клавиши, на всех показывает.

http://i100.fastpic.ru/thumb/2017/1210/f8/a808a3b395da5fa4323dd85c4d25fbf8.jpeg http://i100.fastpic.ru/thumb/2017/1210/33/0535a881062f5faf323372dbc2d56133.jpeg http://i100.fastpic.ru/thumb/2017/1210/32/7b1d71be67c703a89a7b9114106e8932.jpeg

Кроме F4 (включение-выключение микрофона) и F6 (запрашивает пароль от учетной записи). На них AHKSpy так же не реагирует т.е не пишет вообще ничего, как-будто я эти клавиши не нажимал вообще.

91 (изменено: serzh82saratov, 2017-12-10 11:55:10)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

^vk50::MsgBox    ;  "Ctrl+P" 

Так блокируется их срабатывание?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

92

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov

Проверю на следующей смене и отпишусь.

93 (изменено: serzh82saratov, 2017-12-10 12:49:31)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Ну если блокируется, то это по идее должно срабатывать только при F9, а Ctrl+P оставлять как есть.

#If !GetKeyState("vk50", "P")
^vk50::MsgBox F9
#If
^vk50::MsgBox Ctrl+P
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

94 (изменено: svoboden, 2017-12-11 05:30:31)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

Вроде на AHK_H можно определить мультимедийные клавиши (вот тема для обсуждения).

95 (изменено: vlad1986, 2017-12-12 17:48:35)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov пишет:
^vk50::MsgBox    ;  "Ctrl+P" 

Так блокируется их срабатывание?

Да, блокируется.

serzh82saratov пишет:

Ну если блокируется, то это по идее должно срабатывать только при F9, а Ctrl+P оставлять как есть.

Срабатывает MsgBox Ctrl+P.

96

Re: AHK: Определение виртуальных и сканкодов клавиатуры

В смысле так по F9 появляется MsgBox Ctrl+P?


#If !GetKeyState("vk50", "P")
^vk50::MsgBox F9
#If
^vk50::MsgBox Ctrl+P
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

97 (изменено: vlad1986, 2017-12-12 19:59:26)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov

Да, по нажатию F9.

98

Re: AHK: Определение виртуальных и сканкодов клавиатуры

А скан код какой показывает?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

99 (изменено: vlad1986, 2017-12-12 20:18:09)

Re: AHK: Определение виртуальных и сканкодов клавиатуры

serzh82saratov

Скриншот, который я снимал до этого.

http://i100.fastpic.ru/thumb/2017/1210/32/7b1d71be67c703a89a7b9114106e8932.jpeg

100

Re: AHK: Определение виртуальных и сканкодов клавиатуры

А, да.
А так:


#If !GetKeyState("sc19", "P")
^vk50::MsgBox F9
#If

или так:


#If !GetKeyState("vk50", "P")
^vk50::MsgBox F9
#If
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui