Important:
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.
A version of this page is also available for
4/8/2010

In addition to retrieving event notifications from the queue, as discussed in Retrieving Events, an application needs a way to find out when events are waiting in the queue. The Filter Graph Manager provides two ways to do this.

  • Using window notification, the Filter Graph Manager sends a Windows message to an application window whenever there is a new event.

  • Using event handles, the application retrieves a handle to a Windows manual-reset event. The Filter Graph Manager signals the manual-reset event when there are event notifications in the queue and resets it when the queue is empty.

The following sections describe each technique.

Window Notification

To set up window notification, call the IMediaEventEx::SetNotifyWindowmethod and specify a private message. Applications can use message numbers in the range from WM_APP through 0xBFFF as private messages. Whenever the Filter Graph Manager places a new event notification in the queue, it posts this message to the designated window. The application responds to the message from within the window's message loop.

The following code example shows how to set the notification window.

Copy Code
#define WM_GRAPHNOTIFY WM_APP + 1   // Private message.

pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);

The message is an ordinary Windows message, and is posted separately from the DirectShow event notification queue. The advantage of this approach is that most applications already implement a message loop. Therefore, you can incorporate DirectShow event handling without much additional work.

The following code example shows an outline of how to respond to the notification message. For a complete example, see Responding to Events.

Copy Code
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));
}

Because event notification and the message loop are both asynchronous, the queue might contain more than one event by the time your application responds to the message. Also, events can sometimes be cleared from the queue if they become invalid. Therefore, in your event handling code, call GetEventuntil it returns a failure code, indicating that the queue is empty.

Event Handles

The filter graph keeps a manual-reset event that reflects the state of the event queue. If the queue contains pending event notifications, the filter graph signals the manual-reset event. If the queue is empty, a call to the IMediaEvent::GetEventmethod resets the event. An application can use this event to determine the state of the queue.

Note:
The terminology can be confusing here. The manual-reset event is the type of event created by the Windows CreateEventfunction; it has nothing to do with the event notifications defined by DirectShow.

The IMediaEvent::GetEventHandlemethod retrieves a handle to the manual-reset event. Wait for the event to be signaled by calling a function such as WaitForMultipleObjects. Once the event is signaled, call the IMediaEvent::GetEventmethod to retrieve the event notification.

The following code example illustrates this approach. It retrieves the event handle, then waits in 100-millisecond intervals for the event to be signaled. If the event is signaled, it calls GetEventand prints the event code and event parameters to the console window. The loop terminates when the EC_USERABORTevent occurs, indicating that the user has interrupted playback. This example uses the DirectShow CAMEventclass, a helper class that represents a manual-reset or automatic-reset event. The CAMEvent::Waitmethod waits until the event is signaled or a specified timeout elapses.

Copy Code
CAMEvent hEvent;
long evCode, param1, param2;
BOOLEAN bDone = FALSE;

HRESULT hr = pEvent->GetEventHandle((OAEVENT*)&hEvent);

while(!bDone) {
	if (hEvent.Wait(100)) {
		if (hr = pEvent->GetEvent(&evCode, &param1,
&param2, 0), SUCCEEDED(hr)) {
			printf("Event code: %#04x\n\tParams: %d, %d\n", evCode,
param1, param2);
			hr = pEvent->FreeEventParams(evCode, param1,
param2);
			bDone = ((EC_COMPLETE == evCode) || (EC_USERABORT ==
evCode));
	}
}
} 

Because the filter graph automatically sets or resets the event when appropriate, your application should not do so. Also, when you release the filter graph, the filter graph closes the event handle, so do not use the event handle after that point.

See Also