1 (изменено: Foma, 2019-01-05 22:49:23)

Тема: AHK: Визуализация нажатий клавиш

Не нашёл ни одной нормальной программы, корректно выполняющей  эту задачу. И тут поиском не нашёл ничего подходящего для этой цели. Неужели даже для основы ничего нет?

PS. Это не про кейлогер, а про визуализацию.

2

Re: AHK: Визуализация нажатий клавиш

А про что тема?

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

3

Re: AHK: Визуализация нажатий клавиш

Foma, если я правильно понял, нажатая клавиша должна отображаться на экране? Или она должна высвечиваться в списке всех клавиш?

AutoHotkey - 1.1.32.00

4

Re: AHK: Визуализация нажатий клавиш

Мне нужно вывести на экран все нажимаемые, а также удерживаемые клавиши. Даже если 5 сразу или больше. Причём не только хоткеи, а любые, которые будут нажаты или удерживаемы.
  Видел такое пару раз в учебных видео для игр или других программ со сложным управлением.

5 (изменено: Foma, 2019-01-05 23:50:22)

Re: AHK: Визуализация нажатий клавиш

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

https://d.radikal.ru/d32/1901/c8/8a637626588c.png

6 (изменено: serzh82saratov, 2019-01-06 01:17:29)

Re: AHK: Визуализация нажатий клавиш

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


#SingleInstance Force
#NoEnv
ListLines Off
SetBatchLines -1
AutoTrim, Off
CoordMode, ToolTip

DllCall("PostMessage", "Ptr", A_ScriptHWND, "UInt", 0x50, "UInt", 0, "UInt", 0x409) ; eng layout

hHookKeybd := DllCall("SetWindowsHookEx"
	, Int, WH_KEYBOARD_LL := 13
	, Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
	, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
	, UInt, 0, Ptr)
OnExit( Func("Exit").Bind(hHookKeybd) )
Return

Esc::ExitApp

Exit(hHookKeybd)  {
	DllCall("UnhookWindowsHookEx", Ptr, hHookKeybd)
}

LowLevelKeyboardProc(nCode, wParam, lParam)  {
	static oMem := [], lpData, size := VarSetCapacity(lpData, 16, 0)

	DllCall("RtlMoveMemory", Ptr, &lpData, Ptr, lParam, Ptr, size)
	oMem.Push([wParam, &lpData])
	timer := Func("EventHandling").Bind(oMem)  ; во избежание фризов клавиатуры обработка событий должна
	SetTimer, % timer, -10                     ; происходить обязательно по таймеру, а не в теле этой функции
	Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
}

