如何使用AHK确定窗口是否在屏幕上可见?

时间:2019-04-13 21:59:18

标签: windows autohotkey

我正在尝试从此处https://autohotkey.com/board/topic/25619-detect-on-screen/运行此脚本,但是如果Window顶部边框未触及屏幕顶部,则该脚本将不起作用:

^F2::
If ( ID := WinExist("Calculator") ) 
 {
   WinGetPos , X, Y, , , ahk_id %ID%
   If  ( DllCall("WindowFromPoint", Int,X+5, Int,Y+5 ) = ID ) 
       MsgBox, Calculator is ON SCREEN
 }
Return

2 个答案:

答案 0 :(得分:-1)

作为检查窗口是否可见的替代方法,您可以随时间比较窗口文本的内容,并确定它是否足以满足您的需求。

在此示例中,我正在检查Media Player Home Cinema窗口的播放时间,以确定是应该按下Media Play/Stop按钮,还是应该专注于Media Player Home Cinema窗口并按下Space (直接播放/停止播放):

Pause::
window_identifier = ahk_class MediaPlayerClassicW
WinGetTitle, window_title, %window_identifier%

if( !window_title ) {
    Send {Media_Play_Pause}
}
else {
    WinWaitActive, %window_title%, , 0.1
    is_window_focused := true
    if( ErrorLevel ) {
        ; MsgBox, WinWait timed out.
        is_window_focused := false
    }
    else {
        PlayPauseVideo()
        return
    }

    counter := 5
    first_result := GetRunningWindowText(window_title)

    while( counter > 0) {
        sleep, 200
        counter := counter - 1
        second_result := GetRunningWindowText(window_title)

        if( first_result != second_result ) {
            PlayPauseVideo()
            return
        }
    }

    if( is_window_focused ) {
        PlayPauseVideo()
    }
    else {
        Send {Media_Play_Pause}
    }
}
GetRunningWindowText(window_title) {
    WinGetText, window_text, %window_title%

    ; FoundPos := RegExMatch(window_text, "O)(?:\d\d:)+(?<frames>\d\d)", first_result)
    FoundPos := RegExMatch(window_text, "O)drawn: (?<frames>\d+)", first_result)

    ; Msgbox % first_result.Count() ": " first_result.Name(1) "=" first_result["frames"]
    return first_result["frames"]
}

PlayPauseVideo() {
    ; Msgbox, It is running video...
    WinActivate, ahk_class MediaPlayerClassicW
    Send {Space}
}
return

参考文献:

  1. https://autohotkey.com/docs/commands/RegExMatch.htm
  2. How do I create while loop in autohotkey that breaks when I press {Ctrl}?
  3. https://autohotkey.com/board/topic/35905-how-to-get-ahk-to-wait-a-specified-amount-of-time/
  4. http://rouge.jneen.net/

额外

重写函数中的主要代码以提高泛化/重用性:

Pause::CheckForPlayerWindow("ahk_class MediaPlayerClassicW",
        "{Media_Play_Pause}", "{Space}", "false")

^!Left::CheckForPlayerWindow("ahk_class MediaPlayerClassicW", "{Media_Prev}", "^p")
^!Right::CheckForPlayerWindow("ahk_class MediaPlayerClassicW", "{Media_Next}", "^n")


; https://stackoverflow.com/questions/55670223/how-to-determine-whether-a-window
CheckForPlayerWindow(window_identifier, media_key, player_key, reactive=true) {
    WinGetTitle, window_title, %window_identifier%

    if( !window_title ) {
        Send % media_key
    }
    else {
        WinWaitActive, %window_title%, , 0.1
        is_window_focused := true

        if( ErrorLevel ) {
            ; MsgBox, WinWait timed out.
            is_window_focused := false
        }
        else {
            PlayPauseVideo(window_identifier, player_key, reactive)
            return
        }

        counter := 5
        first_result := GetRunningWindowText(window_title)

        while( counter > 0) {
            sleep, 200
            counter := counter - 1
            second_result := GetRunningWindowText(window_title)

            if( first_result != second_result ) {
                PlayPauseVideo(window_identifier, player_key, reactive)
                return
            }
        }

        if( is_window_focused ) {
            PlayPauseVideo(window_identifier, player_key, reactive)
        }
        else {
            Send % media_key
        }
    }
}
GetRunningWindowText(window_title) {
    WinGetText, window_text, %window_title%

    ; FoundPos := RegExMatch(window_text, "O)(?:\d\d:)+(?<frames>\d\d)", first_result)
    FoundPos := RegExMatch(window_text, "O)drawn: (?<frames>\d+)", first_result)

    ; Msgbox % first_result.Count() ": " first_result.Name(1) "=" first_result["frames"]
    return first_result["frames"]
}

PlayPauseVideo(window_identifier, player_key, reactive=true) {
    ; Msgbox, It is running video...

    if( reactive == true ) {
        WinGetActiveTitle, active_window_title
    }

    WinActivate, %window_identifier%
    SendInput % player_key

    if( reactive == true ) {
        WinActivate, %active_window_title%
    }
}
return

新参考文献:

  1. https://autohotkey.com/docs/commands/Send.htm
  2. https://autohotkey.com/board/topic/77928-ctrl-v-sendinput-v-is-not-working-in-many-applications/
  3. https://autohotkey.com/board/topic/148483-how-to-pass-a-key-in-a-function-parameter/
  4. https://autohotkey.com/docs/KeyList.htm

答案 1 :(得分:-2)

它不起作用,因为Windows API https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-windowfrompoint中的函数WindowFromPoint使用不正确。

它仅需要1个参数,而不需要传递2个参数。您是否需要使用此函数将参数从2正确转换为

WindowFromPoint(x, y)
{
    VarSetCapacity(POINT, 8)
    Numput(x, POINT, 0, "int")
    Numput(y, POINT, 4, "int")
    return DllCall("WindowFromPoint", int64, NumGet(POINT, 0, "int64"))
}

完整示例:

Pause::
window_identifier = ahk_class MediaPlayerClassicW

WinGetTitle, window_title, %window_identifier%
is_visible := IsWindowVisible(window_identifier)

If( is_visible > 0 ) {
    MsgBox, Window %window_title% is visible!
}
else {
    If( is_visible < 0 ) {
        MsgBox, Window %window_identifier% not found!
    } else
    {
        MsgBox, Window %window_title% is NOT visible!
    }
}
IsWindowVisible(window_name) {
    ID := WinExist(window_name)

    If( ErrorLevel != 0 ) {
        ; MsgBox, Window %window_name% not found!
        return -1
    }

    If( ID > 0 ) {
        WinGetPos, X, Y, , , ahk_id %ID%
        active_window_id_hwnd := WindowFromPoint(X, Y)

        ; MsgBox, %X%, %Y%, %active_window_id_hwnd%
        If( active_window_id_hwnd = ID ) {
            ; MsgBox, Window %window_name% is visible!
            return 1
        }
        else {
            ; MsgBox, Window %window_name% is NOT visible!
            return 0
        }
    }

    ; MsgBox, Window %window_name% not found!
    return -1
}

WindowFromPoint(x, y)
{
    VarSetCapacity(POINT, 8)
    Numput(x, POINT, 0, "int")
    Numput(y, POINT, 4, "int")
    return DllCall("WindowFromPoint", int64, NumGet(POINT, 0, "int64"))
}
Return

参考文献:

  1. https://autohotkey.com/board/topic/116760-windowfrompoint-broken-in-windows-81/
  2. https://autohotkey.com/board/topic/11978-inidelete-set-errorlevel-if-section-or-key-doesnt-exist/