今回はウィンドウ関連のメンバー関数の実装をUser.hとDirectShowProc.hで見てゆきます。まずはUser.hからです。

【User.h】
///////////////////////////
//ツールバーのサブクラス化
///////////////////////////
WNDPROC g_TBProc = NULL;
//(解説:ツールバーコントロールの本来のコールバック関数を記録する為の変数です。)

//TOOLBARのメッセージからWM_HSCROLLのみを取得する
LRESULT CALLBACK TOOLBARProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

    int pos;
    switch (uMsg) {
    case WM_HSCROLL:
        if(lParam != (LPARAM)GetDlgItem(hWnd, IDC_SLIDER))
            break;                            //スライダーからの通知でなければ何もしない
        switch(LOWORD(wParam)) {            //スライダーコントロールからの通知
        case SB_THUMBTRACK:                    //スライダーのドラッグ時は何もしない
            return 0;
        case SB_THUMBPOSITION:                //摘みを離した時に
            pos = HIWORD(wParam);            //スライダーの位置を取得
            break;
        default:                            //それ以外の場合、HIWORD(wParam)は使えないので
            pos = g_Slider.GetPosition();    //GetPosition関数で位置を取得する
            break;
        }
        g_dshow.SetCurrentPos((REFTIME)pos);
        return 0;

    default:
        break;
    }
    return CallWindowProc(g_TBProc, hWnd, uMsg, wParam, lParam);
}
//(解説:ツールバーコントロールの本来のコールバック関数をかすめ取ってg_TBProcに入れ、その代わりにこのTOOLBARProcを呼ぶようにします。そしてWM_HSCROLLの処理(スライダーの位置を取得して、DirectShowの再生位置を設定する)だけして、後は本来のコールバック関数に処理を任せます。何故SB_THUMBTRACKだけ何もしないかというと、この摘みのスライドの際に出される(膨大な)通知を拾っていると(DirectShowの設定処理が遅いので)メッセージキューが一杯になるのか、プログラムが落ちてしまうらしい(未検証)ので、負荷を下げる意味でこれはDirectShowの再生位置設定の対象外としました。(現在はほぼ正常に動いています。が、乱暴に摘みを扱うと落ちることもあるので、異常値が渡されることもあるかもしれません。あー、デバッガーがあればな。)なお、このサブクラス化という手法は定番ですので覚えておいてください。)

//////////////////////////
//プレイリスト再生注フラグ
//////////////////////////
bool g_AutoPlay = FALSE;
//(解説:プレイリスト実行中の際のフラグです。)

次にDirectShowProc.hを解説します。

【DirectShowProc.h】
//////////////////////////////////////////
// DirectShowProc.h
// Copyright (c) 01/31/2022 by BCCSkelton
//////////////////////////////////////////

