Sign in to follow this  
Followers 0
qwert

Best way to hide/show external window?

8 posts in this topic

I have a script that gets the handle of an external window and then adjusts its size and position. I've tried three different techniques for hiding the window while the adjustments are made -- but none of them provides a good overall result.

Method 1: Hides the window OK, but removes it from the taskbar. Plus, the immediate SHOW step doesn't bring it back -- although calling a separate script with only the SHOW statement does (bring it back).

WinSetState($hWnd, "", @SW_HIDE)

<adjustments>

WinSetState($hWnd, "", @SW_SHOW)

Method 2: Does work, but there's a bit of awkward updating as the different components of the window are brought back to being visible.

WinSetTrans($hWnd, "", 0)

<adjustments>

WinSetTrans($hWnd, "", 255)

Method 3: Probably the best of the three, but (depending on the user's settings) it displays the awkward "collapsing effect" -- which I don't like and would like to avoid.

WinSetState($hWnd, "", @SW_MINIMIZE)

<adjustments>

WinSetState($hWnd, "", @SW_RESTORE)

So my question is this: Is there a way to simply "flip a switch" -- invisible/visible? Or have I left something out of one of the above that's inducing the problem(s)?

Thanks in advance for any help.

Share this post


Link to post
Share on other sites



About your Method1 - this works for me:

Run("notepad.exe")
WinWaitActive("[CLASS:Notepad]")
$hWnd = WinGetHandle("[CLASS:Notepad]")
WinSetState($hWnd, "", @SW_HIDE)
WinMove($hWnd, "", 100, 100, 250, 250) 
WinSetState($hWnd, "", @SW_SHOW)

Share this post


Link to post
Share on other sites

Thanks for the response. It works for me also on notepad -- but not with my application.

There may well be some conflict with the DllCalls I make in <adjustments>. I'll investigate those details.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

In case you are interested.. here is a script I wrote a couple days ago that lists windows of a particular window title into a Listview, shows their hWnd, Instance, and visibility state.. and has a button to change their visibility state.

#Include <GUIConstants.au3>
#Include <GuiListView.au3>

$hWindowList = GUICreate("Hide/Show", 265, 140, 596, 604)
$oWindowList = GUICtrlCreateListView("Instance|hWnd|State", 8, 8, 249, 89)
GUICtrlSendMsg(-1, 0x101E, 0, 100)
GUICtrlSendMsg(-1, 0x101E, 1, 70)
GUICtrlSendMsg(-1, 0x101E, 2, 70)
$oHideShow = GUICtrlCreateButton("Hide/Show", 8, 104, 113, 25, 0)
$oHideShowCancel = GUICtrlCreateButton("Cancel", 128, 104, 113, 25, 0)
GUISetState(@SW_SHOW, $hWindowList)

Global $aOldWinList, $aNewWinList

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $oHideShow
            _HideShow()
    EndSwitch
    _PopulateWindowList()
    Sleep(20)
WEnd

Func _HideShow()
    Local $iSelectedIndex
    Local $aTemp
   
    ConsoleWrite("Selected: " & _GuiCtrlListView_GetNextItem($oWindowList, -1, 0, 8) & @CR)
    $iSelectedIndex = _GuiCtrlListView_GetNextItem($oWindowList, -1, 0, 8)
    If $iSelectedIndex <> -1 Then
        $aTemp = StringSplit(_GuiCtrlListView_GetItemTextString($oWindowList, $iSelectedIndex), "|")
        If IsArray($aTemp) And $aTemp[0]=3 Then
            If $aTemp[3] = "Visible"  Then
                ConsoleWrite("WinSetState("&$aTemp[2]&")"&@CR)
                WinSetState(HWnd($aTemp[2]), "", @SW_HIDE)
            Else
                WinSetState(HWnd($aTemp[2]), "", @SW_SHOW)
            EndIf
        EndIf
    Else
        MsgBox(0, "Error", "You must select a window to hide/show!")
    EndIf
EndFunc   ;==>_HideShow

Func _PopulateWindowList()
    Local $aWinList
    $aWinList = WinList("Untitled - Notepad")

    If IsArray($aWinList) And UBound($aWinList) > 1 Then ; Convert the current window list to my array format [hwnd][visible/hidden]
        Dim $aNewWinList[UBound($aWinList, 1)][2]
        For $i = 1 To UBound($aWinList) - 1
            $aNewWinList[$i][0] = $aWinList[$i][1]
            $aNewWinList[$i][1] = _ReturnVisibility($aWinList[$i][1])
        Next
        If Not _Array2DimCompare($aNewWinList, $aOldWinList) Then ;Compare new window list to the old window list previously applied to the listview
            If _GUICtrlListView_GetItemCount($oWindowList) > 0 Then _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($oWindowList)) ; Clear the listview if it isnt already
            For $i = 1 To UBound($aWinList, 1) - 1 ; Fill the listview with new updated window list/states
                GUICtrlCreateListViewItem("Notepad #" & $i & "|" & $aWinList[$i][1] & "|" & _ReturnVisibility($aWinList[$i][1]), $oWindowList)
            Next
            $aOldWinList = $aNewWinList ; Make the new list now the old one.
        EndIf
    Else
        If _GUICtrlListView_GetItemCount($oWindowList) > 0 Then _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($oWindowList)) ; Clear the listview if it is full and we found no windows
    EndIf
