Determinar se um formulário está completamente fora da tela
Pergunta
Estou desenvolvendo um aplicativo que lembra as preferências do usuário quanto ao local onde o formulário foi passado localizado na tela. Em alguns casos, o usuário vai tê-lo em uma tela secundária, e em seguida, disparar o aplicativo mais tarde sem a segunda tela (por vezes tendo a forma aparecer fora da tela). Outras vezes, o usuário vai mudar a sua resolução, resultando em um efeito semelhante.
Eu estava esperando para fazer esta verificação no manipulador de eventos Form_Shown. Basicamente eu quero determinar se o formulário está completamente fora da tela para que eu possa reposicioná-lo.
Qualquer conselho?
Solução
Verifique com esta função se forma é totalmente na tela :
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;
}
Verificar única top ponto esquerdo se ele está na tela:
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;
}
Outras dicas
A combinação de todas as soluções acima com o "IntersectsWith" -method e Linq extensões nos dar em suma:
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));
}
Solução completa aqui (com base em todas as respostas). Eu adicionei um MinPercentOnScreen
parâmetro, onde pelo menos este% de pixels deve ser visível em todas as telas / monitores. Assim, se este retorna false
você precisará mover a posição de volta da janela para padrão.
// 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;
}
Implementação:
return IsOnScreen(this.Location, this.Size);
discussão antiga, mas ainda útil! Cody e Andrija- graças para o código. Eu tive que fazer um par de pequenos ajustes: Em vez de screen.WorkingArea.Intersect (formRectangle); I utilizado formRectangle.Intersect (screen.WorkingArea); desde Intersect () substitui o objeto com o cruzamento. Se o formulário é completamente fora da tela, formRectangle após o cruzamento é (0,0,0,0), e contém () retorna verdadeiro. Então, eu também verificar para ver se formRectangle superior, esquerda, largura e altura não são todos 0 antes de retornar verdadeiro. Agora o código retorna verdadeiro se qualquer parte do formulário está na tela, e falso se nenhuma parte está na tela.
Para WPF (baseado em Matthias resposta Loerkes)
Adicione uma referência ao System.Windows.Forms e 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));
}
Nenhum destes trabalhos se um monitor passa a ser desligado. A função Screen.AllScreens sempre retornará o número de telas, mesmo se um está desligado.
Verifique a resolução de telas antes de posicionar a janela. Isso permitirá que você a descobrir se você onde vai colocá-lo fora dos limites da resolução, antes de realmente fazê-lo.