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
Telegram jollycoder

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
Telegram jollycoder

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
Telegram jollycoder

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
Telegram jollycoder

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
Telegram jollycoder

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
Telegram jollycoder

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
Telegram jollycoder

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
Telegram jollycoder

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

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

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

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

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
Telegram jollycoder

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
Telegram jollycoder

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
Telegram jollycoder

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
Telegram jollycoder

28

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

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

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

29

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

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

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

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
Telegram jollycoder

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
Telegram jollycoder

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 Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

48

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

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

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

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 Telegram: https://t.me/sergiol982
Win10x64 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 Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

52

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

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

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

53

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

teadrinker пишет:

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

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 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 Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

55

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

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

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

56

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

serzh82saratov пишет:

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

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

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

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

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

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

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

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

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

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

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 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 Telegram: https://t.me/sergiol982
Win10x64 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 Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

61

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

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

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

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 Telegram: https://t.me/sergiol982
Win10x64 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 Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

65

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

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

#Persistent
vkB5::
send {s}
return

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

"На каждое действие есть равная ему противодействующая критика." Постулат Харриссона
OS Windows 7 x64
AutoHotkey v1.1.32.00 - November 24, 2019
Click to Download

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

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

Indomito пишет:

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

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

67

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

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

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

68