答案 0 :(得分:24)
由于窗口不是您的,因此您只能通过调用Windows API来移动它。你必须这样做:
启动流程。
使用FindWindow
检索窗口的句柄。如果窗口尚不存在,则该进程尚未创建它;睡500码,然后再试一次。 (但不要进入无限循环;如果在合理的超时后找不到窗口,请停止。)
使用SetWindowPos
更改窗口的位置。
如果您不知道窗口的标题,则无法使用FindWindow
。在那种情况下,
启动流程并通过检索Process.Handle
来获取流程句柄。
使用EnumWindows
检索所有窗口。对于每个窗口,使用GetWindowThreadProcessId
检查它是否属于您的进程。如果没有窗口属于您的流程,请等待并继续尝试。
使用SetWindowPos
更改窗口的位置。
当然,您可以使用Screen.AllScreens[n].WorkingArea
来检索所需屏幕的位置和大小,然后您可以相对于该窗口定位窗口。
答案 1 :(得分:10)
首先使用以下内容取出第二台显示器的区域:
Rectangle area = Screen.AllScreens[1].WorkingArea;
使用Windows API SetWindowPos移动它,使用从另一个进程启动时获得的Process.MainWindowHandle作为句柄。
答案 2 :(得分:5)
Timwi 提供了一个非常有用的提示,因此我决定创建一个PowerShell脚本,使用这些函数调用库以便于使用,并共享解决方案。
我需要在启动时运行多个Chrome窗口,而GitHub上的解决方案完全针对此问题(相关问题:https://superuser.com/a/901790/111424)。
但基本逻辑是一样的:
查找要使用的Windows句柄。您可以在一般情况下使用FindWindow或EnumWindows,如 Timwi 所述。但是如果你的过程很简单且只有一个主窗口,那就是:
var hndl = proc.MainWindowHandle
有了句柄,您可以使用以下功能。您只需要提供显示编号(从1开始)和句柄:
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。
答案 3 :(得分:2)
您需要启动该过程,获取进程主窗口并使用类似SetWindowPos()的API调用将窗口移动到您想要的屏幕。
答案 4 :(得分:0)
尝试将此代码放入form_load
方法:
this.setdesktoplocation(int x, int y);
this.windowstate = formwindowstate.maximized;
x的值必须大于主屏幕的宽度。例如,如果主屏幕的分辨率为1366 x 786像素,则应为x赋予至少1368或更高的值。
它对我有用。但它仅用于调试目的。毕竟,当应用程序完成时,您必须在主显示器中运行它。
答案 5 :(得分:0)
如果您没有最大化窗口,但在关闭窗口时未最大化窗口,则下次打开该应用程序时,它将出现在上次的监视器上。
如果应用程序/窗口在关闭时已最大化,并且下次再次打开它,它将显示在主监视器上。