Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
[Funkcja skojarzona z tą stroną, DirectShow, jest starszą funkcją. Został zastąpiony przez MediaPlayer, IMFMediaEngineoraz Audio/Video Capture w Media Foundation. Te funkcje zostały zoptymalizowane pod kątem systemów Windows 10 i Windows 11. Firma Microsoft zdecydowanie zaleca, aby nowy kod używał MediaPlayer, IMFMediaEngine i Audio/Video Capture w programie Media Foundation zamiast DirectShow, jeśli to możliwe. Firma Microsoft sugeruje, że istniejący kod, który używa starszych interfejsów API, należy przepisać go do korzystania z nowych interfejsów API, jeśli to możliwe.]
Aby przetworzyć zdarzenia DirectShow, aplikacja potrzebuje sposobu, aby się dowiedzieć, kiedy zdarzenia są w kolejce. Menedżer filtrów programu Graph udostępnia dwa sposoby wykonania tego zadania:
- Powiadomienie Okna: Menedżer Grafu Filtrów wysyła komunikat Windows zdefiniowany przez użytkownika do okna aplikacji przy każdym nowym zdarzeniu.
- Sygnalizowanie zdarzeń: Menedżer Grafów Filtrów sygnalizuje zdarzenie systemu Windows, jeśli w kolejce znajdują się zdarzenia DirectShow, i resetuje zdarzenie, jeśli kolejka jest pusta.
Aplikacja może użyć jednej z tych technik. Powiadomienie o oknie jest zwykle prostsze.
Powiadomienie okna
Aby skonfigurować powiadomienie o oknie, wywołaj metodę IMediaEventEx::SetNotifyWindow i określ wiadomość prywatną. Aplikacje mogą używać numerów wiadomości w zakresie od WM_APP do 0xBFFF jako wiadomości prywatnych. Za każdym razem, gdy Menedżer filtrów programu Graph umieszcza nowe powiadomienie o zdarzeniu w kolejce, publikuje ten komunikat w wyznaczonym oknie. Aplikacja odpowiada na komunikat z poziomu pętli komunikatów okna.
Poniższy przykład kodu pokazuje, jak ustawić okno powiadomień.
#define WM_GRAPHNOTIFY WM_APP + 1 // Private message.
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
Komunikat jest zwykłym komunikatem systemu Windows i jest publikowany oddzielnie od kolejki powiadomień o zdarzeniach DirectShow. Zaletą tego podejścia jest to, że większość aplikacji już implementuje pętlę komunikatów. W związku z tym można włączyć obsługę zdarzeń DirectShow bez dodatkowej pracy.
Poniższy przykład kodu przedstawia konspekt sposobu reagowania na wiadomość z powiadomieniem. Aby uzyskać pełny przykład, zobacz Odpowiadanie na zdarzenia.
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));
}
Ponieważ powiadomienia o zdarzeniach i pętla komunikatów są asynchroniczne, kolejka może zawierać więcej niż jedno zdarzenie o czasie, gdy aplikacja odpowie na komunikat. Zdarza się też, że zdarzenia mogą być usunięte z kolejki, jeśli staną się nieprawidłowe. W związku z tym w kodzie obsługi zdarzeń wywołaj metodę IAMMediaEvent::GetEvent, aż zwróci kod niepowodzenia, co oznacza, że kolejka jest pusta.
Przed zwolnieniem wskaźnika IMediaEventEx anuluj powiadomienie o zdarzeniu, wywołując SetNotifyWindow za pomocą wskaźnika o wartości null NULL. W swoim kodzie do przetwarzania zdarzeń sprawdź, czy wskaźnik IMediaEventEx jest prawidłowy przed wywołaniem GetEvent. Te kroki zapobiegają potencjalnemu błędowi, w którym aplikacja odbiera powiadomienie o zdarzeniu po wydaniu wskaźnika IMediaEventEx.
Sygnalizacja zdarzeń
Menedżer programu Filter Graph zachowuje zdarzenie resetowania ręcznego, które odzwierciedla stan kolejki zdarzeń. Jeśli kolejka zawiera oczekujące powiadomienia o zdarzeniach, program Filter Graph Manager sygnalizuje zdarzenie resetowania ręcznego. Jeśli kolejka jest pusta, wywołanie metody IMediaEvent::GetEvent spowoduje zresetowanie zdarzenia. Aplikacja może użyć tego zdarzenia do określenia stanu kolejki.
Notatka
Terminologia może być tu myląca. Zdarzenie resetowania ręcznego jest typem zdarzenia utworzonego przez funkcjęCreateEvent systemu Windows. nie ma to nic wspólnego ze zdarzeniami zdefiniowanymi przez DirectShow.
Wywołaj metodę IMediaEvent::GetEventHandle, aby uzyskać dojście do zdarzenia resetowania ręcznego. Poczekaj na zasygnalizowanie zdarzenia przez wywołanie funkcji, takiej jak WaitForMultipleObjects. Gdy zdarzenie zostanie zasygnalizowane, wywołaj IMediaEvent::GetEvent, aby pobrać zdarzenie DirectShow.
Poniższy przykład kodu ilustruje to podejście. Pobiera uchwyt zdarzenia, a następnie czeka w 100-milisekundowych interwałach na sygnalizację zdarzenia. Jeśli zdarzenie jest zasygnalizowane, wywołuje GetEvent i wyświetla kod zdarzenia i parametry zdarzenia w oknie konsoli. Pętla kończy się po wystąpieniu zdarzenia EC_COMPLETE wskazującym, że odtwarzanie zostało ukończone.
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, ¶m1, ¶m2, 0))
{
printf("Event code: %#04x\n Params: %d, %d\n", evCode, param1, param2);
pEvent->FreeEventParams(evCode, param1, param2);
bDone = (EC_COMPLETE == evCode);
}
}
}
Ponieważ wykres filtru automatycznie ustawia lub resetuje zdarzenie, jeśli jest to konieczne, aplikacja nie powinna tego robić. Ponadto, po zwolnieniu wykresu filtru, zamyka on uchwyt zdarzenia, więc nie należy go używać do tego momentu.