.NET TIPS

ある座標や領域がコントロールの領域内に含まれるているかを確認するには?

デジタルアドバンテージ 一色 政彦
2005/12/02

 Windowsアプリケーションでは、ある点の座標(例えばマウスの位置など)や、ある領域(四角形で示される範囲)がフォームやコントロールの領域内に含まれているかどうかを判定したいことがある。このような場合、フォームやコントロールの領域を表すRectangle構造体(System.Drawing名前空間)のContainsメソッドにより確認できる。

 Containsメソッドでは、そのパラメータにPoint型(System.Drawing名前空間)の値を指定するか、もしくはRectangle型(System.Drawing名前空間)の値を指定する。Containsメソッドは、パラメータで指定した座標や領域が、対象となる領域内に収まっていればTrueをそうでなければFalseを返す。

 変数rectがRectangle構造体のオブジェクトである場合、例えば次のように記述すればよい。

bool inside = rect.Contains(new Point(10, 20))

WindowsアプリケーションのフォームやコントロールでのContainsメソッドの利用

 Windowsアプリケーションにおけるフォームやコントロールなどの領域に対してContainsメソッドを利用する場合、その領域にはウィンドウ領域とクライアント領域の2種類があり、特にウィンドウ領域の場合は、その領域を示す座標系が条件(例えばフォームかコントロールかの違い)によってスクリーン座標で取得されたり、クライアント座標で取得されたりするので注意が必要だ。これらの座標系については「TIPS:クライアント領域やウィンドウ領域の座標を取得するには?」を参照してほしい。

 本稿では、Containsメソッドを利用するサンプル・プログラムとして、現在のマウス・カーソルのある点が、次の4つの領域に含まれるかどうかをラベル・コントロールに表示するアプリケーションを作成する。

  • フォームのクライアント領域
  • フォームのウィンドウ領域
  • コントロール(ボタン)のクライアント領域
  • コントロール(ボタン)のウィンドウ領域

 まずはラベルに表示する情報を文字列として取得するメソッドを実装しよう。本稿では、ある点がコントロールやフォームのクライアント領域にあるかどうかをチェックするメソッドとしてGetClientContainStateメソッドを、それがウィンドウ領域にあるかどうかをチェックするメソッドとしてGetWindowContainStateメソッドを実装する。この2つのメソッドの違いは、クライアント領域かウィンドウ領域かだけなので、そのほかの共通部分をGetContainStateメソッドにまとめる。

 なお、クライアント領域はウィンドウのClientRectangleプロパティより取得でき、ウィンドウ領域はウィンドウのBoundsプロパティより取得できる。しかしBoundsプロパティの値は、先ほども述べたように条件によってその意味(座標系など)が変化するので、それを吸収するためのGetWindowRectangleメソッドを作成して利用する。このメソッドは、「TIPS:クライアント領域やウィンドウ領域の座標を取得するには?」で作成したものと同じなので本稿では、説明を割愛する。

 以上の内容を実装したのが次のコードである。

// ある点がコントロールやフォームのクライアント領域内に
// 含まれるかどうかに関する情報を取得する
private string GetClientContainState(Control ctrl)
{
  Rectangle rect = ctrl.ClientRectangle;
  return GetContainState(ctrl, rect);
}

// ある点がコントロールやフォームのウィンドウ領域内に
// 含まれるかどうかに関する情報を取得する
private string GetWindowContainState(Control ctrl)
{
  Rectangle rect = GetWindowRectangle(ctrl);
  return GetContainState(ctrl, rect);
}

private string GetContainState(Control ctrl, Rectangle rect)
{
  string output;
  // マウス座標(スクリーン座標系)の取得
  Point mouseScreenPos = Control.MousePosition;
  // マウス座標をクライアント座標系へ変換
  Point mouseClientPos = ctrl.PointToClient(mouseScreenPos);
  // マウス座標(クライアント座標系)が領域内かどうか
  bool inside = rect.Contains(mouseClientPos);
  output = String.Format("{0}\n{1} − {2}",
        rect,
        inside ? "内部": "外部",
        mouseClientPos);
  return output;
}
' ある点がコントロールやフォームのクライアント領域内に
' 含まれるかどうかに関する情報を取得する
Private Function GetClientContainState(ByVal ctrl As Control) As String
  Dim rect As Rectangle = ctrl.ClientRectangle
  Return GetContainState(ctrl, rect)
End Function

' ある点がコントロールやフォームのウィンドウ領域内に

' 含まれるかどうかに関する情報を取得する
Private Function GetWindowContainState(ByVal ctrl As Control) As String
  Dim rect As Rectangle = GetWindowRectangle(ctrl)
  Return GetContainState(ctrl, rect)
