2011-01-13 23 views
9

Windows XP以上では、ウィンドウハンドル(HWND)が指定されていますが、ウィンドウの位置とサイズによってウィンドウがウィンドウから切り離されて画面から回復不能になるかどうかを確認するにはどうすればよいですか?たとえば、タイトルバーがカーソルで使用可能な場合、ウィンドウを画面上に戻すことができます。ウィンドウが実際に表示されているか、少なくともユーザーが利用できるかどうかを調べる必要があります。解像度の変更を検出して対応する方法と、複数のモニタを処理する方法も知っておく必要があります。これはかなり大きな問題のようです。私はC++と通常のSDKを使用していますので、C#などを呼び出すのではなく、そのプラットフォームの答えを制限してください。ウィンドウがオフスクリーンであるかどうかを確認するにはどうすればよいですか?

答えて

15

Windowsでは、プライマリモニタ(つまり、タスクバーによって隠されていない画面の領域)でユーザーの作業領域のサイズを比較的簡単に判断できます。 SystemParametersInfo functionを呼び出し、最初のパラメータ(uiAction)にSPI_GETWORKAREAフラグを指定します。 pvParamパラメータは、仮想スクリーン座標で作業領域の座標を受け取るRECT structureを指す必要があります。

作業領域を表す座標を取得したら、それらをアプリケーションウィンドウの現在の位置と比較して、それらの境界内にあるかどうかを判断するだけです。


複数のモニタをサポートしたいという希望は、少し複雑になります。 SystemParametersInfoのマニュアルでは、プライマリ以外のモニタの作業領域を取得する代わりにGetMonitorInfo functionに電話する必要があることが示唆されています。 という名前の構造体には、そのモニターの作業領域を定義するメンバーrcWorkが含まれており、仮想スクリーン座標でRECT構造体として再び表されます。

これを正しく行うには、ユーザがシステムに接続しているすべてのモニタを列挙し、それぞれの作業領域を取得する必要があります。GetMonitorInfo

インターネットの周りに発見される本のいくつかのサンプルがあります。

  • MSDNはPositioning Objects on a Multiple Display Setupのためのいくつかのサンプルコードを持っているが。
  • MFCを使用している場合、複数のモニタをサポートするan excellent exampleのように見えます。
  • MFCを使用していない場合でも、その記事はthe following linkを参照しています。これは、少し古い学校であっても、Windowsでの複数モニタのサポートの仕組みを説明する限り、本当の宝物です。これと同様に、これ以降のバージョンのWindowsではこれがほとんど変更されていません。


最後に、解像度の変更を検出する必要があると述べました。これは想像以上に簡単です。 Windowsプログラミングを行っている場合は、オペレーティングシステムがアプリケーションと通信する主な方法は、WindowProc functionにメッセージを送信することです。
この場合、ディスプレイの解像度が変更されたときにすべてのウィンドウに送信されるWM_DISPLAYCHANGE messageを監視する必要があります。 wParamには、1ピクセルあたりのビット数で表した新しいイメージの深度が含まれています。 lParamの下位ワードは水平解像度を指定し、lParamの上位ワードは画面の垂直解像度を指定します。

+0

ありがとう、それは素晴らしいスタートです - 私はSystemParametersInfoに出くわしたことはありません。私はまだタイトルバーが見えるかどうかの問題に悩まされています。解像度が変わるとどうなりますか? – hatcat

+0

@hatcat:あなた自身を打ち負かす理由はありません。 Windows APIは大きく、誰も知っていることはありません。私はあなたがまだタイトルバーの可視性にいかに固執することができるか分からない。タイトルバーを含むウィンドウの領域が、上記のいずれかの機能を使用している画面の作業領域内にあるかどうかを確認します。そして私は解像度の変化を検出することをまったく忘れていました。私は私の答えを更新します。 –

+0

ありがとうございました!私は1992年以来Windowsをプログラミングしてきました。最も難しいのは、どの機能が置き換えられたのか、いつ、そしてあなたが知っているものに固執すべきかどうかを知ることです。タイトルバーの部分は、その領域を取得することと関連があり、テストすることができました。私はちょうどトップ10ピクセルとサイド10ピクセルをチェックするつもりです、それは十分でなければなりません。 – hatcat

1

視認性の確認はとても簡単です。

RECT rtDesktop, rtView; 

GetWindowRect(GetDesktopWindow(), &rtDesktop); 
GetWindowRect(m_hWnd, &rtView); 

HRGN rgn = CreateRectRgn(rtDesktop.left, rtDesktop.top, rtDesktop.right, rtDesktop.bottom); 

BOOL viewIsVisible = RectInRegion(rgn, &rtView); 

DeleteObject(rgn); 

RectInRegionを使用する必要はありません。短縮コードに使用します。

WM_SETTINGCHANGEメッセージを処理すると、表示、解像度変更の監視も簡単です。

http://msdn.microsoft.com/en-us/library/ms725497(v=vs.85).aspx

UPDATE

@Codyグレーが指摘したように、私はWM_DISPLAYCHANGEがWM_SETTINGCHANGEよりも適切だと思います。ただし、MFC 9.0ライブラリはWM_SETTINGCHANGEを使用します。

関連する問題