Jump to content

[Solved] How do you detect what window(s) are obstructing another?


 Share

Recommended Posts

I have hit a delima. I have been tasked with a little project. I am going to pick on notepad for lack of anything better to pick on. I need to keep this one notepad document always forefront, always fully visible and not let anything obstruct its view. It must always be forefront and un-obstructed.

I can get the size and coordinates of this notepad window easily but I am stuck trying to determine what other window(s) might be overlapping it and obstructing its view. Any ideas?

Edited by CountyIT
Link to comment
Share on other sites

  • Developers

Should this window also always have the focus or are other windows allowed to have the focus as long as they do not overlap?

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

The help also uses Notepad in the example

WinSetOnTop("[CLASS:Notepad]", "", 1)

It's a good idea to get the handle to the particular window using WinGetHandle() in case another copy of notepad is opened or the user loads a different file changing the title etc..

Also you could periodically use

WinGetState() to see if someone has minimized the window or whatever.

Not sure what happens if some other window is set as Topmost after notepad. I would search MSDN Topmost and read how conflicts are resolved.

Edited by MilesAhead
Link to comment
Share on other sites

Yes there is a lot to be considered. I have been thinking about it. The real problem in a nutshell is how can you tell if one window is obstructing the view of another. I am not sure there is a way to determine this is there?

I mean even if you could determine, for instance by window coordinates, that two windows overlap or take up the same space that you can't really determine which on is on top can you? That would take some kind of 3D "depth" reading would it?

Link to comment
Share on other sites

On another board I saw a suggestion that catching this msg will notify you

WM_WINDOWPOSCHANGED will let you know when the z-order has been changed...

the z order is the depth coordinate

edit: I'm sure there are example of registering a message handler on the forum. One method is GuiRegisterMsg().

Edited by MilesAhead
Link to comment
Share on other sites

  • Developers

Here you have something to play with.

The Script retrieves the Windows "above" the Window you specified in $Mywindow and displays all in a small window including indication whether they over lap your window or not.

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
Global $MyWindow = "Your Window Title"
Global $EditText, $S_EditText
Global $aWinInfo[1][7]
AdlibRegister("GetWinOnTopOnMine", 1000)
$hwin = GUICreate("Z-order Demo", 600, 100, 0, 0, Default, $WS_EX_TOPMOST)
$hEdit = GUICtrlCreateEdit("", 1, 1, 598, 98)
GUISetState()
; Run the GUI until the dialog is closed
While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect
    $EditText = ""
    For $y = 0 To UBound($aWinInfo) - 1
        ; determine whether window is overlapping
        $EditText &= $aWinInfo[$y][6] ;X
        If $aWinInfo[$y][6] Then $EditText &= "*** OverLap***"
        $EditText &= "  POS="
        $EditText &= $aWinInfo[$y][1] ;X
        $EditText &= ":"
        $EditText &= $aWinInfo[$y][2] ;Y
        $EditText &= "  Size="
        $EditText &= $aWinInfo[$y][3] ;Width
        $EditText &= ":"
        $EditText &= $aWinInfo[$y][4] ;Height
        $EditText &= "  Title="
        $EditText &= $aWinInfo[$y][0]
        $EditText &= @CRLF
    Next
    If $EditText <> $S_EditText Then
        GUICtrlSetData($hEdit, $EditText)
        ConsoleWrite("Updated" & @CRLF)
        $S_EditText = $EditText
    EndIf
WEnd