/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//ウィンドウメッセージ関数
/////////////////////////////////
bool CMyWnd::OnCreate(WPARAM wParam, LPARAM lParam) {

    //コモンコントロールの初期化
    InitCommonControls();

    //ツールバー登録-Init(hWnd, hIinstance, ID, (以下省略可)Style)
    TBar.Init(m_hWnd, m_hInstance, TOOLBAR);
    //ツールバーボタン用カスタムビットマップ追加
    TBar.AddBmp(m_hInstance, MAKEINTRESOURCE(IDI_TOOLBAR), 9);
    //ツールバーボタン追加
    TBBUTTON tbb[13];
    ZeroMemory(tbb, sizeof(tbb));
    tbb[0].iBitmap = TBar.m_id + 0;
    tbb[0].fsState = TBSTATE_ENABLED;
    tbb[0].fsStyle = TBSTYLE_BUTTON;
    tbb[0].idCommand = IDM_OPEN;
    tbb[1].fsStyle = TBSTYLE_SEP;    //セパレーター
    tbb[2].iBitmap = TBar.m_id + 1;
    tbb[2].fsState = TBSTATE_ENABLED;
    tbb[2].fsStyle = TBSTYLE_BUTTON;
    tbb[2].idCommand = IDM_EXIT;
    tbb[3].fsStyle = TBSTYLE_SEP;    //セパレーター
    tbb[4].iBitmap = TBar.m_id + 2;
    tbb[4].fsStyle = TBSTYLE_BUTTON;
    tbb[4].idCommand = IDM_SHOW;
    tbb[5].iBitmap = TBar.m_id + 3;
    tbb[5].fsStyle = TBSTYLE_BUTTON;
    tbb[5].idCommand = IDM_PAUSE;
    tbb[6].iBitmap = TBar.m_id + 4;
    tbb[6].fsStyle = TBSTYLE_BUTTON;
    tbb[6].idCommand = IDM_STOP;
    tbb[7].fsStyle = TBSTYLE_SEP;    //セパレーター
    tbb[8].iBitmap = TBar.m_id + 5;
    tbb[8].fsState = TBSTATE_ENABLED;
    tbb[8].fsStyle = TBSTYLE_BUTTON;
    tbb[8].idCommand = IDM_MAKELIST;
    tbb[9].iBitmap = TBar.m_id + 6;
    tbb[9].fsStyle = TBSTYLE_BUTTON;
    tbb[9].idCommand = IDM_AUTOPLAY;
    tbb[10].fsStyle = TBSTYLE_SEP;    //セパレーター
    tbb[11].iBitmap = TBar.m_id + 7;
    tbb[11].fsState = TBSTATE_ENABLED;
    tbb[11].fsStyle = TBSTYLE_BUTTON;
    tbb[11].idCommand = IDM_ABOUT;
    tbb[12].iBitmap = TBar.m_id + 8;
    tbb[12].fsState = TBSTATE_ENABLED;
    tbb[12].fsStyle = TBSTYLE_BUTTON;
    tbb[12].idCommand = IDM_VERSION;
    TBar.AddButtons(13, tbb);

    //ステータスバー登録-Init(hWnd, hIinstance, ID, (以下省略可)Style)
    SBar.Init(m_hWnd, m_hInstance, STATUSBAR);
    //ステータスバー区画設定
    int sec[3] = {120, 240, -1};
    SBar.SetSection(3, sec);
    //ステータスバー文字列設定
    SBar.SetText(0, "DirectShow Ver 1.1");
    SBar.SetText(1, "再生時間");
    SBar.SetText(2, "ファイル名");
//(解説:ここはSkeltonWizard通りです。今回はステータスバーを3区画としました。)

    //メニュー、ツールバーボタン等初期化
    ChangeMenuStatus(0);    //「再生」、「一時停止」、「中止」
    AllowtoOpen(TRUE);        //「動画ファイルを開く」、「URLから開く」
    AutoPlay(TRUE, FALSE);    //「プレイリストの作成・選択」、「プレイリストの再生」
//(解説:コメントにあるメニュー、ツールバーボタンの状態を変えます。)

    //ヘルプファイル登録
    g_HelpFile = arg.Path();
    g_HelpFile = g_HelpFile + "\\DirectShowHelp.chm";
//(解説:ヘルプファイルのパス、名を記録します。)

    //ファイルリストディレクトリーの作成
    g_FileListDir = arg.Path();
    g_FileListDir = g_FileListDir + "\\FileList";
    if(!PathFileExists(g_FileListDir.ToChar()))
        CreateDirectory(g_FileListDir.ToChar(), NULL);
//(解説:プレイリストファイルのフォールダーをプログラムの下の"FileList"フォールダーとします。)

    //再生用スライダーコントロールの作成
    g_Slider.Create(TBar.GetHandle(), IDC_SLIDER, 340, 0, 300, 24);
    ShowWindow(g_Slider.GetHandle(), SW_HIDE);    //スライダーコントロールを隠す
//(解説:スライダーコントロールは再生時にのみ表示します。)
    //スライダーの親であるツールバーのWM_HSCROLL処理を行う為のサブクラス化
    g_TBProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(m_hWnd, TOOLBAR), GWLP_WNDPROC);
    SetWindowLongPtr(GetDlgItem(m_hWnd, TOOLBAR), GWLP_WNDPROC, (LONG_PTR)TOOLBARProc);
