0

When I boot up my computer I open several file explorers and sort them around the screen to help speed up my workflow. It's not time consuming, only tedious, and I'd like a small program to do it for me. I know how to open an explorer, but I don't see any positional arguments.

Is there a way to spawn a file explorer at a set of screen coordinates, or move it programatically after it opens? Preferably with python 3+, but batch will work as well.

DCOPTimDowd
  • 231
  • 1
  • 11
  • 3
    see http://superuser.com/questions/747900/open-browser-window-at-specified-screen-coordinates – Richard Dec 28 '16 at 17:32
  • Looks like there's no way of doing it without extra third-party tools, which I can't access on my network. How unfortunate. Thanks for the link. – DCOPTimDowd Dec 28 '16 at 17:45
  • 2
    I could have sworn I answered a question like this a long time ago (the answer is to have PowerShell use the Win32 API), but I can't find it. If this question is still open when I get home from work, I'll post the code then. – SomethingDark Dec 28 '16 at 17:59
  • You might be interested in [AutoIt](http://autoitscript.com/) or [AutoHotkey](http://autohotkey.com/)... – aschipfl Dec 28 '16 at 19:06
  • @aschipfl I'll check those out too. – DCOPTimDowd Dec 28 '16 at 19:54
  • 2
    Oh, jeez. My existing code only works for applications that have window titles (aka literally everything _except_ Explorer windows). http://stackoverflow.com/q/31347905/4158862 suggests it's possible to differentiate between windows, but I can barely speak PowerShell so this might take a while... – SomethingDark Dec 28 '16 at 22:37

1 Answers1

4

That was simultaneously easier and harder than I thought it was going to be. Everything is commented, let me know if you have any more questions. This is a PowerShell/batch hybrid script (so save it as a .bat file) because PowerShell is disabled on systems by default or something.

<# :
:: Based on https://gist.github.com/coldnebo/1148334
:: Converted to a batch/powershell hybrid via http://www.dostips.com/forum/viewtopic.php?p=37780#p37780
:: Array comparison from http://stackoverflow.com/a/6368667/4158862
@echo off
setlocal
set "POWERSHELL_BAT_ARGS=%*"
if defined POWERSHELL_BAT_ARGS set "POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%"
endlocal & powershell -NoLogo -NoProfile -Command "$_ = $input; Invoke-Expression $( '$input = $_; $_ = \"\"; $args = @( &{ $args } %POWERSHELL_BAT_ARGS% );' + [String]::Join( [char]10, $( Get-Content \"%~f0\" ) ) )"
goto :EOF
#>

# Create an instance of the Win32 API object to handle and manipulate windows
Add-Type @"
  using System;
  using System.Runtime.InteropServices;

  public class Win32 {
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
  }
"@

# Get a list of existing Explorer Windows
$previous_array = @()
$shell_object = New-Object -COM 'Shell.Application'

foreach($old_window in $shell_object.Windows())
{
    $previous_array += $old_window.HWND
}

# Open four more Explorer Windows in the current directory
explorer
explorer
explorer
explorer

# Pause for 1 second so that the windows have time to finish opening
sleep 1

# Get the list of new Explorer Windows
$new_array = @()
foreach($new_window in $shell_object.Windows())
{
    $new_array += $new_window.HWND
}

# Compare the two arrays and only process the new windows
$only_new = Compare-Object -ReferenceObject $previous_array -DifferenceObject $new_array -PassThru

# MoveWindow takes HWND value, X-position on screen, Y-position on screen, window width, and window height
# I've just hard-coded the values, adjust them to suit your needs
[Win32]::MoveWindow($only_new[0],0,0,960,540,$true)
[Win32]::MoveWindow($only_new[1],960,0,960,540,$true)
[Win32]::MoveWindow($only_new[2],0,540,960,540,$true)
[Win32]::MoveWindow($only_new[3],960,540,960,540,$true)
SomethingDark
  • 13,229
  • 5
  • 50
  • 55
  • 1
    This is super cool! And it works for multiple screens without any extra APIs! Exactly what I wanted. :) – DCOPTimDowd Dec 29 '16 at 17:15
  • The only thing I added was a one second pause between each window spawn so they were in the order I needed them. I tried the ['ping' technique](https://www.experts-exchange.com/articles/17805/Inserting-Delays-with-Millisecond-Resolution-in-Windows-Batch-bat-Files.html), but a half second wasn't long enough for some, so went with 'sleep'. – DCOPTimDowd Dec 29 '16 at 17:39