Apprendimento quando si verifica un evento

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Per elaborare gli eventi DirectShow, un'applicazione deve essere in grado di individuare quando gli eventi sono in attesa nella coda. Filter Graph Manager offre due modi per eseguire questa operazione:

  • Notifica finestra: Filter Graph Manager invia un messaggio windows definito dall'utente a una finestra dell'applicazione ogni volta che è presente un nuovo evento.
  • Segnalazione di eventi: Filter Graph Manager segnala un evento di Windows se sono presenti eventi DirectShow nella coda e reimposta l'evento se la coda è vuota.

Un'applicazione può usare entrambe le tecniche. La notifica della finestra è in genere più semplice.

Notifica finestra

Per configurare la notifica della finestra, chiamare il metodo IMediaEventEx::SetNotifyWindow e specificare un messaggio privato. Le applicazioni possono usare numeri di messaggio nell'intervallo tra WM_APP e 0xBFFF come messaggi privati. Ogni volta che Filter Graph Manager inserisce una nuova notifica degli eventi nella coda, invia questo messaggio alla finestra designata. L'applicazione risponde al messaggio dall'interno del ciclo di messaggi della finestra.

Nell'esempio di codice seguente viene illustrato come impostare la finestra di notifica.

#define WM_GRAPHNOTIFY WM_APP + 1   // Private message.
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);

Il messaggio è un normale messaggio di Windows e viene pubblicato separatamente dalla coda di notifica degli eventi DirectShow. Il vantaggio di questo approccio è che la maggior parte delle applicazioni implementa già un ciclo di messaggi. Pertanto, è possibile incorporare la gestione degli eventi DirectShow senza molto lavoro aggiuntivo.

Nell'esempio di codice seguente viene illustrato come rispondere al messaggio di notifica. Per un esempio completo, vedere Risposta agli eventi.

LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
    switch (msg)
    {
        case WM_GRAPHNOTIFY:
            HandleEvent();  // Application-defined function.
            break;
        // Handle other Windows messages here too.
    }
    return (DefWindowProc(hwnd, msg, wParam, lParam));
}

Poiché la notifica degli eventi e il ciclo di messaggi sono entrambi asincroni, la coda potrebbe contenere più di un evento al momento in cui l'applicazione risponde al messaggio. Inoltre, gli eventi possono talvolta essere cancellati dalla coda se diventano non validi. Pertanto, nel codice di gestione degli eventi chiamare IAMMediaEvent::GetEvent fino a quando non restituisce un codice di errore, a indicare che la coda è vuota.

Prima di rilasciare il puntatore IMediaEventEx , annullare la notifica degli eventi chiamando SetNotifyWindow con un puntatore NULL . Nel codice di elaborazione eventi verificare se il puntatore IMediaEventEx è valido prima di chiamare GetEvent. Questi passaggi impediscono un possibile errore, in cui l'applicazione riceve la notifica degli eventi dopo il rilascio del puntatore IMediaEventEx .

Segnalazione di eventi

Filter Graph Manager mantiene un evento di reimpostazione manuale che riflette lo stato della coda di eventi. Se la coda contiene notifiche di evento in sospeso, Filter Graph Manager segnala l'evento di reimpostazione manuale. Se la coda è vuota, una chiamata al metodo IMediaEvent::GetEvent reimposta l'evento. Un'applicazione può usare questo evento per determinare lo stato della coda.

Nota

La terminologia può confondere qui. L'evento di reimpostazione manuale è il tipo di evento creato dalla funzione CreateEvent di Windows; non ha nulla a che fare con gli eventi definiti da DirectShow.

 

Chiamare il metodo IMediaEvent::GetEventHandle per ottenere un handle per l'evento di reimpostazione manuale. Attendere che l'evento venga segnalato chiamando una funzione, ad esempio WaitForMultipleObjects. Dopo aver segnalato l'evento, chiama IMediaEvent::GetEvent per ottenere l'evento DirectShow.

Il seguente esempio di codice illustra questo approccio. Ottiene l'handle dell'evento, quindi attende in intervalli di 100 millisecondi per segnalare l'evento. Se l'evento viene segnalato, chiama GetEvent e stampa il codice evento e i parametri dell'evento nella finestra della console. Il ciclo termina quando si verifica l'evento EC_COMPLETE , a indicare che la riproduzione è stata completata.

HANDLE  hEvent; 
long    evCode, param1, param2;
BOOLEAN bDone = FALSE;
HRESULT hr = S_OK;
hr = pEvent->GetEventHandle((OAEVENT*)&hEvent);
if (FAILED(hr))
{
    /* Insert failure-handling code here. */
}

while(!bDone) 
{
    if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 100))
    { 
        while (S_OK == pEvent->GetEvent(&evCode, &param1, &param2, 0)) 
        {
            printf("Event code: %#04x\n Params: %d, %d\n", evCode, param1, param2);
            pEvent->FreeEventParams(evCode, param1, param2);
            bDone = (EC_COMPLETE == evCode);
        }
    }
} 

Poiché il grafico del filtro imposta o reimposta automaticamente l'evento quando appropriato, l'applicazione non deve farlo. Inoltre, quando si rilascia il grafico del filtro, il grafico del filtro chiude l'handle eventi, quindi non usare l'handle di evento dopo tale punto.