C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

PictureBox内にカーソルが入っているか判定するには /ジャイ子 (19/08/22(Thu) 12:15) #92060
Re[1]: PictureBox内にカーソルが入っているか判定するには /魔界の仮面弁士 (19/08/22(Thu) 14:16) #92062
  └ Re[2]: PictureBox内にカーソルが入っているか判定するには /ジャイ子 (19/08/22(Thu) 15:41) #92067
    └ Re[3]: PictureBox内にカーソルが入っているか判定するには /魔界の仮面弁士 (19/08/22(Thu) 18:47) #92069


親記事 / ▼[ 92062 ]
■92060 / 親階層)  PictureBox内にカーソルが入っているか判定するには
□投稿者/ ジャイ子 (1回)-(2019/08/22(Thu) 12:15:40)

分類:[.NET 全般] 

Picturebox内にカーソルが入っているか判定する方法に関してなのですが
基本的には

If PictureBox1.Bounds.Contains(Me.PointToClient(Cursor.Position)) Then

これでいけると思います。

しかし、PictureBoxを大きく表示した時に
PictureBox内の
左端と上端はきれいにうまくいっているのですが、
右端と下端の7%くらいの領域がなぜか
Pictureboxの外だと判定されてしまいます。

このずれはどのようにすればなくすことができますか?


[ □ Tree ] 返信 編集キー/

▲[ 92060 ] / ▼[ 92067 ]
■92062 / 1階層)  Re[1]: PictureBox内にカーソルが入っているか判定するには
□投稿者/ 魔界の仮面弁士 (2314回)-(2019/08/22(Thu) 14:16:38)
No92060 (ジャイ子 さん) に返信
> Picturebox内にカーソルが入っているか判定する方法に関してなのですが

PictureBox の Enter/Leave イベントでは駄目ですか?


> If PictureBox1.Bounds.Contains(Me.PointToClient(Cursor.Position)) Then

下記 3 つは、それぞれ異なる意味ですが、違いが分かりますか?

1: PictureBox1.Bounds.Contains(Me.PointToClient(Cursor.Position))
2: PictureBox1.Bounds.Contains(PictureBox1.Parent.PointToClient(Cursor.Position))
3: PictureBox1.RectangleToScreen(PictureBox1.ClientRectangle).Contains(Cursor.Position)


今回の質問だと 1 が使われていたようですが、
3 もしくは 2 にした方が良いのではないでしょうか。
[ 親 92060 / □ Tree ] 返信 編集キー/

▲[ 92062 ] / ▼[ 92069 ]
■92067 / 2階層)  Re[2]: PictureBox内にカーソルが入っているか判定するには
□投稿者/ ジャイ子 (3回)-(2019/08/22(Thu) 15:41:24)
ありがとうございます。

2: PictureBox1.Bounds.Contains(PictureBox1.Parent.PointToClient(Cursor.Position))

で完璧にうまくいきました。

これらの3つの違いはどのように違うのでしょうか?

[ 親 92060 / □ Tree ] 返信 編集キー/

▲[ 92067 ] / 返信無し
■92069 / 3階層)  Re[3]: PictureBox内にカーソルが入っているか判定するには
□投稿者/ 魔界の仮面弁士 (2315回)-(2019/08/22(Thu) 18:47:47)
2019/08/22(Thu) 19:15:33 編集(投稿者)

No92067 (ジャイ子 さん) に返信
> これらの3つの違いはどのように違うのでしょうか?
https://www.atmarkit.co.jp/ait/articles/0511/25/news108.html
https://www.atmarkit.co.jp/fdotnet/dotnettips/377screentoclient/screentoclient.html


>> 1: PictureBox1.Bounds.Contains(Me.PointToClient(Cursor.Position))
>> 2: PictureBox1.Bounds.Contains(PictureBox1.Parent.PointToClient(Cursor.Position))
>> 3: PictureBox1.RectangleToScreen(PictureBox1.ClientRectangle).Contains(Cursor.Position)

まずは、計測すべき【領域】について。

PictureBox1.Bounds は「枠線部も含めた領域」を指し、
PictureBox1.ClientRectangle は「枠線部の内側の領域」を指します。

前者をウィンドウ領域、後者をクライアント領域と呼びます。

BorderStyle が None の場合は、結果的には同じ領域となるのですが、
それぞれ意図が異なるので、枠線無しであっても、意図的に使い分けるようにしましょう。
(特に Form の場合、タイトルバーの領域も含むかどうかが異なるため、この違いは重要です)



続いて、【座標系】の話。

Cursor.Position というのは、プライマリモニタの左上を原点とした
「スクリーン座標系」で示されています。
マルチスクリーン環境では、マイナスの座標値を示すこともありますね。


それに対して、MouseMove イベントの e.Location などでは、
「クライアント座標系」が使われています。
これは、先述したクライアント領域の左上を原点とした座標系のことです。


スクリーン座標からクライアント座標の変換には PointToClient や RectangleToClient を使い、
クライアント座標からスクリーン座標の変換には PointToScreen や RectangleToScreen を使います。



……ここまでが前提知識。

>>> If PictureBox1.Bounds.Contains(Me.PointToClient(Cursor.Position)) Then
>> 2: PictureBox1.Bounds.Contains(PictureBox1.Parent.PointToClient(Cursor.Position))

あらためて、上記の違いと座標ズレの理由について見てみます。


たとえば Form1 の上に Panel1 を貼っておき、
さらにその Panel1 の上に、
PictureBox1 が配置してあるとしましょう。

この場合、PictureBox1 の Location プロパティや Bounds プロパティが指す値というのは、
Panel1 におけるクライアント座標として示されます。

一方 Cursor.Position は、スクリーン座標を示すわけですよね。


座標系が異なるので、Contais メソッドで判定するためには、
いずれかの座標系に揃えてやらなければならない、ということです。

たとえば――

(1) 両方をスクリーン座標に揃えてから比較する。
(2) 両方を Form1 のクライアント座標に揃えてから比較する。
(3) 両方を Panel1 のクライアント座標に揃えてから比較する。
(4) 両方を PictureBox1 のクライアント座標に揃えてから比較する。

――といった具合に。

(長文になりましたが、この説明で分かりますか?)
[ 親 92060 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -