VB2008で開発時の配置コントロールのような事をしたい

タグの編集
投稿者 モル  (社会人) 投稿日時 2009/12/8 23:59:37
色々教えていただいているモルです。
前回からの画像関連の最後の仕上げとして範囲指定をしたいと思っています。
その際に開発時のようなコントロールを貼り付けたら八方にハンドルが出て、クリックしながら移動するとサイズを任意で変わるような事を実際のプログラムでやりたいと思っています。

一応作ってみたのですが、右下と真ん中下と右真ん中(=+方向への動き)の動きは思った通りの事が出来ましたが、それ以外(=-方向への動き)が上手く行きません。
どうか知恵を貸していただきたいと思います。
よろしくお願いします。

下記に載せますサンプルじゃなくても、こうやれば出来るよというのがあればお教え下さい。
ユーザーコントロールで作ろうと思ったのは、今後同じような事をしたい時にdllだけ持っていけば出来るかな?と安易な考えからです・・・
投稿者 モル  (社会人) 投稿日時 2009/12/9 00:02:30
サンプル(長いですが)
新しいプロジェクト→クラスライブラリ→プロジェクト→ユーザーコントロールの追加
UserControl1の上にPictureBoxを8個配置。
Imports System.Drawing
Imports System.Windows.Forms

Public Class UserControl1
    Private MousePoint As Point

    Private Sub FCHandle_UC_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load
        Call CtrlSyoki()
    End Sub

    Private Sub CtrlSyoki()
        Me.BackColor = Color.Black
        For Each c As Control In Me.Controls
            If 0 < InStr(c.Name, "PictureBox"Then
                c.Width = 10 : c.Height = 10 : c.BackColor = Color.Yellow
            End If
        Next

        With PictureBox1
            .Left = 0 : .Top = 0
        End With
        With PictureBox2
            .Left = Me.Width / 2 - .Width / 2 : .Top = 0
        End With
        With PictureBox3
            .Left = Me.Width - .Width : .Top = 0
        End With

        With PictureBox4
            .Left = 0 : .Top = Me.Height / 2 - .Height / 2
        End With
        With PictureBox5
            .Left = Me.Width - .Width : .Top = Me.Height / 2 - .Height / 2
        End With

        With PictureBox6
            .Left = 0 : .Top = Me.Height - .Height
        End With
        With PictureBox7
            .Left = Me.Width / 2 - .Width / 2 : .Top = Me.Height - .Height
        End With
        With PictureBox8
            .Left = Me.Width - .Width : .Top = Me.Height - .Height
        End With
    End Sub

    Private Sub PictureBox1_MouseDown(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs) Handles _
                    PictureBox1.MouseDown, PictureBox2.MouseDown, PictureBox3.MouseDown, PictureBox4.MouseDown, _
                     PictureBox5.MouseDown, PictureBox6.MouseDown, PictureBox7.MouseDown, PictureBox8.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then
            MousePoint = New Point(e.X, e.Y) : Call HandleHide(True)
        End If
    End Sub

    Private Sub PictureBox1_MouseMove(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs) Handles _
                    PictureBox1.MouseMove, PictureBox2.MouseMove, PictureBox3.MouseMove, PictureBox4.MouseMove, _
                     PictureBox5.MouseMove, PictureBox6.MouseMove, PictureBox7.MouseMove, PictureBox8.MouseMove
        If e.Button = Windows.Forms.MouseButtons.Left Then
            sender.left += e.X - MousePoint.X : sender.top += e.Y - MousePoint.Y
            Select Case sender.name
                Case "PictureBox1"

                Case "PictureBox2"

                Case "PictureBox3"

                Case "PictureBox4"

                Case "PictureBox5"
                    Me.Width = sender.left + sender.width
                Case "PictureBox6"

                Case "PictureBox7"
                    Me.Height = sender.top + sender.height
                Case "PictureBox8"
                    Me.Width = sender.left + sender.width : Me.Height = sender.top + sender.height
            End Select
            Me.Refresh()
        End If
    End Sub

    Private Sub PictureBox1_MouseUp(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs) Handles _
                    PictureBox1.MouseUp, PictureBox2.MouseUp, PictureBox3.MouseUp, PictureBox4.MouseUp, _
                     PictureBox5.MouseUp, PictureBox6.MouseUp, PictureBox7.MouseUp, PictureBox8.MouseUp
        Call HandleHide(False) : Call CtrlSyoki()
    End Sub

    Private Sub HandleHide(ByVal TF As Boolean)
        For Each c As Control In Me.Controls
            If 0 < InStr(c.Name, "PictureBox"Then
                c.Visible = Not TF
            End If
        Next
    End Sub
End Class
投稿者 あにす  (社会人) 投稿日時 2009/12/9 05:30:22
一から書くよりは元のサンプルとの差分を見てもらった方が要点がわかりやすいだろうと思ったので、出来るだけ元のコードを残して無理やり改修してみました。
長過ぎて1レスに収まらないので2回に分けて投稿します。

Imports System.Drawing
Imports System.Windows.Forms

Public Class UserControl1
    Private MousePoint As Point
    Private MouseDownSize As Size
    Private senderPictureBox As PictureBox

    Private Sub FCHandle_UC_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load
        Call CtrlSyoki()
    End Sub

    Private Sub CtrlSyoki()
        Me.BackColor = Color.Black
        For Each c As Control In Me.Controls
            If 0 < InStr(c.Name, "PictureBox"Then
                c.Width = 10 : c.Height = 10 : c.BackColor = Color.Yellow
            End If
        Next

        With PictureBox1 '左上 
            .Left = 0 : .Top = 0
        End With
        With PictureBox2 '上 
            .Left = Me.Width / 2 - .Width / 2 : .Top = 0
        End With
        With PictureBox3 '右上 
            .Left = Me.Width - .Width : .Top = 0
        End With

        With PictureBox4 '左 
            .Left = 0 : .Top = Me.Height / 2 - .Height / 2
        End With
        With PictureBox5 '右 
            .Left = Me.Width - .Width : .Top = Me.Height / 2 - .Height / 2
        End With

        With PictureBox6 '左下 
            .Left = 0 : .Top = Me.Height - .Height
        End With
        With PictureBox7 '下 
            .Left = Me.Width / 2 - .Width / 2 : .Top = Me.Height - .Height
        End With
        With PictureBox8 '右下 
            .Left = Me.Width - .Width : .Top = Me.Height - .Height
        End With
    End Sub

    Private Sub PictureBox1_MouseDown(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs) Handles _
                    PictureBox1.MouseDown, PictureBox2.MouseDown, PictureBox3.MouseDown, PictureBox4.MouseDown, _
                     PictureBox5.MouseDown, PictureBox6.MouseDown, PictureBox7.MouseDown, PictureBox8.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then
            MousePoint = New Point(e.X, e.Y) : Call HandleHide(True)
            MouseDownSize = Me.Size

            senderPictureBox = sender
        End If
    End Sub
投稿者 あにす  (社会人) 投稿日時 2009/12/9 05:30:59
    Private Sub PictureBox1_MouseMove(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs) Handles _
                    PictureBox1.MouseMove, PictureBox2.MouseMove, PictureBox3.MouseMove, PictureBox4.MouseMove, _
                     PictureBox5.MouseMove, PictureBox6.MouseMove, PictureBox7.MouseMove, PictureBox8.MouseMove
        If e.Button = Windows.Forms.MouseButtons.Left Then
            Dim diffX As Integer = e.X - MousePoint.X
            Dim diffY As Integer = e.Y - MousePoint.Y

            Select Case Me.senderPictureBox.Name
                Case "PictureBox1" '左上 
                    Dim w As Integer = Me.Width
                    Me.Width -= diffX
                    Me.Left += w - Me.Width

                    Dim h As Integer = Me.Height
                    Me.Height -= diffY
                    Me.Top += h - Me.Height
                Case "PictureBox2" '上 
                    Dim h As Integer = Me.Height
                    Me.Height -= diffY
                    Me.Top += h - Me.Height
                Case "PictureBox3" '右上 
                    Me.Width = MouseDownSize.Width + diffX

                    Dim h As Integer = Me.Height
                    Me.Height -= diffY
                    Me.Top += h - Me.Height
                Case "PictureBox4" '左 
                    Dim w As Integer = Me.Width
                    Me.Width -= diffX
                    Me.Left += w - Me.Width
                Case "PictureBox5" '右 
                    Me.Width = MouseDownSize.Width + diffX
                Case "PictureBox6" '左下 
                    Dim w As Integer = Me.Width
                    Me.Width -= diffX
                    Me.Left += w - Me.Width

                    Me.Height = MouseDownSize.Height + diffY
                Case "PictureBox7" '下 
                    Me.Height = MouseDownSize.Height + diffY
                Case "PictureBox8" '右下 
                    Me.Width = MouseDownSize.Width + diffX

                    Me.Height = MouseDownSize.Height + diffY
            End Select
            Me.Refresh()
        End If
    End Sub

    Private Sub PictureBox1_MouseUp(ByVal sender As ObjectByVal e As System.Windows.Forms.MouseEventArgs) Handles _
                    PictureBox1.MouseUp, PictureBox2.MouseUp, PictureBox3.MouseUp, PictureBox4.MouseUp, _
                     PictureBox5.MouseUp, PictureBox6.MouseUp, PictureBox7.MouseUp, PictureBox8.MouseUp, MyBase.MouseUp
        Call HandleHide(False) : Call CtrlSyoki()
    End Sub

    Private Sub HandleHide(ByVal TF As Boolean)
        For Each c As Control In Me.Controls
            If 0 < InStr(c.Name, "PictureBox"Then
                c.Visible = Not TF
            End If
        Next
    End Sub
End Class

投稿者 モル  (社会人) 投稿日時 2009/12/9 09:07:06
あにす様、返答&サンプルありがとうございます。
MouseDownとMouseMove時の処理の八方の動きを勉強させていただきました。
載せていただいたサンプルを参考にさせてもらって、いいものを作りたいと思います。
投稿者 hori  (社会人) 投稿日時 2009/12/11 23:27:44
私も同じようなものを作りたいと考えており、サンプルを参考にさせていただきましたが
エラーがでてしまいます。
それにPictureBoxはなぜ8個配置する必要があるのでしょうか?
投稿者 葉月  (社会人) 投稿日時 2009/12/12 10:51:40
>>>エラーがでてしまいます。
サンプルはユーザーコントロールになります。
ユーザーコントロール???
でしたら参考サイトで先に勉強しておくのをお勧めします。
http://msdn.microsoft.com/ja-jp/events/dd283314.aspx

>>>それにPictureBoxはなぜ8個配置する必要があるのでしょうか?
回答者のあにすさんが、
「出来るだけ元のコードを残して無理やり改修してみました」
と言っていますように、モルさんが理解しやすいようサンプルをできるだけ残して書いております。
PictureBoxかPanelが1つあれば、縮小や最大化はできます。

>>>画像の拡大/縮小
詳しくは「アスペクト比」で検索してみてください。
ざっくりと説明します。
①画像のサイズを求める。
②画像を描画させるコントロール(PictureBoxなど)のサイズを求める。
③画像と描画するコントロールの高さを比較→
 高さの場合は以下の計算式になります(画像の方が大きい場合は、以下の式になります)→
 高さの比率 = 画像の高さ / 描画するコントロールの高さ
④画像と描画するコントロールの幅を比較→
 幅の場合は以下の計算式になります(幅の方が大きい場合は、以下の式になります)→
 幅の比率 = 画像の幅 / 描画するコントロールの幅
⑤画像の方が大きかったらかけ算、描画するコントロールの方が大きかったら割り算します。
⑥余白を求めて÷2した位置で表示します。

計算式が多いので一見難しそうに見えますが、式は算数レベルです。
手順さえ理解してしまえば難しくありません。
.NETやJavaの場合は、イメージの再作成してくれるメソッドがあるので、メインになるのは上記の計算になります。

サンプルは私用優先のため書きません。
とりあえず、上記の計算式を使ってやってみてください。
投稿者 葉月  (社会人) 投稿日時 2009/12/12 10:57:51
サンプルが全くないのもきついかも知れません。
動画の拡大縮小で使ったサンプルの一部を提示します。
動画ですが、やってることは画像の拡大縮小と変わりません。
サンプルの一部を切り抜いただけなので、これだけでは動きません。
先ほど提示した計算を行っているのを確認してください。

>追伸
VB2008でノリで作ったコードなので、出来はよくないです。
Javaで作った方が丁寧ですが、こちらに載せる訳にはいかないので。

■サンプル
	 ' 隙間を求めるための割り算用 
        Const INT_SPACE_DIVISION As Integer = 2

        ' 動画の幅 
        Dim iMovieW As Integer
        ' 動画の高さ 
        Dim iMovieH As Integer
        ' 幅の隙間 
        Dim iSpaceW As Integer
        ' 高さの隙間 
        Dim iSpaceH As Integer
        ' 幅の倍率 
        Dim dMagnificationW As Double
        ' 高さの倍率 
        Dim dMagnificationH As Double
        ' 枠のサイズ 
        Dim strViewSize As String = String.Empty


' 幅のアスペクト比を求める。 
        If iMovieW > iPnlW Then
            dMagnificationW = iMovieW / iPnlW
        Else
            dMagnificationW = iPnlW / iMovieW
        End If

        ' 表示場所(パネル)が再生中の動画よりサイズが大きくなったら拡大処理を行う。 
        If iPnlW > iMovieW And iPnlH > iMovieH Then

            If dMagnificationW > dMagnificationH Then
                iMovieW = CInt(Math.Floor(iMovieW * dMagnificationH))
                iMovieH = CInt(Math.Floor(iMovieH * dMagnificationH))
            Else
                iMovieW = CInt(Math.Floor(iMovieW * dMagnificationW))
                iMovieH = CInt(Math.Floor(iMovieH * dMagnificationW))
            End If

            Console.WriteLine("MciCommand.vb WindowSizeChange iMovieW: " & iMovieW)
            Console.WriteLine("MciCommand.vb WindowSizeChange iMovieH: " & iMovieH)
        ElseIf (iPnlW.Equals(iMovieW) Or iPnlH.Equals(iMovieH)) Then
            ' 幅か高さが同一なので処理しない。 
        ElseIf dMagnificationW < dMagnificationH Then
            iMovieW = CInt(Math.Floor(iMovieW / dMagnificationH))
            iMovieH = CInt(Math.Floor(iMovieH / dMagnificationH))
        ElseIf dMagnificationW > dMagnificationH Then
            iMovieW = CInt(Math.Floor(iMovieW / dMagnificationW))
            iMovieH = CInt(Math.Floor(iMovieH / dMagnificationW))
        End If

        iSpaceW = CInt(Math.Floor(iPnlW - iMovieW) / INT_SPACE_DIVISION)
        iSpaceH = CInt(Math.Floor(iPnlH - iMovieH) / INT_SPACE_DIVISION)

投稿者 hori  (社会人) 投稿日時 2009/12/12 18:30:49
葉月さん、有り難うございます。
少し勉強してみます。