Page 1 of 1

Center Window and Move Window (yet more Powershell hybrids)

Posted: 06 Sep 2018 13:44
by aGerman
Center Window:

Code: Select all

@echo off &setlocal
mode con cols=50 lines=20

call :init_Center

for /l %%i in () do (
  %Center% middle
  %Center% left
  %Center% right
  %Center% top
  %Center% bottom
)

goto :eof

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:init_Center
setlocal DisableDelayedExpansion
:: prefer PowerShell Core if installed
for %%i in ("pwsh.exe") do if "%%~$PATH:i"=="" (set "ps=powershell") else set "ps=pwsh"

:: - BRIEF -
::  Center the console window.
:: - SYNTAX -
::  %center% middle|left|top|right|bottom [pid]
::    middle|left|top|right|bottom  either of them specifies the position where
::                                   to center the window on the monitor
::    pid                           (optional) ID of a process whose main window
::                                   is to be centered 
:: - EXAMPLES -
::  Place the window in the middle of the monitor:
::    %Center%
::  Place the window in the middle of the top of the monitor:
::    %Center% top
set Center=for %%- in (1 2) do if %%-==2 (for /f "tokens=1,2" %%. in ("^^!arg^^! x") do^
%=% %ps%.exe -nop -ep Bypass -c ^"^
%===% $w=Add-Type -Name WAPI -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void SetProcessDPIAware();^
%=====% [DllImport(\"shcore.dll\")]^
%=======% public static extern void SetProcessDpiAwareness(int value);^
%=====% [DllImport(\"kernel32.dll\")]^
%=======% public static extern IntPtr GetConsoleWindow();^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void GetWindowRect(IntPtr hwnd, int[] rect);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void GetClientRect(IntPtr hwnd, int[] rect);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void GetMonitorInfoW(IntPtr hMonitor, int[] lpmi);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern int SetWindowPos(IntPtr hwnd, IntPtr hwndAfterZ, int x, int y, int w, int h, int flags);^
%===% ';^
%===% $PROCESS_PER_MONITOR_DPI_AWARE=2;^
%===% try {$w::SetProcessDpiAwareness($PROCESS_PER_MONITOR_DPI_AWARE)} catch {$w::SetProcessDPIAware()}^
%===% $tpid=0;^
%===% if ([Int32]::TryParse('%%~/', [ref]$tpid)) {^
%=====% $hwnd=(gps -id $tpid -ea SilentlyContinue).MainWindowHandle;^
%===% } else {^
%=====% $hwnd=$w::GetConsoleWindow();^
%===% }^
%===   The $moninf array is a replacement for the MONITORINFO structure. The elements at index         =% ^
%===   5, 6, 7, and 8 represent left, top, right, and bottom boundaries of the monitor's work space.   =% ^
%===% $moninf=[int[]]::new(10);^
%===% $moninf[0]=40;^
%===% $MONITOR_DEFAULTTONEAREST=2;^
%===% $w::GetMonitorInfoW($w::MonitorFromWindow($hwnd, $MONITOR_DEFAULTTONEAREST), $moninf);^
%===% $monwidth=$moninf[7] - $moninf[5];^
%===% $monheight=$moninf[8] - $moninf[6];^
%===   The $wrect array is a replacement for the RECT structure. The elements at index   =% ^
%===   0, 1, 2, and 3 represent left, top, right, and bottom boundaries of the window.   =% ^
%===% $wrect=[int[]]::new(4);^
%===% $w::GetWindowRect($hwnd, $wrect);^
%===% $winwidth=$wrect[2] - $wrect[0];^
%===% $winheight=$wrect[3] - $wrect[1];^
%===% $x=0; $y=0;^
%===% if ('%%~.' -eq 'middle') {^
%=====% $x=[int][math]::Round($moninf[5] + $monwidth / 2 - $winwidth / 2);^
%=====% $y=[int][math]::Round($moninf[6] + $monheight / 2 - $winheight / 2);^
%===% } elseif ('%%~.' -eq 'left') {^
%=====% $x=$moninf[5];^
%=====% $y=[int][math]::Round($moninf[6] + $monheight / 2 - $winheight / 2);^
%===% } elseif ('%%~.' -eq 'top') {^
%=====% $x=[int][math]::Round($moninf[5] + $monwidth / 2 - $winwidth / 2);^
%=====% $y=$moninf[6];^
%===% } elseif ('%%~.' -eq 'right') {^
%=====% $x=$moninf[7] - $winwidth;^
%=====% $y=[int][math]::Round($moninf[6] + $monheight / 2 - $winheight / 2);^
%===% } elseif ('%%~.' -eq 'bottom') {^
%=====% $x=[int][math]::Round($moninf[5] + $monwidth / 2 - $winwidth / 2);^
%=====% $y=$moninf[8] - $winheight;^
%===% } else {exit 1}^
%===% $SWP_NOSIZE=0x0001;^
%===% $SWP_NOZORDER=0x0004;^
%===% exit [int]($w::SetWindowPos($hwnd, [IntPtr]::Zero, $x, $y, 0, 0, $SWP_NOSIZE -bOr $SWP_NOZORDER) -eq 0);^
%=% ^" ^&endlocal) else setlocal EnableDelayedExpansion ^&set arg=

endlocal &set "Center=%Center%"
if !!# neq # set "Center=%Center:^^=%"
exit /b
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Press [Ctrl]+[C] if you can't catch the red X :lol:

~~~~~~~~~~~~~~~~~~~~~~~~~~~
Move Window:

Code: Select all

@echo off &setlocal

call :init_MoveWindow
%MoveWindow% 100 50
echo %errorlevel%

pause
exit /b


::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:init_MoveWindow
setlocal DisableDelayedExpansion
:: prefer PowerShell Core if installed
for %%i in ("pwsh.exe") do if "%%~$PATH:i"=="" (set "ps=powershell") else set "ps=pwsh"

:: - BRIEF -
::  Move the window to a certain position on the virtual screen.
:: - SYNTAX -
::  %MoveWindow% X Y [pid]
::    X    left side of the window on the screen in dots
::    Y    top of the window on the screen in dots
::    pid  (optional) ID of a process whose main window is to be moved
:: - EXAMPLES -
::  Move the left side of the window to position 100, and its top to position 50:
::    %MoveWindow% 100 50
set MoveWindow=for %%- in (1 2) do if %%-==2 (for /f "tokens=1-3" %%. in ("^^!args^^! x x x") do^
%=% %ps%.exe -nop -ep Bypass -c ^"^
%===% $w=Add-Type -Name WAPI -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void SetProcessDPIAware();^
%=====% [DllImport(\"shcore.dll\")]^
%=======% public static extern void SetProcessDpiAwareness(int value);^
%=====% [DllImport(\"kernel32.dll\")]^
%=======% public static extern IntPtr GetConsoleWindow();^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern int SetWindowPos(IntPtr hwnd, IntPtr hwndAfterZ, int x, int y, int w, int h, int flags);^
%===% ';^
%===% $PROCESS_PER_MONITOR_DPI_AWARE=2;^
%===% try {$w::SetProcessDpiAwareness($PROCESS_PER_MONITOR_DPI_AWARE)} catch {$w::SetProcessDPIAware()}^
%===% $x=0; $y=0; $tpid=0;^
%===% if (-not [Int32]::TryParse('%%~.', [ref]$x) -or -not [Int32]::TryParse('%%~/', [ref]$y)) {exit 1}^
%===% if ([Int32]::TryParse('%%~0', [ref]$tpid)) {^
%=====% $wnd=(gps -id $tpid -ea SilentlyContinue).MainWindowHandle;^
%===% } else {^
%=====% $wnd=$w::GetConsoleWindow();^
%===% }^
%===% $HWND_TOP=[IntPtr]::Zero;^
%===% $SWP_NOSIZE=0x0001;^
%===% $SWP_SHOWWINDOW=0x0040;^
%===% exit [int]($w::SetWindowPos($wnd, $HWND_TOP, $x, $y, 0, 0, $SWP_NOSIZE -bOr $SWP_SHOWWINDOW) -eq 0);^
%=% ^" ^&endlocal) else setlocal EnableDelayedExpansion ^&set args=

endlocal &set "MoveWindow=%MoveWindow%"
if !!# neq # set "MoveWindow=%MoveWindow:^^=%"
exit /b
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Both macros default to update the position of the console window. However, other windows can be moved by passing the ID of the belonging process as optional argument. In case of the Windows Terminal use the %TermPid% macro. Refer to:
viewtopic.php?f=3&t=10576

Steffen

Re: Center Window (yet another Powershell hybrid)

Posted: 06 Sep 2018 14:40
by IcarusLives
Ooooo I like this release! Very nice! Is it possible to place in more dynamic positions, or just the 5?

Re: Center Window (yet another Powershell hybrid)

Posted: 06 Sep 2018 14:59
by aGerman
Since the macro is called "center" I can't think of any further locations that deserve this name :wink: Of course it would be possible to move the window to any position you want but in that case "center" would be rather misleading. If you want me to write another script to move the window to certain x,y coordinates I would be able to modify the code accordingly.

Steffen

Re: Center Window (yet another Powershell hybrid)

Posted: 07 Sep 2018 07:08
by IcarusLives
Haha, I guess you've got a point! No, this script is great! Thank you very much for this release.

Re: Center Window and Move Window (yet more Powershell hybrids)

Posted: 07 Sep 2018 14:15
by aGerman
I updated the initial post with an additional move_window macro.

Steffen

Re: Center Window and Move Window (yet more Powershell hybrids)

Posted: 07 Sep 2018 14:20
by IcarusLives
I love the move window macro! This is great, thank you very much for this.

I also respect how short and concise it is.

Both working Win 10 64bit

Re: Center Window and Move Window (yet more Powershell hybrids)

Posted: 07 Sep 2018 14:25
by aGerman
Thanks for your feedback, IcarusLives :) Much appreciated.

Steffen

Re: Center Window and Move Window (yet more Powershell hybrids)

Posted: 29 Oct 2022 09:34
by aGerman
I updated the initial post to support other windows, such like Windows Terminal.

Steffen