//(解説:↑で見たように、スライダーコントロールの通知を拾うためにツールバーのコールバック関数をサブクラス化します。)

    //ドラッグアンドドロップの受付開始
    DragAcceptFiles(m_hWnd, TRUE);

    //ファイル起動時の処理
    if(arg.c() > 1) {
        if( strstr(arg.v(1), ".avi") || strstr(arg.v(1), ".AVI") ||
            strstr(arg.v(1), ".mp4") || strstr(arg.v(1), ".MP4") ||
            strstr(arg.v(1), ".mov") || strstr(arg.v(1), ".MOV") ||
            strstr(arg.v(1), ".mp3") || strstr(arg.v(1), ".MP3") ||
            strstr(arg.v(1), ".wav") || strstr(arg.v(1), ".WAV") ||
            strstr(arg.v(1), ".mid") || strstr(arg.v(1), ".MID")) {
            g_ByFile = TRUE;
            g_dshow.SetFileName(arg.v(1));
            OnOpen();
        }
        else
            MessageBox(m_hWnd, "再生対象外のファイルです", "エラー", MB_OK | MB_ICONERROR);
    }
//(解説:対象ファイル名か否かをチェックしてOnOpen関数へ渡します。ファイル起動はメディアファイルだけでplfは対象外です。)

    return TRUE;
}

bool CMyWnd::OnTimer(WPARAM wParam, LPARAM lParam) {

    int cp = (int)g_dshow.GetCurrentPos();
    char* tm = GetTimeStr(g_Mtm - cp);
    //スライダーコントロールの表示
    g_Slider.SetPosition(cp);
    //ステータスバー文字列設定
    SBar.SetText(1, tm);
    return TRUE;
}
//(解説:DirectShowの再生状態(経過時間)を取得し、スライダーの位置を変え、残再生時間を表示します。)

bool CMyWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam) {

    //一時停止(1)または再生中(2)(タイムラグ10/1000秒)
    if(g_dshow.GetState(10) == 1 || g_dshow.GetState(10) == 2) {
        OnPause();
        return TRUE;
    }
    return FALSE;
}
//(解説:マウス左ボタンをクリックするとOnPause関数を呼び、一時停止(またはその解除)になります。)

bool CMyWnd::OnRButtonDown(WPARAM wParam, LPARAM lParam) {

    //ポップアップメニューを読みこむ
    HMENU hPopupMenu = GetSubMenu(GetMenu(m_hWnd), 1);
    //ポップアップメニューの表示
    POINT pt;
    GetCursorPos(&pt);
    TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
                  pt.x, pt.y, 0, m_hWnd, NULL);
    return TRUE;
}
//(解説:マウス右ボタンをクリックすると、動画メニューがポップアップします。)

bool CMyWnd::OnNotify(WPARAM wParam, LPARAM lParam) {

    //ツールバーからのツールチップ情報取得
    if(((LPNMHDR)lParam)->code == TTN_NEEDTEXT) {
        static LPTOOLTIPTEXT lptip;
        lptip = (LPTOOLTIPTEXT)lParam;
        switch (lptip->hdr.idFrom) {
            case IDM_OPEN:
                lptip->lpszText = "動画ファイルを開く";
                break;
            case IDM_EXIT:
                lptip->lpszText = "終了";
                break;
            case IDM_SHOW:
                lptip->lpszText = "再生";
                break;
            case IDM_PAUSE:
                lptip->lpszText = "一時停止";
                break;
            case IDM_STOP:
                lptip->lpszText = "中止";
                break;
            case IDM_MAKELIST:
                lptip->lpszText = "プレイリストの作成・選択";
                break;
            case IDM_AUTOPLAY:
                lptip->lpszText = "プレイリストの再生";
                break;
            case IDM_ABOUT:
                lptip->lpszText = "DirectShowについて";
                break;
            case IDM_VERSION:
                lptip->lpszText = "バージョン情報";
                break;
        }
        return TRUE;
    }
    return FALSE;
//(解説:定番のツールバーツールチップ処理です。)
}

