PictureBoxの座標とPicutreBox内Imageの座標変換

PictureBox上のマウス位置をPictureBoxのImageの座標に変換しようと思ったらはまった話。
単純にPictureBoxとPictureBox.Imageの縦横の倍率で変換するといいように思ったけど、どうもPictureBox.SizeModeによっては、Imageの周りにパディングがあるっぽい。
たとえば、PictureBoxSizeMode.Zoomだとこんな感じ。
f:id:ultraist:20080303174736p:image
Imageの縦横比が保持されたままスケーリングされたあとで、PictureBox内にセンタリングされている。
この場合、マウスの座標を変換するには、

  1. 画像が縦・横どちらがコントロールサイズに合わせられているか調べる(画像の縦横比とコントロールの縦横比を比べると分かる)
  2. その方向から画像の表示倍率を求める(揃えられている側同士で割る)
  3. 元画像サイズとコントロールサイズと表示倍率からパディングのサイズを求める(倍率を同じにした場合の差分を計算する)
  4. 座標を変換(パディングによる差分を引いた後、表示倍率をかける)

ということが必要になる。
他、PictureBoxSizeMode.StretchImageとか、PictureBoxSizeMode.CenterImageとかあったりで、それぞれに対応しようと思って、コードを書いていると、そもそもこの表示方法って今こうなっているだけじゃないのか?(未定義じゃないの?) みたいな疑問が。
で、実はこんなことをしなくても、PictureBoxにImageRectangleというメンバがいて、こいつがPictureBox内のImageを描画している領域を持っているみたいなんだけど、privateになっているようでアクセスできない。なぜだー。
とりあえず、挙動が変更されないことを信じることにする、しかない。