在 C++ 中处理事件

[与此页面关联的功能(Windows 媒体播放器 SDK)是旧版功能。 它已被 MediaPlayer 取代。 MediaPlayer 已针对Windows 10和Windows 11进行了优化。 如果可能,Microsoft 强烈建议新代码使用 MediaPlayer 而不是 Windows 媒体播放器 SDK。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

可以通过两种方式从Windows 媒体播放器接收事件。

  • 通过使用 _WMPOCXEvents 接口通过 IDispatch。 这是用于大多数嵌入方案的接口。
  • 通过 IWMPEvents 接口。 当代码连接到全模式 Player 时,例如远程处理Windows 媒体播放器控件或 UI 插件时,此接口可用。

在每个方案中,你都使用 COM 连接点开始侦听事件。

以下示例代码使用三个成员变量:

CComPtr<IWMPPlayer>         m_spWMPPlayer;
CComPtr<IConnectionPoint>   m_spConnectionPoint;
DWORD                       m_dwAdviseCookie;

若要检索连接点,请先为连接点容器使用 QueryInterface

HRESULT  hr = S_OK;
// Smart pointer to IConnectionPointContainer
CComPtr<IConnectionPointContainer>  spConnectionContainer;

hr = m_spWMPPlayer->QueryInterface(&spConnectionContainer);

接下来,请求要使用的事件接口的连接点。 以下示例代码首先尝试使用 IWMPEvents。 如果该接口不可用,则使用 _WMPOCXEvents

// Test whether the control supports the IWMPEvents interface.
if(SUCCEEDED(hr))
{
    hr = spConnectionContainer->FindConnectionPoint(__uuidof(IWMPEvents), &m_spConnectionPoint);
    if (FAILED(hr))
    {
        // If not, try the _WMPOCXEvents interface, which uses IDispatch.
        hr = spConnectionContainer->FindConnectionPoint(__uuidof(_WMPOCXEvents), &m_spConnectionPoint);
    }
}

最后,调用 IConnectionPoint::Advise 以请求事件。

if(SUCCEEDED(hr))
{
    hr = m_spConnectionPoint->Advise(this, &m_dwAdviseCookie);
}

在前面的示例中,第一个参数假定调用类同时实现 IWMPEvents_WMPOCXEvents。 第二个参数是用于停止侦听事件(例如程序退出时)的返回值,使用类似于下面的代码:

// Stop listening to events
if (m_spConnectionPoint)
{
    if (0 != m_dwAdviseCookie)
        m_spConnectionPoint->Unadvise(m_dwAdviseCookie);
        m_spConnectionPoint.Release();
}

IWMPEvents_WMPOCXEvents 实现事件处理程序有所不同。 对于 IWMPEvents,必须实现一个函数来处理接口定义的每个事件,即使你不打算使用该事件。

// IWMPEvents methods
void STDMETHODCALLTYPE OpenStateChange( long NewState ){ return; }
void STDMETHODCALLTYPE PlayStateChange( long NewState ){ return; }
void STDMETHODCALLTYPE AudioLanguageChange( long LangID ){ return; }
// And so on...

若要实现 _WMPOCXEvents 处理程序,必须使用 IDispatch::Invoke,它是针对 IDispatch 接口上发生的所有事件的单个事件处理程序实现。 这意味着可以选择仅处理某些事件,而忽略其他事件。 以下示例代码演示了一个使用 Invoke的 _WMPOCXEvents 处理程序,该处理程序仅处理 OpenStateChangePlayStateChange 事件:

HRESULT CMyClass::Invoke(
    DISPID  dispIdMember,      
    REFIID  riid,              
    LCID  lcid,                
    WORD  wFlags,              
    DISPPARAMS FAR*  pDispParams,  
    VARIANT FAR*  pVarResult,  
    EXCEPINFO FAR*  pExcepInfo,  
    unsigned int FAR*  puArgErr )
{
    if (!pDispParams)
        return E_POINTER;

    if (pDispParams->cNamedArgs != 0)
        return DISP_E_NONAMEDARGS;

    HRESULT hr = DISP_E_MEMBERNOTFOUND;

    switch (dispIdMember)
    {
        case DISPID_WMPCOREEVENT_OPENSTATECHANGE:
            OpenStateChange(pDispParams->rgvarg[0].lVal /* NewState */ );
            break;

        case DISPID_WMPCOREEVENT_PLAYSTATECHANGE:
            PlayStateChange(pDispParams->rgvarg[0].lVal /* NewState */);
            break;

        // Other cases can handle additional events by using DISPIDs.
    }

    return( hr );
}

在前面的示例代码中,每个情况都只是通过 调用相应事件的 IWMPEvents 处理程序。 如果代码仅处理 _WMPOCXEvents,则只需调用自定义函数或在 case 语句后内联处理事件。

从 Windows 媒体播放器 10 移动版接收事件

Windows 媒体播放器 10 Mobile 控件仅支持通过 _WMPOCXEventsIWMPEvents 接收某些事件。 有关详细信息,请参阅 IWMPEvents 的文档。

示例

Windows 媒体播放器安装包安装一个演示事件处理的示例。 有关详细信息,请参阅 WMPHost 示例。

示例

在 C++ 程序中使用 Windows 媒体播放器 控件