bool CMyWnd::OnSize(WPARAM wParam, LPARAM lParam) {

    TBar.AutoSize();
    SBar.AutoSize();
    //スライダーコントロールの自動位置調整
    g_Slider.AutoSize(1);        //右上隅にmarginxは0、marginyは2で表示
    //クライアントエリアサイズ
    int w = LOWORD(lParam);        //ウインドウ幅
    int h = HIWORD(lParam);        //ウインドウ高さ
    //TBarとSBarの高さを控除
    RECT rec;
    GetWindowRect(SBar.GetHandle(), &rec);
    h -= rec.bottom - rec.top;
    GetWindowRect(TBar.GetHandle(), &rec);
    int barh = rec.bottom - rec.top;
    h -= barh;
    g_dshow.Move(0, barh, w, h);
    return TRUE;
//(解説:ツールバー、ステータスバーの調整の後、IMVideoWindowをクライアントエリアに広げます。)
}

bool CMyWnd::OnClose(WPARAM wParam, LPARAM lParam) {

    if(MessageBox(m_hWnd, "終了しますか", "終了確認",
                    MB_YESNO | MB_ICONINFORMATION) == IDYES)
        //処理をするとDestroyWindow、PostQuitMessageが呼ばれる
        return TRUE;
    else
        //そうでなければウィンドウではDefWindowProc関数をreturn、ダイアログではreturn FALSEとなる。
        return FALSE;
}

bool CMyWnd::OnMinMax(WPARAM wParam, LPARAM lParam) {

    //典型的なウィンドウのサイズ制限処理
    MINMAXINFO *pmmi;
    pmmi = (MINMAXINFO*)lParam;
    pmmi->ptMinTrackSize.x = 656;    //クライアントエリア640 + 16
    pmmi->ptMinTrackSize.y = 541;    //クライアントエリア480 + 61
    return FALSE;                    //処理はDefWndProcに任す
}
//(解説:私の場合、最小サイズを懐かしのVGAサイズ、640 x 480にしました。)

bool CMyWnd::OnGraphNotify(WPARAM wParam, LPARAM lParam) {

    long evnt;                    //EC_COMPLETE - 再生終了、EC_USERABORT - 再生中止、EC_ERRORABORT - エラー
    if(!g_dshow.IsOver(evnt))    //再生開始前や再生中は何もしない
        return FALSE;
    //終了処理
    WhenComplete();
    //プレイリスト再生中
    if(g_AutoPlay) {
        if(*m_FileList.ToChar())    //まだ完了していない場合
            OnAutoPlay();
        else {                        //完了した場合
            g_AutoPlay = FALSE;
            AutoPlay(TRUE, FALSE);    //プレイリストの作成・選択、再生
        }
    }    
    return TRUE;
}
//(解説:これがユーザー定義通知の処理です。再生終了時(eventに終了事由が入りますが、どのような終了事由であっても今回は関係ないので使いません)のみ終了処理を行い、プレイリスト再生中はプレイリストに再生ファイルが残っている間はプレイリスト再生を続けます。)

