web-dev-qa-db-ja.com

フォームが完全に画面外にあるかどうかの判断

フォームが画面の最後に配置された場所に関するユーザーの設定を記憶するアプリケーションを開発しています。場合によっては、ユーザーはそれを2番目の画面に表示し、後で2番目の画面なしでアプリを起動します(フォームが画面外に表示されることもあります)。また、ユーザーが解像度を変更すると、同様の効果が得られる場合もあります。

Form_Shownイベントハンドラーでこのチェックを実行したいと思っていました。基本的に、フォームが完全に画面から外れているかどうかを確認して、再配置できるようにします。

何かアドバイス?

39
Cody

フォームが完全に画面に表示されている:であるかどうかをこの関数で確認します。

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;
}
63
Andrija

上記のすべてのソリューションを「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));
}
16
Matthias Loerke

ここで完全な解決策(すべての回答に基づく)。パラメータ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);
10
CrazyTim

古いスレッドですが、それでも役に立ちます! CodyとAndrija-コードをありがとう。 screen.WorkingArea.Intersect(formRectangle);の代わりに、いくつかの小さな調整を行う必要がありました。 formRectangle.Intersect(screen.WorkingArea);を使用しました。 Intersect()は、そのオブジェクトを交差に置き換えるためです。フォームが完全に画面から外れている場合、交差後のformRectangleは(0,0,0,0)であり、Contains()はtrueを返します。したがって、trueを返す前に、formRectangleのTop、Left、Width、Heightがすべて0ではないかどうかも確認します。これで、フォームのいずれかの部分が画面に表示されている場合、コードはtrueを返し、画面に表示されている部分がない場合はfalseを返します。

4
Sean

モニターがオフになっている場合、これらはいずれも機能しません。 Screen.AllScreens関数は、画面がオフの場合でも常に画面数を返します。

1
Tom

[〜#〜] wpf [〜#〜]の場合(Matthias Loerkesの回答に基づく)

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));
}
1
salle55

ウィンドウを配置する前に、画面の解像度を確認してください。これにより、実際に実行する前に、解像度の範囲外に配置するかどうかを判断できます。

0
Allen Rice