前回コントロールとしてMediaElementを使いました。今回は一味違うMediaPlayerを使ってみます。

 

実はこのMediaPlayer、(WPFのことを何も知らない)以前にWinFormで貼り付けたことがあります。この時の結果は、

追記:アップしてから、「↑のコードでどうなったの?」という結論を書き忘れましたぁ!実は↑のコードは「正常にコンパイルされ、動くことは動き」ます。ただ、動画ファイルを読み込んで再生しても「音しか出ない」だけです。まぁ、画像処理部分が解説した通りなので、再生されるわけがないのですが...

となりました。今回はきちんとWPFで書きますので、赤字部分がどうなるか解説します。(なお、以下の色分けはコメント解説MediaPlayerが動画を表示するUIElementビデオ再生VideoDrawingクラス)、ピンク描画ブラシとなります。)

 

【Test_MediaPlayer.cs】

///////////////////////////////////////////
//Test_MediaPlayer.cs - MediaPlayer Sample
///////////////////////////////////////////

using System;
using System.Windows;            //PresentationFramework.dllにある
using System.Windows.Controls;    //PresentationFramework.dllにある
using System.Windows.Media;        //PresentationCore.dllにある(MediaPlayer, Brushes構造体使用の為)
/* 参照DLL
RefFile=C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll
RefFile01=C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationCore.dll
RefFile02=C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\WindowsBase.dll
RefFile03=C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Xaml.dll
*/


namespace Test_MediaPlayer
{
    ///////////////////////////
    //エントリーポイントクラス
    ///////////////////////////

    class MainApp
    {
        [STAThread]
        public static void Main()
        {
            DlgWindow dlg = new DlgWindow();
            Application ap = new Application();    //明示的にインスタンスを作らなければならない
            ap.Run(dlg);
        }
    }

    public partial class DlgWindow : Window    //派生元が"Form"から"Window"となる
    {
        //コントロール
        //private MediaElement me;    //解説:今回はMediaElementを使いません。

        private MediaPlayer mp = null;    //解説:これが噂のMediaPlayerクラスインスタンスです。
        private Canvas canvas = null;    //解説:今回は動画再生画面をUIElement配置用のCanvasコントロールにしてみます。(詳細は後記)
        //private Button canvas = null;    //解説:Canvasで実験したら、Buttonクラスに入れ替えてみてください。

        private VideoDrawing vd = null;    //解説:VideoDrawingはビデオ再生機能の為のクラスです。(詳細は後記)
        private Button Btn1, Btn2, Btn3, Btn4, extBtn;
        //ファイル名
        string fName = "";
        //MediaPlayerコントロール用変数
        bool toggle = true;

        public DlgWindow()
        {
            this.Title = "MediaPlayer サンプル";
            this.Width = 640;
            this.Height = 480;
            this.WindowStyle = WindowStyle.ThreeDBorderWindow;
            this.ResizeMode = ResizeMode.NoResize;
            this.WindowState = WindowState.Normal;
            this.WindowStartupLocation = WindowStartupLocation.CenterScreen;    //Manual, CenterOwnerもある(Manyualの場合のTopとLeftで設定)
            this.Background = SystemColors.ControlBrush;
            InitControls();
        }