bool CMyWnd::OnDropFiles(WPARAM wParam) {

    //ドラッグアンドドロップされたファイル名取得と処理
    char FileName[MAX_PATH];
    DragQueryFile((HDROP)wParam, 0, FileName, MAX_PATH);
    if( strstr(FileName, ".avi") || strstr(FileName, ".AVI") ||
        strstr(FileName, ".mp4") || strstr(FileName, ".MP4") ||
        strstr(FileName, ".mov") || strstr(FileName, ".MOV") ||
        strstr(FileName, ".mp3") || strstr(FileName, ".MP3") ||
        strstr(FileName, ".wav") || strstr(FileName, ".WAV") ||
        strstr(FileName, ".mid") || strstr(FileName, ".MID")) {
        g_ByFile = TRUE;
        g_dshow.SetFileName(FileName);
        OnOpen();
        DragFinish((HDROP)wParam);
        return TRUE;
    }
    MessageBox(m_hWnd, "再生対象外のファイルです", "エラー", MB_OK | MB_ICONERROR);
    return FALSE;
//(解説:定番のドラッグアンドドロップ処理です。再生対象リストか否かの処理を行っています。)
}

/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//メニュー項目、コントロール関数
/////////////////////////////////
bool CMyWnd::OnOpen() {

    if(g_ByFile)
        g_ByFile = FALSE;
    else {
        //動画ファイルを読む
        if(!g_dshow.SetFileName(""))
            return FALSE;
    }
    //メニュー、ボタンの状態変更
    ChangeMenuStatus(1);
    //ステータスバー文字列設定
    SBar.SetText(2, g_dshow.m_FileName);
    SBar.SendMsg(SB_SETTIPTEXT, 2, (LPARAM)g_dshow.m_FileName);    //ToolTipをつける
    return TRUE;
//(解説:DirectShowにメディアファイルをセットします。D&Dの場合(g_ByFile == TRUE)は既にセット済でそうでない場合は「ファイルを開く」ダイアログで指定します。)

bool CMyWnd::OnUrl() {

    urldlg.DoModal(m_hWnd, "IDD_URL", urldlgProc, m_hInstance);
    //メニュー、ボタンの状態変更
    ChangeMenuStatus(1);
    //ステータスバー文字列設定
    SBar.SetText(2, g_dshow.m_FileName);
    SBar.SendMsg(SB_SETTIPTEXT, 2, (LPARAM)g_dshow.m_FileName);    //ToolTipをつける
    return TRUE;
//(解説:DirectShowにダイアログを使ってメディアファイル(URL)パス、名をセットします。}
}

bool CMyWnd::OnExit() {

    SendMsg(WM_CLOSE, 0, 0);
    return TRUE;
//(解説:定番の終了処理です。}
}

bool CMyWnd::OnShow() {

    //再生開始
    if(g_dshow.Show(m_hWnd)) {
        g_Mtm = (int)g_dshow.GetDuration();
        char* tm = GetTimeStr(g_Mtm);
        //ステータスバー文字列設定
        SBar.SetText(1, tm);
        SBar.SendMsg(SB_SETTIPTEXT, 1, (LPARAM)tm);    //ToolTipをつける
        //メニュー、ボタンの状態変更
        ChangeMenuStatus(2);
        AllowtoOpen(FALSE);        //ファイル読み込みを不能にする
        //再生用スライダーコントロールの設定
        g_Slider.SetRange(0, (int)g_Mtm);
        g_Slider.SetPosition(0);
        //スライダーコントロールを表示する
        ShowWindow(g_Slider.GetHandle(), SW_SHOW);
        //タイマー開始(毎1秒)
        g_tmr.Begin(m_hWnd, 1, 1000);
        return TRUE;
//(解説:コメントにある通り、再生を開始し、再生時間の文字列を取得してステータスバーに表示し、ファイル読み込みを不可にして「一時停止」「中止」を有効にします。また、スライダーを表示し、その後の再生時間とスライダーの処理をタイマー割り込みに任せます。}
    }
    else
        return FALSE;
}

bool CMyWnd::OnPause() {

    static bool toggle = FALSE;
    if(toggle) {
        //再生再開(Run()メソッド)
        g_dshow.Continue();
        //メニュー、ボタンの状態変更
        ChangeMenuStatus(2);
        g_tmr.Begin(m_hWnd, 1, 1000);    //タイマー開始(毎1秒)
    }
    else {
        //再生一時停止
        g_dshow.Pause();
        //メニュー、ボタンの状態変更
        ChangeMenuStatus(3);
        g_tmr.Stop();                    //タイマー中止
    }
    toggle = !toggle;
    return TRUE;
//(解説:「一時停止」の場合、メニュー、ボタン状態を変更してタイマーを止めます。再度「一時停止」ボタンを押すと再生を再開し、メニュー、ボタン状態を再変更してタイマーを復活させます。)
}

bool CMyWnd::OnStop() {

    //再生中止
    g_dshow.Stop();
    //終了処理
    WhenComplete();
    //プレイリスト再生中
    if(g_AutoPlay) {
        if(*m_FileList.ToChar()) {        //まだ完了していない場合
            if(MessageBox(m_hWnd, "プレイリスト再生を続けますか?", "プレイリスト再生確認",
                        MB_YESNO | MB_ICONQUESTION) == IDYES)
                OnAutoPlay();
            else {                        //プレイリスト再生の中止
                m_FileList = "";
                g_AutoPlay = FALSE;
                AutoPlay(TRUE, FALSE);    //プレイリストの作成・選択、再生
            }
        }
        else {                            //完了した場合
            g_AutoPlay = FALSE;
            AutoPlay(TRUE, FALSE);        //プレイリストの作成・選択、再生
        }
    }    
    return TRUE;
//(解説:再生を中止し、終了後処理を行います。プレイリスト再生中は、まだ再生ファイルがある場合、再生を継続するか否か確認し、再生継続または完全中止にします。)
}

bool CMyWnd::OnMakelist() {

    //FileList.dllからダイアログを呼ぶ
    char* fn = GetFileList("プレイリストファイル(*.plf)\0*.plf\0\0", FILTER, g_FileListDir.ToChar());
    if(!*fn) {
        MessageBox(m_hWnd, "plfファイルが選択されませんでした", "エラー", MB_OK | MB_ICONERROR);
        return FALSE;
    }
    m_FileList.FromFile(fn);
    //プレイリストの再生メニューとツールボタンを有効化する
    AutoPlay(FALSE, TRUE);
    return TRUE;
//(解説:FileList.dllを使ってファイルリスト(プレイリスト)を作成、指定します。指定があればプレイリストをm_FileListに読み込み、「プレイリストの作成、指定」メニューを無効として、「プレイリスト再生」メニューを有効にします。)
}

bool CMyWnd::OnAutoPlay() {

    CSTR fn, comment;
    if(!m_FileList.Next(fn)) {        //ファイルリストから再生ファイルのフルパス名を切り出す
        g_AutoPlay = FALSE;
        AutoPlay(TRUE, FALSE);
    }
    else {                            //ファイルリストに再生ファイルがあったならば
        m_FileList.Next(comment);    //ファイルリストから不要な「備考」を切り出す
        //DirectShowに再生ファイルを登録
        g_dshow.SetFileName(fn.ToChar());
        //ステータスバー文字列設定
        SBar.SetText(2, g_dshow.m_FileName);
        SBar.SendMsg(SB_SETTIPTEXT, 2, (LPARAM)g_dshow.m_FileName);    //ToolTipをつける
        //プレイリストの作成・選択、再生メニューを無効化する
        AutoPlay(FALSE, FALSE);
        //プレイリスト再生状態
        g_AutoPlay = TRUE;
        //再生
        if(!OnShow())                    //プレイリストの再生に失敗した場合
            OnStop();
    }
    return TRUE;
//(解説:「プレイリスト再生」が指定されると、メニュー、ボタン状態を変更し、プレイリスト(m_FileList)が空になるまで再生を継続します。再生でエラーが生じた場合、再生を中止し、再生継続の確認をします。(ここで結構考えました。)再生ファイルが無くなればプレイリスト再生を終了します。)
}

bool CMyWnd::OnPlayList() {

    CSTR List, FileList, FileName;
    CARG arg;
    FileList = m_FileList;
    while(FileList.Next(FileName)) {
        arg = FileName.ToChar();
        List = List + arg.FileName();
        List = List + "\r\n";
        FileList.Next(FileName);        //備考をスキップする
    }
    MessageBox(m_hWnd, List.ToChar(), "プレイリスト", MB_OK | MB_ICONINFORMATION);
    return TRUE;
//(解説:m_FileListに残っている再生ファイルをメッセージボックスで表示します。)
}

bool CMyWnd::OnAbout() {

    CSTR cmd = "hh ";
    cmd = cmd + g_HelpFile;
    WinExec(cmd.ToChar(), SW_SHOWNORMAL);
    return TRUE;
//(解説:ヘルプファイルをHTMLHelpで表示します。)
}

bool CMyWnd::OnVersion() {

    versiondlg.DoModal(m_hWnd, "IDD_VERSION", versiondlgProc, m_hInstance);
    return TRUE;
//(解説:バージョンダイアログを表示します。)
}

////////////////////////////////////////////////////////
//ユーザー定義関数
//スライダー非表示とタイマー、再生時間メニュー等の初期化
////////////////////////////////////////////////////////
void CMyWnd::WhenComplete() {

    //タイマー中止
    g_tmr.Stop();
    //再生時間の初期化
    g_Mtm = 0;
    //スライダーコントロールを隠す
    ShowWindow(g_Slider.GetHandle(), SW_HIDE);
    //再生終了後、ファイル読み込み後状態にする(再生可)
    ChangeMenuStatus(1);
    //ファイル読み込みを可能にする
    AllowtoOpen(TRUE);
//(解説:ファイル毎の終了処理です。)
}

///////////////////////////////////////////////////
//ユーザー定義関数
//初期状態・終了時0
//ファイル読込み時1、再生時2、一時停止時3(トグル)
///////////////////////////////////////////////////
void CMyWnd::ChangeMenuStatus(int flag) {

    HMENU hMenu = GetSubMenu(GetMenu(m_hWnd), 1);    //メニューハンドルの取得
    switch(flag) {
    case 0:        //全て無効化する
        //メニューアイテム
        EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_GRAYED);
        EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_GRAYED);
        EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);
        //ツールバーボタン
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SHOW, MAKELONG(FALSE, 0));
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_PAUSE, MAKELONG(FALSE, 0));
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_STOP, MAKELONG(FALSE, 0));
        break;
    case 1:        //再生のみ有効化する
        //メニューアイテム
        EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_ENABLED);
        EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_GRAYED);
        EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);
        //ツールバーボタン
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SHOW, MAKELONG(TRUE, 0));
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_PAUSE, MAKELONG(FALSE, 0));
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_STOP, MAKELONG(FALSE, 0));
        break;
    case 2:        //再生を無効化し、一時停止、中止を有効化する
        //メニューアイテム
        EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_GRAYED);
        EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_ENABLED);
        EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);
        //ツールバーボタン
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SHOW, MAKELONG(FALSE, 0));
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_PAUSE, MAKELONG(TRUE, 0));
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_STOP, MAKELONG(TRUE, 0));
        break;
    case 3:        //再生、中止を共に無効化する
        //メニューアイテム
        EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_GRAYED);
        EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);
        //ツールバーボタン
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SHOW, MAKELONG(FALSE, 0));
        SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_STOP, MAKELONG(FALSE, 0));
        break;
    default:
        return;
    }
    DrawMenuBar(m_hWnd);    //Re-draw
