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

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

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

PictureBox内にカーソルが入っているか判定するには

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■92060 / inTopicNo.1)  PictureBox内にカーソルが入っているか判定するには
  
□投稿者/ ジャイ子 (1回)-(2019/08/22(Thu) 12:15:40)

分類:[.NET 全般] 

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

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

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

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

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


引用返信 編集キー/
■92062 / inTopicNo.2)  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 にした方が良いのではないでしょうか。
引用返信 編集キー/
■92067 / inTopicNo.3)  Re[2]: PictureBox内にカーソルが入っているか判定するには
□投稿者/ ジャイ子 (3回)-(2019/08/22(Thu) 15:41:24)
ありがとうございます。

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

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

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

引用返信 編集キー/
■92069 / inTopicNo.4)  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 のクライアント座標に揃えてから比較する。

――といった具合に。

(長文になりましたが、この説明で分かりますか?)
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