EndFunc   ;==>_PopulateWindowList

Func _ReturnVisibility($hWND)
    If WinExists($hWND) Then
        If BitAND(WinGetState($hWND), 2) Then
            Return "Visible"
        Else
            Return "Hidden"
        EndIf
    EndIf
EndFunc   ;==>_ReturnVisibility

Func _Array2DimCompare($Array1, $Array2, $iBase1 = 1, $iBase2 = 0, $iCase = 1)
    If UBound($Array1, 1) <> UBound($Array2, 1) Then Return SetError(1, 0, 0)
    If UBound($Array1, 2) <> UBound($Array2, 2) Then Return SetError(2, 0, 0)
    For $iCC = $iBase1 To UBound($Array1, 1) - 1
        For $xCC = $iBase2 To UBound($Array1, 2) - 1
            If $iCase Then
                If Not ($Array1[$iCC][$xCC] == $Array2[$iCC][$xCC]) Then _
                        Return SetError(3, 0, 0)
            Else
                If Not ($Array1[$iCC][$xCC] = $Array2[$iCC][$xCC]) Then _
                        Return SetError(3, 0, 0)
            EndIf
        Next
    Next
    Return 1
EndFunc   ;==>_Array2DimCompare

EDIT: Open up a few blank notepad instances to see them show up in the list.

Edited by Simucal

AutoIt Scripts:Aimbot: Proof of Concept - PixelSearching Aimbot with several search/autoshoot/lock-on techniques.Sliding Toolbar - Add a nice Sliding Toolbar to your next script. Click the link to see an animation of it in action!FontInfo UDF - Get list of system fonts, or search to see if a particular font is installed.Get Extended Property UDF - Retrieve a files extended properties (e.g., video/image dimensions, file version, bitrate of song/video, etc)

Share this post


Link to post
Share on other sites

Thanks for that utility.

I used it to confirm my earlier result. After my own script issues the Show step (and then exits), your script shows that the external window is Visible -- except that it isn't. But clicking Hide, then Show with your utility makes it visible.

I've also found that portions of the external window will become visible when they're clicked on -- so it's definitely in some odd state.

Share this post


Link to post
Share on other sites

What program is it?


AutoIt Scripts:Aimbot: Proof of Concept - PixelSearching Aimbot with several search/autoshoot/lock-on techniques.Sliding Toolbar - Add a nice Sliding Toolbar to your next script. Click the link to see an animation of it in action!FontInfo UDF - Get list of system fonts, or search to see if a particular font is installed.Get Extended Property UDF - Retrieve a files extended properties (e.g., video/image dimensions, file version, bitrate of song/video, etc)

Share this post


Link to post
Share on other sites

It's a database application. I've isolated the problem to these script steps:

$Style = 0x14030000; visible + clipsib + min/max boxes
$ExtStyle = 0
$flags = 0x43; nosize + nomove + showwindow
$res = DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", -16, "int", $Style) 
$res = DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", -20, "int", $ExtStyle)
$res = DllCall("User32.dll", "int", "SetWindowPos", "hwnd", $hWnd, "hwnd", -1, _
            "int", 0, "int", 0, "int", 0, "int", 0, "int", $flags); 
Sleep(200)
DllClose($dll)
WinSetState($hWnd, "", @SW_SHOW)

BTW, I use DllCalls to keep my scripts as small as possible. Note also that to make the code sample smaller, I've omitted the steps that confirm returned $res isn't zero. All steps are executing properly.

I'll continue working to isolate the cause -- unless someone spots a problem with the above.

Share this post


Link to post
Share on other sites

I located the Dll-related problem. It seems that setting the SWP_SHOWWINDOW flag in the SetWindowPos call invokes a conflict with the normal WinSetState HIDE/SHOW script steps. If the Dll flag is used, then the SHOW step never works. I've tried virtually every combination of hide/show, set/don't set -- and the only sequence that works is the Dll flag w/HIDE followed by a WinSetState w/SHOW.

So, after an entire day of testing, I'm back where I was in my first post. Method 1 works, but it momentarily drops the window's name from the taskbar. It's not an ideal result -- but unless someone can suggest a better way, I suppose it will have to do, because I'm out of ideas.

Thanks again for the responses.

Share this post


Link to post
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
Sign in to follow this  
Followers 0