情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

WPFで動画のサムネイルを表示する(2)

イベントハンドラを実装していきます。

ツリービューかコンボボックスの選択項目が変化した時にリストボックスを更新します。

//選択されているツリービュー項目
private TreeViewItem selectedTreeViewItem = null;
//選択されているコンボボックス項目
private ComboBoxItem selectedComboBoxItem = null;

//ツリービューの選択項目が変化した時
private void treeViewFolder_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    //選択されているツリービュー項目を格納
    selectedTreeViewItem = (TreeViewItem)treeViewFolder.SelectedItem;

    //リストボックスを更新
    UpdateListBoxFile();
}

//コンボボックスの選択項目が変化した時
private void comboBoxFilter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    //選択されているコンボボックス項目を格納
    selectedComboBoxItem = (ComboBoxItem)comboBoxFilter.SelectedItem;

    //リストボックスを更新
    UpdateListBoxFile();
}

後で必要になるので選択されている項目を変数に保持しています。

UpdateListBoxFileメソッドでリストボックスを更新します。

対象フォルダ内にあるファイルをフィルタリングして、リストボックスに追加しています。フォルダ名はツリービューの選択項目のTagプロパティに格納されています。

その後、サムネイルを作成して一時ファイルとして保存するデリゲートをBeginInvokeで非同期的に実行します。デリゲートの引数は、一つ目が先にリストボックスに追加したリストボックス項目とそのコンテンツ(ファイルパス)の鍵値対、二つ目が選択されているツリービュー項目、三つ目が選択されているコンボボックス項目です。態々鍵値対を作って渡すのはコントロールのメンバにはUIスレッド以外からアクセス出来ないからです。クエリ式は遅延評価されるので予め配列化しておく必要があります。

//サムネイルを読み込むデリゲート
private delegate void DEL_ThumnailLoader(IEnumerable<KeyValuePair<ListBoxItem, string>> _item, TreeViewItem _selectedTreeViewItem, ComboBoxItem _selectedComboBoxItem);

//リストボックスを更新する
private void UpdateListBoxFile()
{
    //ツリービューの選択項目がないか選択項目のタグがヌルの場合は終了
    if (treeViewFolder.SelectedItem == null || ((TreeViewItem)treeViewFolder.SelectedItem).Tag == null)
        return;

    //リストボックスに表示するフォルダの名前はツリービューの選択項目のタグ
    string folderName = ((TreeViewItem)treeViewFolder.SelectedItem).Tag.ToString();

    //コンボボックスのフィルタ取得
    List<string> filter = null;
    if (comboBoxFilter.SelectedItem == comboBoxItemAvi)
        filter = new List<string>() { ".avi" };
    else if (comboBoxFilter.SelectedItem == comboBoxItemFlv)
        filter = new List<string>() { ".flv" };
    else if (comboBoxFilter.SelectedItem == comboBoxItemMkv)
        filter = new List<string>() { ".mkv" };
    else if (comboBoxFilter.SelectedItem == comboBoxItemMov)
        filter = new List<string>() { ".mov", ".qt" };
    else if (comboBoxFilter.SelectedItem == comboBoxItemMp4)
        filter = new List<string>() { ".mp4", ".m4v", ".m4a" };
    else if (comboBoxFilter.SelectedItem == comboBoxItemMpg)
        filter = new List<string>() { ".mpg", ".mpeg", ".m1v" };
    else if (comboBoxFilter.SelectedItem == comboBoxItemTs)
        filter = new List<string>() { ".ts", ".m2ts" };
    else if (comboBoxFilter.SelectedItem == comboBoxItemWmv)
        filter = new List<string>() { ".wmv" };

    //ファイル名のコレクション
    IEnumerable<string> fileName = new List<string>();
    //フィルターがヌルの場合はフォルダ内の全てのファイル
    if (filter == null)
        fileName = Directory.GetFiles(folderName);
    //フィルターがヌルでない場合はフィルターの拡張子を持ったファイル
    else
        fileName = from s in Directory.GetFiles(folderName) where filter.Contains(Path.GetExtension(s)) == true select s;

    //リストボックス更新
    listBoxFile.Items.Clear();
    foreach (var s in fileName)
    {
        ListBoxItem listBoxItem = new ListBoxItem();
        listBoxItem.Content = s;
        listBoxFile.Items.Add(listBoxItem);
    }

    //リストボックス項目とリストボックス項目の内容(このようにするのはUIスレッド以外のスレッドからUIにアクセス出来ないため)
    var item = (from l in listBoxFile.Items.Cast<ListBoxItem>() select new KeyValuePair<ListBoxItem, string>(l, l.Content.ToString())).ToArray();

    //サムネイルを読み込むデリゲート
    DEL_ThumnailLoader act_ThumnailLoader = LoadThumbnail;
    //デリゲートを非同期的に実行
    act_ThumnailLoader.BeginInvoke(item, (TreeViewItem)treeViewFolder.SelectedItem, (ComboBoxItem)comboBoxFilter.SelectedItem , ProcessAsyncCallback2, act_ThumnailLoader);
}

