有没有一种方法可以在Windows系统中同时激活多个窗口?

3

假设我创建了一个屏幕键盘程序,我想让它处于活动状态,以便在另一个程序(如Google Chrome或Notepad.exe)接收我的键盘输入时也能接收。我主要希望我的键盘运行像“Nohboard”,但我遇到了问题,因为一旦我让我的键盘看起来和我想要的一样,每当我打开另一个窗口时,只要“Windows 7”专注于“notepad.exe”等,我的键盘就不会工作。我之所以这样做是为了使用自己的软件在屏幕上监视我的按键。我正在尝试使用gm studio 1.4设计我的键盘,但由于无法同时激活多个窗口,每次我离开我创建的键盘程序时,我的键盘都变得无用。 有什么解决方法吗?也许可以使用第三方脚本,由其他程序创建,以允许我的程序窗口处于“活动”状态并在另一个程序处于活动状态并接收键盘按键输入时也能接收输入? 提前感谢任何能够想出有用解决方案的人。 我的键盘程序外观的图片。
Space::
SetTitleMatchMode, 2
ControlSend, , {Space Down}, Typing Lessons
ControlSend, , {Space Down}, kb
Keywait, Space
ControlSend, , {Space Up}, kb
ControlSend, , {Space Up}, Typing Lessons
Return

我刚刚通过使用Autohotkey脚本学会了如何向多个程序发送按键。是否有一种方法可以使用AutoHotkey将其发送到“最后活动的窗口”和“当前活动的窗口”?


我如何创建一个窗口,拒绝激活但仍然接收指针输入? - IInspectable
这允许在另一个应用程序具有输入焦点的同时使用屏幕键盘。如果您还需要在您的应用程序没有输入焦点时监视键盘输入,请设置低级别键盘钩子(这似乎是NohBoard所做的)。如果您想查看NohBoard的实现方式,它已发布在GitHub上。 - IInspectable
2个回答

2
在Windows系统上,不可能同时激活多个窗口。
只有一个窗口可以处于活动状态(即焦点)。
但是有两种方法可以帮助解决您的问题。
1-例如,您可以使用屏幕键盘窗口来忽略/禁用该键盘窗口的焦点(无焦点)(无激活+ +E0x08000000)。
尝试此Ahk脚本。
注意:这是F1到F12的屏幕键条。
Example1.ahk
Gui, +LastFound +AlwaysOnTop +ToolWindow -Caption +Border +E0x08000000
Gui, Font, s07, Arial
Loop, 12
Gui, Add, Button, % "x" 5+(A_Index-1)*60 " y5 w60 h25 vF" A_Index " gButton", F%A_Index%
Gui, Show, y0 w730 h35 NoActivate
Return

Button:
    SendInput, % "{" A_GuiControl "}"
Return

GuiClose:
    ExitApp
Return

~esc::exitapp

2-或者您可以使用第三方脚本,

注意:将这两个脚本一起运行。(KeypressValueToREG + ShowKeypressValue)

第一个是一个大型脚本,但您可以做很多事情,它将把您所有的鼠标和键盘移动放入仅一个Windows注册表键。

KeypressValueToREG脚本的强大之处在于,您可以在后台运行它,然后在其他应用程序或其他语言的Visual Studio/Visual Basic/c++/Python/Autohotkey/?中使用它。他们只需要访问/读取那一个注册表键。

keypressvalue to windows registry key

KeypressValueToREG.ahk

;KeypressValueToREG.ahk comes from KeypressOSD.ahk that was Created by Author RaptorX
; Open this Script in Wordpad and For Changelog look to the Bottom of the script. 
;This code works with a getkeyname from a Dllcall (See Bottom Script- by Lexikos)
;you can press the esc key to exit.

#SingleInstance force
#NoEnv
SetBatchLines, -1
ListLines, Off

; Settings
    global TransN                := 200      ; 0~255
    global ShowSingleKey         := True
    global ShowMouseButton       := True
    global ShowSingleModifierKey := True
    global ShowModifierKeyCount  := true
    global ShowStickyModKeyCount := false
    global DisplayTime           := 2000     ; In milliseconds
    global GuiPosition           := "Bottom" ; Top or Bottom
    global FontSize              := 50
    global GuiHeight             := 115