//(解説:「再生」、「一時停止」、「中止」のメニュー、ボタンの状態を変化させます。)
}

/////////////////////////////////////////////////////
//ユーザー定義関数
//「ファイルを開く」と「URLから開く」の状態を変更する
/////////////////////////////////////////////////////
void CMyWnd::AllowtoOpen(bool flag) {

    HMENU hMenu = GetSubMenu(GetMenu(m_hWnd), 0);    //メニューハンドルの取得
    //メニューアイテム
    EnableMenuItem(hMenu, 0, MF_BYPOSITION | (flag ? MF_ENABLED : MF_GRAYED));
    EnableMenuItem(hMenu, 1, MF_BYPOSITION | (flag ? MF_ENABLED : MF_GRAYED));
    //ツールバーボタン
    SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_OPEN, MAKELONG(flag, 0));
    SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_URL, MAKELONG(flag, 0));
//(解説:「動画ファイルを開く」、「URLから開く」のメニュー、ボタンの状態を変化させます。)
}

//////////////////////////////////////////////////////////////////////
//ユーザー定義関数
//「プレイリストの作成・選択」と「プレイリストの再生」の状態を変更する
//////////////////////////////////////////////////////////////////////
void CMyWnd::AutoPlay(bool flag1, bool flag2) {

    HMENU hMenu = GetSubMenu(GetMenu(m_hWnd), 2);    //メニューハンドルの取得
    //メニューアイテム
    EnableMenuItem(hMenu, 0, MF_BYPOSITION | (flag1 ? MF_ENABLED : MF_GRAYED));
    EnableMenuItem(hMenu, 1, MF_BYPOSITION | (flag2 ? MF_ENABLED : MF_GRAYED));
    //ツールバーボタン
    SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_MAKELIST, MAKELONG(flag1, 0));
    SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_AUTOPLAY, MAKELONG(flag2, 0));
