Dela via


Svara på händelser

[Funktionen som är associerad med den här sidan, DirectShow, är en äldre funktion. Det har ersatts av MediaPlayer, IMFMediaEngineoch Audio / Video Capture i Media Foundation. Dessa funktioner har optimerats för Windows 10 och Windows 11. Microsoft rekommenderar starkt att ny kod använder MediaPlayer, IMFMediaEngine och Audio/Video Capture i Media Foundation i stället för DirectShow, när det är möjligt. Microsoft föreslår att befintlig kod som använder äldre API:er skrivs om för att använda de nya API:erna om möjligt.]

Den här artikeln beskriver hur du svarar på händelser som inträffar i ett filterdiagram.

Så här fungerar händelsemeddelande

När ett DirectShow-program körs kan händelser inträffa i filterdiagrammet. Ett filter kan till exempel stöta på ett strömningsfel. Filter varnar Filter Graph Manager genom att skicka händelser, som består av en händelsekod och två händelseparametrar. Händelsekoden anger typen av händelse och händelseparametrarna anger ytterligare information. Innebörden av parametrarna beror på händelsekoden. En fullständig lista över händelsekoder finns i Händelsemeddelandekoder.

Vissa händelser hanteras tyst av Filter Graph Manager, utan att programmet meddelas. Andra händelser placeras i en kö för applikationen. Beroende på programmet finns det olika händelser som du kan behöva hantera. Den här artikeln fokuserar på tre händelser som är mycket vanliga:

  • Händelsen EC_COMPLETE anger att uppspelningen har slutförts normalt.
  • Händelsen EC_USERABORT anger att användaren har avbrutit uppspelningen. Videoåtergivningar skickar den här händelsen om användaren stänger videofönstret.
  • Händelsen EC_ERRORABORT anger att ett fel har gjort att uppspelningen har stoppats.

Använda händelsemeddelande

Ett program kan instruera Filter Graph Manager att skicka ett Windows-meddelande till ett angivet fönster när en ny händelse inträffar. På så sätt kan programmet svara i fönstrets meddelandeloop. Definiera först det meddelande som ska skickas till programfönstret. Program kan använda meddelandenummer i intervallet från WM_APP till 0xBFFF som privata meddelanden:

#define WM_GRAPHNOTIFY  WM_APP + 1

Fråga sedan Filter Graph Manager efter IMediaEventEx--gränssnittet och anropa metoden IMediaEventEx::SetNotifyWindow:

IMediaEventEx *g_pEvent = NULL;
g_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&g_pEvent);
g_pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);

Den här metoden anger det angivna fönstret (g_hwnd) som mottagare av meddelandet. Anropa metoden när du har skapat filterdiagrammet, men innan du kör diagrammet.

WM_GRAPHNOTIFY är ett vanligt Windows-meddelande. När Filter Graph Manager placerar en ny händelse i händelsekön skickar den ett WM_GRAPHNOTIFY meddelande till det avsedda programfönstret. Meddelandets parameter lParam är lika med den tredje parametern i SetNotifyWindow. Med den här parametern kan du skicka instansdata med meddelandet. Fönstermeddelandets wParam-parametern är alltid noll.

Lägg till en case-sats för WM_GRAPHNOTIFY-meddelandet i din applikations WindowProc-funktion.

case WM_GRAPHNOTIFY:
    HandleGraphEvent();
    break;

I händelsehanterarfunktionen anropar du metoden IMediaEvent::GetEvent för att hämta händelser från kön:

void HandleGraphEvent()
{
    // Disregard if we don't have an IMediaEventEx pointer.
    if (g_pEvent == NULL)
    {
        return;
    }
    // Get all the events
    long evCode;
    LONG_PTR param1, param2;
    HRESULT hr;
    while (SUCCEEDED(g_pEvent->GetEvent(&evCode, &param1, &param2, 0)))
    {
        g_pEvent->FreeEventParams(evCode, param1, param2);
        switch (evCode)
        {
        case EC_COMPLETE:  // Fall through.
        case EC_USERABORT: // Fall through.
        case EC_ERRORABORT:
            CleanUp();
            PostQuitMessage(0);
            return;
        }
    } 
}

Metoden GetEvent hämtar händelsekoden och de två händelseparametrarna. Den fjärde parametern GetEvent anger hur lång tid det tar att vänta på en händelse i millisekunder. Eftersom programmet anropar den här metoden som svar på ett WM_GRAPHNOTIFY meddelande, är händelsen redan i kö. Därför anger vi timeout-värdet till noll.

Händelsemeddelandet och meddelandeloopen är båda asynkrona, så kön kan innehålla mer än en händelse när programmet svarar på meddelandet. Filter Graph Manager kan också ta bort vissa händelser från kön om de blir ogiltiga. Därför bör du anropa GetEvent- tills den returnerar en felkod som anger att kön är tom.

I det här exemplet svarar programmet på EC_COMPLETE, EC_USERABORToch EC_ERRORABORT genom att anropa den programdefinierade CleanUp-funktionen, vilket gör att programmet avslutas korrekt. Exemplet ignorerar de två händelseparametrarna. När du har hämtat en händelse anropar du IMediaEvent::FreeEventParams till eventuella kostnadsfria resurser som är associerade med händelseparametrarna.

Observera att en EC_COMPLETE händelse inte gör att filterdiagrammet stoppas. Programmet kan antingen stoppa eller pausa diagrammet. Om du stoppar diagrammet frigör filter alla resurser som de håller i. Om du pausar diagrammet fortsätter filtren att innehålla resurser. När en videoåtergivning pausar visas dessutom en statisk bild av den senaste ramen.

Innan du släpper pekaren IMediaEventEx avbryter du händelsemeddelandet genom att anropa SetNotifyWindow med ett NULL--fönsterhandtag:

// Disable event notification before releasing the graph.
g_pEvent->SetNotifyWindow(NULL, 0, 0);
g_pEvent->Release();
g_pEvent = NULL;

I WM_GRAPHNOTIFY-meddelandehanteraren kontrollerar du pekaren IMediaEventEx innan du anropar GetEvent:

if (g_pEvent == NULL) return;

Detta förhindrar ett möjligt fel som kan inträffa om programmet tar emot händelsemeddelandet när pekaren har släppts.

Grundläggande DirectShow-uppgifter

Händelsemeddelande i DirectShow