qwert Posted February 4, 2008 Posted February 4, 2008 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.
whim Posted February 4, 2008 Posted February 4, 2008 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)
qwert Posted February 4, 2008 Author Posted February 4, 2008 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.
Simucal Posted February 4, 2008 Posted February 4, 2008 (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. expandcollapse popup#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 February 4, 2008 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)
qwert Posted February 4, 2008 Author Posted February 4, 2008 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.
Simucal Posted February 4, 2008 Posted February 4, 2008 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)
qwert Posted February 4, 2008 Author Posted February 4, 2008 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.
qwert Posted February 5, 2008 Author Posted February 5, 2008 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.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now