//(解説:プレイリストの「プレイリストの作成・選択」と「プレイリスト再生」のメニュー、ボタンの状態を変化させます。)
}

////////////////////////////////////////////
//ユーザー定義関数
//整数の秒数を「時間分秒」の文字列にして返す
////////////////////////////////////////////
char* CMyWnd::GetTimeStr(int tm) {

    static CSTR tmstr;
    int hour, min, sec;
    hour = tm / 3600;
    min = sec = tm % 3600;
    min /= 60;
    sec %= 60;
    tmstr = "残り";
    if(hour) {
        tmstr = tmstr + hour;
        tmstr = tmstr + "時間";
    }
    tmstr = tmstr + min + "分";
    tmstr = tmstr + sec + "秒";
    return tmstr.ToChar();
//(解説:整数の秒を「残り(H時間)M分S秒」形式の文字列にして返します。)
}

///////////////////////////////
//ユーザーダイアログの関数定義
//コントロール関数
///////////////////////////////
bool URLDLG::OnIdok() {

    char buff[MAX_PATH];
    SendItemMsg(IDC_URL, WM_GETTEXT, MAX_PATH, (LPARAM)buff);
    if(g_dshow.SetFileName(buff)) {
        EndModal(TRUE);
        return TRUE;
    }
    else {
        EndModal(FALSE);
        return FALSE;
    }
//(解説:エディットボックスに入力された文字列をDirectShowにファイル名としてセットします。手を抜いて、入力文字列のエラーチェックはしていません。)
}

bool URLDLG::OnCancel() {

    EndModal(FALSE);
    return FALSE;
}

///////////////////////////////
//ユーザーダイアログの関数定義
//コントロール関数
///////////////////////////////
bool VERSIONDLG::OnIdok() {

    EndModal(TRUE);
    return TRUE;
//(解説:バージョンダイアログを閉じるだけです。)
}

以上でDirectShow Version 1.1のプログラム解説を終わります。次回はバッチファイルと開発後記にしようと思います。