スクリーン座標←→クライアント座標の変換を行うには?.NET TIPS

» 2005年11月18日 05時00分 公開
[一色政彦デジタルアドバンテージ]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「.NET TIPS」のインデックス

連載目次

2005/12/12 更新

 Windowsが管理する座標系には次の2種類が存在する。

  • スクリーン座標
  • クライアント座標

 以下の画面は、これら2つの座標系を図示したものだ。

スクリーン座標とクライアント座標
Windowsの座標系はすべて左上隅の点を原点としており、座標軸のX軸は右方向が正、Y軸は下方向が正となる。Y軸が下に進むのは、数学における座標系と違ってコンピュータのGUIに独特なので注意すること。
 (1)スクリーン座標。画面の左上隅の点を原点とした座標。
 (2)フォームのクライアント座標。フォームの描画可能なクライアント領域の左上隅の点を原点とした座標。
 (3)ボタンのクライアント座標。ボタンの描画可能なクライアント領域の左上隅の点を原点とした座標。

 スクリーン座標とは、画面の左上隅の点を基準とした絶対的な座標系である。

 一方のクライアント座標とは、Windowsアプリケーションが持つ「ウィンドウ領域」の中に含まれる描画可能な領域(これを「クライアント領域」と呼ぶ)を基準にした座標系である(ここではクライアント<座標>とクライアント<領域>という単語の違いに注意すること)。つまりクライアント座標は、クライアント領域の原点からの相対的な位置を示す座標系である(なお本稿ではクライアント領域とウィンドウ領域の違いの説明は割愛するが、詳しくは「TIPS:クライアント領域やウィンドウ領域の座標を取得するには?」を参照してほしい)。

 なおWindows OSレベルでは、デスクトップ上のGUI要素はすべてウィンドウとして管理されている。例えばボタンなどのコントロールも1つのウィンドウである。そのウィンドウそれぞれがクライアント領域を持っているため、すべてのウィンドウはクライアント座標を持っていることになる。

.NETアプリケーションでの座標の取り扱い

 このように.NETアプリケーションでは2種類の座標系が存在するわけだが、Windowsアプリケーションでの座標の取り扱いは、基本的にクライアント座標で行われる。このようになっているのは、Windowsアプリケーションでは基本的にクライアント領域内にしか描画やコントロールの配置などを行わないためだ。

 しかし.NETの一部のメソッドやプロパティでは、クライアント座標ではなく、スクリーン座標を取り扱うものがある。代表的なものでいえば、マウス・カーソルの座標などがそれである(マウス・カーソルの座標の扱いについては、「TIPS:カーソルの位置を取得・設定するには?」を参照してほしい)。

 このようなプロパティから取得したスクリーン座標の点(位置)の情報を、ウィンドウ内部の処理で使用する際には、それをいったんクライアント座標に変換しなければならないケースが非常に多い。これは、(前述したように)ウィンドウ内部の処理では、クライアント座標による計算が基本となっているからだ。また逆に、ウィンドウ内部のクライアント座標をこのようなプロパティに設定したい場合には、すべてスクリーン座標に変換したうえで行う必要がある。

スクリーン座標からクライアント座標に変換するには?

 実際にスクリーン座標の点(位置)をクライアント座標に変換するには、そのウィンドウのPointToClientメソッドを利用すればよい。例えば、スクリーン座標の点をフォームのクライアント座標に変換するには、フォームのPointToClientメソッドを呼び出せばよいし、スクリーン座標の点をボタンのクライアント座標に変換したい場合は、ボタンのPointToClientメソッドを呼び出せばよい。

 なおPointToClientメソッドは、パラメータにPoint型(System.Drawing名前空間)の値を取り、戻り値としてPoint型の値を返す。要するに、パラメータが変換前の座標で、戻り値が変換後の座標だ。

 以下のサンプル・プログラムは、このPointToClientメソッドの利用例である。このサンプル・プログラムでは、マウス・カーソルの位置をスクリーン座標で取得した後、フォームのクライアント座標とボタンのクライアント座標へ変換している。そしてそれぞれの座標をラベル・コントロール上に表示している。この一連の処理を10ミリ秒ごとに繰り返している(10ミリ秒ごとに処理を実行する方法の詳細は「TIPS:タイマにより一定時間間隔で処理を行うには?(Windowsタイマ編)」を参考にしていただきたい)。