Func GetWinOnTopOnMine()
    Local $var = WinList()
    ReDim $aWinInfo[UBound($var)][7]
    Local $NWin = 0
    Local $Overlap = 0
    $MyWinPos = WinGetPos($MyWindow)
    If @error Then
        MsgBox(0, "Error", "Your specified window title is not found: " & @lf & $MyWindow)
        Exit
    EndIf
    For $i = 1 To $var[0][0]
        ; Only check for visble windows
        If IsVisible($var[$i][1]) Then
            ; Check for MYWNDOW and exit when found
            If $var[$i][0] = $MyWindow Then
                ReDim $aWinInfo[$NWin][7]
                Return
            EndIf
            ; save all Window info of windows with an Higher Z-Order in an Array
            $WinPos = WinGetPos($var[$i][1])
            $aWinInfo[$NWin][0] = $var[$i][0]
            $aWinInfo[$NWin][1] = $WinPos[0]
            $aWinInfo[$NWin][2] = $WinPos[1]
            $aWinInfo[$NWin][3] = $WinPos[2]
            $aWinInfo[$NWin][4] = $WinPos[3]
            $aWinInfo[$NWin][5] = $var[$i][1]
            ; *** Check for Full overlap
            $Overlap = 0
            If $MyWinPos[0] > $WinPos[0] And $MyWinPos[0] + $MyWinPos[2] < $WinPos[0] + $WinPos[2] _
                    And $MyWinPos[1] > $WinPos[1] And $MyWinPos[1] + $MyWinPos[3] < $WinPos[1] + $WinPos[3] Then
                $Overlap = 1
                ; *** Check for app corners inside my window
                ; Check if left top is inside my window
            ElseIf $MyWinPos[0] < $WinPos[0] And $MyWinPos[0] + $MyWinPos[2] > $WinPos[0] _
                    And $MyWinPos[1] < $WinPos[1] And $MyWinPos[1] + $MyWinPos[3] > $WinPos[1] Then
                $Overlap = 2
                ; Check if left bottom is inside my window
            ElseIf $MyWinPos[0] < $WinPos[0] And $MyWinPos[0] + $MyWinPos[2] > $WinPos[0] _
                    And $MyWinPos[1] < $WinPos[1] + $WinPos[3] And $MyWinPos[1] + $MyWinPos[3] > $WinPos[1] + $WinPos[3] Then
                $Overlap = 3
                ; Check if Right Top is inside my window
            ElseIf $MyWinPos[0] < $WinPos[0] + $WinPos[2] And $MyWinPos[0] + $MyWinPos[2] > $WinPos[0] + $WinPos[2] _
                    And $MyWinPos[1] < $WinPos[1] And $MyWinPos[1] + $MyWinPos[3] > $WinPos[1] Then
                $Overlap = 4
                ; Check if Right bottom is inside my window
            ElseIf $MyWinPos[0] < $WinPos[0] + $WinPos[2] And $MyWinPos[0] + $MyWinPos[2] > $WinPos[0] + $WinPos[2] _
                    And $MyWinPos[1] < $WinPos[1] + $WinPos[3] And $MyWinPos[1] + $MyWinPos[3] > $WinPos[1] + $WinPos[3] Then
                $Overlap = 5
                ; Check for Myapp corners inside App
                ; Check if left top is inside my window
            ElseIf $WinPos[0] < $MyWinPos[0] And $WinPos[0] + $WinPos[2] > $MyWinPos[0] _
                    And $WinPos[1] < $MyWinPos[1] And $WinPos[1] + $WinPos[3] > $MyWinPos[1] Then
                $Overlap = 6
                ; Check if left bottom is inside my window
            ElseIf $WinPos[0] < $MyWinPos[0] And $WinPos[0] + $WinPos[2] > $MyWinPos[0] _
                    And $WinPos[1] < $MyWinPos[1] + $MyWinPos[3] And $WinPos[1] + $WinPos[3] > $MyWinPos[1] + $MyWinPos[3] Then
                $Overlap = 7
                ; Check if Right Top is inside my window
            ElseIf $WinPos[0] < $MyWinPos[0] + $MyWinPos[2] And $WinPos[0] + $WinPos[2] > $MyWinPos[0] + $MyWinPos[2] _
                    And $WinPos[1] < $MyWinPos[1] And $WinPos[1] + $WinPos[3] > $MyWinPos[1] Then
                $Overlap = 8
                ; Check if Right bottom is inside my window
            ElseIf $WinPos[0] < $MyWinPos[0] + $MyWinPos[2] And $WinPos[0] + $WinPos[2] > $MyWinPos[0] + $MyWinPos[2] _
                    And $WinPos[1] < $MyWinPos[1] + $MyWinPos[3] And $WinPos[1] + $WinPos[3] > $MyWinPos[1] + $MyWinPos[3] Then
                $Overlap = 9
                ; Check for app side go through MyApp
                ; Check Horizontal is inside my window
            ElseIf $MyWinPos[0] > $WinPos[0] And $MyWinPos[0] + $MyWinPos[2] < $WinPos[0] + $WinPos[2] _
                    And $MyWinPos[1] < $WinPos[1] And $MyWinPos[1] + $MyWinPos[3] > $WinPos[1] Then
                $Overlap = 10
                ; Check Vertical is inside my window
            ElseIf $MyWinPos[1] > $WinPos[1] And $MyWinPos[1] + $MyWinPos[3] < $WinPos[1] + $WinPos[3] _
                    And $MyWinPos[0] < $WinPos[0] And $MyWinPos[0] + $MyWinPos[2] > $WinPos[0] Then
                $Overlap = 11
            EndIf
            $aWinInfo[$NWin][6] = $Overlap
            $NWin += 1
        EndIf
    Next
    ConsoleWrite("- Not Found -----------------------------------------" & @LF)
EndFunc   ;==>GetWinOnTopOnMine

Func IsVisible($handle)
    If BitAND(WinGetState($handle), 2) Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc   ;==>IsVisible

Jos :)

Edited by Jos
Some improvements

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...