由于窗口不是您的窗口,因此您只能通过调用Windows API来移动它。您需要执行以下操作:
启动进程。
使用FindWindow
检索窗口句柄。如果窗口尚不存在,则进程还没有创建它;睡眠500毫秒,然后再次尝试。(但不要陷入无限循环; 如果在合理的超时时间内找不到窗口,请停止。)
使用SetWindowPos
更改窗口的位置。
如果您不知道窗口的标题,就不能使用FindWindow
。在这种情况下,
启动进程,并通过检索Process.Handle
获取进程句柄。
使用EnumWindows
检索所有窗口。对于每个窗口,使用GetWindowThreadProcessId
检查它是否属于您的进程。如果没有窗口属于您的进程,请等待并继续尝试。
使用SetWindowPos
更改窗口的位置。
当然,您可以使用Screen.AllScreens[n].WorkingArea
检索所需屏幕的位置和大小,然后根据此来定位窗口。
首先,使用类似以下的方法获得第二个显示器的区域:
Rectangle area = Screen.AllScreens[1].WorkingArea;
使用SetWindowPos Windows API来移动它,使用从另一个进程启动时获取的Process.MainWindowHandle作为句柄。
我需要在启动时运行多个 Chrome 窗口,而 GitHub 上的解决方案正是针对这个问题(相关问题:https://superuser.com/a/901790/111424)。
但底层逻辑是相同的:
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);
}
您可以在http://www.pinvoke.net/上找到所有的枚举和函数导入,或者只需复制我的GitHub代码:https://github.com/alex-tomin/Tomin.Tools.KioskMode。
您需要启动该进程, 获取进程的主窗口并使用类似SetWindowPos()的API调用来将窗口移动到想要的屏幕。
如果您在关闭窗口时未将其最大化,而是以非最大化状态关闭它,则下次打开应用程序时,它将出现在上一次所在的监视器上。
如果应用程序/窗口在关闭时处于最大化状态,并且下次再次打开它时,它将出现在您的主要监视器上。
form_load
方法中:this.setdesktoplocation(int x, int y);
this.windowstate = formwindowstate.maximized;
x的值必须大于您的主屏幕的宽度。例如,如果您的主屏幕分辨率为1366 x 786像素,则应将x的值设置为至少1368或更高。
这对我有用。但这仅用于调试目的。毕竟,在应用程序完成后,您将不得不在主监视器上运行它。