CreateGUI()
CreateHotkey()
return

OnKeyPressed:
    try {
        key := GetKeyStr()
        ShowHotkey(key)
        SetTimer, HideGUI, % -1 * DisplayTime
    }
return

OnKeyUp:
return

_OnKeyUp:
    tickcount_start := A_TickCount
return


CreateGUI() {
    global

    Gui, +AlwaysOnTop -Caption +Owner +LastFound +E0x20
    Gui, Margin, 0, 0
    Gui, Color, Black
    Gui, Font, cWhite s%FontSize% bold, Arial
    Gui, Add, Text, vHotkeyText Center y20

    WinSet, Transparent, %TransN%
}

CreateHotkey() {
    Loop, 95
    {
        k := Chr(A_Index + 31)
        k := (k = " ") ? "Space" : k

        Hotkey, % "~*" k, OnKeyPressed
        Hotkey, % "~*" k " Up", _OnKeyUp
    }

    Loop, 24 ; F1-F24
    {
        Hotkey, % "~*F" A_Index, OnKeyPressed
        Hotkey, % "~*F" A_Index " Up", _OnKeyUp
    }

    Loop, 10 ; Numpad0 - Numpad9
    {
        Hotkey, % "~*Numpad" A_Index - 1, OnKeyPressed
        Hotkey, % "~*Numpad" A_Index - 1 " Up", _OnKeyUp
    }

    Otherkeys := "WheelDown|WheelUp|WheelLeft|WheelRight|XButton1|XButton2|Browser_Forward|Browser_Back|Browser_Refresh|Browser_Stop|Browser_Search|Browser_Favorites|Browser_Home|Volume_Mute|Volume_Down|Volume_Up|Media_Next|Media_Prev|Media_Stop|Media_Play_Pause|Launch_Mail|Launch_Media|Launch_App1|Launch_App2|Help|Sleep|PrintScreen|CtrlBreak|Break|AppsKey|NumpadDot|NumpadDiv|NumpadMult|NumpadAdd|NumpadSub|NumpadEnter|Tab|Enter|Esc|BackSpace"
               . "|Del|Insert|Home|End|PgUp|PgDn|Up|Down|Left|Right|ScrollLock|CapsLock|NumLock|Pause|sc145|sc146|sc046|sc123"
    Loop, parse, Otherkeys, |
    {
        Hotkey, % "~*" A_LoopField, OnKeyPressed
        Hotkey, % "~*" A_LoopField " Up", _OnKeyUp
    }

    If ShowMouseButton {
        Loop, Parse, % "LButton|MButton|RButton", |
            Hotkey, % "~*" A_LoopField, OnKeyPressed
    }

    for i, mod in ["Ctrl", "Shift", "Alt"] {
        Hotkey, % "~*" mod, OnKeyPressed
        Hotkey, % "~*" mod " Up", OnKeyUp
    }
    for i, mod in ["LWin", "RWin"]
        Hotkey, % "~*" mod, OnKeyPressed
}

ShowHotkey(HotkeyStr) {
    WinGetPos, ActWin_X, ActWin_Y, ActWin_W, ActWin_H, A
    if !ActWin_W
        throw

    text_w := (ActWin_W > A_ScreenWidth) ? A_ScreenWidth : ActWin_W

    ;remove this gui codeline if you want only to Write the Value to Windows registry
    ;GuiControl,     , HotkeyText, %HotkeyStr%
    ;GuiControl,     , HotkeyText, %HotkeyStr%

    RegWrite, REG_SZ, HKEY_CURRENT_USER,software\GetKeypressValue,KeypressValue,%HotkeyStr%

    ;remove this gui codeline if you want only to Write the Value to Windows registry
    ;GuiControl, Move, HotkeyText, w%text_w% Center
    ;GuiControl, Move, HotkeyText, w%text_w% Center

    if (GuiPosition = "Top")
        gui_y := ActWin_Y
    else
        gui_y := (ActWin_Y+ActWin_H) - 115 - 50

    ;remove this gui codeline if you want only to Write the Value to Windows registry
    ;Gui, Show, NoActivate x%ActWin_X% y%gui_y% h%GuiHeight% w%text_w%
    ;Gui, Show, NoActivate x%ActWin_X% y%gui_y% h%GuiHeight% w%text_w%
}