        public void InitControls()
        {
            //グリッド(Grid)と縦二列を作成
            Grid grid = new Grid();
            ColumnDefinition colL = new ColumnDefinition();
            ColumnDefinition colR = new ColumnDefinition();
            //列を定義
            //colL.Width = GridLength.Auto;    //解説:何も入れていないと幅0となる。

            colL.Width = new GridLength(540, GridUnitType.Pixel);
            colR.Width = GridLength.Auto;
            //colR.Width = new GridLength(80, GridUnitType.Pixel);    //解説:右列を固定幅にする場合
            grid.ColumnDefinitions.Add(colL);
            grid.ColumnDefinitions.Add(colR);

            //スタックパネル(StackPanel)を作成
            StackPanel stackPanel = new StackPanel();
            stackPanel.Width = 80;
            stackPanel.Height = 420;
            stackPanel.HorizontalAlignment = HorizontalAlignment.Right;

            //Canvas    //解説:Canvasコントロールを単にGridの左列に貼り付けるだけです。
            canvas = new Canvas();
            //canvas = new Button();    //解説:Canvasで実験したら、Buttonクラスに入れ替えてみてください。
            //canvas.Content = "I'm a mere button.";

            canvas.Margin = new Thickness(10, 10, 10, 10);    //構造体 Thickness(左, 上, 右, 下)

            //グリッド左列に動画再生用Canvasコントロールを登録
            Grid.SetColumn(canvas, 0);
            grid.Children.Add(canvas);

            //ボタン1
            Btn1 = new Button();
            Btn1.Width = 60;
            Btn1.Height = 24;
            Btn1.HorizontalAlignment = HorizontalAlignment.Right;
            Btn1.VerticalAlignment = VerticalAlignment.Top;
            Btn1.Margin = new Thickness(10, 10, 10, 0);    //構造体 Thickness(左, 上, 右, 下)
            Btn1.Content = "Open";
            Btn1.Click += Button1_Click;
            stackPanel.Children.Add(Btn1);

            //ボタン2ボタン
            Btn2 = new Button();
            Btn2.Width = 60;
            Btn2.Height = 24;
            Btn2.HorizontalAlignment = HorizontalAlignment.Right;
            Btn2.VerticalAlignment = VerticalAlignment.Top;
            Btn2.Margin = new Thickness(10, 10, 10, 0);    //構造体 Thickness(左, 上, 右, 下)
            Btn2.Content = "Play";
            Btn2.Click += Button2_Click;
            stackPanel.Children.Add(Btn2);

            //ボタン3ボタン
            Btn3 = new Button();
            Btn3.Width = 60;
            Btn3.Height = 24;
            Btn3.HorizontalAlignment = HorizontalAlignment.Right;
            Btn3.VerticalAlignment = VerticalAlignment.Top;
            Btn3.Margin = new Thickness(10, 10, 10, 0);    //構造体 Thickness(左, 上, 右, 下)
            Btn3.Content = "Pause";
            Btn3.Click += Button3_Click;
            stackPanel.Children.Add(Btn3);

            //ボタン4ボタン
            Btn4 = new Button();
            Btn4.Width = 60;
            Btn4.Height = 24;
            Btn4.HorizontalAlignment = HorizontalAlignment.Right;
            Btn4.VerticalAlignment = VerticalAlignment.Top;
            Btn4.Margin = new Thickness(10, 10, 10, 0);    //構造体 Thickness(左, 上, 右, 下)
            Btn4.Content = "Stop";
            Btn4.Click += Button4_Click;
            stackPanel.Children.Add(Btn4);

            //終了ボタン
            extBtn = new Button();
            extBtn.Width = 60;
            extBtn.Height = 24;
            extBtn.HorizontalAlignment = HorizontalAlignment.Right;
            extBtn.VerticalAlignment = VerticalAlignment.Bottom;
            extBtn.Margin = new Thickness(10, 10, 10, 10);    //構造体 Thickness(左, 上, 右, 下)
            extBtn.Content = "終了";
            extBtn.Click += extBtn_Click;
            stackPanel.Children.Add(extBtn);

            //グリッド右列にスタックパネルを登録
            Grid.SetColumn(stackPanel, 1);
            grid.Children.Add(stackPanel);

            //ウィンドウにグリッドを登録
            this.Content = grid;

            //MediaPlayerとVideoDrawing
            mp = new MediaPlayer();    //解説:メディアプレーヤーのインスタンス実体を生成します。
            vd = new VideoDrawing();    //解説:ビデオ再生のインスタンス実体を生成します。
        }

        void Button1_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
            ofd.AddExtension = true;
            ofd.DefaultExt = "*.*";
            ofd.Filter = "Media(*.*)|*.*";
            ofd.ShowDialog();
            fName = ofd.FileName;
            //ofd.Dispose();    //WPFでは不要(https://learn.microsoft.com/ja-jp/dotnet/desktop/wpf/windows/how-to-open-common-system-dialog-box?view=netdesktop-8.0)
        }

