ExpertNoob Posted September 7, 2012 Share Posted September 7, 2012 Hi folks, Every thing wants to mess up my windows ! At first there was Zuma. I play in full screen, and it changes display geometry, so when I get back to my desktop, all windows are messed up ! Sometimes desktop icons too. Then I noticded "The Drift": whenever I connect to my PC using Remote Desktop, windows are slightly pushed down and to the right. Since I connect to my PC on and off all day long, at the end of the day, when I get home, guess what ! One day I decided I would restore all windows to their normal positions and sizes before leaving so I wouldn't have to do it later. When I got home and unlocked my session, they were pushed like I was connecting through RD !!! I have no explanation for this, but the conclusion is obvious: everyone and their dog have an opinion about my windows' (MY windows' !!) best positions and sizes ! Me too, god damn it ! This started to sound like a conspiracy against my poor windows, and I decided enough is enough ! So I looked around for one big dog to guard those damn windows' positions when my back is turned.. And came up with many tools to restore desktop icons' positions (like IconRestorer), but nothing for the windows' placements. It looked like I was the only one suffering from the windows' placements mess up syndrom Maybe it IS a conspiracy !! So, reluctantly, and with the daily suffering of seeing my beloved windows take the spin, I slowly came to the conclusion that I needed to do it myself. Me ! So, if you share my pain, suffer no more ! This little AutoIt script of mine woks surprisingly well, and I'm sure it can even be made better : expandcollapse popup#Include <WinAPI.au3> ; _WinAPI_Get/SetWindowPlacement() #include <Process.au3> ; ProcessExists() Global Const $sleepTime = 4000 Opt ( "TrayAutoPause", 0 ) Global $ZumaMinimized = True, $noRDesktop = True, $desktopLocked = False Global $i = 0, $j = 0, $list Dim $plsZuma[100][2], $plsRDP[100][2], $plsLogon[100][2] ; windows placements ; Windows Terminal Services stuff Global Const $WTSUserName = 5, $WTSWinStationName = 6, $WTSConnectState = 8, $WTSClientAddress = 14, $WTSClientDisplay = 15, $WTSClientName = 10 Global Const $WTS_CURRENT_SESSION = -1 Global Const $SessStates[10] = ["Active", "Connected", "Connect Query", "Shadow", "Disconnected", "Idle", "Listen", "Reset", "Down", "Init"] Global Const $hWTSAPI32 = DllOpen("wtsapi32.dll") ; WTSRegisterSessionNotification() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Get session ID Global $mySessID = 0 Dim $myResult = DllCall("Kernel32.dll", "dword", "WTSGetActiveConsoleSessionId") If @error Then MsgBox(16, "WindowWatchDog", "Failed to get current session ID with WTSGetActiveConsoleSessionId() !") Exit EndIf $mySessID = $myResult[0] ; Catch session change events $hGUI = GUICreate("Catch RDP Session Connection", 600, 400) DllCall($hWTSAPI32, "int", "WTSRegisterSessionNotification", "hwnd", $hGUI, "dword", 1) ; NOTIFY_FOR_ALL_SESSIONS If @error Then MsgBox(0,"", "Err WTSRegisterSessionNotification") Exit EndIf GUIRegisterMsg(0x2B1, "WTSSESSION_CHANGE") ; WM_WTSSESSION_CHANGE ; Save windows placements every $sleepTime. Restore when appropriate While True ;------------------------------------------------------------------------------------------------- $listZuma = WinList( "[REGEXPTITLE:^Zuma Deluxe 1.0$]" ) if 2 == $listZuma[0][0] Then ; Zuma running If BitAnd(WinGetState($listZuma[1][1], ""), 16) Then ; minimized now If Not $ZumaMinimized Then ; was up RestorePlacements($plsZuma) _NoHaltMsgBox(0, "Zuma", "Restored placements") Sleep($sleepTime) EndIf $ZumaMinimized = True CollectPlacements($plsZuma) Else $ZumaMinimized = False EndIf EndIf ;------------------------------------------------------------------------------------------------- If $noRDesktop Then CollectPlacements($plsRDP) ;------------------------------------------------------------------------------------------------- If Not ProcessExists("logonui.exe") Then ; desktop not locked anymore If $desktopLocked Then ; desktop was locked sleep(3000) RestorePlacements($plsLogon) _NoHaltMsgBox(0, "Logon", "Restored placements") $desktopLocked = False ; do placement only once ! Sleep($sleepTime) EndIf CollectPlacements($plsLogon) Else ; desktop locked $desktopLocked = True ; session gone, continue collecting placements : CollectPlacements($plsLogon) EndIf ;------------------------------------------------------------------------------------------------- Sleep($sleepTime) WEnd Exit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func WTSSESSION_CHANGE($hWndGUI, $MsgID, $WParam, $LParam) If Not ( $mySessID = Dec(Hex($LParam)) ) Then Return ; Out, bad session ! Go get your own instance of this wonderful script ! ; WTS_REMOTE_CONNECT = 0x3, WTS_REMOTE_DISCONNECT = 0x4 ; WTS_SESSION_UNLOCK = 0x8, WTS_SESSION_LOGON = 0x5 If $WParam = 3 Then ; Connect event If Not StringInStr(SessionInfo($WTSWinStationName, $LParam), "RDP-Tcp#") Then Return If "" = SessionInfo($WTSUserName, $LParam) Then Return If $SessStates[0] <> SessionInfo($WTSConnectState, $LParam) Then Return ; Active sleep(3000) ; give time for display to refresh and stablize RestorePlacements($plsRDP) _NoHaltMsgBox(0, "RDP", "Restored placements") $noRDesktop = False ; do placement only once ! EndIf If $WParam = 4 Then $noRDesktop = True; session disconnected EndFunc Func SessionInfo($request = $WTSClientAddress, $session = $WTS_CURRENT_SESSION) #cs BOOL WTSQuerySessionInformation( hServer: WTS_CURRENT_SERVER_HANDLE=0 to indicate the RD Session Host server on which your application is running. __in HANDLE hServer, SessionId: WTS_CURRENT_SESSION=-1 __in DWORD SessionId, __in WTS_INFO_CLASS WTSInfoClass, __out LPTSTR *ppBuffer, __out DWORD *pBytesReturned ); ret = 0 : failure WTSInfoClass: WTSClientProtocolType = 16 => USHORT : 0=The console session, 1=Value retained for legacy purposes, 2=The RDP protocol. WTSIsRemoteSession = 29 => TRUE or FALSE WTSSessionId = 4 => ULONG value containing the session identifier WTSUserName = 5 => null-terminated string containing the name of the user associated with the session WTSWinStationName = 6 => null-terminated string containing the name of the Remote Desktop Services session, NOT the winstation ! WTSConnectState = 8 => enum {WTSActive,WTSConnected,WTSConnectQuery,WTSShadow,WTSDisconnected,WTSIdle,WTSListen,WTSReset,WTSDown,WTSInit} WTSClientName = 10 => null-terminated string containing the name of the client WTSClientAddress = 14 => struct {DWORD AddressFamily; BYTE Address[20];} WTS_CLIENT_ADDRESS, IP@ is Address[2..n] WTSClientDisplay = 15 => struct {DWORD HorizontalResolution; DWORD VerticalResolution; DWORD ColorDepth;} WTS_CLIENT_DISPLAY WTSLogonTime = 18 => ERROR_NOT_SUPPORTED (!!) #ce Local $ret, $stString, $s Switch $request Case $WTSUserName, $WTSWinStationName, $WTSClientName, $WTSConnectState, $WTSClientAddress, $WTSClientDisplay $ret = DllCall("Wtsapi32.dll","int", "WTSQuerySessionInformationW", "Ptr", 0, "int", $session, "int", $request, "ptr*", 0, "dword*", 0) If (@error = True) Or ($ret[0] = False) Then Return "WTSQuerySessionInformationW() Error !!" Case Else Return $request & " unsupported !!" EndSwitch Switch $request Case $WTSUserName, $WTSWinStationName, $WTSClientName $stString = DllStructGetData ( DllStructCreate( "WCHAR[" & Ceiling($ret[5]/2) & "]", $ret[4] ) , 1 ) $stString = BinaryToString($stString, 4) Case $WTSConnectState $stString = $SessStates[ DllStructGetData ( DllStructCreate( "int", $ret[4] ) , 1 ) ] Case $WTSClientAddress $stString = DllStructGetData ( DllStructCreate( "byte[" & $ret[5] & "]", $ret[4] ) , 1 ) ; 14 WTSClientAddress Local $ip = StringTrimLeft($stString,14) $stString = Dec(StringLeft($ip,2)) For $i = 1 to 3 $ip = StringTrimLeft($ip,2) $stString &= "." & Dec(StringLeft($ip,2)) Next Case $WTSClientDisplay Local $display = DllStructCreate( "DWORD[" & Ceiling($ret[5]/4) & "]", $ret[4] ) ; 15 WTSClientDisplay $stString = DllStructGetData($display, 1,1) &" x "& DllStructGetData($display, 1,2) & " pixels, " $display = DllStructGetData($display, 1,3) If $display < 5 Then $display = $display * 4 If $display = 15 Then $display = 16 ; oO If $display = 8 Then $stString &= "RGB colors" Else $stString &= "color depth = " & $display & " bits" EndIf EndSwitch DllCall("Wtsapi32.dll", "int", "WTSFreeMemory", "ptr", $ret[4]) Return $stString EndFunc Func RestorePlacements(ByRef $pls) For $i = 1 to (UBound($pls, 1) - 1) If 0 <> WinGetState($pls[$i][0]) Then _WinAPI_SetWindowPlacement( $pls[$i][0], DllStructGetPtr($pls[$i][1]) ) Next EndFunc Func CollectPlacements(ByRef $pls) $j = 0 $list = WinList() ReDim $pls[ $list[0][0] ][2] For $i = 1 to $list[0][0] $hwd = $list[$i][1] If BitAnd( WinGetState($hwd), 2 ) Then ; 2 = Window is visible $pls[$j][0] = $hwd $pls[$j][1] = _WinAPI_GetWindowPlacement($hwd) $j+=1 EndIf Next $j-=1 ReDim $pls[ $j ][2] EndFunc Func _NoHaltMsgBox($code=0, $title = "",$text = "" ,$timeout = 0) Run (@AutoItExe & ' /AutoIt3ExecuteLine "MsgBox(' & $code & ', '''& $title & ''', '''& $text &''',' & $timeout & ')"') EndFunc This works like a charm, AutoIt PAWA ! It needs to be extended to handle desktop icon positions too. IconRestorer is not dynamic like this script, which takes care of things and restores stuff automatically when needed.. argumentum 1 Link to comment Share on other sites More sharing options...
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