Reputation: 4050
I want to place windows on my screen at various positions. I can calculate the dimensions of the screen as below (these are arrays if have multi-display setups):
$widths = (Get-WmiObject -Class Win32_DesktopMonitor | Select-Object ScreenWidth).ScreenWidth
$heights = (Get-WmiObject -Class Win32_DesktopMonitor | Select-Object ScreenHeight).ScreenHeight
To properly place windows, I need to also calculate the height of the Start bar. Does anyone know how to programmatically collect the Start bar height using PowerShell?
I would also like to know how to caculate the position of the Start bar (so that I know if it is placed at the top, bottom, left, right of the screen) if possible?
Upvotes: 0
Views: 838
Reputation: 4050
Just to share some uses for the info that @Theo gave me above, I wanted to make a function that could position PowerShell consoles. This currently does not cope with multi-monitor setups (if anyone wants to extend functionality to that, I would be glad to see that!).
I keep them as lll
and rrr
and fff
("full size") for quick access and keep them in my Custom-Tools
Module that is available to all of my console sessions. fff
relies on the $host.UI.RawUI
method which is not as accurate as setting the ConsolePosition (I trim off 1 character from the height as sometimes it does not fit this way) but I'm pretty happy with the ability to flip console settings very easily in this way.
function Global:Set-ConsolePosition ($x, $y, $w, $h) {
# Note: the DLL code below should not be indented from the left-side
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int W, int H); '
# Do the Add-Type outside of the function as repeating it in a session can cause errors
$consoleHWND = [Console.Window]::GetConsoleWindow();
$consoleHWND = [Console.Window]::MoveWindow($consoleHWND, $x, $y, $w, $h);
# $consoleHWND = [Console.Window]::MoveWindow($consoleHWND,75,0,600,600);
# $consoleHWND = [Console.Window]::MoveWindow($consoleHWND,-6,0,600,600);
}
function lll {
Add-Type -AssemblyName System.Windows.Forms
$Screen = [System.Windows.Forms.Screen]::PrimaryScreen
$width = $Screen.WorkingArea.Width # .WorkingArea ignores the taskbar, .Bounds is whole screen
$height = $Screen.WorkingArea.Height
$w = $width/2 + 13
$h = $height + 8
$x = -7
$y = 0
Set-ConsolePosition $x $y $w $h
$MyBuffer = $Host.UI.RawUI.BufferSize
$MyWindow = $Host.UI.RawUI.WindowSize
$MyBuffer.Height = 9999
"`nWindowSize $($MyWindow.Width)x$($MyWindow.Height) (Buffer $($MyBuffer.Width)x$($MyBuffer.Height))"
"Position : Left:$x Top:$y Width:$w Height:$h`n"
}
function rrr {
Add-Type -AssemblyName System.Windows.Forms
$Screen = [System.Windows.Forms.Screen]::PrimaryScreen
$width = $Screen.WorkingArea.Width # .WorkingArea ignores the taskbar, .Bounds is whole screen
$height = $Screen.WorkingArea.Height
$w = $width/2 + 13
$h = $height + 8
$x = $w - 20
$y = 0
Set-ConsolePosition $x $y $w $h
$MyBuffer = $Host.UI.RawUI.BufferSize
$MyWindow = $Host.UI.RawUI.WindowSize
$MyBuffer.Height = 9999
"`nWindowSize $($MyWindow.Width)x$($MyWindow.Height) (Buffer $($MyBuffer.Width)x$($MyBuffer.Height))"
"Position : Left:$x Top:$y Width:$w Height:$h`n"
}
function fff {
Set-ConsolePosition -7 0 600 600
if ($Host.Name -match "console") {
$MaxHeight = $host.UI.RawUI.MaxPhysicalWindowSize.Height - 1
$MaxWidth = $host.UI.RawUI.MaxPhysicalWindowSize.Width
$MyBuffer = $Host.UI.RawUI.BufferSize
$MyWindow = $Host.UI.RawUI.WindowSize
$MyWindow.Height = $MaxHeight
$MyWindow.Width = $Maxwidth
$MyBuffer.Height = 9999
$MyBuffer.Width = $Maxwidth
# $host.UI.RawUI.set_bufferSize($MyBuffer)
# $host.UI.RawUI.set_windowSize($MyWindow)
$host.UI.RawUI.BufferSize = $MyBuffer
$host.UI.RawUI.WindowSize = $MyWindow
"`nWindowSize $($MyWindow.Width)x$($MyWindow.Height) (Buffer $($MyBuffer.Width)x$($MyBuffer.Height))`n"
}
}
Upvotes: 0
Reputation: 61068
Instead of using WMI, you should be safe using the $Screen.WorkingArea
you can retrieve using for instance [System.Windows.Forms.Screen]::PrimaryScreen
.
Having said that, the function below will get you the dimensions and position of the TaskBar for a certain screen:
Add-Type -AssemblyName System.Windows.Forms
function Get-TaskBarDimensions {
param (
[System.Windows.Forms.Screen]$Screen = [System.Windows.Forms.Screen]::PrimaryScreen
)
$device = ($Screen.DeviceName -split '\\')[-1]
if ($Screen.Primary) { $device += ' (Primary Screen)' }
if ($Screen.Bounds.Equals($Screen.WorkingArea)) {
Write-Warning "Taskbar is hidden on device $device or moved to another screen."
return
}
# calculate heights and widths for the possible positions (left, top, right and bottom)
$ScreenRect = $Screen.Bounds
$workingArea = $Screen.WorkingArea
$left = [Math]::Abs([Math]::Abs($ScreenRect.Left) - [Math]::Abs($WorkingArea.Left))
$top = [Math]::Abs([Math]::Abs($ScreenRect.Top) - [Math]::Abs($workingArea.Top))
$right = ($ScreenRect.Width - $left) - $workingArea.Width
$bottom = ($ScreenRect.Height - $top) - $workingArea.Height
if ($bottom -gt 0) {
# TaskBar is docked to the bottom
return [PsCustomObject]@{
X = $workingArea.Left
Y = $workingArea.Bottom
Width = $workingArea.Width
Height = $bottom
Position = 'Bottom'
Device = $device
}
}
if ($left -gt 0) {
# TaskBar is docked to the left
return [PsCustomObject]@{
X = $ScreenRect.Left
Y = $ScreenRect.Top
Width = $left
Height = $ScreenRect.Height
Position = 'Left'
Device = $device
}
}
if ($top -gt 0) {
# TaskBar is docked to the top
return [PsCustomObject]@{
X = $workingArea.Left
Y = $ScreenRect.Top
Width = $workingArea.Width
Height = $top
Position = 'Top'
Device = $device
}
}
if ($right -gt 0) {
# TaskBar is docked to the right
return [PsCustomObject]@{
X = $workingArea.Right
Y = $ScreenRect.Top
Width = $right
Height = $ScreenRect.Height
Position = 'Right'
Device = $device
}
}
}
To get the TaskBar dimensions for the Primary screen only:
Get-TaskBarDimensions
To get the TaskBar dimensions for all connected screens:
[System.Windows.Forms.Screen]::AllScreens | ForEach-Object {
Get-TaskBarDimensions $_
}
This will return an object with the following properties:
X : 0 Y : 1160 Width : 1920 Height : 40 Position : Bottom Device : DISPLAY1 (Primary Screen)
Or -in case the taskbar is hidden or not present on that screen- a warning like:
Taskbar is hidden on device DISPLAY2 or moved to another screen.
Upvotes: 1