Is there any way to start/lunch a program through Process in another screen?
Someone asked that here but there was no answer.
Note: it is not a form in my app, I'm asking about running an external program in another screen!
Is there any way to start/lunch a program through Process in another screen?
Someone asked that here but there was no answer.
Note: it is not a form in my app, I'm asking about running an external program in another screen!
Since the window is not yours, you can only move it by invoking the Windows API. You will have to do this:
Launch the process.
Use FindWindow
to retrieve the handle to the window. If the window doesn’t exist yet, the process hasn’t created it yet; sleep for 500ms and then try again. (But don’t go into an infinite loop; stop if you can’t find the window after a reasonable timeout.)
Use SetWindowPos
to change the position of the window.
If you don’t know the title of the window, you can’t use FindWindow
. In that case,
Launch the process and get the process handle by retrieving Process.Handle
.
Use EnumWindows
to retrieve all the windows. For each window, use GetWindowThreadProcessId
to check whether it belongs to your process. If no window belongs to your process, wait and keep trying.
Use SetWindowPos
to change the position of the window.
Of course, you can use Screen.AllScreens[n].WorkingArea
to retrieve the position and size of the screen you want, and then you can position the window relative to that.
First get out the area of the second monitor using something like:
Rectangle area = Screen.AllScreens[1].WorkingArea;
The use the Windows API SetWindowPos to move it, using the Process.MainWindowHandle you got from the starting of the other process as the handle.
Timwi provided a very useful tip, so I decided to create a powershell script calling a library with these functions for easier use, and share the solution.
I needed to run multiple Chrome windows on startup, and the solution on GitHub targets exactly this problem (related question: https://superuser.com/a/901790/111424).
But the underlying logic is the same:
Find Windows Handle to operate with. You may use FindWindow or EnumWindows in generic case as Timwi mentioned. But if your process is simple one and has a single main window, it is just:
var hndl = proc.MainWindowHandle
Having the handle, you may use the following function. You just need to provide Display number (starting from 1) and the handle:
public static bool MoveToMonitor(IntPtr windowHandle, int monitor)
{
monitor = monitor - 1;
return WinApi.SetWindowPos(windowHandle, IntPtr.Zero, Screen.AllScreens[monitor].WorkingArea.Left,
Screen.AllScreens[monitor].WorkingArea.Top, 1000, 800, SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOREDRAW);
}
All enums and function imports you may find on http://www.pinvoke.net/ or just copy my code on GitHub: https://github.com/alex-tomin/Tomin.Tools.KioskMode.
You would need to start the process, get the processes main window and use an API call like SetWindowPos() to move the window to the screen you want.
Try to put this code in the form_load
method:
this.setdesktoplocation(int x, int y);
this.windowstate = formwindowstate.maximized;
The value of x must be greater than the width of your main screen. For example, if your main screen has a resolution of 1366 by 786 pixels, you should give x a value of at least 1368 or above.
It worked for me. But it is just for debugging purposes only. After all, you'll have to run it in the main monitor when the app is finished.
If you do not maximize your window but have it non-maximized when you close it, the next time the app is being opened, it will appear on the monitor it was on last time.
If the app / window is maximized when you close it, and if you open it up again next time, it will appear on your primary monitor instead.
© 2022 - 2024 — McMap. All rights reserved.