启动应用程序并将其发送到第二台显示器?

时间:2010-09-20 09:28:23

标签: c# monitor multiple-monitors

有没有办法在另一个屏幕上通过Process开始/午餐?

有人问here,但没有答案。

注意:它不是我的应用中的表单,我问的是在另一个屏幕上运行外部程序!

6 个答案:

答案 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)。

但基本逻辑是一样的:

  1. 查找要使用的Windows句柄。您可以在一般情况下使用FindWindow或EnumWindows,如 Timwi 所述。但是如果你的过程很简单且只有一个主窗口,那就是:

    var hndl = proc.MainWindowHandle
    
  2. 有了句柄,您可以使用以下功能。您只需要提供显示编号(从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);
    }
    
  3. 您可以在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)

如果您没有最大化窗口,但在关闭窗口时未最大化窗口,则下次打开该应用程序时,它将出现在上次的监视器上。

如果应用程序/窗口在关闭时已最大化,并且下次再次打开它,它将显示在主监视器上。