如何确定我的 .NET Windows Forms 程序在哪个监视器上运行?

Posted

技术标签:

【中文标题】如何确定我的 .NET Windows Forms 程序在哪个监视器上运行?【英文标题】:How do I determine which monitor my .NET Windows Forms program is running on? 【发布时间】:2010-11-10 10:22:48 【问题描述】:

我有一个 C# Windows 应用程序,我想确保如果用户将其移至第二台显示器,它会显示在第二台显示器上。我需要保存主窗体的大小、位置和窗口状态——我已经处理过了——但我还需要知道用户关闭应用程序时它在哪个屏幕上。

我正在使用 Screen 类来确定当前屏幕的大小,但我找不到任何关于如何确定应用程序在哪个屏幕上运行的信息。

编辑:感谢大家的回复!我想确定窗口在哪个监视器上,这样我就可以进行适当的边界检查,以防用户不小心将窗口放在查看区域之外或更改了屏幕大小,从而使表单不再完全可见。

【问题讨论】:

如果这不是与***.com/questions/937298/…类似的问题 【参考方案1】:

如果您记住窗口的位置和大小,那就足够了。当您将位置设置为之前使用的位置时,如果它恰好在第二台显示器上,它将回到那里。

例如,如果您有 2 台显示器,尺寸均为 1280x1024,并且您将窗口的左侧位置设置为 2000 像素,则它将出现在第二台显示器上(假设第二台显示器在第一台显示器的右侧。):)

如果您担心下次启动应用程序时第二个监视器不在,您可以使用此方法来确定您的窗口是否与任何屏幕相交:

private bool isWindowVisible(Rectangle rect)

    foreach (Screen screen in Screen.AllScreens)
    
        if (screen.Bounds.IntersectsWith(rect))
            return true;
    
    return false;

只需传入您窗口的所需位置,它就会告诉您它是否会在其中一个屏幕上可见。享受吧!

【讨论】:

同意,但是在启动时进行一些检查会很好,这样在重新配置后您的应用就不会出现在所有监视器之外 实际上,如果有人移除了第二个监视器,并且当有两个监视器时,您的应用程序将尝试使用上一个会话中的 Top/Left,Windows 会自动将其移动到第一个监视器。所以实际上,你不需要调用 isWindowVisible 方法。 我同意 Henk - 检查我添加的示例,以便您可以检查您的窗口是否可见。 :) 只是一个 LINQy 版本,供使用 .NET 3.5 或更高版本的人使用:return Screen.AllScreens.Any(s => s.Bounds.IntersectsWith(rect));【参考方案2】:

您可以使用“屏幕”对象: System.Windows.Forms.Screen

开始玩这样的东西:

        Screen[] screens = Screen.AllScreens;
        for (int i = 0; i < screens.Length ; i++)
        
            Debug.Print(screens[i].Bounds.ToString());
            Debug.Print(screens[i].DeviceName);
            Debug.Print(screens[i].WorkingArea.ToString());
        

它可能会为您提供所需的东西

【讨论】:

【参考方案3】:

您可以使用此代码获取您拥有的一组屏幕。

Screen[] screens = Screen.AllScreens;

您还可以通过运行此代码来确定您在哪个屏幕上(这个是您所在的窗口)

Screen screen = Screen.FromControl(this); //this is the Form class

简而言之,请查看 Screen 类和静态辅助方法,它们可能会对您有所帮助。

MSDN Link, 没有太多..我建议你自己乱搞代码。

【讨论】:

是的,人们似乎忘记了 Form 继承自 Control,所以 Screen.FromControl 可以处理它。 也许我应该重新表述一下... Form 继承自 ContainerControl,ContainerControl 继承自 ScrollableControl,后者继承自 Control。 @Janie:很抱歉你有这种感觉。我提供的代码完全符合我所说的。不多也不少。如果您想进一步研究它,请按照同时提供的 MSDN 链接进行操作。 @Janie:如果您对为什么它可能不适合您有疑问,请将其作为问题发布,一定会有人帮助您。我确信它对 OP 有效,否则他不会接受答案。 @Janie:FromControl() 方法返回一个 Screen 对象。您是否认为它会返回屏幕编号或其他内容?您需要查询屏幕的边界以确定屏幕的位置。【参考方案4】:

您可以通过

获取当前屏幕
var s = Screen.FromControl(this);

其中this 是表单(或表单上的任何控件)。至于如何记住这有点棘手,但我会选择 Screen.AllScreens 数组中的索引,或者可能是 s.DeviceName。无论哪种情况,请在启动时使用设置之前进行检查,以防止使用已断开连接的显示器。

【讨论】:

我不会选择 DeviceName,DeviceName 可以随时更改,比如当您获得新的视频卡或显示器时... 我在 Vista 上将它们设为 \\.\DISPLAY1 和 \\.\DISPLAY2。但对于 XP,它可能会有所不同,我不确定。 我同意,没有人真正确定..这就是我不使用它的原因。 :) DisplayName 似乎只是根据 Screen 认为屏幕的样子生成的值。在屏幕分辨率对话框中使用识别时,您有完全不同的屏幕 ID,与说 nvidia 管理器相同,它显示与屏幕分辨率对话框相同的数字,但 .net 绝对必须这样做不同。【参考方案5】:

表单的位置会告诉您表单在哪个屏幕上。我真的不明白为什么您需要知道它在哪个屏幕上,因为如果您使用保存的位置恢复它,它应该只恢复到相同的位置(也许您可以详细说明原因)。

否则你可以这样做:

Screen[] scr = Screen.AllScreens;
scr[i].Bounds.IntersectsWith(form.Bounds);

每个屏幕都有一个 Bounds 属性,它返回一个 Rectangle。您可以使用 IntersectsWith() 函数来确定表单是否在屏幕内。

此外,它们基本上提供了一个在 Screen 类上也能做到这一点的函数

Screen screen = Screen.FromControl(form);

【讨论】:

以上是关于如何确定我的 .NET Windows Forms 程序在哪个监视器上运行?的主要内容,如果未能解决你的问题,请参考以下文章

Windows Forms .NET 中的热键(非全局)

.net Windows Forms 应用程序的自动 CRUD 表单生成

如何清除 System.Windows.Forms.WebBrowser 会话数据?

用不了System.Windows.Forms,如何使用MessageBox?

如何衡量c#中两个关键事件之间的时间?(不是windows.forms)

如何在 Windows Forms 2.0 中从子窗体关闭父窗体?