C# 如何确定Windows应用程序是否在屏幕外?

C# 如何确定Windows应用程序是否在屏幕外?,c#,.net,c++,windows,winapi,C#,.net,C++,Windows,Winapi,我正试图调试一个与已安装的用户有关的奇怪问题。几天后,我的应用程序打开的一些对话框可能会出现在屏幕外。如果我能够可靠地检测到这一点,我就可以通过编程将对话框移回它们再次可见的位置 注意:这必须适用于多个监视器并使用win32 API。然而,如果你知道如何从.NET做这件事,我可能可以从那里推断 更新:出于好奇,上面提到的bug与wxWidgets有关。如果你运行一个wxWidgets应用程序,然后走开,放开屏幕保护程序,然后使用LogMeIn远程登录,然后尝试从应用程序打开一个对话框,如果你使用

我正试图调试一个与已安装的用户有关的奇怪问题。几天后,我的应用程序打开的一些对话框可能会出现在屏幕外。如果我能够可靠地检测到这一点,我就可以通过编程将对话框移回它们再次可见的位置

注意:这必须适用于多个监视器并使用win32 API。然而,如果你知道如何从.NET做这件事,我可能可以从那里推断


更新:出于好奇,上面提到的bug与wxWidgets有关。如果你运行一个wxWidgets应用程序,然后走开,放开屏幕保护程序,然后使用LogMeIn远程登录,然后尝试从应用程序打开一个对话框,如果你使用wxDisplay::GetFromPoint(pos)或wxWindowBase::Center()来定位对话框,你会遇到麻烦。

嗯。这可能没有帮助,但当我使用VB时,你可以做screen.width和screen.height,然后是window.x和window.y


当然,我不知道这在多个监视器上是如何工作的。

在.NET中,您可以使用Screen.PrimaryScreen.WorkingArea结构来获取主屏幕的边界(我认为Screen.Screens[x].WorkingArea用于其他监视器),然后使用窗口的左侧和顶部属性来找出窗口的位置(如果它不在屏幕上,顶部和左侧将大于[screen].Width和.Height.

在.NET中,我将在screen.AllScreen中的每个屏幕上迭代,然后调用screen.Bounds.Contains()传递窗体的矩形,如果您想确保所有窗口都在边界(*)内,或者调用screen.Bounds.IntersectsWith()如果您只想确保表单的至少一部分是可见的

(*)不完全在一个屏幕边界内并不意味着它不在总屏幕边界内。您也可以在每个屏幕边界上调用Rectangle.Union来创建一个单独的矩形来测试窗体的矩形,但是您必须注意屏幕边界的大小是否不相同,因为englobing矩形不是完全可见的ther


这是一个较长的答案。较短的答案是:据我所知,没有简单的方法。

看起来就像是Danny的建议的Win32等价物。我不确定您将如何为系统上的所有监视器获取HMONITOR,但看起来从文档链接的示例有一些方法可以做到这一点。

所有的基础知识关于1997年6月Microsoft Systems Journal提供的多监视器支持:

在多显示器设置上定位对象:


只需将MonitorFromWindow与MONITOR\u DefaultToFull标志一起使用即可。如果返回值为空,则窗口不可见。您可以随后传递MONITOR\u DEFAULTTONEAREST,以便能够在最近的监视器上重新定位窗口。

无论您做什么,请考虑多个具有数千像素坐标的监视器在任何方向上远离(0,0)。我讨厌当一个应用程序强迫自己回到另一个屏幕上时,经常把我当时可能正在玩的任何全屏游戏弄得一团糟。

另请参见

这是我在表单构造器中使用的代码。在您卸下笔记本电脑或其他任何使屏幕不动产消失的操作后,将表单移动到可见屏幕是一种快捷方式。为您自己的消费进行优化

if (!Screen.FromControl(this).Bounds.Contains(this.Location))
            {
                this.DesktopLocation = new Point(100,100);
            }

这已经是很久以前的事了,但是Marin Plante的回答满足了我的需要,所以我写了一个简单的扩展方法:

public static class WindowLocation
{
    public static Boolean VisibleOnScreen(this Form form)
    {
        foreach (Screen screen in Screen.AllScreens)
        {
            if (screen.Bounds.Contains(form.Bounds)) return true;
        }

        return false;
    }
}

可能会帮助其他人!

FYI:右键单击任务栏中的屏幕外窗口,选择“移动”,然后按箭头键(它应该跳到鼠标上)。然后使用鼠标或多个键完成移动。如果您认为这是wxWidgets中的错误,您报告过吗?我最后使用了MonitorFromPoint,它的工作原理与MonitorFromWindow类似。