VB2012でpictureboxを使って動画を再生する方法

タグの編集
投稿者 もっちり太郎  (学生) 投稿日時 2016/4/2 11:44:33
私は、vbのことについてただいま勉強中です。そこで今回皆様に教えていただきたいのが題名にも書いてある通り、VB2012でpictureboxを使って動画を再生する方法です。コードは以下のものです(dobon.net様のものを使わせていただきました)
 <System.Runtime.InteropServices.DllImport("winmm.dll", CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
    Private Shared Function mciSendString(ByVal command As String, _
    ByVal buffer As System.Text.StringBuilder, _
    ByVal bufferSize As Integer, ByVal hwndCallback As IntPtr) As Integer
    End Function

    Private aliasName As String = "MediaFile"

    'Button1のClickイベントハンドラ
    Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
        '再生するファイル名
        Dim fileName As String = "Wildlife.wmv"

        Dim cmd As String
        'ファイルを開く
        cmd = "open """ + fileName + """ alias " + aliasName
        If mciSendString(cmd, Nothing, 0, IntPtr.Zero) <> 0 Then
            Return
        End If '再生する
        cmd = "play " + aliasName
        mciSendString(cmd, Nothing, 0, IntPtr.Zero)
        Me.Left = 0
        Me.Top = 0
        Me.StartPosition = FormStartPosition.Manual
        Me.Show()
        Me.TopMost = True
    End Sub

よろしければ、どうやって動画を再生するのか、その仕組みも教えていただけると助かります。
投稿者 もっちり太郎  (学生) 投稿日時 2016/4/2 12:12:09
コードの中にpictureboxが一度も出てきていない理由ですが、まだpictureboxでどうやればいいからわからないからです。
このコードでやったら新しいformのようなものが出てきて動画が再生されました。
投稿者 (削除されました)  () 投稿日時 2016/4/2 18:41:24
(削除されました)
投稿者 daive  (社会人) 投稿日時 2016/4/2 18:44:38
>このコードでやったら新しいformのようなものが出てきて動画が再生されました。 
OS、のバージョン、エディション
VB.NET のエディション
が書かれていませんが、

 VisualBasic2010で動画プレーヤを作ろう!
  http://r--k.tumblr.com/post/65317678283/visualbasic2010%E3%81%A7%E5%8B%95%E7%94%BB%E3%83%97%E3%83%AC%E3%83%BC%E3%83%A4%E3%82%92%E4%BD%9C%E3%82%8D%E3%81%86
 が、参考になりませんか?

DirectShow を使う事になる場合には、
マイクロソフトの関係の資料をあたってください。
鎌田茂雄氏の旧著作が、高値流通しているかもしれませんが、
ノースブレインの新し書籍の方が良いかもです。
  ノースブレイン:鎌田茂雄
  http://northbrain.org/?page_id=77
投稿者 るきお  (社会人) 投稿日時 2016/4/3 21:12:06
とりあえず、私の手元では動くものを作ってみました。
動画の形式によっては使用されている環境のコーデックの影響を受けると思います。
このあたりは詳しくないのですが、私の環境ではmpgは再生できました。mp4はダメでした。wmvは未確認ですが、古い形式なので再生できるのではないかと思います。


Public Class Form1

    Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As StringByVal lpstrReturnString As StringByVal uReturnLength As IntegerByVal hwndCallback As IntegerAs Integer
    Private Declare Function mciGetErrorString Lib "winmm.dll" Alias "mciGetErrorStringA" (ByVal fdwError As IntegerByVal lpszErrorText As StringByVal cchErrorText As IntegerAs Integer

    Public Sub SendString(cmdString As String)

        Dim result As Integer = mciSendString(cmdString, "", 0, 0)

        If result <> 0 Then
            'エラーメッセージを取得して表示します。 
            Dim ErrorMessage As String = GetErrorString(result)
            MsgBox(ErrorMessage, MsgBoxStyle.Exclamation, "Error " & result)
        End If
    End Sub

    '■再生 
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim fileName As String = "C:\vb\test.mpg"

        SendString("open """ & fileName & """ alias MyMovie")
        SendString("window MyMovie handle " & PictureBox1.Handle.ToString)
        SendString("play MyMovie")
    End Sub

    '■停止 
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        SendString("close MyMovie")

    End Sub

    '■GetErrorString 
    '''  <summary>mciSendString関数の戻り値からエラーメッセージを取得します。</summary> 
    '''  <param name="APIResult">mciSendString関数の戻り値。エラーコード。</param> 
    '''  <returns>APIResultに対応するエラーメッセージを返します。</returns> 
    Private Function GetErrorString(ByVal apiResult As IntegerAs String

        Dim buffer As String = New String(Chr(0), 255)
        Dim errorMessage As String

        Call mciGetErrorString(apiResult, buffer, Len(buffer))

        errorMessage = Replace(buffer, Chr(0), "")

        Return errorMessage

    End Function


End Class
投稿者 (削除されました)  () 投稿日時 2016/4/6 13:09:46
(削除されました)
投稿者 もっちり太郎  (学生) 投稿日時 2016/4/6 14:49:47
返信遅れてすみません
 実際に動かしてみましたが、pictureboxのサイズによって、動画が見きれてしまうのですが、pictureboxでいうところのStretchImageのようにできませんか? 
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2016/4/6 16:49:31
これでどうでしょう。

Dim cs As Size = PictureBox1.ClientSize
SendString(String.Format("put MyMovie destination at 0 0 {0} {1}", cs.Width, cs.Height))


なお、MCI コマンドの一覧を知りたい場合は下記を参照してみてください。
https://msdn.microsoft.com/en-us/library/dd743572.aspx

> StretchImageのようにできませんか? 

初期表示は、SizeMode = Normal 相当の表示ですね。

手持ちの動画ファイルで試してみましたが、上記のコードを実行しても、
表示結果が Zoom になるか StretchImage になるかは、元の動画に依存するようです。


縦横比が固定な動画は、常に Zoom 相当の表示になりましたし、
縦横比の縛りが無い場合は、StretchImage 相当で表示されました。


> pictureboxのサイズによって、動画が見きれてしまうのですが

なお、StretchImage で表示される動画の場合、
Zoom 相当の表示(縦横比を維持して縮小/拡大)するために、
元の動画サイズを調べる必要があります。今回は関係ないですが。


Private Function GetSourceRect() As Rectangle
    Dim resText As New String(ControlChars.NullChar, 128)
    Dim ret As Integer = mciSendString("where MyMovie source", resText, 128, 0)
    If ret = 0 Then
        Dim ltwh() As String = Split(resText.TrimEnd(ControlChars.NullChar))
        Return New Rectangle(CInt(ltwh(0)), CInt(ltwh(1)), CInt(ltwh(2)), CInt(ltwh(3)))
    Else
        Return Rectangle.Empty
    End If
End Function


「where デバイス名 source」だと、元動画の大きさを返します。
「where デバイス名 destination」で、現在の描画領域を返します。
投稿者 もっちり太郎  (学生) 投稿日時 2016/4/9 11:06:53
皆様ありがとうございます。
おかげで動画を再生することができました。ちなみにお一つ気になる点があるのですが、動画の音量を0にすることはできますか?
投稿者 るきお(管理者)  (社会人) 投稿日時 2016/4/10 21:12:17
動画の音量を0にすることはできます。
次のようにMCIコマンドを使用します。

SendString("setaudio MyMovie volume to 0")


>おかげで動画を再生することができました。
できましたら、そのプログラムも載せてください。
追加の質問に答えるときにプログラムがどのようになっているかわかれば、より良い回答ができる場合が多いです。

また、このような有志の集まる掲示板は一方的に情報を得る場ではなく、双方向に情報を交換する場所として利用していただきたいと思います。
投稿者 もっちり太郎  (学生) 投稿日時 2016/4/11 17:04:04
すみません。まだここのルールに慣れていなくて・・・
ところで、るきおさんのコードを入れても、音が消えないのですが、間違っている個所があれば、教えていただけますか?
Public Class Form1

    Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer
    Private Declare Function mciGetErrorString Lib "winmm.dll" Alias "mciGetErrorStringA" (ByVal fdwError As Integer, ByVal lpszErrorText As String, ByVal cchErrorText As Integer) As Integer

    Public Sub SendString(cmdString As String)

        Dim result As Integer = mciSendString(cmdString, "", 0, 0)

        If result <> 0 Then
            'エラーメッセージを取得して表示します。 
            Dim ErrorMessage As String = GetErrorString(result)

        End If
    End Sub
    Private Sub PictureBox2_Click(sender As Object, e As EventArgs) Handles PictureBox2.Click
        Dim fileName As String = "Wildlife.wmv"
        SendString("open """ & fileName & """ alias MyMovie")
        SendString("window MyMovie handle " & PictureBox1.Handle.ToString)
        SendString("play MyMovie")
        SendString("setaudio MyMovie volume to 0")
    End Sub

    Private Sub PictureBox3_Click(sender As Object, e As EventArgs) Handles PictureBox3.Click

        SendString("stop MyMovie")
    End Sub
    Private Sub PictureBox4_Click(sender As Object, e As EventArgs) Handles PictureBox4.Click
        SendString("close MyMovie")
    End Sub
    '■GetErrorString 
    '''  <summary>mciSendString関数の戻り値からエラーメッセージを取得します。</summary> 
    '''  <param name="APIResult">mciSendString関数の戻り値。エラーコード。</param> 
    '''  <returns>APIResultに対応するエラーメッセージを返します。</returns> 
    Private Function GetErrorString(ByVal apiResult As Integer) As String

        Dim buffer As String = New String(Chr(0), 255)
        Dim errorMessage As String

        Call mciGetErrorString(apiResult, buffer, Len(buffer))

        errorMessage = Replace(buffer, Chr(0), "")

        Return errorMessage

    End Function

 
End Class
投稿者 Batel  (その他) 投稿日時 2016/5/9 16:18:41
ふざけた名前はやめましょう。