emendelson Posted March 23, 2021 Share Posted March 23, 2021 I have a script that runs another application (vDos.exe), and the same script can be run multiple times to open other instances of the same vDos.exe application. When I open a new instance of vDos.exe, I want to make sure that its window does not open directly over a previous instance, so I want to get the window positions of previous instances. Has someone written a method of finding the PIDs of all instances of the same executable, so that I can get the window positions of each of them? I've found various application counters in the forum, but they seem to be designed to find multiple instances of the script, not of another application. Many thanks for any pointers. Link to comment Share on other sites More sharing options...
TheXman Posted March 23, 2021 Share Posted March 23, 2021 (edited) 2 hours ago, emendelson said: Has someone written a method of finding the PIDs of all instances of the same executable, so that I can get the window positions of each of them? Lookup the ProcessList() function in the help file. Edited March 23, 2021 by TheXman CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
Nine Posted March 23, 2021 Share Posted March 23, 2021 8 hours ago, emendelson said: I want to make sure that its window does not open directly over a previous instance, so I want to get the window positions of previous instances Well PIDs will not tell you what are the position of the windows. I believe the best way would be to use WinList() with the title special definition [CLASS:vdos class here]. Within the array obtained you can loop thru getting position of each window through WinGetPos. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
emendelson Posted March 23, 2021 Author Share Posted March 23, 2021 Nine, this is clearly the answer I needed. I should have thought of WinList() but didn't. Thank you! Link to comment Share on other sites More sharing options...
emendelson Posted March 24, 2021 Author Share Posted March 24, 2021 (edited) Again, thanks to Nine, I think I've mostly solved this problem, but I have more question. I created a function that loops through the windows of the existing instances of vDos.exe, and, if the newly-created instance matches the location of one of the earlier ones, sets the new window to be moved 30 pixels down and to the right. This causes a potential problem where the move down and to the right could put the new window into the position of an instances tested EARLIER in the loop. So I tried putting the loop inside another loop that performs the testing loop multiple times (the same number of times as there are instances). I think there must be a better or more efficient way to do this, though it seems to work reasonably well. Here is the code (with the _GetHwndFromPID() function taken from some excellent code posted in the forum years ago): expandcollapse popup$running = ProcessExists("vdos.exe") $PID = Run("vDos.exe") ; this is simplified from the actual code If $running <> 0 Then MoveNew($PID) Func MoveNew($PID) Local $hWnd, $w, $vList, $oldWnd Local $tmpWinPos, $tmpXpos, $tmpYpos, $finalXpos, $finalYpos $hWnd = _GetHwndFromPID($PID) WinWait($hWnd) $w = WinGetPos($hWnd) $xNew = $w[0] $yNew = $w[1] $finalXpos = $xNew $finalYpos = $yNew $vList = WinList("[CLASS:vDos]", "") For $n = 1 To UBound($vList) - 1 For $i = 1 To UBound($vList) - 1 If $i <> $hWnd Then ;; don't test new instance against itself $oldWnd = $vList[$i][1] $tmpWinPos = WinGetPos($oldWnd) $tmpXpos = $tmpWinPos[0] $tmpYpos = $tmpWinPos[1] If (($tmpXpos = $finalXpos) Or ($tmpYpos = $finalYpos)) Then $finalXpos = $finalXpos + 30 $finalYpos = $finalYpos + 30 EndIf EndIf Next Next If (($xNew <> $finalXpos) Or ($yNew <> $finalYpos)) Then WinMove($hWnd, "", $finalXpos, $finalYpos) EndIf EndFunc ;==>MoveNew Func _GetHwndFromPID($PID) $hWnd = 0 $stPID = DllStructCreate("int") Do $winlist2 = WinList() For $i = 1 To $winlist2[0][0] If $winlist2[$i][0] <> "" Then DllCall("user32.dll", "int", "GetWindowThreadProcessId", "hwnd", $winlist2[$i][1], "ptr", DllStructGetPtr($stPID)) If DllStructGetData($stPID, 1) = $PID Then $hWnd = $winlist2[$i][1] ExitLoop EndIf EndIf Next Sleep(100) Until $hWnd <> 0 Return $hWnd EndFunc ;==>_GetHwndFromPID Edited March 24, 2021 by emendelson Fix code Link to comment Share on other sites More sharing options...
Nine Posted March 24, 2021 Share Posted March 24, 2021 Here the way I would do it. That will ensure that no other window share the same position : #include <Constants.au3> Const $sClass = "[CLASS:Notepad]" Local $PID = Run("Notepad") Sleep(1000) MoveNew($PID, $sClass) Func MoveNew($PID, $sClass) Local $hCurrent = _GetHwndFromPID($PID, $sClass) If Not $hCurrent Then Exit MsgBox($MB_SYSTEMMODAL, "Error", "Unable to find current window") Local $aCurrent = WinGetPos($hCurrent) Local $aPos, $xMax = -1, $yMax = -1, $bFound = False Local $aList = WinList($sClass) For $i = 1 To $aList[0][0] If WinGetProcess($aList[$i][1]) = $PID Then ContinueLoop $aPos = WinGetPos($aList[$i][1]) $xMax = $aPos[0] > $xMax ? $aPos[0] : $xMax $yMax = $aPos[1] > $yMax ? $aPos[1] : $yMax If $aCurrent[0] = $aPos[0] And $aCurrent[1] = $aPos[1] Then $bFound = True Next If $bFound Then WinMove($hCurrent, "", $xMax + 30, $yMax + 30) EndFunc ;==>MoveNew Func _GetHwndFromPID($PID, $sClass) Local $aList = WinList($sClass) For $i = 1 To $aList[0][0] If WinGetProcess($aList[$i][1]) = $PID Then Return $aList[$i][1] Next Return 0 EndFunc ;==>_GetHwndFromPID That is supposing that users cannot change the position of a window. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
emendelson Posted March 24, 2021 Author Share Posted March 24, 2021 (edited) Thank you for doing this! It seems to work perfectly when I tested it with vDos, but I don't understand what it means to say that "users cannot change the position of a window." When I tested your code, I sometimes moved the vDos window after launching it, and the next time I ran your code, the next vDos window appeared correctly 30 pixels to the right and 30 pixels below the previous one. I think I'm missing something important. Could you let me know more? (I know I'm asking for more after you've already given a lot.) By the way, I originally wanted to use some method of calculating a maximum setting, but could not figure out how to do. I'm very grateful to have your example! Edited March 24, 2021 by emendelson Link to comment Share on other sites More sharing options...
Nine Posted March 24, 2021 Share Posted March 24, 2021 If a user changes the position of a window (by dragging the title bar for example) and puts the window at the very bottom of the screen, the next window could be partly hidden because it would exceed the screen size. It is not important but just want to let you know. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
emendelson Posted March 24, 2021 Author Share Posted March 24, 2021 Ah - I see. Thank you. I suppose I could add some code that tested the current screen dimensions, and changed the window position if the next window would be in a completely inconvenient location. I hadn't thought of that, but it should be fairly easy. Thank you again! Link to comment Share on other sites More sharing options...
Nine Posted March 24, 2021 Share Posted March 24, 2021 You are welcome. Yes, it is not a big problem and users can understand that they need to change position to make it more appropriate anyway. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy 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