Opening Process and Changing Window Position

Opening process and changing window position

Try SetWindowPos as described here. This page shows how to call it from C#.

How to get and set the window position of another application in C#

I actually wrote an open source DLL just for this sort of thing.
Download Here

This will allow you to find, enumerate, resize, reposition, or do whatever you want to other application windows and their controls.
There is also added functionality to read and write the values/text of the windows/controls and do click events on them. It was basically written to do screen scraping with - but all the source code is included so everything you want to do with the windows is included there.

Is it possible to position a window when starting a process with PowerShell (Start-Process)?

Try this, which uses the -Passthru option for Start-Process to get the process info. Then, we use a bit of pInvoke magic to move the window we've just created to somewhere else.

This example will enable you to snap the spawned window to the edges of the windows current screen. You can specify X or Y edges, or both. Top, Left wins if all 4 switches are specified.

Add-Type -AssemblyName System.Windows.Forms

Add-Type @"
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}

public class pInvoke
{
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, ExactSpelling = true, SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect);
}
"@

function Move-Window([System.IntPtr]$WindowHandle, [switch]$Top, [switch]$Bottom, [switch]$Left, [switch]$Right) {
# get the window bounds
$rect = New-Object RECT
[pInvoke]::GetWindowRect($WindowHandle, [ref]$rect)

# get which screen the app has been spawned into
$activeScreen = [System.Windows.Forms.Screen]::FromHandle($WindowHandle).Bounds

if ($Top) { # if top used, snap to top of screen
$posY = $activeScreen.Top
} elseif ($Bottom) { # if bottom used, snap to bottom of screen
$posY = $activeScreen.Bottom - ($rect.bottom - $rect.top)
} else { # if neither, snap to current position of the window
$posY = $rect.top
}

if ($Left) { # if left used, snap to left of screen
$posX = $activeScreen.Left
} elseif ($Right) { # if right used, snap to right of screen
$posX = $activeScreen.Right - ($rect.right - $rect.left)
} else { # if neither, snap to current position of the window
$posX = $rect.left
}

[pInvoke]::MoveWindow($app.MainWindowHandle, $posX, $posY, $rect.right - $rect.left, $rect.bottom - $rect.top, $true)
}

# spawn the window and return the window object
$app = Start-Process dotnet -ArgumentList "run" -PassThru

Move-Window -WindowHandle $app.MainWindowHandle -Bottom -Left

How can I control the size and position of a new process Window from a WinForms app?

The Windows API method in question is SetWindowPos. You can declare it like so:

[DllImport("user32.dll")]
private extern static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

and read about it here:
http://msdn.microsoft.com/en-us/library/ms633545.aspx

Added

Process.MainWindowHandle is the hWnd parameter you will use.
hWndInsertAfter will probably be your own Form's handle (Form.Handle).
You can use the Screen type to access information about the desktop:
http://msdn.microsoft.com/en-us/library/system.windows.forms.screen.aspx

Added Thomas' comment

Make sure you WaitForInputIdle before calling SetWindowPos.

Process process = Process.Start(...);
if (process.WaitForInputIdle(15000))
SetWindowPos(process.MainWindowHandle, this.Handle, ...);

The declaration for SetWindowPos above works for both 32- and 64-bit Windows.



Related Topics



Leave a reply



Submit