private void timer1_Tick(object sender, System.EventArgs e)
{
  // マウス・カーソルのスクリーン座標での位置を取得
  label1.Text = Cursor.Position.ToString();

  // フォームを基準に(スクリーン座標を)クライアント座標に変換
  Point formClientCurPos = this.PointToClient(Cursor.Position);
  label2.Text = formClientCurPos.ToString();

  // ボタンを基準に(スクリーン座標を)クライアント座標に変換
  Point btnClientCurPos = button1.PointToClient(Cursor.Position);
  label3.Text = btnClientCurPos.ToString();
}

Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles timer1.Tick
  ' マウス・カーソルのスクリーン座標での位置を取得
  label1.Text = Cursor.Position.ToString()

  ' フォームを基準に(スクリーン座標を)クライアント座標に変換

  Dim formClientCurPos As Point = Me.PointToClient(Cursor.Position)
  label2.Text = formClientCurPos.ToString()

  ' ボタンを基準に(スクリーン座標を)クライアント座標に変換
  Dim btnClientCurPos As Point = _
    button1.PointToClient(Cursor.Position)
  label3.Text = btnClientCurPos.ToString()
End Sub

スクリーン座標からクライアント座標に変換するサンプル・プログラム(上:C#、下:VB.NET)
PointToClientメソッドは、フォームや各種コントロールの基本クラスであるControlクラス(System.Windows.Forms名前空間)のメソッドである。ちなみにWin32 APIでは、この機能はScreenToClient関数により提供されていた。

 このサンプル・プログラムを実際に実行したのが次の画面である。この画面ではマウス・カーソルはボタン・コントロールの左上隅に位置している。

スクリーン座標からクライアント座標に変換するサンプル・プログラムの実行結果
マウス・カーソルの現在位置のスクリーン座標およびクライアント座標がリアルタイムに表示されている。マウス・カーソルはボタン・コントロールの左上隅に位置している。
 (1)マウス・カーソルの現在位置のスクリーン座標。この例ではX座標は「173」、Y座標は「472」である。これは画面の左上隅の原点から173ピクセル右、472ピクセル下の場所に、マウス・カーソルが位置することを意味している。
 (2)マウス・カーソルの現在位置のフォームを基準にした場合のクライアント座標。この例ではX座標は「16」、Y座標は「240」である。これはマウス・カーソルが、フォーム上の左上隅の点から右に16ピクセル、下に240ピクセルの場所に位置していることを意味する。
 (3)マウス・カーソルの現在位置のボタンを基準にした場合のクライアント座標。X座標は「0」、Y座標も「0」である。つまりマウス・カーソルの位置は、ボタンのクライアント座標の原点にある。

クライアント座標からスクリーン座標に変換するには?

 逆にクライアント座標の点(位置)をスクリーン座標に変換するには、ウィンドウのPointToScreenメソッドを利用すればよい。例えば、フォームのクライアント座標の点をスクリーン座標に変換するにはフォームのPointToScreenメソッドを呼び出せばよいし、ボタンのクライアント座標の点をスクリーン座標に変換したい場合はボタンのPointToScreenメソッドを呼び出せばよい。

 なおPointToScreenメソッドも、先ほどのPointToClientメソッドと同様に、パラメータにPoint型(System.Drawing名前空間)の値を取り、戻り値としてPoint型の値を返す。パラメータが変換前の座標で、戻り値が変換後の座標だ。

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。