サムネイルを作成し保存するメソッドは次のようになります。

ツリービューやコンボボックスの選択項目が変更された場合はそれ以上処理する必要がないので終了するようにします。

サムネイルの保存が終わったら、そのファイルを読み込んで表示するためにサムネイルを追加するデリゲートを作り、コントロールにアクセスする必要があるのでUIスレッドで非同期的に実行します。デリゲートの引数は、一つ目が対象リストボックス項目で二つ目がサムネイルのファイル名です。

//サムネイルを追加するデリゲート
private delegate void DEL_AddThumbnail(ListBoxItem _listBoxItem, string _fileName);

//サムネイルを読み込む
private void LoadThumbnail(IEnumerable<KeyValuePair<ListBoxItem, string>> _item, TreeViewItem _selectedTreeViewItem, ComboBoxItem _selectedComboBoxItem)
{
    try
    {
        //動画の拡張子
        List<string> extension = new List<string>() { ".avi", ".flv", ".mkv", ".mov", ".qt", ".mp3", ".mp4", ".m4v", ".mpg", ".mpeg", ".m1v", ".m2v", ".ts", ".m2ts", ".wav", ".wma", ".wmv" };

        //一時フォルダ
        string tempFolderName = Environment.CurrentDirectory + "\\temp";
        //一時フォルダが存在する場合は中のファイルを全て削除
        if (Directory.Exists(tempFolderName))
            foreach (var s in Directory.GetFiles(tempFolderName))
                File.Delete(s);
        //一時フォルダが存在しない場合は一時フォルダを作成
        else
            Directory.CreateDirectory(tempFolderName);

        foreach (var l in _item)
        {
            //選択項目が変更された場合は終了
            if (selectedTreeViewItem != _selectedTreeViewItem || selectedComboBoxItem != _selectedComboBoxItem)
                break;

            //ファイルが動画の場合(上の動画の拡張子を持つ場合)
            if (extension.Contains(Path.GetExtension(l.Value)))
            {
                //サムネイル作成クラス
                ThumbnailCreator thumbnailCreator = new ThumbnailCreator();
                try
                {
                    //サムネイルのファイル名
                    string thumbnailFileName = tempFolderName + "\\" + Path.GetFileNameWithoutExtension(l.Value) + ".bmp";

                    //サムネイルを作成し保存
                    thumbnailCreator.GetThumbnail(l.Value).Save(thumbnailFileName);

                    //サムネイルを追加するデリゲート
                    DEL_AddThumbnail act_AddThumbnail = AddThumbnail;
                    //デリゲートをUIスレッドで非同期的に実行
                    Dispatcher.BeginInvoke(DispatcherPriority.Normal, act_AddThumbnail, l.Key, thumbnailFileName);
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    if (thumbnailCreator != null)
                        thumbnailCreator.Dispose();
                }
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

サムネイルを追加するメソッドは次のようになります。

追加すると言っても、実際はリストボックス項目のTagプロパティにサムネイルのファイル名を指定するだけです。

すると、前回示したvc_PathToImageSourceコンバータが働いてサムネイルファイルを開き画像データがImage.Sourceプロパティに流し込まれます。

//サムネイルを追加する
private void AddThumbnail(ListBoxItem _listBoxItem, string _fileName)
{
    _listBoxItem.Tag = _fileName;
}

以上でリストボックス部分の実装は完成です。

エクスプローラ風ツリービューの実装については前回示したリンク先の説明を覧てください。

(終)

pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-C#, wpf