事件提示是怎么工作的呢,如下
filters 报警通知filter graph manager是通过发送事件实现,被发送的事件由一个事件代码和两个事件参数组成。事件代码表示了事件的类型,而params 表示了其他信息。一些事件被filter manager graph 安静地处理了,用不着程序notify; 而其他的一些事件被放到程序的消息队列中,
以下介绍3中常见的事件类型:
*. EC_COMPLETE 事件
*. EC_USERABORT事件 ,表示用户中断了播放;
*. EC_ERRORABORT事件,表示一个错误的发生导致回放失败;
调用事件提示机制
1.首先定义将要被发送到程序窗口的消息,
#define WM_GRAPHNOTIFY WM_APP+1
2.接着访问IMediaEventEx接口通过filter graph manager ,调用IMediaEventEx::SetNotifyWindow方法,绑定消息的接收窗口。当filter graph manager 放置一条新的事件到事件队列中的时候,filter graph manager同时也会post一条WM_GRAPHNOTIY消息给指定的程序窗口
IMediaEventEx *g_pEvent = NULL;
g_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&g_pEvent); //主角登场
g_pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
本段操作应在filter graph manager 创建之后,在运行graph之前;
3.在程序的WindowProc函数中,添加case语句来响应WM_GRAPHNOTIFY消息的到来
case WM_GRAPHNOTIFY:
HandleGraphEvent();
break;
以下是HandleGraphEvent()函数的定义:当消息到来后,调用IMediaEvent::GetEvent方法来检索事件从队列中。
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; // time to wait
while (SUCCEEDED(g_pEvent->GetEvent(&evCode, ¶m1, ¶m2, 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;
}
}
}
事件通知和消息循环是异步进行的
4.取消事件通知,通过调用SetNotifyWindow 并设置NULL实现,此时窗口不会在响应事件消息
// Disable event notification before releasing the graph.
g_pEvent->SetNotifyWindow(NULL, 0, 0);
g_pEvent->Release();
g_pEvent = NULL;
[POST BY Leon Chan,suse]