共用方式為


步驟 6:處理圖形事件

[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、imfMediaEngine 取代,並在媒體基金會 音訊/視訊擷取。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayerIMFMediaEngine 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]

本主題是 DirectShow 音訊/視訊播放教學課程的步驟 6。 完整的程式代碼會顯示在 DirectShow 播放範例 主題中,

當應用程式建立 Filter Graph Manager 的新實例時,應用程式會呼叫 IMediaEventEx::SetNotifyWindow。 這個方法會註冊應用程式視窗,以從篩選圖形接收事件。

    hr = m_pGraph->QueryInterface(IID_PPV_ARGS(&m_pEvent));
    if (FAILED(hr))
    {
        goto done;
    }

    // Set up event notification.
    hr = m_pEvent->SetNotifyWindow((OAHWND)m_hwnd, WM_GRAPH_EVENT, NULL);
    if (FAILED(hr))
    {
        goto done;
    }

WM_GRAPH_EVENT 值是私人視窗訊息。 每當應用程式收到此訊息時,就會呼叫 DShowPlayer::HandleGraphEvent 方法。

    case WM_GRAPH_EVENT:
       g_pPlayer->HandleGraphEvent(OnGraphEvent);
       return 0;

DShowPlayer::HandleGraphEvent 方法會執行下列動作:

  1. 在迴圈中呼叫 IMediaEvent::GetEvent,以取得所有佇列事件。
  2. 叫用回呼函式 (pfnOnGraphEvent)。
  3. IMediaEvent::FreeEventParams 來釋放與每個事件相關聯的數據。
// Respond to a graph event.
//
// The owning window should call this method when it receives the window
// message that the application specified when it called SetEventWindow.
//
// Caution: Do not tear down the graph from inside the callback.

HRESULT DShowPlayer::HandleGraphEvent(GraphEventFN pfnOnGraphEvent)
{
    if (!m_pEvent)
    {
        return E_UNEXPECTED;
    }

    long evCode = 0;
    LONG_PTR param1 = 0, param2 = 0;

    HRESULT hr = S_OK;

    // Get the events from the queue.
    while (SUCCEEDED(m_pEvent->GetEvent(&evCode, &param1, &param2, 0)))
    {
        // Invoke the callback.
        pfnOnGraphEvent(m_hwnd, evCode, param1, param2);

        // Free the event data.
        hr = m_pEvent->FreeEventParams(evCode, param1, param2);
        if (FAILED(hr))
        {
            break;
        }
    }
    return hr;
}

下列程式代碼顯示傳遞至 DShowPlayer::HandleGraphEvent的回呼函式。 函式會處理圖形事件數目下限 (EC_COMPLETEEC_ERRORABORTEC_USERABORT] 。您可以展開 函式來處理其他事件。

void CALLBACK OnGraphEvent(HWND hwnd, long evCode, LONG_PTR param1, LONG_PTR param2)
{
    switch (evCode)
    {
    case EC_COMPLETE:
    case EC_USERABORT:
        g_pPlayer->Stop();
        break;

    case EC_ERRORABORT:
        NotifyError(hwnd, L"Playback error.");
        g_pPlayer->Stop();
        break;
    }
}

DirectShow 中進行 音訊/視訊播放

DirectShow 播放範例

DirectShow 中的 事件通知

回應事件