GetKeyStr() {
    static modifiers := ["Ctrl", "Shift", "Alt", "LWin", "RWin"]
    static repeatCount := 1

    for i, mod in modifiers {
        if GetKeyState(mod)
            prefix .= mod " + "
    }

    if (!prefix && !ShowSingleKey)
        throw

    key := SubStr(A_ThisHotkey, 3)

    if (key ~= "i)^(Ctrl|Shift|Alt|LWin|RWin)$") {
        if !ShowSingleModifierKey {
            throw
        }
        key := ""
        prefix := RTrim(prefix, "+ ")

        if ShowModifierKeyCount {
            if !InStr(prefix, "+") && IsDoubleClickEx() {
                if (A_ThisHotKey != A_PriorHotKey) || ShowStickyModKeyCount {
                    if (++repeatCount > 1) {
                        prefix .= " ( * " repeatCount " )"
                    }
                } else {
                    repeatCount := 0
                }
            } else {
                repeatCount := 1
            }
        }
    } else {
        if ( StrLen(key) = 1 ) {
            key := GetKeyChar(key, "A")
        } else if ( SubStr(key, 1, 2) = "sc" ) {
            key := SpecialSC(key)
        } else if (key = "LButton") && IsDoubleClick() {
            key := "Double-Click"
        }
        _key := (key = "Double-Click") ? "LButton" : key

        static pre_prefix, pre_key, keyCount := 1
        global tickcount_start
        if (prefix && pre_prefix) && (A_TickCount-tickcount_start < 300) {
            if (prefix != pre_prefix) {
                result := pre_prefix pre_key ", " prefix key
            } else {
                keyCount := (key=pre_key) ? (keyCount+1) : 1
                key := (keyCount>2) ? (key " (" keyCount ")") : (pre_key ", " key)
            }
        } else {
            keyCount := 1
        }

        pre_prefix := prefix
        pre_key := _key

        repeatCount := 1
    }
    return result ? result : prefix . key
}

SpecialSC(sc) {
    static k := {sc046: "ScrollLock", sc145: "NumLock", sc146: "Pause", sc123: "Genius LuxeMate Scroll"}
    return k[sc]
}

; by Lexikos - https://autohotkey.com/board/topic/110808-getkeyname-for-other-languages/#entry682236
GetKeyChar(Key, WinTitle:=0) {
    thread := WinTitle=0 ? 0
        : DllCall("GetWindowThreadProcessId", "ptr", WinExist(WinTitle), "ptr", 0)
    hkl := DllCall("GetKeyboardLayout", "uint", thread, "ptr")
    vk := GetKeyVK(Key), sc := GetKeySC(Key)
    VarSetCapacity(state, 256, 0)
    VarSetCapacity(char, 4, 0)
    n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
        , "ptr", &state, "ptr", &char, "int", 2, "uint", 0, "ptr", hkl)
    return StrGet(&char, n, "utf-16")
}

IsDoubleClick(MSec = 300) {
    Return (A_ThisHotKey = A_PriorHotKey) && (A_TimeSincePriorHotkey < MSec)
}

IsDoubleClickEx(MSec = 300) {
    preHotkey := RegExReplace(A_PriorHotkey, "i) Up$")
    Return (A_ThisHotKey = preHotkey) && (A_TimeSincePriorHotkey < MSec)
}

HideGUI() {
    Gui, Hide
}

