我正在开发一个应用程序,用于记住用户对表单在屏幕上的位置首选项。在某些情况下,用户会将其放在辅助屏幕上,然后稍后启动应用程序而没有第二个屏幕(有时表单会出现在屏幕外)。其他情况下,用户将更改分辨率,从而产生类似的效果。
我希望在Form_Shown事件处理程序中进行此检查。基本上,我想确定表单是否完全超出了屏幕范围,以便重新定位它。
有什么建议吗?
我正在开发一个应用程序,用于记住用户对表单在屏幕上的位置首选项。在某些情况下,用户会将其放在辅助屏幕上,然后稍后启动应用程序而没有第二个屏幕(有时表单会出现在屏幕外)。其他情况下,用户将更改分辨率,从而产生类似的效果。
我希望在Form_Shown事件处理程序中进行此检查。基本上,我想确定表单是否完全超出了屏幕范围,以便重新定位它。
有什么建议吗?
使用此函数检查表单是否完全显示在屏幕上:
public bool IsOnScreen( Form form )
{
Screen[] screens = Screen.AllScreens;
foreach( Screen screen in screens )
{
Rectangle formRectangle = new Rectangle( form.Left, form.Top,
form.Width, form.Height );
if( screen.WorkingArea.Contains( formRectangle ) )
{
return true;
}
}
return false;
}
检查仅顶部左侧点是否在屏幕上:
public bool IsOnScreen( Form form )
{
Screen[] screens = Screen.AllScreens;
foreach( Screen screen in screens )
{
Point formTopLeft = new Point( form.Left, form.Top );
if( screen.WorkingArea.Contains( formTopLeft ) )
{
return true;
}
}
return false;
}
结合上述所有解决方案,使用"IntersectsWith"方法和LINQ扩展方法,简而言之:
public bool IsOnScreen(Form form)
{
// Create rectangle
Rectangle formRectangle = new Rectangle(form.Left, form.Top, form.Width, form.Height);
// Test
return Screen.AllScreens.Any(s => s.WorkingArea.IntersectsWith(formRectangle));
}
基于所有答案,这里提供完整的解决方案。我添加了一个参数 MinPercentOnScreen
,其中至少在所有屏幕/显示器上可见的像素占比为此百分比。因此,如果返回false
,您需要将窗口位置移回默认位置。
// Return True if a certain percent of a rectangle is shown across the total screen area of all monitors, otherwise return False.
public bool IsOnScreen(System.Drawing.Point RecLocation, System.Drawing.Size RecSize, double MinPercentOnScreen = 0.2)
{
double PixelsVisible = 0;
System.Drawing.Rectangle Rec = new System.Drawing.Rectangle(RecLocation, RecSize);
foreach (Screen Scrn in Screen.AllScreens)
{
System.Drawing.Rectangle r = System.Drawing.Rectangle.Intersect(Rec, Scrn.WorkingArea);
// intersect rectangle with screen
if (r.Width != 0 & r.Height != 0)
{
PixelsVisible += (r.Width * r.Height);
// tally visible pixels
}
}
return PixelsVisible >= (Rec.Width * Rec.Height) * MinPercentOnScreen;
}
实现:
return IsOnScreen(this.Location, this.Size);
虽然这个帖子有点老,但仍然很有用! Cody和Andrija-感谢您的代码。 我不得不进行一些小的调整: 我使用了formRectangle.Intersect(screen.WorkingArea)而不是screen.WorkingArea.Intersect(formRectangle); 因为Intersect()替换其对象与交集。 如果表单完全脱离屏幕,则交叉口后的formRectangle为(0,0,0,0),并且Contains()返回true。 因此,我还检查formRectangle的Top、Left、Width和Height是否都不为0,然后再返回true。 现在,如果表单的任何部分位于屏幕上,则代码返回true,如果没有部分位于屏幕上,则返回false。
对于基于Matthias Loerkes答案的WPF
添加对System.Windows.Forms和System.Drawing的引用。
//using System.Windows.Forms;
public bool IsOnScreen(Window window)
{
var windowRect = new System.Drawing.Rectangle((int)window.Left, (int)window.Top, (int)window.Width, (int)window.Height);
return Screen.AllScreens.Any(s => s.WorkingArea.IntersectsWith(windowRect));
}
如果显示器关闭,这些都不起作用。即使其中一个显示器关闭,Screen.AllScreens函数仍将返回屏幕数量。
Screen.AllScreens
将开始仅返回1个监视器。我的恢复代码运行良好。它将一个窗体窗口移动到主监视器。已测试!但非常感谢这个提示。可能某些视频连接器在这种情况下会出现问题。 - it3xl在定位窗口之前,请检查屏幕分辨率。这将使您能够确定是否将其放置在分辨率范围之外,而不是实际上这样做。
DesktopBounds
的一行解决方案:Array.Exists(Screen.AllScreens, screen => screen.WorkingArea.Contains(DesktopBounds))