Bra*_*ann 12 c# windows multiple-monitors virtual-screen
有没有办法检查WinForm在屏幕上是否完全可见(例如,是否超出屏幕范围?)
我已经尝试过使用SystemInformation.VirtualScreen,只要虚拟屏幕是一个矩形就能很好地工作,但是一旦它不是(例如L形状的3个屏幕),SystemInformation.VirtualScreen将返回包含所有的最小矩形.可见像素(因此,虽然它在虚拟屏幕中,但L的右上角的窗口将不可见)
我试图实现这一点的原因是我希望我的程序在他们所在的最后位置打开它的子窗口,但如果用户更改设置,我不希望这些窗口不在视图中(例如从他的笔记本电脑上拔掉额外的屏幕)
Bra*_*ann 11
这是我最终做到的方式:
bool isPointVisibleOnAScreen(Point p)
{
foreach (Screen s in Screen.AllScreens)
{
if (p.X < s.Bounds.Right && p.X > s.Bounds.Left && p.Y > s.Bounds.Top && p.Y < s.Bounds.Bottom)
return true;
}
return false;
}
bool isFormFullyVisible(Form f)
{
return isPointVisibleOnAScreen(new Point(f.Left, f.Top)) && isPointVisibleOnAScreen(new Point(f.Right, f.Top)) && isPointVisibleOnAScreen(new Point(f.Left, f.Bottom)) && isPointVisibleOnAScreen(new Point(f.Right, f.Bottom));
}
Run Code Online (Sandbox Code Playgroud)
如果用户在他的显示设置中有一个"洞",可能会有一些误报(参见下面的例子),但我不认为我的任何用户都会遇到这样的情况:)
[1]
[2][X][3]
Run Code Online (Sandbox Code Playgroud)
这是我将如何做到的:
这会将 Display 边界内的控件(窗体)移动到尽可能靠近原始位置的位置。
private void EnsureVisible(Control ctrl)
{
Rectangle ctrlRect = ctrl.DisplayRectangle; //The dimensions of the ctrl
ctrlRect.Y = ctrl.Top; //Add in the real Top and Left Vals
ctrlRect.X = ctrl.Left;
Rectangle screenRect = Screen.GetWorkingArea(ctrl); //The Working Area fo the screen showing most of the Ctrl
//Now tweak the ctrl's Top and Left until it's fully visible.
ctrl.Left += Math.Min(0, screenRect.Left + screenRect.Width - ctrl.Left - ctrl.Width);
ctrl.Left -= Math.Min(0, ctrl.Left - screenRect.Left);
ctrl.Top += Math.Min(0, screenRect.Top + screenRect.Height - ctrl.Top - ctrl.Height);
ctrl.Top -= Math.Min(0, ctrl.Top - screenRect.Top);
}
Run Code Online (Sandbox Code Playgroud)
当然,要回答您的原始问题而不是移动控件,您只需检查 4 个 Math.Min 中的任何一个是否返回 0 以外的值。
这是我的解决方案。解决了“洞”的问题。
/// <summary>
/// True if a window is completely visible
/// </summary>
static bool WindowAllVisible(Rectangle windowRectangle)
{
int areaOfWindow = windowRectangle.Width * windowRectangle.Height;
int areaVisible = 0;
foreach (Screen screen in Screen.AllScreens)
{
Rectangle windowPortionOnScreen = screen.WorkingArea;
windowPortionOnScreen.Intersect(windowRectangle);
areaVisible += windowPortionOnScreen.Width * windowPortionOnScreen.Height;
if (areaVisible >= areaOfWindow)
{
return true;
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)