【问题标题】:What is the right way to add buttons to the Media Foundation Interfaces video screen将按钮添加到 Media Foundation Interfaces 视频屏幕的正确方法是什么
【发布时间】:2018-05-05 01:34:31
【问题描述】:

我目前正在尝试使用媒体基础接口从头开始构建播放器。

我使用取自此处的示例: https://msdn.microsoft.com/en-us/library/windows/desktop/dd979592(v=vs.85).aspx

作为播放器的基础。

我想在视频屏幕窗口中添加按钮(后退/前进按钮、进度条等),但我不太清楚如何操作。

我不能简单地添加一个按钮作为主窗口的子窗口,因为它被播放器隐藏,我尝试将按钮添加为视频窗口的子窗口,但它不起作用...

向视频窗口添加按钮的正确方法是什么?

这是您注册到播放器窗口的代码的一部分(完整代码请输入我附上的链接)。

// create the instance of the player hwnd = handle of main window
HRESULT hr = CPlayer::CreateInstance(hwnd, hwnd, &g_pPlayer);

// inner call to cplayer
CPlayer *pPlayer = new (std::nothrow) CPlayer(hVideo, hEvent);

// Create a partial topology. (m_hwndVideo == hVideo == hwnd)
hr = CreatePlaybackTopology(m_pSource, pSourcePD, m_hwndVideo, &pTopology);

我尝试使用这个功能来改变视频绘画,所以我会有一些 左下角放我的按钮,这是我的功能:

VOID update_lower_window(HWND hwnd)
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);

    RECT rc;
    GetClientRect(hwnd, &rc);

    //rc = father size
    RECT repaint;
    memcpy(&repaint, &rc, sizeof(RECT));
    repaint.top = repaint.bottom - DOWN_SPACE; // DOWN_SPACE == 50

    // paint back bottom to white
    FillRect(hdc, &repaint, (HBRUSH)COLOR_WINDOW);

    EndPaint(hwnd, &ps);
}

我在以下情况下调用此函数:

  1. WM_PAINT碰巧
  2. WM_SIZE碰巧
  3. WM_CREATE碰巧

话虽如此,我仍然无法实现我的目标:

  1. 当电影开始播放时,它开始全屏并且没有留下我想要的空间(我似乎找不到播放电影时发送的消息,或者换句话说,当电影在屏幕上绘制时它没有发送我插入函数的消息之一)
  2. 当我缩小屏幕时,前一个屏幕的残余仍然保持向下,我看不到背景。
  3. 使用“最小化”按钮时,会出现与 2 中相同的现象。

另一个有趣的细节我在2中提到的现象仅在我通过从下往上拖动来更改窗口大小时发生,如果我通过从一个角拖动来更改窗口大小(同时放大或减小高度和宽度)然后窗口会自行纠正我一直在底部的白色部分(背景)看到。

【问题讨论】:

    标签: c++ winapi ms-media-foundation


    【解决方案1】:

    您可以重新定位视频区域,以便您的 win32 GUI(按钮和进度)位于下方。请参阅该示例中的 WM_SIZE 处理程序以了解如何操作,它们计算矩形以占据窗口,您可以调整以适应您的控件。

    如果您想要半透明的叠加控件,您可以编写 EVR Presenter。 https://msdn.microsoft.com/en-us/library/windows/desktop/bb530107(v=vs.85).aspx https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/Win7Samples/multimedia/mediafoundation/evrpresenter

    但这比较难。

    附:如果您只想要一个简单的解决方案,请使用更高级别的解决方案。就像Windows Media Player control 一样,请注意他们有一个 C++ 示例,或用于 GUI 和 MediaElement 的 .NET。

    更新:我认为在该示例中设置初始视频位置的正确位置可能是 CPlayer::OnTopologyStatus,位于 MFGetService(MR_VIDEO_RENDER_SERVICE) 行之后。

    无论如何,另一种可能对您的任务更简单的方法是创建一个专用于视频的子窗口。定位它,使其占据应用程序主窗口的大部分,并且只留下底部 50px 未被占用。不要忘记处理至少 WM_SIZE 以重新定位,理想情况下还要处理 WM_DISPLAYCHANGED、WM_ENDSESSION、WM_GETMINMAXINFO。设置 MF 播放,使视频占据整个子视频窗口。 这将确保视频不会干扰您在底部 50 像素面板上绘制的 Win32 内容。

    顺便说一句,这就是 MPC-HC 正在做的事情,请参见图片。 正如您在 Spy++ 屏幕截图中看到的那样,它们有专用的视频窗口,以及播放器的 Win32 控件的其他子窗口。

    【讨论】:

    • 我试图替换这一行:g_pPlayer-> ResizeVideo (width, height);在这一行中:g_pPlayer-> ResizeVideo (width, height - 50);不幸的是,这不能正常工作,当视频打开时它仍然会一直拉伸,只有当你改变它的大小时(这是有道理的,我只有在窗口变大或变小的时候才得到命令)才会留下一小部分。 (在下一个消息中继续)
    • 更大的问题是当下部没有显示时,即使我尝试使用 UpdateWindow (hwnd);或 b SetBkColor (hwnd, WHITE_BRUSH);情况还没有改变……
    • 要设置初始大小,请尝试从 WM_CREATE 事件处理程序调用 ResizeVideo()。关于第二个问题,您需要正确处理 WM_PAINT 。请注意示例如何检查视频是否正在播放,如果没有播放则调用 FillRect 来绘制窗口。如果您的视频没有占据整个窗口,则无论如何您都需要绘制,只是窗口的不同部分。为获得最佳性能,请使用 ps.rcPaint 矩形,与底部面板矩形相交(IntersectRect API,或使用 中的 CRect),然后仅绘制那个。
    • @GaryG。较新的样本更复杂。除非您想将 Direct3D 11 着色器应用于视频,或与 DirectWrite 互操作,否则我不知道使用 DX9 Presenter 的缺点。 MS 甚至在 Win10 上也使用 d3d9,例如他们的 WPF 框架是基于它的,并且向后兼容在 Windows 中传统上是可以的。
    • 另外,所有微软多媒体样本的质量都很糟糕。使用 ATL 将导致代码大小减少 3 倍:CComObjectRoot、模板集合、CComPtr、CWindowImpl,它们对这类东西有很大帮助。当我需要使用这些示例中的任何一个时,我首先会重构它们以使它们保持正常,例如这是 Direct2D:github.com/Const-me/Direct2D-demo
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 2023-04-09
    相关资源
    最近更新 更多