diff --git a/Echo.ahk b/Echo.ahk index cec51a4..9f34465 100644 --- a/Echo.ahk +++ b/Echo.ahk @@ -1,372 +1,363 @@ -#NoEnv -#Warn -SendMode Input -SetWorkingDir %A_ScriptDir% -#SingleInstance force -#Persistent - -SetBatchLines, -1 -SetKeyDelay, -1, 100 -SetControlDelay, 500 - -ih := InputHook("B") -ih.KeyOpt("{All}", "NV") -ih.OnKeyDown := Func("OnKeyDown") -ih.OnKeyUp := Func("OnKeyUp") -ih.Start() - -global addNext := 0 -global removeNext := 0 - -global enabledWindows := Array() -enabledWindows.Push(Array()) -enabledWindows.Push(Array()) - -global keyLog := Array() -global whitelistKeys := Array() - -global paused := 0 - -SetTimer, ResetHook, -60000 - -OnKeyDown(InputHook, VK, SC) { - if (!paused) { - key := GetKeyName(Format("vk{:x}sc{:x}", VK, SC)) - if (addNext) { - if (!whitelistKeys.HasKey(Key)) { - whitelistKeys[key] := 1 - sstring := "Added " - sstring .= key - ShowTooltip(sstring) - addNext := 0 - } else { - sstring := "Key already exists" - ShowTooltip(sstring) - addNext := 0 - } - return - } - if (removeNext) { - if (whitelistKeys.HasKey(Key)) { - whitelistKeys.Remove(key) - sstring := "Removed " - sstring .= key - ShowTooltip(sstring) - removeNext := 0 - } else { - sstring := "Key not found" - ShowTooltip(sstring) - removeNext := 0 - } - return - } - if (whitelistKeys.HasKey(key)) { - for k, v in enabledWindows[1] { - ; ControlSend,, {%key% down}, ahk_pid %v% - ControlSend,, {%key% down}, ahk_id %v% - } - } - if (!keyLog.HasKey(key)) { - keyLog[key] := SC, - } - } -} - -OnKeyUp(InputHook, VK, SC) { - if (!paused) { - key := GetKeyName(Format("vk{:x}sc{:x}", VK, SC)) - if (whitelistKeys.HasKey(key)) { - for k, v in enabledWindows[1] { - ; ControlSend,, {%key% up}, ahk_pid %v% - ControlSend,, {%key% up}, ahk_id %v% - } - } - } -} - -ShowTooltip(text) { - ToolTip, %text% - SetTimer, RemoveToolTip, -800 -} - -RemoveToolTip: - ToolTip -return - -; Not really mine at all -SortArray(Array, Order="A") { - ;Order A: Ascending, D: Descending, R: Reverse - MaxIndex := ObjMaxIndex(Array) - If (Order = "R") { - count := 0 - Loop, % MaxIndex - ObjInsert(Array, ObjRemove(Array, MaxIndex - count++)) - Return - } - Partitions := "|" ObjMinIndex(Array) "," MaxIndex - Loop { - comma := InStr(this_partition := SubStr(Partitions, InStr(Partitions, "|", False, 0)+1), ",") - spos := pivot := SubStr(this_partition, 1, comma-1) , epos := SubStr(this_partition, comma+1) - if (Order = "A") { - Loop, % epos - spos { - if (Array[pivot] > Array[A_Index+spos]) - ObjInsert(Array, pivot++, ObjRemove(Array, A_Index+spos)) - } - } else { - Loop, % epos - spos { - if (Array[pivot] < Array[A_Index+spos]) - ObjInsert(Array, pivot++, ObjRemove(Array, A_Index+spos)) - } - } - Partitions := SubStr(Partitions, 1, InStr(Partitions, "|", False, 0)-1) - if (pivot - spos) > 1 ;if more than one elements - Partitions .= "|" spos "," pivot-1 ;the left partition - if (epos - pivot) > 1 ;if more than one elements - Partitions .= "|" pivot+1 "," epos ;the right partition - } Until !Partitions -} - -WinGetAll() { - PIDs := Array() - winTitles := Array() - output := Array() - WinGet, all, list - Loop, %all% - { - WinGet, PID, PID, % "ahk_id " all%A_Index% - WinGet, name, ProcessName, % "ahk_id " all%A_Index% - if (name != "") { - PIDs.Push(PID) - winTitles.Push(name) - } - } - output.Push(PIDs) - output.Push(winTitles) - return output -} - -AllWindowsToString() { - allWindows := WinGetAll() - output := "" - for k, v in allWindows[1] { - output .= allWindows[1][k] - output .= ", " - output .= allWindows[2][k] - output .= "|" - } - StringTrimRight, output, output, 1 - return output -} - -Find(arr, val) { - for k, v in arr { - if (v == val) { - return k - } - } - return 0 -} - -EnableWindows(istring) { - while (enabledWindows.Length() > 0) { - enabledWindows.Pop() - } - enabledWindows.Push(Array()) - enabledWindows.Push(Array()) - if (InStr(istring, "|") == 0) { - ostring := StrSplit(istring, ", ") - if (!Find(enabledWindows[1], (ostring[1]))) { - enabledWindows[1].Push(ostring[1]) - enabledWindows[2].Push(ostring[2]) - } - } else { - ostring := StrSplit(istring, "|") - for k, v in ostring { - ostring2 := StrSplit(v, ", ") - if (!Find(enabledWindows[1], (ostring2[1]))) { - enabledWindows[1].Push(ostring2[1]) - enabledWindows[2].Push(ostring2[2]) - } - } - } - ; TODO: Remove all non selected windows -} - -GuiSelectActiveWindows(allWindows) { - output := Array() - for k, v in allWindows[1] { - if (Find(enabledWindows[1], "" v)) { - ; GuiControl, Choose, WindowListGUI, k - output.Push(k) - } - } - return output -} - -MakeUI() { - Gui, Destroy - string := AllWindowsToString() - Gui, Add, ListBox, Multi h600 w800 vWindowListGUI, %string% - Gui, Add, Button, Default, OK - Gui, Show - for k, v in GuiSelectActiveWindows(WinGetAll()) { - ; See what's wrong with choose, maybe it doesn't like to be called many times though just that is being done on forum guy - GuiControl, Choose, WindowListGUI, v - } -} - -KeyLogToString() { - output := "" - for k, v in keyLog { - output .= k - output .= "|" - } - StringTrimRight, output, output, 1 - return output -} - -WhitelistButtonUI() { - Gui, Destroy - SortArray(keyLog) - string := KeyLogToString() - Gui, Add, ListBox, Multi h600 w800 vKeyLogUI, %string% - Gui, Add, Button, Default, Save - Gui, Show - for k, v in GuiSelectActiveWindows(WinGetAll()) { - ; See what's wrong with choose, maybe it doesn't like to be called many times though just that is being done on forum guy - GuiControl, Choose, WindowListGUI, v - } -} - -WhitelistKeys(string) { - whitelistKeys := Array() - for k, v in StrSplit(string, "|") { - whitelistKeys[v] := 1 - } -} - -AddCurrentWindow() { - ; WinGet, activePID, PID, A - WinGet, activeID, ID, A - if (!Find(enabledWindows[1], activeID)) { - WinGet, activeName, ProcessName, A - enabledWindows[1].Insert(activeID) - enabledWindows[2].Insert(activeName) - sstring := "Added " - sstring .= activeID - sstring .= " (" - sstring .= activeName - sstring .= ") to echo list" - ShowTooltip(sstring) - } -} - -RemoveCurrentWindow() { - ; WinGet, activePID, PID, A - WinGet, activeID, ID, A - if (Find(enabledWindows[1], activeID)) { - WinGet, activeName, ProcessName, A - enabledWindows[1].RemoveAt(Find(enabledWindows[1], activeID)) - enabledWindows[2].RemoveAt(Find(enabledWindows[2], activeName)) - sstring := "Removed " - sstring .= activeID - sstring .= " (" - sstring .= activeName - sstring .= ") from echo list" - ShowTooltip(sstring) - } -} - -ResetHook: - ih.Stop() - ih := InputHook("B") - ih.KeyOpt("{All}", "NV") - ih.OnKeyDown := Func("OnKeyDown") - ih.OnKeyUp := Func("OnKeyUp") - ih.Start() - ; Tooltip, WIN - SetTimer, ResetHook, -30000 -return - -TogglePause() { - if (paused) { - ShowTooltip("Unpaused") - paused := 0 - return - } - ShowTooltip("Paused") - paused := 1 - return -} - - -F5:: - ih.Stop() - ih := InputHook("B") - ih.KeyOpt("{All}", "NV") - ih.OnKeyDown := Func("OnKeyDown") - ih.OnKeyUp := Func("OnKeyUp") - ih.Start() -return - -; F3:: -; MakeUI() -; return - -; F4:: -; WhitelistButtonUI() -; return - -F3:: - ShowTooltip("Adding key") - addNext := 1 -return - -F4:: - ShowTooltip("Removing key") - removeNext := 1 -return - -^!S:: - ShowTooltip("Adding window") - AddCurrentWindow() -return - -^!D:: - ShowTooltip("Removing window") - RemoveCurrentWindow() -Return - -F6:: - TogglePause() -return - -F7:: - whitelistKeys["q"] := 1 - whitelistKeys["e"] := 1 - whitelistKeys[1] := 1 - whitelistKeys[2] := 1 - whitelistKeys[3] := 1 - whitelistKeys[4] := 1 - whitelistKeys[5] := 1 - whitelistKeys["LShift"] := 1 - whitelistKeys["LControl"] := 1 - whitelistKeys["g"] := 1 - whitelistKeys["v"] := 1 - whitelistKeys["r"] := 1 - whitelistKeys["f"] := 1 - whitelistKeys["c"] := 1 - whitelistKeys["y"] := 1 -return - -ButtonSave: - Gui, Submit - WhitelistKeys(KeyLogUI) -return - -ButtonOK: - Gui, Submit - EnableWindows(WindowListGUI) -return - +#NoEnv +SendMode Input +SetWorkingDir %A_ScriptDir% +#SingleInstance force +#Persistent + +SetBatchLines, -1 +SetKeyDelay, -1, 100 +SetControlDelay, 500 + +ih := InputHook("B") +ih.KeyOpt("{All}", "NV") +ih.OnKeyDown := Func("OnKeyDown") +ih.OnKeyUp := Func("OnKeyUp") +ih.Start() + +global addNext := 0 +global removeNext := 0 + +global enabledWindows := Array() +enabledWindows.Push(Array()) +enabledWindows.Push(Array()) + +global keyLog := Array() +global whitelistKeys := Array() + +global paused := 0 + +SetTimer, ResetHook, -60000 + +OnKeyDown(InputHook, VK, SC) { + if (!paused) { + key := GetKeyName(Format("vk{:x}sc{:x}", VK, SC)) + if (addNext) { + if (!whitelistKeys.HasKey(Key)) { + whitelistKeys[key] := 1 + sstring := "Added " + sstring .= key + ShowTooltip(sstring) + addNext := 0 + } else { + sstring := "Key already exists" + ShowTooltip(sstring) + addNext := 0 + } + return + } + if (removeNext) { + if (whitelistKeys.HasKey(Key)) { + whitelistKeys.Remove(key) + sstring := "Removed " + sstring .= key + ShowTooltip(sstring) + removeNext := 0 + } else { + sstring := "Key not found" + ShowTooltip(sstring) + removeNext := 0 + } + return + } + if (whitelistKeys.HasKey(key)) { + for k, v in enabledWindows[1] { + ; ControlSend,, {%key% down}, ahk_pid %v% + ; Random, rand, 50, 2000 + ; Sleep %rand% + ControlSend,, {%key% down}, ahk_id %v% + } + } + if (!keyLog.HasKey(key)) { + keyLog[key] := SC, + } + } +} + +; ~LButton:: +; MouseGetPos, xpos, ypos +; for k, v in enabledWindows[1] { +; ControlClick, xpos ypos, ahk_id %v% +; ControlClick,, {%key% down}, ahk_id %v% +; } +; return + +OnKeyUp(InputHook, VK, SC) { + if (!paused) { + key := GetKeyName(Format("vk{:x}sc{:x}", VK, SC)) + if (whitelistKeys.HasKey(key)) { + for k, v in enabledWindows[1] { + ; ControlSend,, {%key% up}, ahk_pid %v% + ControlSend,, {%key% up}, ahk_id %v% + } + } + } +} + +ShowTooltip(text) { + ToolTip, %text% + SetTimer, RemoveToolTip, -800 +} + +RemoveToolTip: + ToolTip +return + +; Not really mine at all +SortArray(Array, Order="A") { + ;Order A: Ascending, D: Descending, R: Reverse + MaxIndex := ObjMaxIndex(Array) + If (Order = "R") { + count := 0 + Loop, % MaxIndex + ObjInsert(Array, ObjRemove(Array, MaxIndex - count++)) + Return + } + Partitions := "|" ObjMinIndex(Array) "," MaxIndex + Loop { + comma := InStr(this_partition := SubStr(Partitions, InStr(Partitions, "|", False, 0)+1), ",") + spos := pivot := SubStr(this_partition, 1, comma-1) , epos := SubStr(this_partition, comma+1) + if (Order = "A") { + Loop, % epos - spos { + if (Array[pivot] > Array[A_Index+spos]) + ObjInsert(Array, pivot++, ObjRemove(Array, A_Index+spos)) + } + } else { + Loop, % epos - spos { + if (Array[pivot] < Array[A_Index+spos]) + ObjInsert(Array, pivot++, ObjRemove(Array, A_Index+spos)) + } + } + Partitions := SubStr(Partitions, 1, InStr(Partitions, "|", False, 0)-1) + if (pivot - spos) > 1 ;if more than one elements + Partitions .= "|" spos "," pivot-1 ;the left partition + if (epos - pivot) > 1 ;if more than one elements + Partitions .= "|" pivot+1 "," epos ;the right partition + } Until !Partitions +} + +WinGetAll() { + PIDs := Array() + winTitles := Array() + output := Array() + WinGet, all, list + Loop, %all% + { + WinGet, PID, PID, % "ahk_id " all%A_Index% + WinGet, name, ProcessName, % "ahk_id " all%A_Index% + if (name != "") { + PIDs.Push(PID) + winTitles.Push(name) + } + } + output.Push(PIDs) + output.Push(winTitles) + return output +} + +AllWindowsToString() { + allWindows := WinGetAll() + output := "" + for k, v in allWindows[1] { + output .= allWindows[1][k] + output .= ", " + output .= allWindows[2][k] + output .= "|" + } + StringTrimRight, output, output, 1 + return output +} + +Find(arr, val) { + for k, v in arr { + if (v == val) { + return k + } + } + return 0 +} + +EnableWindows(istring) { + while (enabledWindows.Length() > 0) { + enabledWindows.Pop() + } + enabledWindows.Push(Array()) + enabledWindows.Push(Array()) + if (InStr(istring, "|") == 0) { + ostring := StrSplit(istring, ", ") + if (!Find(enabledWindows[1], (ostring[1]))) { + enabledWindows[1].Push(ostring[1]) + enabledWindows[2].Push(ostring[2]) + } + } else { + ostring := StrSplit(istring, "|") + for k, v in ostring { + ostring2 := StrSplit(v, ", ") + if (!Find(enabledWindows[1], (ostring2[1]))) { + enabledWindows[1].Push(ostring2[1]) + enabledWindows[2].Push(ostring2[2]) + } + } + } + ; TODO: Remove all non selected windows +} + +GuiSelectActiveWindows(allWindows) { + output := Array() + for k, v in allWindows[1] { + if (Find(enabledWindows[1], "" v)) { + ; GuiControl, Choose, WindowListGUI, k + output.Push(k) + } + } + return output +} + +MakeUI() { + Gui, Destroy + string := AllWindowsToString() + Gui, Add, ListBox, Multi h600 w800 vWindowListGUI, %string% + Gui, Add, Button, Default, OK + Gui, Show + for k, v in GuiSelectActiveWindows(WinGetAll()) { + ; See what's wrong with choose, maybe it doesn't like to be called many times though just that is being done on forum guy + GuiControl, Choose, WindowListGUI, v + } +} + +KeyLogToString() { + output := "" + for k, v in keyLog { + output .= k + output .= "|" + } + StringTrimRight, output, output, 1 + return output +} + +WhitelistButtonUI() { + Gui, Destroy + SortArray(keyLog) + string := KeyLogToString() + Gui, Add, ListBox, Multi h600 w800 vKeyLogUI, %string% + Gui, Add, Button, Default, Save + Gui, Show + for k, v in GuiSelectActiveWindows(WinGetAll()) { + ; See what's wrong with choose, maybe it doesn't like to be called many times though just that is being done on forum guy + GuiControl, Choose, WindowListGUI, v + } +} + +WhitelistKeys(string) { + whitelistKeys := Array() + for k, v in StrSplit(string, "|") { + whitelistKeys[v] := 1 + } +} + +AddCurrentWindow() { + ; WinGet, activePID, PID, A + WinGet, activeID, ID, A + if (!Find(enabledWindows[1], activeID)) { + WinGet, activeName, ProcessName, A + enabledWindows[1].Insert(activeID) + enabledWindows[2].Insert(activeName) + sstring := "Added " + sstring .= activeID + sstring .= " (" + sstring .= activeName + sstring .= ") to echo list" + ShowTooltip(sstring) + } +} + +RemoveCurrentWindow() { + ; WinGet, activePID, PID, A + WinGet, activeID, ID, A + if (Find(enabledWindows[1], activeID)) { + WinGet, activeName, ProcessName, A + enabledWindows[1].RemoveAt(Find(enabledWindows[1], activeID)) + enabledWindows[2].RemoveAt(Find(enabledWindows[2], activeName)) + sstring := "Removed " + sstring .= activeID + sstring .= " (" + sstring .= activeName + sstring .= ") from echo list" + ShowTooltip(sstring) + } +} + +ResetHook: + ih.Stop() + ih := InputHook("B") + ih.KeyOpt("{All}", "NV") + ih.OnKeyDown := Func("OnKeyDown") + ih.OnKeyUp := Func("OnKeyUp") + ih.Start() + ; Tooltip, WIN + SetTimer, ResetHook, -30000 +return + +TogglePause() { + if (paused) { + ShowTooltip("Unpaused") + paused := 0 + return + } + ShowTooltip("Paused") + paused := 1 + return +} + + +F5:: + ih.Stop() + ih := InputHook("B") + ih.KeyOpt("{All}", "NV") + ih.OnKeyDown := Func("OnKeyDown") + ih.OnKeyUp := Func("OnKeyUp") + ih.Start() +return + +; F3:: +; MakeUI() +; return + +; F4:: +; WhitelistButtonUI() +; return + +F3:: + ShowTooltip("Adding key") + addNext := 1 +return + +F4:: + ShowTooltip("Removing key") + removeNext := 1 +return + +^!X:: + ShowTooltip("Adding window") + AddCurrentWindow() +return + +^!C:: + ShowTooltip("Removing window") + RemoveCurrentWindow() +Return + +F6:: + TogglePause() +return + +ButtonSave: + Gui, Submit + WhitelistKeys(KeyLogUI) +return + +ButtonOK: + Gui, Submit + EnableWindows(WindowListGUI) +return + ; F5::reload \ No newline at end of file diff --git a/MouseTest.ahk b/MouseTest.ahk new file mode 100644 index 0000000..633ea0d --- /dev/null +++ b/MouseTest.ahk @@ -0,0 +1,9 @@ +#NoEnv +SetBatchLines, -1 +#InstallMouseHook + +; Mouse button event handlers +~LButton:: + MouseGetPos, xpos, ypos + ToolTip, %xpos% %ypos% +return diff --git a/README.md b/README.md index dd8d53a..f26fcc0 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,37 @@ -# Echoes keyboard events to selectable windows - -Mainly used (and made) for World of Warcraft but it might have it's other uses - -F3 brings up UI which allows the user to select 1 or more applications to echo **all** keyboard events to - -In the current state ALL events are echoed, ~~customizability is planned~~ - -## 1.1.x - -Keys can now be whitelisted and only whitelisted keys will be echoed - -The whitelist menu can be accessed by pressing F4 and only keys pressed since the start of the program will be shown, user can then pick as many as they please to whitelist and only those the user picks will be echoed to other windows - -## 1.1.2 - -Keys can now be whitelisted by using hotkeys - -Pressing - -`Ctrl + Alt + A` - -Will add the next hit key to the whitelist - -`Ctrl + Alt + R` - -Will remove the next hit key from the whitelist - -## 1.1.3 - -Windows can now be added to the echo list using `Ctrl+Alt+S` and `Ctrl+Alt+D` where S adds the **current** window and D removes the **current** window - -## 1.1.4 - -For some reason the keyboard hook sometimes gives up - +# Echoes keyboard events to selectable windows + +Mainly used (and made) for World of Warcraft but it might have it's other uses + +F3 brings up UI which allows the user to select 1 or more applications to echo **all** keyboard events to + +In the current state ALL events are echoed, ~~customizability is planned~~ + +## 1.1.x + +Keys can now be whitelisted and only whitelisted keys will be echoed + +The whitelist menu can be accessed by pressing F4 and only keys pressed since the start of the program will be shown, user can then pick as many as they please to whitelist and only those the user picks will be echoed to other windows + +## 1.1.2 + +Keys can now be whitelisted by using hotkeys + +Pressing + +`Ctrl + Alt + A` + +Will add the next hit key to the whitelist + +`Ctrl + Alt + R` + +Will remove the next hit key from the whitelist + +## 1.1.3 + +Windows can now be added to the echo list using `Ctrl+Alt+S` and `Ctrl+Alt+D` where S adds the **current** window and D removes the **current** window + +## 1.1.4 + +For some reason the keyboard hook sometimes gives up + Added option to re-hook keyboard on `F5` \ No newline at end of file