Directshow 学习入门
来源:互联网 发布:ubuntu查看qt安装目录 编辑:程序博客网 时间:2024/06/05 09:24
处理窗口消息
因为VMR没有自己的窗口,所以当视频需要重画或者改变的时候你要通知它。
1、当你接到一个WM_PAINT消息,你就要调用IVMRWindowlessControl::RepaintVideo来重画视频
2、当你接到一个WM_DISPLAYCHANGE消息,你就要调用IVMRWindowlessControl::DisplayModeChanged.
3、当你接到一个WM_SIZE消息时,重新计算视频的位置,然后调用SetVideoPostion。
下面的代码演示了WM_PAINT消息的处理:
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rcClient;
GetClientRect(hwnd, &rcClient);
hdc = BeginPaint(hwnd, &ps);
if (g_pWc != NULL)
{
// Find the region where the application can paint by subtracting
// the video destination rectangle from the client area.
// (Assume that g_rcDest was calculated previously.)
HRGN rgnClient = CreateRectRgnIndirect(&rcClient);
HRGN rgnVideo = CreateRectRgnIndirect(&g_rcDest);
CombineRgn(rgnClient, rgnClient, rgnVideo, RGN_DIFF);
// Paint on window.
HBRUSH hbr = GetSysColorBrush(COLOR_BTNFACE);
FillRgn(hdc, rgnClient, hbr);
// Clean up.
DeleteObject(hbr);
DeleteObject(rgnClient);
DeleteObject(rgnVideo);
// Request the VMR to paint the video.
HRESULT hr = g_pWc->RepaintVideo(hwnd, hdc);
}
else // There is no video, so paint the whole client area.
{
FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE + 1));
}
EndPaint(hwnd, &ps);
}
尽管我们要自己处理onpaint消息,但是已经非常简单了。
如何处理事件通知(Event Notification)
当一个Directshow的应用程序运行的时候,在 filter Graph内部就会发生各种各样的事件,例如,一个filter也许发生数据流错误。Filter通过给graph mangaer发送事件通知来和graph通信,这个事件通知包括一个事件码和两个事件参数。事件码表示发生事件的类型,两个参数用来传递信息。
Filter发送的这些事件,其中的一部分可以被Manager直接处理,不通知应用程序,但有一部分事件,Manager将事件放入到一个队列中,等待应用程序处理。这里我们主要讨论在应用程序中经常遇到的三种事件
EC_COMPLETE表明回放已经结束
EC_USERABORT表明用户中断了回放。用户关闭视频播放窗口时,视频Render会发生这个事件
EC_ERRORABORT表明出现了一个错误。
应用程序可以通知filter graph manager,在某个指定的事件发生时,向指定的窗口发生一个指定的消息。这样应用程序就可以在消息循环中对发生的事件产生反应。
首先定义消息:
#define WM_GRAPHNOTIFY WM_APP + 1
然后向filter graph manager请求IMediaEventEx接口,然后调用IMediaEventEx::SetNotifyWindow方法来设置消息通知窗口:
IMediaEventEx *g_pEvent = NULL;
g_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&g_pEvent);
g_pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
然后在WindowProc函数增加一个处理WM_GRAPHNOTIFY消息的函数:
case WM_GRAPHNOTIFY:
HandleGraphEvent();
break;
HandleGraphEvent()函数具体定义如下
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;
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;
}
}
}
在释放IMediaEventEx指针前,要取消事件通知消息,代码如下:
// Disable event notification before releasing the graph.
g_pEvent->SetNotifyWindow(NULL, 0, 0);
g_pEvent->Release();
g_pEvent = NULL;
因为VMR没有自己的窗口,所以当视频需要重画或者改变的时候你要通知它。
1、当你接到一个WM_PAINT消息,你就要调用IVMRWindowlessControl::RepaintVideo来重画视频
2、当你接到一个WM_DISPLAYCHANGE消息,你就要调用IVMRWindowlessControl::DisplayModeChanged.
3、当你接到一个WM_SIZE消息时,重新计算视频的位置,然后调用SetVideoPostion。
下面的代码演示了WM_PAINT消息的处理:
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rcClient;
GetClientRect(hwnd, &rcClient);
hdc = BeginPaint(hwnd, &ps);
if (g_pWc != NULL)
{
// Find the region where the application can paint by subtracting
// the video destination rectangle from the client area.
// (Assume that g_rcDest was calculated previously.)
HRGN rgnClient = CreateRectRgnIndirect(&rcClient);
HRGN rgnVideo = CreateRectRgnIndirect(&g_rcDest);
CombineRgn(rgnClient, rgnClient, rgnVideo, RGN_DIFF);
// Paint on window.
HBRUSH hbr = GetSysColorBrush(COLOR_BTNFACE);
FillRgn(hdc, rgnClient, hbr);
// Clean up.
DeleteObject(hbr);
DeleteObject(rgnClient);
DeleteObject(rgnVideo);
// Request the VMR to paint the video.
HRESULT hr = g_pWc->RepaintVideo(hwnd, hdc);
}
else // There is no video, so paint the whole client area.
{
FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE + 1));
}
EndPaint(hwnd, &ps);
}
尽管我们要自己处理onpaint消息,但是已经非常简单了。
如何处理事件通知(Event Notification)
当一个Directshow的应用程序运行的时候,在 filter Graph内部就会发生各种各样的事件,例如,一个filter也许发生数据流错误。Filter通过给graph mangaer发送事件通知来和graph通信,这个事件通知包括一个事件码和两个事件参数。事件码表示发生事件的类型,两个参数用来传递信息。
Filter发送的这些事件,其中的一部分可以被Manager直接处理,不通知应用程序,但有一部分事件,Manager将事件放入到一个队列中,等待应用程序处理。这里我们主要讨论在应用程序中经常遇到的三种事件
EC_COMPLETE表明回放已经结束
EC_USERABORT表明用户中断了回放。用户关闭视频播放窗口时,视频Render会发生这个事件
EC_ERRORABORT表明出现了一个错误。
应用程序可以通知filter graph manager,在某个指定的事件发生时,向指定的窗口发生一个指定的消息。这样应用程序就可以在消息循环中对发生的事件产生反应。
首先定义消息:
#define WM_GRAPHNOTIFY WM_APP + 1
然后向filter graph manager请求IMediaEventEx接口,然后调用IMediaEventEx::SetNotifyWindow方法来设置消息通知窗口:
IMediaEventEx *g_pEvent = NULL;
g_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&g_pEvent);
g_pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
然后在WindowProc函数增加一个处理WM_GRAPHNOTIFY消息的函数:
case WM_GRAPHNOTIFY:
HandleGraphEvent();
break;
HandleGraphEvent()函数具体定义如下
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;
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;
}
}
}
在释放IMediaEventEx指针前,要取消事件通知消息,代码如下:
// Disable event notification before releasing the graph.
g_pEvent->SetNotifyWindow(NULL, 0, 0);
g_pEvent->Release();
g_pEvent = NULL;
0 0
- Directshow 学习入门
- Directshow 学习入门
- directshow 学习入门 3
- Directshow 学习入门 4
- Directshow 学习入门 5
- DirectShow入门
- DirectShow入门
- directshow入门
- directshow入门
- 学习directshow
- MSDN学习DirectShow——第二章 入门指南
- DirectShow应用程序快速入门
- DirectShow应用程序快速入门
- DirectShow应用程序快速入门
- DirectShow应用程序快速入门
- DirectShow应用程序快速入门
- [转]directshow 入门篇
- DirectShow应用程序快速入门
- C#調用User32api
- IP分片,TCP分片
- ABAP查找用户出口程序
- mongodb windows下以及linux下的配置
- android HTTP Client 与 HttpURLConnection对比
- Directshow 学习入门
- Pro Android学习笔记(七二):HTTP服务(6):HttpURLConnection
- ODBC 编程API .
- PE和动态PE
- 上班语录 2014-01-24
- Dependency Walker使用说明
- 命令mysqld和mysql的区别
- 真的,相信我,电脑可以预测未来
- Unity中导入图片失真-小结