2018/09/09(Sun) 04:49:21 編集(投稿者)
■No88572 (熊さん さん) に返信
> すると位置が変化するはずのない赤色の中央線がぴくぴく動くことがご確認いただけると思います。
「位置がまったく変化していない」ことは確認済みでしょうか。
たとえば、現在の処理方法で詰めていくのなら、
PictureBox1.SetBounds(…)
ProfilePosition.Y_Int = …
の直後に
Me.Text = CStr(PictureBox1.Top + ProfilePosition.Y_Int)
などを置いてみて、NumericUpDown を動かしたときに
タイトルバーに記載される値がブレないことを確認するなど。
> PBox1.Top + CInt(PBox1.Height * (1 - YRate) * 0.5)
上記の計算式の場合、YRate が Single なので、
0.5 や 0.5R ではなく、0.5F と書いた方が良いですよ。
さて、以下は提示頂いたコードとは別のやり方になるのですが:
中央線は、PictureBox の位置に合わせて調整するとはいえ、
Form 上から見れば、常に同じ位置にあるわけですよね。
であれば Load 時にでも、その中央線の交点座標を、
PictureBox1 の中での位置として保持するのではなく、
「Form のクライアント座標」に変換して保持されては如何でしょう。
そうすれば、NumericUpDown は PictureBox1 の位置調整に
特化して処理できますので、描画処理も簡潔になりそうな気がします。
ということで、書き直してみました。
Public Class Form6
Private pPen As Pen '十字線の描画用ペン
Private PBox1 As Rectangle '100% の時の PictureBox1 の位置情報
Private CenterPos As Point '十字線の中央位置(Formのクライアント領域基準)
Private Sub Form6_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
pPen.Dispose() '不要になった Pen の処分
End Sub
Private Sub Form6_Imaging_Load(sender As Object, e As EventArgs) Handles MyBase.Load
pPen = New Pen(Color.FromArgb(60, Color.Red), 2) '十字線描画用
PBox1 = PictureBox1.Bounds '初期位置の保存
'十字線の中央位置(PictureBoxのクライアント領域基準)
Dim centerPic As New Point(PictureBox1.Width \ 2, PictureBox1.Height \ 2)
'十字線の中央位置(Formのクライアント領域基準)
CenterPos = centerPic + New Size(PictureBox1.Location)
End Sub
Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles PictureBox1.Paint
Dim Pbox As PictureBox = CType(sender, PictureBox)
'十字線の中央位置(PictureBoxのクライアント領域基準)
Dim xy = CenterPos - New Size(PictureBox1.Location)
Dim g = e.Graphics
g.DrawLine(pPen, 0, xy.Y, PictureBox1.Width, xy.Y)
g.DrawLine(pPen, xy.X, 0, xy.X, PictureBox1.Height)
End Sub
Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
If PBox1.IsEmpty Then
Return 'ロード前なので何もしない
End If
'位置調整の「前」に、描画状態を無効化しておく
PictureBox1.Invalidate()
'位置調整
Dim val As Integer = CInt(NumericUpDown1.Value) '10〜100
Dim sz As New Size(PBox1.Width, PBox1.Height * val \ 100)
Dim xy As New Point(PBox1.Left, PBox1.Top + (PBox1.Height - sz.Height) \ 2)
PictureBox1.Bounds = New Rectangle(xy, sz)
End Sub
End Class
なお元のコードでは、座標の計算時に、
Decimal, Integer, Single, Double の型が混ざっていたので、
勝手ながらすべて Integer のみで演算されるよう改修しています。
ただし「CInt(z * 0.5)」を「z \ 2」で代用した関係上、
NumericUpDown の値によっては、PictureBox1 の位置と大きさが
ごく僅かにズレが生じることがあります。
具体的には、「CInt(z * 0.5)」と「z \ 2」の計算を比較すると、
z = 105 の場合は、どちらの計算でも 52 と算出されますが、
z = 103 の場合は、前者が 52、後者は 51 となるというものです。