~esc::exitapp    
;---------------------------------------------
; ChangeLog : v2.22 (2017-02-25) - Now pressing the same combination keys continuously more than 2 times,
;                                  for example press Ctrl+V 3 times, will displayed as "Ctrl + v (3)"
;             v2.21 (2017-02-24) - Fixed LWin/RWin not poping up start menu
;             v2.20 (2017-02-24) - Added displaying continuous-pressed combination keys.
;                                  e.g.: With CTRL key held down, pressing K and U continuously will shown as "Ctrl + k, u"
;             v2.10 (2017-01-22) - Added ShowStickyModKeyCount option
;             v2.09 (2017-01-22) - Added ShowModifierKeyCount option
;             v2.08 (2017-01-19) - Fixed a bug
;             v2.07 (2017-01-19) - Added ShowSingleModifierKey option (default is True)
;             v2.06 (2016-11-23) - Added more keys. Thanks to SashaChernykh.
;             v2.05 (2016-10-01) - Fixed not detecting "Ctrl + ScrollLock/NumLock/Pause". Thanks to lexikos.
;             v2.04 (2016-10-01) - Added NumpadDot and AppsKey
;             v2.03 (2016-09-17) - Added displaying "Double-Click" of the left mouse button.
;             v2.02 (2016-09-16) - Added displaying mouse button, and 3 settings (ShowMouseButton, FontSize, GuiHeight)
;             v2.01 (2016-09-11) - Display non english keyboard layout characters when combine with modifer keys.
;             v2.00 (2016-09-01) - Removed the "Fade out" effect because of its buggy.
;                                - Added support for non english keyboard layout.
;                                - Added GuiPosition setting.
;             v1.00 (2013-10-11) - First release.
;--------------------------------------------

第二个功能可以在您的桌面屏幕上显示所有鼠标和键盘移动的可视化效果,您可以稍微修改此脚本,然后制作自己的键盘,以显示所有键盘移动的可视化效果。

如果您使用Example1.ahk中的技巧,则可以制作一个专业的屏幕键盘而无需聚焦窗口。

show keyboard movements

ShowKeypressValue.ahk

#SingleInstance force
Gui, +AlwaysOnTop -MaximizeBox ; -Caption +Resize -MinimizeBox +Disabled -SysMenu -Owner +OwnDialogs
Gui, Add, Text, center y10 h50 w300 vVar,  %KeypressValue%
Gui, Color, White
Gui, show
size=20
Gui, Font, s%size%
GuiControl, Font, var

;run KeypressValueToREG.ahk - together with ShowKeypressValue.ahk
;The Features Are:
; - It will Show On your Screen, [All your Mouse Movements] and [All Keyboard Shortcuts Movement]
; - You can Make Scripts, that can do actions with MultiClicks on All Keyboard Shortcuts Clicks, How Cool Is that. 

loop
{
RegRead, KeypressValue, HKEY_CURRENT_USER,software\GetKeypressValue,KeypressValue ; read KeypressValue
sleep 50
GuiControl,, var, %KeypressValue%



if (KeypressValue="Alt ( * 2 )") ;use this for [1x=Alt][2x=Alt ( * 2 )][3x=Alt ( * 3 )] [and many more]
{
;Here you can put any AHK CODE 
msgbox you did click Alt 2x Times
}

if (KeypressValue="Alt ( * 3 )") ;use this for [1x=Alt][2x=Alt ( * 2 )][3x=Alt ( * 3 )] [and many more]
{
;Here you can put any AHK CODE 
msgbox you did click Alt 3x Times
}


} ;End Loop

~esc::exitapp

这看起来很棒,我需要编辑哪个部分才能将按键重定向到“kb.exe”?@stevecody - Iroamalone Atnight
@Iroamalone Atnight - 有两种方法可以重定向按键 - 1:您可以编辑ShowKeypressValue.ahk并将按键重定向到kb.exe - 2:或者您可以使用其他语言,该语言只能访问Windows注册表键(附注-我不确定您是否使用gamemaker studio 1.4制作了kb.exe,如果是,则需要找出该语言是否能够读取该Windows注册表键) - stevecody
@Iroamalone Atnight - 如果Gamemaker Studio 1.4语言无法访问Windows注册表键,则可以考虑使用第三方自动化软件,我正在使用Buttoncommander - 使用它,您可以在桌面上创建非常简单的按钮图标,可以执行任何类型的Autohotkey脚本 - 然后,如果Windows注册表键值为“a”,则突出显示按钮图标a。 - stevecody
@Iroamalone Atnight - Autohotkey结合Buttoncommander,您可以制作许多更加实用的工具,观看这些视频后,您就会明白为什么需要工具栏,剪贴板,虚拟键盘,监视器键盘,启动板,输入板,以及智能谷歌搜索按钮 - stevecody
你有兴趣为我设计吗?你会收取多少费用?这些东西对我来说非常困惑,我认为如果没有大量的培训,我目前无法做到。如果你有兴趣,请发送电子邮件至“Bladevampirek@aol.com”,我可以将程序发送给你,以便查看你是否能够完成它。 - Iroamalone Atnight