End Function

Private Function GetContainState(ByVal ctrl As Control, ByVal rect As Rectangle) As String
  Dim output As String
  ' マウス座標(スクリーン座標系)の取得
  Dim mouseScreenPos As Point = Control.MousePosition
  ' マウス座標をクライアント座標系へ変換
  Dim mouseClientPos As Point = ctrl.PointToClient(mouseScreenPos)
  ' マウス座標(クライアント座標系)が領域内かどうか
  Dim inside As Boolean = rect.Contains(mouseClientPos)
  output = String.Format("{0}" & vbLf & "{1} − {2}", _
     rect, _
     IIf(inside, "内部", "外部"), _
     mouseClientPos)
  Return output
End Function
Containsメソッドを利用したサンプル・コード(上:C#、下:VB.NET)

 以上のようにして実装したGetClientContainStateメソッドとGetWindowContainStateメソッドを10ミリ秒間隔で呼び出して、それによって取得した情報をラベルに表示する(なお10ミリ秒ごとに処理を実行する方法の詳細は「TIPS:タイマにより一定時間間隔で処理を行うには?(Windowsタイマ編)」を参考にされたい)。

 この実装は難しくはないが、念のためにコードを示しておく。なおソース・コード全体は、このサンプル・プログラムの説明欄のリンク(下の「C#版のダウンロード」「VB.NET版のダウンロード」)からダウンロードできる。

private void timer1_Tick(object sender, System.EventArgs e)
{
  // フォーム・クライアント領域での情報をラベルに表示
  label1.Text = GetClientContainState(this);

  // フォーム・ウィンドウ領域での情報をラベルに表示
  label2.Text = GetWindowContainState(this);

  // ボタン・クライアント領域での情報をラベルに表示
  label3.Text = GetClientContainState(button1);

  // ボタン・ウィンドウ領域での情報をラベルに表示
  label4.Text = GetWindowContainState(button1);
}
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles timer1.Tick
  ' フォーム・クライアント領域での情報をラベルに表示
  label1.Text = GetClientContainState(Me)

  ' フォーム・ウィンドウ領域での情報をラベルに表示
  label2.Text = GetWindowContainState(Me)

  ' ボタン・クライアント領域での情報をラベルに表示

  label3.Text = GetClientContainState(button1)

  ' ボタン・ウィンドウ領域での情報をラベルに表示
  label4.Text = GetWindowContainState(button1)
End Sub
Containsメソッドにより取得した情報をラベルに設定するコード(上:C#、下:VB.NET)

 以上のサンプル・プログラムをコンパイルして実行したのが、次の画面だ。

サンプル・プログラムの実行結果
マウス・カーソルを動かすと、(ほぼ)リアルタイムに、そのマウス・カーソルの指す点が、フォームやボタンのクライアント領域/ウィンドウ領域に含まれているかどうかを示す(上の画面の「外部」「内部」という記述部分)。
  前述した4つの領域を示すタイトル。
  クライアント座標における領域の値。「X」はX座標、「Y」はY座標、「Width」は幅、「Height」は高さである。
  中間にある「−」を挟んで左側の「外部」「内部」は、マウス・カーソルの現在位置がそれぞれの領域の内部にあるか、外部にあるかを示している。「−」の右側は、クライアント座標におけるマウス・カーソルの現在位置(点)の値。

 上記の画面では、マウス・カーソルがフォームのタイトル・バーの上に位置しているため、フォームのクライアント領域では「外部」となり、ウィンドウ領域では「内部」となっている。繰り返しになるが、このような違いが生じるため、フォームやコントロールの領域を判定する場合には、クライアント領域を基準にするのか、ウィンドウ領域を基準にするのかを、十分に注意した方がよい。End of Article

カテゴリ:Windowsフォーム 処理対象:コントロール
使用ライブラリ:Rectangle構造体(System.Drawing名前空間)
使用ライブラリ:Point構造体(System.Drawing名前空間)
関連TIPS:クライアント領域やウィンドウ領域の座標を取得するには?
関連TIPS:タイマにより一定時間間隔で処理を行うには?(Windowsタイマ編)

この記事と関連性の高い別の.NET TIPS
クライアント領域やウィンドウ領域の座標を取得するには?
スクリーン座標←→クライアント座標の変換を行うには?
ウィンドウのリサイズ時に再描画を行うには?
スクリーンやウィンドウをキャプチャするには?
マウス・カーソルの移動可能領域を制限するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

Insider.NET 記事ランキング

本日 月間
ソリューションFLASH