        void Button2_Click(object sender, RoutedEventArgs e)
        {
            if(fName == "")    //解説:メディアファイルが指定されていない場合
                MessageBox.Show("メディアファイルを選択してください。", "エラー", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            else    //解説:メディアファイルが指定されている場合、再生を開始します。
            {
                //解説:先ずメディアプレーヤーにソースファイルを喰わせます。

                mp.Open(new System.Uri(fName, UriKind.Absolute));    //Uri:URI(Uniform Resource Identifier) のオブジェクト表現を可能にし、URI の一部へ簡単にアクセスできるようにします。

                //解説:ビデオ再生サイズを指定します。
                vd.Rect = new System.Windows.Rect(0, 0, 200, 200);

                //解説:ビデオ再生のソースをメディアプレーヤーに指定します。
                vd.Player = mp;

                //解説:ビデオ再生を描画ブラシとして生成します。
                DrawingBrush br = new DrawingBrush(vd);
                canvas.Background = br;     //解説:Canvasコントロールの背景にビデオ再生描画ブラシを登録します。
                mp.Play();     //解説:再生を開始します。
                Btn3.Content = "Pause";     //解説:ボタン3の「一時停止」の表示(MediaElementの場合と同じ)
                toggle = true;     //解説:トグルスイッチを真にします。(MediaElementの場合と同じ。)
            }
        }

        void Button3_Click(object sender, RoutedEventArgs e)
        {
            if(toggle)
            {
                //解説:MediaPlayerになった以外は、MediaElementの場合と同じです。

                mp.Pause();
                Btn3.Content = "Resume";
            }
            else
            {
                //解説:MediaPlayerになった以外は、MediaElementの場合と同じです。

                mp.Play();
                Btn3.Content = "Pause";
            }
            toggle = !toggle;
        }

        void Button4_Click(object sender, RoutedEventArgs e)
        {
            //解説:MediaPlayerになった以外は、MediaElementの場合と同じです。

            mp.Stop();
            Btn3.Content = "Pause";
            toggle = true;
        }

        void extBtn_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}

 

いかがでしょうか?

 

MediaElementクラスは、インスタンスを生成するだけでそれ自体がコントロールとなって動画再生が出来ましたが、MediaPlayerの場合は、

 

(1)動画ソースファイルの読み込みと管制→MediaPlayer

 ↓(登録)

(2)動画データの再生→VideoDrawing

 ↓(登録)

(3)描画ブラシ→DrawingBrush

 ↓(登録)

(4)(コントロール等)UIElementの背景(Backgroundメンバー)

 

という手続きを経て動画を再生します。(

:と言っても、Microsoft Learningのサンプルには(1)→(2)までしか載っておらず、私はwebをググって英文のサイトに辿り着き、(3)→(4)を行うことで動画がUIElementに表示されることを知りました。

 

なーんだ、MediaElementの方が簡単じゃん!又は、

MediaPlayerは面倒くさい。又は、

結局動画の再生、一時停止、中止はMediaElementとおんなじじゃん!

 

と思ったあなた、正解ですっ!

 

ただしっ

MediaPlayerは、

(背景がある)どんなUIElementでも動画再生できる

というところがMediaElementと違うのです。↑のサンプルでCanvasの代わりにButton等他のコントロールを使ってテスト()してみたり、そのコントロールのContentメンバーに何か登録したらどうなるかテストしてみてください。

:↑のコードの「//解説:Canvasで実験したら、Buttonクラスに入れ替えてみてください。」というコメントが付いている行の行頭のコメント記号(//)を切り取り、Canvasクラスにしている相対する行の頭に貼り付けて、コメントを入れ替えてコンパイルしてみてください。又、ボタンにはContentメンバーに文字列を設定しています。それがどう見えるかも確認してください。(インスタンス名canvasは、Buttonクラスにしてもそのまま使っているのでいじらなくて結構です。)

 

これこそがWEBデザイン時代の動画再生なんだなぁ

 

と思いました。

(未再生)

(Canvasクラスで再生する場合)

(Buttonクラスで再生する場合)

 

まぁ、いずれにしてもWin32ではDirectShowのラッパーを作る必要があった(昔の)C++やWinFormとは異なり、WPF+C#では「MediaElementというコントロールを使う」か「どんなコントロールでも背景をMediaPlayerで描画する」ことで動画再生はとても簡単になりました。

 

と、いうことが分かったので、動画再生は一件落着です。

 

今度はもう一つ引っ掛かっていたSAPIがWPFでどう扱われているか確かめたのでご紹介しましょう。