EventHandling(oMem)  {
	static oMembers := ["vk", "sc", "flags"]
		, oFlagOffsets := {LLKHF_EXTENDED: 0, LLKHF_UP: 7}
		, oArr := {}, Str := " > " 
		
	while (oMem[1] != "")   {
		key := oMem.RemoveAt(1)
		lp := key[2]
		
		for k, v in oMembers
			%v% := NumGet(lp + (k - 1)*4, "UInt")

		for k, v in oFlagOffsets
			%k% := (flags >> v) & 1 
			
		sc |= LLKHF_EXTENDED << 8
		vkCode := Format("vk{:X}", vk) 
		scCode := Format("sc{:X}", sc)
		
		If LLKHF_UP
		{  
			Str := StrReplace(Str, " > " oArr.Delete(vkCode . scCode) " > ", " > ", , 1) 
		}		
		Else If (oArr[vkCode . scCode] = "")
		{
			Str := Str . (oArr[vkCode . scCode] := GetKeyName(vkCode . scCode)) . " > "
		}
		ToolTip % Str, 5, 5, 2
	}
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

7 (изменено: serzh82saratov, 2019-01-06 03:00:03)

Re: AHK: Визуализация нажатий клавиш

Если только с костылём GetKeyState.

#SingleInstance Force
#NoEnv
ListLines Off
SetBatchLines -1
AutoTrim, Off
CoordMode, ToolTip

DllCall("PostMessage", "Ptr", A_ScriptHWND, "UInt", 0x50, "UInt", 0, "UInt", 0x409) ; eng layout

hHookKeybd := DllCall("SetWindowsHookEx"
	, Int, WH_KEYBOARD_LL := 13
	, Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
	, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
	, UInt, 0, Ptr)
OnExit( Func("Exit").Bind(hHookKeybd) )
Return

Esc::ExitApp

Exit(hHookKeybd)  {
	DllCall("UnhookWindowsHookEx", Ptr, hHookKeybd)
}
   
LowLevelKeyboardProc(nCode, wParam, lParam)  {
	static oMem := [], lpData, size := VarSetCapacity(lpData, 16 + A_PtrSize*2, 0)

	DllCall("RtlMoveMemory", Ptr, &lpData, Ptr, lParam, Ptr, size)
	oMem.Push([wParam, &lpData])
	timer := Func("EventHandling").Bind(oMem)  ; во избежание фризов клавиатуры обработка событий должна
	SetTimer, % timer, -10                     ; происходить обязательно по таймеру, а не в теле этой функции
	Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
}

EventHandling(oMem)  {
	static oMembers := ["vk", "sc", "flags"]
		, oFlagOffsets := {LLKHF_EXTENDED: 0, LLKHF_UP: 7}
		, oArr := {}, Str := " > " 
		
	while (oMem[1] != "")   {
		key := oMem.RemoveAt(1)
		lp := key[2]
		for k, v in oMembers
			%v% := NumGet(lp + (k - 1)*4, "UInt")

		for k, v in oFlagOffsets
			%k% := (flags >> v) & 1  
			
		sc |= LLKHF_EXTENDED << 8
		vkCode := Format("vk{:X}", vk) 
		scCode := Format("sc{:X}", sc)
		
		If LLKHF_UP
		{  
			Str := StrReplace(Str, " > " oArr.Delete(vkCode . scCode) " > ", " > ", , 1) 
		}		
		Else If (oArr[vkCode . scCode] = "")
		{
			Str := Str . (oArr[vkCode . scCode] := GetKeyName(vkCode . scCode)) . " > "
			SetTimer, KeyState, 100
		}
		ToolTip % Str, 5, 5, 2
	}
	Return
	
	KeyState: 
		If !oArr.Count()
			SetTimer, KeyState, Off
		Else
			For k, v in oArr
			{
				If GetKeyState(v, "P")
					Continue
				Str := StrReplace(Str, " > " oArr.Delete(k) " > ", " > ", , 1) 
				ToolTip % Str, 5, 5, 2
			}
		Return
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

8

Re: AHK: Визуализация нажатий клавиш

Попробовал. Замечательно работает, спасибо.
Подумаю надо ли добавить какую-то минимальную задержку, чтобы клавиши которые были быстро отпущены не исчезали мгновенно.

9

Re: AHK: Визуализация нажатий клавиш

Меня в принципе в таком виде всё устраивает, но если Вам интересно довести код до совершенства:
1. Один разделитель в ToolTip остаётся после прекращения всех нажатий
2. Если нажатий много одновременно, то некоторые клавиши тоже остаются выведенными, как будто всё ещё нажаты. Пропадают после повторного их нажатия и отпускания.

10 (изменено: serzh82saratov, 2019-01-06 13:36:16)

Re: AHK: Визуализация нажатий клавиш

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

некоторые клавиши тоже остаются выведенными

У меня и в том и в этом варианте ни разу такого не было.


#SingleInstance Force
#NoEnv
ListLines Off
SetBatchLines -1
AutoTrim, Off
CoordMode, ToolTip

DllCall("PostMessage", "Ptr", A_ScriptHWND, "UInt", 0x50, "UInt", 0, "UInt", 0x409) ; eng layout

hHookKeybd := DllCall("SetWindowsHookEx"
	, Int, WH_KEYBOARD_LL := 13
	, Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
	, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
	, UInt, 0, Ptr)
OnExit(Func("Exit").Bind(hHookKeybd))
Return

Esc::ExitApp

Exit(hHookKeybd)  {
	DllCall("UnhookWindowsHookEx", Ptr, hHookKeybd)
}
   
LowLevelKeyboardProc(nCode, wParam, lParam)  {
	static oMem := [], lpData, size := VarSetCapacity(lpData, 16 + A_PtrSize*2, 0)

	DllCall("RtlMoveMemory", Ptr, &lpData, Ptr, lParam, Ptr, size)
	oMem.Push([wParam, &lpData])
	timer := Func("EventHandling").Bind(oMem)  ; во избежание фризов клавиатуры обработка событий должна
	SetTimer, % timer, -10                     ; происходить обязательно по таймеру, а не в теле этой функции
	Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
}

EventHandling(oMem)  {
	static oMembers := ["vk", "sc", "flags"]
		, oFlagOffsets := {LLKHF_EXTENDED: 0, LLKHF_UP: 7}
		, oArr := {}, Str := " > ", Sleep := 500
		
	if !isobject(oMem)
		goto KeyDelete
		
	while (oMem[1] != "")   {
		key := oMem.RemoveAt(1)
		lp := key[2]
		for k, v in oMembers
			%v% := NumGet(lp + (k - 1)*4, "UInt")
		for k, v in oFlagOffsets
			%k% := (flags >> v) & 1  
		sc |= LLKHF_EXTENDED << 8
		vkCode := Format("vk{:X}", vk) 
		scCode := Format("sc{:X}", sc)
		If !LLKHF_UP && (oArr[vkCode . scCode] = "")
		{
			Str .= (oArr[vkCode . scCode] := GetKeyName(vkCode . scCode)) " > "
			SetTimer, KeyState, -1
		}
		ToolTip % Str, 5, 5, 2
	}
	Return
	
	KeyState:  
		If !oArr.Count()
		{
			SetTimer, KeyState, Off
			Return
		}
		For key, name in oArr
		{
			If GetKeyState(name, "P")
				Continue
			oArr.Delete(key)
			funcobj := Func("EventHandling").Bind(name)
			SetTimer, % funcobj, -%Sleep%
		}
		SetTimer, KeyState, -1 
		Return  
		
	KeyDelete: 
		Str := StrReplace(Str, " > " oMem " > ", " > ", , 1)
		ToolTip % Str, 5, 5, 2 
		If (Str = " > ")
			ToolTip, , , , 2 
		Return
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

11

Re: AHK: Визуализация нажатий клавиш

В последнем все остаются.

12

Re: AHK: Визуализация нажатий клавиш

Кто остаются?

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

13 (изменено: Foma, 2019-01-06 21:40:10)

Re: AHK: Визуализация нажатий клавиш

Уже отпущенные клавиши в ToolTip остаются на длительное время.

Post's attachments

Скриншот 06-01-2019 183656.png
Скриншот 06-01-2019 183656.png 1.38 kb, 1 downloads since 2019-01-06 

You don't have the permssions to download the attachments of this post.

14

Re: AHK: Визуализация нажатий клавиш

Скорее всего конфликт с другими запущенными скриптами.
После первой версии я как раз это и исправлял, у меня ни разу такого нет.
Попробуйте нажимать только клавиши 1 2 3 4, и после тоже самое попробуйте с этим кодом.


#SingleInstance Force
#NoEnv
ListLines Off
SetBatchLines -1
AutoTrim, Off
CoordMode, ToolTip

Global Str := " > "
oArr := {}
Sleep := 500

#If !oArr[A_ThisHotkey]
~1::
~2::
~3::
~4::
	name := SubStr(A_ThisHotkey, 2)
	oArr[A_ThisHotkey] := 1
	Str .= name " > "
	ToolTip % Str, 5, 5, 2
	Return
#If

~1 Up::
~2 Up::
~3 Up::
~4 Up:: 
	name := SubStr(A_ThisHotkey, 1, -3)
	oArr[name] := 0   
	funcobj := Func("KeyDelete").Bind(SubStr(name, 2))
	SetTimer, % funcobj, -%Sleep% 
	Return  

KeyDelete(name) { 
	Str := StrReplace(Str, " > " name " > ", " > ", , 1)
	ToolTip % Str, 5, 5, 2 
	If (Str = " > ")
		ToolTip, , , , 2 
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

15

Re: AHK: Визуализация нажатий клавиш

Foma пишет:

остаются на длительное время

На полсекунды, или пока снова их не нажмешь?

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

16

Re: AHK: Визуализация нажатий клавиш

На минуты точно.

17

Re: AHK: Визуализация нажатий клавиш

Странное общение получается, а про то как код из 14 поста работает, рассказывать уже лишнее...

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

18

Re: AHK: Визуализация нажатий клавиш

Плохо искали:
KeypressOSD

19 (изменено: Foma, 2019-01-08 12:58:34)

Re: AHK: Визуализация нажатий клавиш

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

stealzy, спасибо, посмотрел. Она не делает то, что мне нужно:

Мне нужно вывести на экран все нажимаемые, а также удерживаемые клавиши. Даже если 5 сразу или больше. Причём не только хоткеи, а любые, которые будут нажаты или удерживаемы.

  Наверное там можно что-то изменить, но мне такое не осилить.

20

Re: AHK: Визуализация нажатий клавиш

Foma пишет:

Вы написали, что совершенствовать Вам не интересно

Я имел ввиду что переделывать визуализацию из тултипа во что то приличное. Если в 14 кнопки не остаются, то тоже самое на хоткеи не сложно переделать.

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

21 (изменено: Foma, 2019-01-08 21:27:05)

Re: AHK: Визуализация нажатий клавиш

В 14 не остаются. Небольшая задержка, как и задумано и исчезают. Даже если сделать от 1 до 8, а не до 4.

22 (изменено: serzh82saratov, 2019-01-09 02:09:35)

Re: AHK: Визуализация нажатий клавиш

Но всё равно если быстро крутить колёсиком, иногда остаётся.


#SingleInstance Force
#HotkeyInterval 0
#KeyHistory 0
#UseHook
#NoEnv
SetBatchLines -1
ListLines Off 
AutoTrim, Off
CoordMode, ToolTip	;	, Window

Sleep := 700		;	Задержка исчезновения после отпускания клавиши
Del := " > "		;	Разделитель между именами клавиш
Mouse := 1			;	Определять нажатия мыши
PrefixHotkey = *~	;	Префикс горячей клавиши для команды Hotkey
BanKeys := ""		;	Список запрещённых клавиш
NumPadEqual := 0	;	Если равно нулю, выводить имена Numpad клавиш в зависимости от состояния NumLock

  ;	---------

Str := Del, oArr := {}
LenPrefix := StrLen(PrefixHotkey) + 1
NotUp:= "vk9C|vk9D|vk9E|vk9F" 
Extended := "scF|sc7c|sc2B|sc56"
NotVk := "sc11C|sc147|sc148|sc149|sc14B|sc14D|sc14F|sc150|sc151|sc152|sc153"
ScNum := "sc53|sc52|sc4F|sc50|sc51|sc4B|sc4D|sc47|sc48|sc49|sc4C|sc59"
oScToName := {sc53:"NumpadDot",sc52:"Numpad0",sc4F:"Numpad1",sc50:"Numpad2",sc51:"Numpad3",sc4B:"Numpad4"
				, sc4D:"Numpad6",sc47:"Numpad7",sc48:"Numpad8",sc49:"Numpad9",sc4C:"Numpad5",sc59:"Numpad5"}
If !Mouse
	BanKeys .= "|vk1|vk2|vk4|vk5|vk6|vk9C|vk9D|vk9E|vk9F"

Loop % 0xFF
{
	Key := Format("vk{:x}", A_Index)
	if InStr("|" BanKeys "|", "|" Key "|") || InStr("|" NotUp "|", "|" Key "|") 
		Continue
	Try Hotkey, % PrefixHotkey . Key . " Up", HotkeysUp, On
	Try Hotkey, % PrefixHotkey . Key, Hotkeys, On
}
Loop, Parse, % Extended "|" NotVk "|" ScNum, |
{
	if InStr("|" BanKeys "|", "|" A_LoopField "|") || InStr("|" NotUp "|", "|" A_LoopField "|")
		Continue
	Try Hotkey, % PrefixHotkey . A_LoopField . " Up", HotkeysUp, On
	Try Hotkey, % PrefixHotkey . A_LoopField, Hotkeys, On
}
Loop, Parse, % NotUp, |
{
	if InStr("|" BanKeys "|", "|" A_LoopField "|")
		Continue
	Try Hotkey, % PrefixHotkey . A_LoopField, HotkeysNotUp, On  
}
Return

Esc::ExitApp

HotkeysNotUp:
	Critical
	KeyName := GetKeyName(SubStr(A_ThisHotkey, LenPrefix))
	Str .= KeyName . Del
	ToolTip % Str, 5, 5, 2
	funcobj := Func("KeyDelete").Bind(KeyName)
	SetTimer, % funcobj, -%Sleep% 
	Return

Hotkeys:
	If (oArr[A_ThisHotkey] != "")
		Return
	ThisHotkey := SubStr(A_ThisHotkey, LenPrefix)
	If !NumPadEqual && oScToName[ThisHotkey] && GetKeyState("Numlock", "T")
		KeyName := oScToName[ThisHotkey]
	Else
		KeyName := GetKeyName(ThisHotkey)
	Str .= (oArr[A_ThisHotkey] := KeyName) . Del
	ToolTip % Str, 5, 5, 2
	Return

HotkeysUp:
	Critical
	funcobj := Func("KeyDelete").Bind(oArr.Delete(SubStr(A_ThisHotkey, 1, -3)))
	SetTimer, % funcobj, -%Sleep% 
	Return 
	
KeyDelete(name) {
	Global Str, Del
	Str := StrReplace(Str, Del name Del, Del, , 1)
	ToolTip % Str, 5, 5, 2 
	If (Str = Del)
		ToolTip, , , , 2 
}

АП: Вроде Critical решает проблему, без него пропадают таймеры.

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