0

试试这个。

#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
#InstallKeybdHook
#UseHook

; Add the keys you want send to the last active window in this array:
Keys := ["a","b","c","1","2","3","space",",",".","-","_","F3"]  ; ... 
for each, key in Keys
    Hotkey, %key%, send_key_to_last_active_window, on

SetTimer get_last_active_window, 300 ; you can decrease this period (number of milliseconds that pass before the timer is executed)
return

send_key_to_last_active_window:
    Send, {%A_ThisHotkey%}
    ; WinGetTitle, Title, ahk_id %LastActive_ID%
    ; WinGetClass, Class, ahk_id %LastActive_ID%
    ; ToolTip, last_active_window=%Title% ahk_class %Class%,,, 2
    ; If Class in Notepad,WordPadClass ; if the last active window is Notepad or WordPad
        ControlSend,, {%A_ThisHotkey%}, ahk_id %LastActive_ID%
return

    get_last_active_window:
WinGet, CurrentActive_ID, ID, A
If (CurrentActive_ID != NewActive_ID)
{
    LastActive_ID = %NewActive_ID%
    NewActive_ID := CurrentActive_ID
    ; WinGetTitle, NewActiveTitle,  ahk_id %NewActive_ID%   
    ; WinGetTitle, LastActiveTitle,  ahk_id %LastActive_ID%
    SetTimer get_last_active_window, off
    ; CoordMode, ToolTip, Screen
    ; ToolTip, Current active window:`nTitle: %NewActiveTitle%`nID: %NewActive_ID%`n`nLast active window:`nTitle: %LastActiveTitle%`nID: %LastActive_ID%, 0, 0, 1
    WinWaitNotActive, ahk_id %NewActive_ID% 
    SetTimer get_last_active_window, on
}
return

请参考文档中的For-LoopHotkeySetTimer

完全不可靠,有很多闪烁。这是没有用的,甚至不能作为概念验证(除非你试图证明这不是一个解决方案)。 - IInspectable
在我的系统上它可以工作。这些工具提示仅用于测试。 - user3419297
“在我的机器上可以运行”认证并不意味着代码是正确的。显然,该脚本使用任意时间运行计时器以进行轮询。轮询是一种采样方式。与所有采样一样,您会错过采样点之间发生的所有事件。不,恐怕这只是一个修补程序,而不是解决方案。解决方案在注释中给出。 - IInspectable
从逻辑上讲,如果它在您的系统/程序上不起作用,那么它或者使用方式中肯定有问题或者缺失。就我所看,您可能是其他领域的专家,但不是 AHK 方面的。用户要求的是 AHK 的解决方案。 - user3419297
我刚刚解释了一种失败模式(轮询)之一。无论我是否在这里回答AHK问题都无关紧要。我处于一个相当舒适的位置,知道AHK运行的系统,并为OP似乎提出的问题提供了系统级解决方案。系统制定了任何程序需要遵循的规则,AHK也不例外。将您提出的解决方案与我的评论进行对比,您很快就会看到哪种方法更有可能产生可靠的解决方案。解决方案不需要在我的系统上失败,我也能看到它如何失败。 - IInspectable
我无法测试您的解决方案,因为我不知道如何安装和/或使用它。如果可以的话,也许您能够解释一下如何操作,这并不过分。 - user3419297

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接