PictureBoxの座標とPicutreBox内Imageの座標変換
PictureBox上のマウス位置をPictureBoxのImageの座標に変換しようと思ったらはまった話。
単純にPictureBoxとPictureBox.Imageの縦横の倍率で変換するといいように思ったけど、どうもPictureBox.SizeModeによっては、Imageの周りにパディングがあるっぽい。
たとえば、PictureBoxSizeMode.Zoomだとこんな感じ。
Imageの縦横比が保持されたままスケーリングされたあとで、PictureBox内にセンタリングされている。
この場合、マウスの座標を変換するには、
- 画像が縦・横どちらがコントロールサイズに合わせられているか調べる(画像の縦横比とコントロールの縦横比を比べると分かる)
- その方向から画像の表示倍率を求める(揃えられている側同士で割る)
- 元画像サイズとコントロールサイズと表示倍率からパディングのサイズを求める(倍率を同じにした場合の差分を計算する)
- 座標を変換(パディングによる差分を引いた後、表示倍率をかける)
ということが必要になる。
他、PictureBoxSizeMode.StretchImageとか、PictureBoxSizeMode.CenterImageとかあったりで、それぞれに対応しようと思って、コードを書いていると、そもそもこの表示方法って今こうなっているだけじゃないのか?(未定義じゃないの?) みたいな疑問が。
で、実はこんなことをしなくても、PictureBoxにImageRectangleというメンバがいて、こいつがPictureBox内のImageを描画している領域を持っているみたいなんだけど、privateになっているようでアクセスできない。なぜだー。
とりあえず、挙動が変更されないことを信じることにする、しかない。