WindowsMediaPlayerコントロールを使って動画プレイヤーを作成してみました。できることは再生と停止、一時停止、mp4ファイルのリストを作って指定した部分だけ再生する・・・です。
Contents
ツールボックスにWindowsMediaPlayerコントロールを追加する
デザイナでWindowsMediaPlayerコントロールをフォームにドラッグアンドドロップできればいいのですが、通常はないので、自分で追加します。
ツールボックスを右クリックして[アイテムを選択]を選択、そのあと表示されるダイアログのCOMの部分からWindowsMediaPlayerを選択します。
ただしWindowsForms(.NET5.0)の場合はうまくいきません。
WindowsForms(.NET Framework)でおこなってください。
するとツールボックスにWindowsMediaPlayerコントロールが追加されるので、これをフォームにドラッグアンドドロップすれば使うことができます。
ただし、このままでは
COM 参照 WMPLib は ActiveX コントロール AxWMPLib の相互運用アセンブリですが、コンパイラによって /link フラグでリンクされるように設定されています。この COM 参照は参照として処理され、リンクされません。
という警告が出てきます。
そこでソリューションエクスプローラーのなかの[参照]のなかからAxInterop.WMPLibを選択し、[プロパティの相互運用型の埋め込み]をfalseにしてください。これでうまくいくはずです。
WindowsForms(.NET5.0)の場合
ではWindowsForms(.NET5.0)の場合はどうすることもできないのでしょうか? WindowsForms(.NET Framework)でいったんビルドすると実行ファイルが生成されるフォルダのなかにAxInterop.WMPLib.dllとInterop.WMPLib.dllが生成されます。これを拾ってきて、参照マネージャーをつかって追加します。そしてAxInterop.WMPLibを選択し、[プロパティの相互運用型の埋め込み]を「いいえ」に変更します。
あとは以下のようにすればWindowsMediaPlayerコントロールが表示されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class Form1 : Form { AxWMPLib.AxWindowsMediaPlayer mediaPlayer = new AxWMPLib.AxWindowsMediaPlayer(); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { mediaPlayer = new AxWMPLib.AxWindowsMediaPlayer(); Controls.Add(this.mediaPlayer); mediaPlayer.Dock = DockStyle.Fill; // UIを無効化 mediaPlayer.uiMode = "none"; // 右クリックによるコンテキストメニューの出力を無効化 mediaPlayer.enableContextMenu = false; } } |
WindowsMediaPlayerコントロールを使って動画プレイヤーを作成する
それではメニューを追加します。
まず再生ですが、
1 2 |
// 最初から再生 mediaPlayer.URL = PlaybackInfos[CurIndex].FilePath; |
これでできます。
もし一時停止しているのであれば上記の方法では最初からの再生になるので
1 2 |
// 一時停止からの再生 mediaPlayer.Ctlcontrols.play(); |
これで続きから再生できます。
停止と一時停止はそれぞれ
1 2 3 4 5 |
// 停止 mediaPlayer.Ctlcontrols.stop(); // 一時停止 mediaPlayer.Ctlcontrols.pause(); |
です。
ではオリジナルのメディアプレーヤーをつくっていきましょう。
PlaybackInfoクラス
動画を最後まで再生するのではなく指定した場所まで再生したら次の動画を再生する仕様なので、mp4ファイルのパス、開始時間、終了時間をクラスで管理します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class PlaybackInfo { public PlaybackInfo() { } public PlaybackInfo(string filePath, double startSecond, double endSecond) { StartSecond = startSecond; EndSecond = endSecond; FilePath = filePath; } public double StartSecond = 0; public double EndSecond = 0; public string FilePath = ""; } |
FormPlaylistクラス 登録されているファイルリストを編集する
次に登録されているファイルのリストを確認、編集するために別のフォームを作成します。
フィールド変数 PlaybackInfosにPlaybackInfoのリストを格納して表示させるとリストビューにファイルと再生時間の一覧が表示されます。そして[新規登録]や[編集]を選択すると新しく動画を登録できたり、すでに登録されている内容を変更することができます。
本当は順番を変更したりいらなくなったデータを削除する機能もつけたほうがいいのですが、今回は割愛ということで・・・。
FormPlaylistクラスのコンストラクタを示します。
1 2 3 4 5 6 7 8 9 10 |
public partial class FormPlaylist : Form { public List<PlaybackInfo> PlaybackInfos = new List<PlaybackInfo>(); public FormPlaylist() { InitializeComponent(); buttonOK.DialogResult = DialogResult.OK; } } |
次にダイアログが表示されるときに行なわれる処理を示します。リストビューを初期化して自作メソッド LoadDataを呼び出してデータを表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class FormPlaylist : Form { protected override void OnLoad(EventArgs e) { listView1.View = View.Details; listView1.FullRowSelect = true; listView1.HideSelection = false; listView1.MultiSelect = false; listView1.Columns.Add("ファイル名"); listView1.Columns.Add("ファイルパス"); listView1.Columns.Add("開始時間"); listView1.Columns.Add("終了時間"); LoadData(); base.OnLoad(e); } } |
登録されている動画ファイルを表示
PlaybackInfosに格納されているデータを表示させる処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class FormPlaylist : Form { void LoadData() { listView1.Items.Clear(); foreach (PlaybackInfo info in PlaybackInfos) { string fullPath = info.FilePath; FileInfo fi = new FileInfo(fullPath); string name = fi.Name; TimeSpan tsStart = new TimeSpan(0, 0, (int)info.StartSecond); TimeSpan tsEnd = new TimeSpan(0, 0, (int)info.EndSecond); string[] strs = new string[] { name, fullPath, tsStart.ToString(), tsEnd.ToString(), }; ListViewItem item = new ListViewItem(strs); listView1.Items.Add(item); } } } |
登録されているデータを編集する
リストビューのアイテムが選択されている状態でデータを編集するための処理を示します。ここではまた新しいダイアログを表示させます。FormEditクラスは後述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public partial class FormPlaylist : Form { private void buttonEdit_Click(object sender, EventArgs e) { var items = listView1.SelectedIndices; if (items.Count == 0) return; var index = items[0]; PlaybackInfo info = PlaybackInfos[index]; FormEdit formEdit = new FormEdit(); formEdit.FilePath = info.FilePath; formEdit.StartSecond = info.StartSecond; formEdit.EndSecond = info.EndSecond; if (formEdit.ShowDialog() == DialogResult.OK) { if (File.Exists(formEdit.FilePath) && formEdit.StartSecond < formEdit.EndSecond) { info.FilePath = formEdit.FilePath; info.StartSecond = formEdit.StartSecond; info.EndSecond = formEdit.EndSecond; LoadData(); } else MessageBox.Show("設定が正しくありません"); } formEdit.Dispose(); } } |
新しいデータを登録する
新しいデータを登録するための処理を示します。この処理も先ほどと同じダイアログを表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class FormPlaylist : Form { private void buttonNew_Click(object sender, EventArgs e) { FormEdit formEdit = new FormEdit(); if (formEdit.ShowDialog() == DialogResult.OK) { if (File.Exists(formEdit.FilePath) && formEdit.StartSecond < formEdit.EndSecond) PlaybackInfos.Add(new PlaybackInfo(formEdit.FilePath, formEdit.StartSecond, formEdit.EndSecond)); else MessageBox.Show("設定が正しくありません"); LoadData(); } formEdit.Dispose(); } } |
FormEditクラス
次にデータを新しく追加したり既存のデータを編集するためのFormEditクラスを示します。
コンストラクタ内でNumericUpDownコントロールの上限値の設定と登録ボタンがおされたときにDialogResult.OKを返すための処理、テキストボックスにドラッグアンドドロップでファイルパスを設定できるようにするための準備をしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class FormEdit : Form { public double StartSecond = 0; public double EndSecond = 0; public string FilePath = ""; public FormEdit() { InitializeComponent(); numStartHour.Maximum = 12; numStartMinute.Maximum = 59; numStartSecond.Maximum = 59; numEndHour.Maximum = 12; numEndMinute.Maximum = 59; numEndSecond.Maximum = 59; textBox1.AllowDrop = true; textBox1.DragOver += TextBox1_DragOver; textBox1.DragDrop += TextBox1_DragDrop; buttonOK.DialogResult = DialogResult.OK; } } |
テキストボックスにファイルをドラッグアンドドロップしたときにファイル名を取得して文字列をセットできるようにしています。拡張子が.mp4でない場合は無視です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public partial class FormEdit : Form { private void TextBox1_DragOver(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Copy; } else { e.Effect = DragDropEffects.None; } } private void TextBox1_DragDrop(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); string filePath = files[0]; FileInfo info = new FileInfo(filePath); if (info.Extension.ToLower() != ".mp4") return; textBox1.Text = filePath; } } } |
編集前のデータを表示する
ダイアログが表示されたときの処理を示します。FilePathが空文字列でない場合はファイルのパスを表示させます。また開始時間と終了時間もそれぞれ表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class FormEdit : Form { protected override void OnLoad(EventArgs e) { textBox1.Text = FilePath; TimeSpan tsStart = new TimeSpan(0, 0, (int)StartSecond); TimeSpan tsEnd = new TimeSpan(0, 0, (int)EndSecond); numStartHour.Value = tsStart.Hours; numStartMinute.Value = tsStart.Minutes; numStartSecond.Value = tsStart.Seconds; numEndHour.Value = tsEnd.Hours; numEndMinute.Value = tsEnd.Minutes; numEndSecond.Value = tsEnd.Seconds; base.OnLoad(e); } } |
登録・確定したときの処理
登録ボタンがおされたときの処理を示します。NumericUpDownコントロールとテキストボックスから取得したデータをフィールド変数に格納します。この値が正当かどうかはFormPlaylistクラスで判断します。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class FormEdit : Form { private void buttonOK_Click(object sender, EventArgs e) { FilePath = textBox1.Text; TimeSpan tsStart = new TimeSpan((int)numStartHour.Value, (int)numStartMinute.Value, (int)numStartSecond.Value); TimeSpan tsEnd = new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value); StartSecond = (double)tsStart.TotalSeconds; EndSecond = (double)tsEnd.TotalSeconds; } } |
Form1クラスの処理
最後にForm1クラスの処理を示します。
タイマーをつかって0.1秒おきにどこまで再生されているか調べて終了位置まで再生されていたら次の動画を再生し、次の動画がなければ終了となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using WMPLib; public partial class Form1 : Form { AxWMPLib.AxWindowsMediaPlayer mediaPlayer = new AxWMPLib.AxWindowsMediaPlayer(); int CurIndex = 0; List<PlaybackInfo> PlaybackInfos = new List<PlaybackInfo>(); Timer Timer = new Timer(); public Form1() { InitializeComponent(); Timer.Interval = 100; Timer.Tick += Timer_Tick; Timer.Start(); } } |
WindowsMediaPlayerコントロールの初期化
フォームが表示されたらWindowsMediaPlayerコントロール初期化の処理をおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { protected override void OnLoad(EventArgs e) { Controls.Add(this.mediaPlayer); mediaPlayer.Dock = DockStyle.Fill; mediaPlayer.uiMode = "none"; mediaPlayer.enableContextMenu = false; base.OnLoad(e); } } |
再生リストの保存と読み出し
すでに作成された再生リストの保存と読み出しの処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
using System.Xml.Serialization; using System.IO; public class Doc { public Doc() { } public List<PlaybackInfo> PlaybackInfos = new List<PlaybackInfo>(); } public partial class Form1 : Form { private void SaveFileMenuItem_Click(object sender, EventArgs e) { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "再生リスト(*.mylist)| *.mylist"; if (dialog.ShowDialog() == DialogResult.OK) { string filePath = dialog.FileName; Doc doc = new Doc(); doc.PlaybackInfos = PlaybackInfos; XmlSerializer xml = new XmlSerializer(typeof(Doc)); StreamWriter sw = new StreamWriter(filePath); xml.Serialize(sw, doc); sw.Close(); } dialog.Dispose(); } private void OpenFileMenuItem_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "再生リスト(*.mylist)| *.mylist"; if (dialog.ShowDialog() == DialogResult.OK) { string filePath = dialog.FileName; XmlSerializer xml = new XmlSerializer(typeof(Doc)); StreamReader sr = new StreamReader(filePath); Doc doc = (Doc)xml.Deserialize(sr); PlaybackInfos = doc.PlaybackInfos; sr.Close(); // CurIndex をリセットし、新しく読み込んだものを再生する CurIndex = 0; if (PlaybackInfos.Count > 0) { mediaPlayer.URL = PlaybackInfos[CurIndex].FilePath; mediaPlayer.Ctlcontrols.currentPosition = PlaybackInfos[CurIndex].StartSecond; } } dialog.Dispose(); } } |
登録されているデータを編集する
メニュー [リストを編集する]が選択されたときの処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public partial class Form1 : Form { private void EditListMenuItem_Click(object sender, EventArgs e) { List<PlaybackInfo> playbackInfo = new List<PlaybackInfo>(); foreach (PlaybackInfo info in PlaybackInfos) { PlaybackInfo info1 = new PlaybackInfo(info.FilePath, info.StartSecond, info.EndSecond); playbackInfo.Add(info1); } FormPlaylist formPlaylist = new FormPlaylist(); formPlaylist.PlaybackInfos = playbackInfo; if (formPlaylist.ShowDialog() == DialogResult.OK) { PlaybackInfos = formPlaylist.PlaybackInfos; } formPlaylist.Dispose(); } } |
再生、停止、一時停止
再生、停止、一時停止が選択されたときの処理を示します。一時停止の場合は再生時にはその位置から再開します。停止している場合は最初からの再生になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public partial class Form1 : Form { private void PlaybackMenuItem_Click(object sender, EventArgs e) { if (mediaPlayer.playState == WMPLib.WMPPlayState.wmppsPaused) mediaPlayer.Ctlcontrols.play(); else { CurIndex = 0; // 最初からの再生なので0に戻す if (PlaybackInfos.Count > 0) { // 最初の動画の再生開始位置に移動 mediaPlayer.URL = PlaybackInfos[CurIndex].FilePath; mediaPlayer.Ctlcontrols.currentPosition = PlaybackInfos[CurIndex].StartSecond; } } } private void StopMenuItem_Click(object sender, EventArgs e) { mediaPlayer.Ctlcontrols.stop(); } private void PauseMenuItem_Click(object sender, EventArgs e) { mediaPlayer.Ctlcontrols.pause(); } } |
終了位置に達したら次の動画へ
0.1秒ごとに再生終了位置に達しているかどうかを確認して、終了位置に達しているのであれば次の動画を再生します。また再生中はどの動画ファイルをどこまで再生しているのかをステータスバーに表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
public partial class Form1 : Form { private void Timer_Tick(object sender, EventArgs e) { if (PlaybackInfos.Count == 0) { TimeSpan timeSpan = new TimeSpan(0, 0, 0); ShowTimeInfo(timeSpan); ShowFileInfo("リストが登録されていません。"); return; } else if (mediaPlayer.playState != WMPLib.WMPPlayState.wmppsStopped) { string status = ""; if (mediaPlayer.playState == WMPLib.WMPPlayState.wmppsPlaying) status = "再生中 - "; if (mediaPlayer.playState == WMPLib.WMPPlayState.wmppsPaused) status = "一時停止 - "; string str1 = status + "(" + CurIndex + ") " + PlaybackInfos[CurIndex].FilePath; double d = mediaPlayer.Ctlcontrols.currentPosition; TimeSpan timeSpan = new TimeSpan(0, 0, (int)d); string str2 = timeSpan.ToString(); ShowTimeInfo(timeSpan); ShowFileInfo(str1); } else if (mediaPlayer.playState == WMPLib.WMPPlayState.wmppsStopped) { ShowFileInfo("停止"); } // 終了位置に達しているのであれば次の動画を再生する if (mediaPlayer.Ctlcontrols.currentPosition > PlaybackInfos[CurIndex].EndSecond) { if (PlaybackInfos.Count > CurIndex + 1) { CurIndex++; mediaPlayer.URL = PlaybackInfos[CurIndex].FilePath; mediaPlayer.Ctlcontrols.currentPosition = PlaybackInfos[CurIndex].StartSecond; } else mediaPlayer.Ctlcontrols.stop(); } } } |
ステータスバーに動画再生の情報を表示
これはステータスバーに文字列を表示させるためのメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form1 : Form { void ShowTimeInfo(TimeSpan timeSpan) { string str = timeSpan.ToString(); if(toolStripStatusLabel1.Text != str) { toolStripStatusLabel1.Text = str; } } void ShowFileInfo(string str) { if (toolStripStatusLabel2.Text != str) { toolStripStatusLabel2.Text = str; } } } |
すいません、もしよければなんですけど
この記事の完成品のソースコードを頂けないでしょうか?
自分のレベルが低すぎて質問しだすと延々と質問する事になりそうなので、
どこがどう違うか見比べて勉強したいのですが、どうでしょうか・・・?
Frameworkでしか使えなWindowsMediaPlayerを、.NETで使用する方法、大変参考になりました。この理屈なら、VisualBasicとC#の違いもなくなると言うことだと思いました。貴重な情報公開、ありがとうございます。orz