前回のWindowsMediaPlayerコントロールを使って動画プレイヤーを作成するでは指定した部分だけを再生できるようなアプリとして作りましたが、指定すべき時間をどうやって取得するかは考えませんでした。従来のWindowsMediaPlayerを起動してやればいいのかもしれませんが、今回はキーとマウスでWindowsMediaPlayerコントロールを操作してみます。
まずはデザイナで以下のようなものをつくります。パネルをフォームに貼り付け、その下にトラックバーを貼り付けます。ステータスバーにテキストを表示させる領域を2つつくります。
パネルとトラックバーにAnchorを設定すればフォームの大きさが変更されたとき、これにあわせて表示位置とサイズを変更されるようになります。
でははじめてみましょう。
以下の部分は前回とほとんど同じです。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 |
public partial class Form1 : Form { AxWMPLib.AxWindowsMediaPlayer MediaPlayer = new AxWMPLib.AxWindowsMediaPlayer(); Timer Timer = new Timer(); public Form1() { InitializeComponent(); this.AllowDrop = true; Timer.Interval = 1000; Timer.Tick += Timer_Tick; Timer.Start(); trackBar1.ValueChanged += TrackBar1_ValueChanged; trackBar1.KeyDown += TrackBar1_KeyDown; panel1.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom; trackBar1.Anchor = AnchorStyles.Left | AnchorStyles.Bottom; } private void Form1_Load(object sender, EventArgs e) { MediaPlayer = new AxWMPLib.AxWindowsMediaPlayer(); panel1.Controls.Add(this.MediaPlayer); MediaPlayer.Dock = DockStyle.Fill; // UIを無効化 MediaPlayer.uiMode = "none"; // 右クリックによるコンテキストメニューの出力を無効化 MediaPlayer.enableContextMenu = false; } } |
ドラッグアンドドロップすれば再生できるようにする
ファイルを指定するときにダイアログで指定してもいいのですが、基本管理人は面倒くさがりなのでフォームにドラッグアンドドロップすれば再生されるようにします。
まずドラッグアンドドロップされたときのイベントハンドラの引数 DragEventArgsからドロップされようとしているファイル名を取得するメソッドをつくります。
ファイルがドラッグアンドドロップされようとしているときで、ファイルの拡張子が.mp4のときだけファイルのパスを返します。それ以外のときは空文字列を返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class Form1 : Form { string GetMp4FilePath(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 filePath; } return ""; } } |
ファイルがドラッグされドロップされたときの処理を示します。
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 { protected override void OnDragOver(DragEventArgs e) { if(GetMp4FilePath(e) != "") e.Effect = DragDropEffects.Copy; else e.Effect = DragDropEffects.None; base.OnDragOver(e); } protected override void OnDragDrop(DragEventArgs e) { string filePath = GetMp4FilePath(e); if (filePath != "") { MediaPlayer.URL = filePath; } base.OnDragDrop(e); } } |
動画の長さと現在位置を表示させる
あとは再生中かどうか調べて再生中であればその情報がわかるようにすればいいですね。1秒ごとにTimer_Tickが呼び出されるので再生されているファイルのパス、長さ、現在再生されている位置を取得してステータスバーに表示させ、トラックバーも移動させます。
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 |
public partial class Form1 : Form { private void Timer_Tick(object sender, EventArgs e) { var curMedia = MediaPlayer.currentMedia; if (curMedia != null) { string sourceURL = curMedia.sourceURL; int duration = (int)MediaPlayer.currentMedia.duration; int curPosition = (int)MediaPlayer.Ctlcontrols.currentPosition; trackBar1.Maximum = duration; trackBar1.Value = curPosition; TimeSpan span1 = new TimeSpan(0, 0, duration); TimeSpan span2 = new TimeSpan(0, 0, curPosition); toolStripStatusLabel1.Text = String.Format("{0} / {1} ", span2.ToString(), span1.ToString()); toolStripStatusLabel2.Text = sourceURL; } else { toolStripStatusLabel1.Text = ""; toolStripStatusLabel2.Text = ""; } } } |
トラックバーで再生位置を変更する
トラックバーを操作すれば再生位置を変更することができるようにします。なにもしなくても動画が再生されればトラックバーは移動します。これによって再生位置が毎秒変更されてはいけないので3秒以上のズレがない場合はなにもしません。それ以上にトラックバーのValueと再生位置がずれている場合はユーザーによるトラックバーの操作とみなして再生位置を変更します。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { private void TrackBar1_ValueChanged(object sender, EventArgs e) { int misalignment = (int)Math.Abs(MediaPlayer.Ctlcontrols.currentPosition - trackBar1.Value); if (misalignment > 2) { MediaPlayer.Ctlcontrols.currentPosition = trackBar1.Value; } } } |
実際に試してみると、トラックバーを移動することで現在の再生位置も変更されます。これならトラックバーをドラッグしながら再生状態を確認できるので便利です。
ただ再生自体はおこなわれているのでトラックバーはドラッグ中であっても移動していることに気づきます。ドラッグ中は一時停止状態になってほしいものです。
TrackBar.Valueがユーザーによって変更されたら一時停止状態にすればいいのですが、これではうまくいきません。一時停止から復帰することができないのでトラックバーを移動してもその部分の再生状態が表示されません。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { private void TrackBar1_ValueChanged(object sender, EventArgs e) { int misalignment = (int)Math.Abs(MediaPlayer.Ctlcontrols.currentPosition - trackBar1.Value); if (misalignment > 2) { MediaPlayer.Ctlcontrols.currentPosition = trackBar1.Value; MediaPlayer.Ctlcontrols.pause(); } } } |
そこで一時停止状態でトラックバーを移動したら再生状態にしてすぐに一時停止状態に変更します。これならトラックバーを移動することでその部分の再生状態が表示されるようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public partial class Form1 : Form { private void TrackBar1_ValueChanged(object sender, EventArgs e) { int misalignment = (int)Math.Abs(MediaPlayer.Ctlcontrols.currentPosition - trackBar1.Value); if (misalignment > 2) { MediaPlayer.Ctlcontrols.currentPosition = trackBar1.Value; MediaPlayer.Ctlcontrols.play(); MediaPlayer.Ctlcontrols.pause(); } } } |
のちのことを考えてこの部分は別メソッドにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class Form1 : Form { private void TrackBar1_ValueChanged(object sender, EventArgs e) { int misalignment = (int)Math.Abs(MediaPlayer.Ctlcontrols.currentPosition - trackBar1.Value); if (misalignment > 2) { SetCurrentPositionTrackBarValue(); } } void SetCurrentPositionTrackBarValue() { MediaPlayer.Ctlcontrols.currentPosition = trackBar1.Value; MediaPlayer.Ctlcontrols.play(); MediaPlayer.Ctlcontrols.pause(); } } |
キー入力で再生位置を変更する
一時停止状態から再生状態に戻す手段も用意しておかなければなりません。スペースキーをおせば一時停止と再生を切り替えることができるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { protected override bool ProcessDialogKey(Keys keyData) { // キーの本来の処理をさせたくないときは、trueを返す if ((keyData & Keys.KeyCode) == Keys.Space) { if (MediaPlayer.playState == WMPLib.WMPPlayState.wmppsPaused || MediaPlayer.playState == WMPLib.WMPPlayState.wmppsStopped) MediaPlayer.Ctlcontrols.play(); else MediaPlayer.Ctlcontrols.pause(); return true; } return base.ProcessDialogKey(keyData); } } |
それ以外の機能も追加します。左右の方向キーでも再生位置を変更できるようにして、Ctrlキーもいっしょに押せば10秒間前または後に移動できるようにしました。それからCを押せば動画の状態(ファイル名、長さ、現在位置)をクリップボードにコピーできるようにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { protected override bool ProcessDialogKey(Keys keyData) { if ((keyData & Keys.KeyCode) == Keys.Space) { if (MediaPlayer.playState == WMPLib.WMPPlayState.wmppsPaused || MediaPlayer.playState == WMPLib.WMPPlayState.wmppsStopped) MediaPlayer.Ctlcontrols.play(); else MediaPlayer.Ctlcontrols.pause(); return true; } if ((keyData & Keys.KeyCode) == Keys.C) CopyMediaPlayerInfo(); if ((keyData & Keys.KeyCode) == Keys.Left) OnKeyDownLeft(); if ((keyData & Keys.KeyCode) == Keys.Right) OnKeyDownRight(); return base.ProcessDialogKey(keyData); } } |
左右のキーが押されたときに再生位置を変更する処理を示します。
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 |
public partial class Form1 : Form { void OnKeyDownLeft() { int value = trackBar1.Value; if(Control.ModifierKeys != Keys.Control) value--; else value -= 10; if (value > 0) { trackBar1.Value = value; SetCurrentPositionTrackBarValue(); } } void OnKeyDownRight() { int value = trackBar1.Value; if (Control.ModifierKeys != Keys.Control) value++; else value += 10; if (value < trackBar1.Maximum) { trackBar1.Value = value; SetCurrentPositionTrackBarValue(); } } } |
現在の状態をクリップボードにコピーする処理を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { void CopyMediaPlayerInfo() { var curMedia = MediaPlayer.currentMedia; if (curMedia != null) { string sourceURL = curMedia.sourceURL; int duration = (int)MediaPlayer.currentMedia.duration; int curPosition = (int)MediaPlayer.Ctlcontrols.currentPosition; TimeSpan span1 = new TimeSpan(0, 0, duration); TimeSpan span2 = new TimeSpan(0, 0, curPosition); string str = String.Format( "ファイルパス:{0}\n長さ:{1}\n現在位置:{2}", sourceURL, span1.ToString(), span2.ToString()); Clipboard.SetText(str); } } } |