[DirectShow] 019 - Learning When an Event Occurs

来源:互联网 发布:数据采集传输系统 编辑:程序博客网 时间:2024/06/06 09:34

To process DirectShow events, an application needs a way to find out whenevents are waiting in the queue. The Filter Graph Manager provides two ways todo this:

·        Window notification: The Filter Graph Manager sends a user-defined Windows message to anapplication window whenever there is a new event.

·        Event signaling: The Filter Graph Manager signals a Windows event if there are DirectShowevents in the queue, and reset the event if the queue is empty.

An application can use either technique. Window notification is usuallysimpler.

为了处理DirectShow事件,应用程序需要一种方法发现什么时候事件等待在队列中。Filter Graph Manager 提供两种方式:

·        Window notification: 每当有新的事件的时候,Filter Graph Manager就发送一个用户自定义的Windows消息给应用程序窗口。

·        Event signaling: 如果队列中有DirectShow事件,Filter Graph Manager 就激发一个windows事件,并在队列为空的时候使事件为非激发状态。。

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

调用ImediaEventEx::SetNotifyWindow方法并指定私有消息来建立window notification。应用程序可以使用WM_APP0XBFFF之间的消息值作为私有消息。只要Filter Graph Manager把一个新的事件通知放到队列中,它就发送这个消息到指定的窗口。应用程序在窗口消息循环中响应。

The following code example shows how to set the notificationwindow.

下面代码显示如何设置通知窗口。

#defineWM_GRAPHNOTIFY WM_APP + 1   // Privatemessage.

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

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

消息是普通的windows消息。这种方法的好处就是大部分的应用程序早已实现了消息循环。因此,不需要附加太多的工作就能包含DirectShow的事件处理。

The following code example shows an outline of how to respond tothe notification message

接下来的代码显示了如何响应通知消息。

LRESULTCALLBACK WindowProc( HWND hwnd, UINT msg, UINT wParam, LONG lParam)

{

    switch (msg)

    {

        case WM_GRAPHNOTIFY:

            HandleEvent();  // Application-defined function.

            break;

        // Handle other Windows messages heretoo.

    }

    return (DefWindowProc(hwnd, msg, wParam,lParam));

}

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

因为事件通知和消息循环是异步的,所以在应用程序响应消息的时候,队列中可能包含不止一个事件。如果事件变的无效,那可能会从队列中清除。因此,在事件处理代码中,一直调用GetEvent直到这个函数返回失败代码为止,这表明队列为空了。

Before you release the IMediaEventEx pointer, cancel eventnotification by calling SetNotifyWindow with a NULL pointer. In yourevent processing code, check whether your IMediaEventEx pointer is validbefore calling GetEvent. These steps prevent a possible error, in whichthe application receives the event notification after it has released the IMediaEventExpointer.

在释放IMediaEventEx指针之前,调用SetNotifyWindow函数,传递一个NULL指针取消事件通知。在事件处理代码中,调用GetEvent之前判断IMediaEventEx指针是否有效。这些步骤尽可能的避免了当IMediaEventEx指针被释放以后应用程序接到通知事件的错误。

The Filter Graph Manager keeps a manual-reset event that reflectsthe state of the event queue. If the queue contains pending eventnotifications, the Filter Graph Manager signals the manual-reset event. If thequeue is empty, a call to the IMediaEvent::GetEvent method resets theevent. An application can use this event to determine the state of the queue.

Filter Graph Manager 保存一个手动复位的事件,这个事件反映事件队列的状态。如果队列中包含未处理的事件通知,,Filter Graph Manager 激发这个手动复位的事件。如果队列为空,调用IMediaEvent::GetEvent方法复位事件。应用程序可以使用这个事件决定队列的状态。

Call the IMediaEvent::GetEventHandlemethod to retrieve a handle to the manual-reset event. Wait for the event to besignaled by calling a function such as WaitForMultipleObjects. Once theevent is signaled, call IMediaEvent::GetEvent to retrieve the DirectShowevent.

调用IMediaEvent::GetEventHandle方法获得手动复位事件的句柄。调用类似WaitForMultipleObjects的函数等待事件被激发。一旦事件被激发,立刻调用IMediaEvent::GetEvent获得DirectShow 事件。

The following code example illustrates this approach. It retrievesthe event handle, then waits in 100-millisecond intervals for the event to besignaled. If the event is signaled, it calls GetEvent and prints theevent code and event parameters to the console window. The loop terminates whenthe EC_COMPLETEevent occurs, indicating that playback has completed.

接下来的代码说明了这个方法。他获得一个事件句柄,然后在100毫秒的时间间隔内等待事件被激发。如果事件被激发,就调用GetEvent并通过控制台窗口打印出事件代码和参数。当发生EC_COMPLETE事件时循环结束,表明回放完成。

HANDLE  hEvent;

long    evCode, param1, param2;

BOOLEANbDone = FALSE;

HRESULThr = 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 (hr =pEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(hr))

        {

            printf("Event code: %#04x/nParams: %d, %d/n", evCode, param1, param2);

            pEvent->FreeEventParams(evCode,param1, param2);

            bDone = (EC_COMPLETE == evCode);

        }

    }

}

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

因为filter graph会在适当的时候自动激发或复位事件,所以应用程序不用关心。当应用程序释放filtergraph之后,filtergraph会关闭事件句柄,在这之后不要再使用事件句柄做任何事。

 

 

 

 

 

 

原创粉丝点击