Start a program on different screen

222 views Asked by At

I've already checked out:

SetWindowPos not working on Form.Show()

Launch an application and send it to second monitor?

However, none of these solutions seem to work for me. I want to open an external program on a different monitor.

This is my current code:

 public const int SWP_NOSIZE = 0x0001;
 public const int SWP_NOZORDER = 0x0004;
 public const int SWP_SHOWWINDOW = 0x0040;

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


 [DllImport("user32.dll")]
 public static extern bool UpdateWindow(IntPtr hWnd);


 Process application = new Process();
 application.StartInfo.UseShellExecute = false;
 application.StartInfo.FileName = ".......";
 if (application.Start())
 {
     Rectangle monitor = Screen.AllScreens[1].Bounds; // for monitor no 2

     SetWindowPos(
         application.MainWindowHandle,
         IntPtr.Zero,
         monitor.Left,
         monitor.Top,
         monitor.Width,
         monitor.Height,
         SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
                
     UpdateWindow(application.MainWindowHandle); // tried even with application.Handle
 }
1

There are 1 answers

0
41686d6564 On

First of all, you don't need UpdateWindow, calling SetWindowPos is probably enough. You just need to make sure that the window handle is created (because the process is being started). Simply add the following line before calling SetWindowPos:

application.WaitForInputIdle();

If WaitForInputIdle() doesn't work for you, you might try something like:

while (application.MainWindowHandle == IntPtr.Zero)
{
    await Task.Delay(100);
}

The following code works fine for me:

Process application = new Process();
application.StartInfo.UseShellExecute = false;
application.StartInfo.FileName = "notepad.exe";
if (application.Start())
{
    application.WaitForInputIdle();
    /* Optional
    while (application.MainWindowHandle == IntPtr.Zero)
    {
        await Task.Delay(100);
    } */

    Rectangle monitor = Screen.AllScreens[1].Bounds; // for monitor no 2

    SetWindowPos(
        application.MainWindowHandle,
        IntPtr.Zero,
        monitor.Left,
        monitor.Top,
        monitor.Width,
        monitor.Height,
        SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
}

Note that this will only set the position of the window, not its size though. If you want the size to be changed as well, you'll need to remove the SWP_NOSIZE flag.