C++ 为什么我的IWMPEvents函数从未被调用?
我对C++ 为什么我的IWMPEvents函数从未被调用?,c++,wmp,C++,Wmp,我对IWMPEvents有问题,我建议成功,但从未提出。以下是我如何创建嵌入式Windows Media Player的方法: HRESULT MyWMP::setURL(wchar_t* url) { return pMediaPlayer->put_URL(url); // Load and play songs successfully; } bool MyWMP::CreatePlayer() { HRESULT hr; const CLSID CLS
IWMPEvents
有问题,我建议成功,但从未提出。以下是我如何创建嵌入式Windows Media Player的方法:
HRESULT MyWMP::setURL(wchar_t* url)
{
return pMediaPlayer->put_URL(url); // Load and play songs successfully;
}
bool MyWMP::CreatePlayer()
{
HRESULT hr;
const CLSID CLSID_WindowsMediaPlayer = { 0x6BF52A52, 0x394A, 0x11d3,{ 0xB1, 0x53, 0x00, 0xC0, 0x4F, 0x79, 0xFA, 0xA6 } };
hr = ::OleCreate(CLSID_WindowsMediaPlayer, IID_IOleObject, OLERENDER_DRAW, 0, this, this, (void**)&oleObject);
if (SUCCEEDED(hr) && oleObject)
{
if (SUCCEEDED(hr)) hr = oleObject->SetClientSite(this);
if (SUCCEEDED(hr)) hr = OleSetContainedObject(oleObject, TRUE);
if (SUCCEEDED(hr))
{
RECT posRect;
::SetRect(&posRect, -300, -300, 300, 300);
hr = oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, -1, this->hwnd, &posRect);
}
hr = oleObject->QueryInterface(&pMediaPlayer);
}
if (FAILED(hr) || !pMediaPlayer)
{
MessageBox(NULL, L"Create Browser failed!", L"Error", MB_ICONERROR);
return false;
}
return true;
}
MyWMP::MyWMP(HWND parentHWND, HINSTANCE hInstance) :
isFullyCreated(false)
{
OleInitialize(NULL);
HRESULT hr = E_FAIL;
IConnectionPointContainer* container = nullptr;
IUnknown* punk = nullptr;
this->parentHWND = parentHWND;
this->hwnd = CreateWindow(L"Static", NULL, WS_CHILD | WS_VISIBLE, 221, 0, 300, 300, parentHWND, NULL, hInstance, 0);
iComRefCount = 0;
::SetRect(&rObject, 0, 0, 300, 300);
if (CreatePlayer())
{
hr = pMediaPlayer->get_settings(&pMediaPlayerSettings);
if (SUCCEEDED(hr) && pMediaPlayerSettings)
{
pMediaPlayerSettings->put_autoStart(VARIANT_TRUE);
pMediaPlayerSettings->put_volume(100);
}
hr = pMediaPlayer->QueryInterface(IID_IConnectionPointContainer, (void**)&container);
if (SUCCEEDED(hr) && container) hr = container->FindConnectionPoint(__uuidof(IWMPEvents), &callback);
if (FAILED(hr) && container)
{
hr = container->FindConnectionPoint(__uuidof(_WMPOCXEvents), &callback);
}
if (SUCCEEDED(hr) && callback)
{
CWMPEventDispatch *cw = new CWMPEventDispatch();
IUnknown *cwUnk = NULL;
if (SUCCEEDED(cw->QueryInterface(IID_IUnknown, (void**)&cwUnk)))
{
if (SUCCEEDED(hr) && container)
{
hr = callback->Advise(cwUnk, &eventCookie);
if (SUCCEEDED(hr) && eventCookie)
{
isFullyCreated = true; // Set breakpoint here and is triggered
// by debugger
// hr = S_OK
}
}
}
if (cwUnk) cwUnk->Release();
}
if (punk) punk->Release();
if (container) container->Release();
}
}
下面是CWMPEventDispatch
类。我在所有IDispatch
函数上设置了断点,但调试器不会触发任何函数。当我加载新歌、播放/暂停(在嵌入的UI控制按钮上)时,这些函数永远不会被调用
// CWMPEventDispatch.h : Declaration of the event dispatcher
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#include "stdafx.h"
#include "wmpids.h"
#include "wmp.h"
class CWMPEventDispatch :
public IWMPEvents,
public _WMPOCXEvents
{
public:
// ----- IUnknown -----
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void**ppvObject) override;
virtual ULONG STDMETHODCALLTYPE AddRef(void);
virtual ULONG STDMETHODCALLTYPE Release(void);
// IDispatch methods
STDMETHOD(GetIDsOfNames)(REFIID /*riid*/,
__in_ecount(cNames) LPOLESTR FAR * /*rgszNames*/,
unsigned int /*cNames*/,
LCID /*lcid*/,
DISPID FAR * /*rgDispId*/)
{
return(E_NOTIMPL);
}
STDMETHOD(GetTypeInfo)(unsigned int /*iTInfo*/,
LCID /*lcid*/,
ITypeInfo FAR *FAR * /*ppTInfo*/)
{
return(E_NOTIMPL);
}
STDMETHOD(GetTypeInfoCount)(unsigned int FAR * /*pctinfo*/)
{
return(E_NOTIMPL);
}
STDMETHOD(Invoke)(DISPID dispIdMember,
REFIID /*riid*/,
LCID /*lcid*/,
WORD /*wFlags*/,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* /*pVarResult*/,
EXCEPINFO FAR* /*pExcepInfo*/,
unsigned int FAR* /*puArgErr*/);
private:
int iComRefCount;
};
#include "stdafx.h"
#include "myWMPEventDispatch.h"
#pragma region ----- IUnknown -----
ULONG STDMETHODCALLTYPE CWMPEventDispatch::AddRef(void) { return ++iComRefCount; }
ULONG STDMETHODCALLTYPE CWMPEventDispatch::Release(void) { return --iComRefCount; }
HRESULT STDMETHODCALLTYPE CWMPEventDispatch::QueryInterface(REFIID riid, void**ppvObject)
{
if (riid == __uuidof(IUnknown)) *ppvObject = static_cast<IDispatch*>(this);
else if (riid == __uuidof(IDispatch)) *ppvObject = static_cast<IDispatch*>(this);
else if (riid == __uuidof(IWMPEvents)) *ppvObject = static_cast<IWMPEvents*>(this);
else if (riid == __uuidof(_WMPOCXEvents)) *ppvObject = static_cast<_WMPOCXEvents*>(this);
else
return E_NOINTERFACE;
AddRef();
return S_OK;
}
#pragma endregion
HRESULT CWMPEventDispatch::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;
return(hr);
}
//CWMPEventDispatch.h:事件调度器的声明
//
//版权所有(c)微软公司。版权所有。
//
#包括“stdafx.h”
#包括“wmpids.h”
#包括“wmp.h”
CWMPEventDispatch类:
公共事件,
公共事件
{
公众:
//----IUnknown-----
虚拟HRESULT STDMETHODCALLTYPE查询接口(refid riid,void**ppvObject)重写;
虚拟ULONG STDMETHODCALLTYPE AddRef(void);
虚拟ULONG标准方法调用类型发布(void);
//IDispatch方法
标准方法(GetIDsOfNames)(refid/*riid*/,,
__in_ecount(cNames)LPOLESTR FAR*/*rgszNames*/,,
无符号int/*cNames*/,,
LCID/*LCID*/,,
DISPID FAR*/*rgDispId*/)
{
返回(E_NOTIMPL);
}
STDMETHOD(GetTypeInfo)(unsigned int/*iTInfo*/,,
LCID/*LCID*/,,
ITypeInfo FAR*FAR*/*ppTInfo*/)
{
返回(E_NOTIMPL);
}
STDMETHOD(GetTypeInfoCount)(无符号int-FAR*/*pctinfo*/)
{
返回(E_NOTIMPL);
}
STDMETHOD(Invoke)(DISPID DISPID成员,
refid/*riid*/,,
LCID/*LCID*/,,
WORD/*wFlags*/,,
DISPPARAMS FAR*pDispParams,
变量FAR*/*pVarResult*/,,
除FAR*/*pExcepInfo*/,,
无符号整数FAR*/*puArgErr*/);
私人:
int-iComRefCount;
};
#包括“stdafx.h”
#包括“myWMPEventDispatch.h”
#布拉格马地区---IUnknown-----
ULONG STDMETHODCALLTYPE CWMPEventDispatch::AddRef(void){return++iComRefCount;}
ULONG STDMETHODCALLTYPE CWMPEventDispatch::Release(void){return--iComRefCount;}
HRESULT STDMETHODCALLTYPE CWMPEventDispatch::QueryInterface(refid-riid,void**ppvoObject)
{
如果(riid===(IUnknown))*ppvObject=static\u cast(this);
否则,如果(riid==(IDispatch))*ppvObject=static\u cast(此);
否则,如果(riid==(IWMPEvents))*ppvObject=static\u cast(此);
否则,如果(riid====uuuuuIdof(\u WMPOCXEvents))*ppvObject=static\u cast(此);
其他的
返回E_NOINTERFACE;
AddRef();
返回S_OK;
}
#布拉格端区
HRESULT CWMPEventDispatch::Invoke(
DISPID DISPID成员,
refid/*riid*/,,
LCID/*LCID*/,,
WORD/*wFlags*/,,
DISPPARAMS FAR*pDispParams,
变量FAR*/*pVarResult*/,,
除FAR*/*pExcepInfo*/,,
无符号整数FAR*/*puArgErr*/)
{
如果(!pDispParams)
返回E_指针;
如果(pDispParams->cNamedArgs!=0)
返回DISP_E_nonamadargs;
HRESULT hr=DISP_E_MEMBERNOTFOUND;
回报率(hr);
}
问题:
为什么从未调用我的IWMPEvents
函数,以及如何修复它
我将完整的源代码作为7z存档进行攻击。你可以下载它
环境:赢10 x64,VS 2017社区这段代码:
if (SUCCEEDED(hr) && container) hr = container->FindConnectionPoint(__uuidof(IWMPEvents), &callback);
if (FAILED(hr) && container)
{
hr = container->FindConnectionPoint(__uuidof(_WMPOCXEvents), &callback);
}
将在第一行成功,因此您将仅钩住IWMPEvents
上的事件,而不会继续钩住\u WMPOCXEvents
IwmEvents是早期绑定(IUnknown派生)事件,因此媒体播放器确实会调用IwmEvents::PlayStateChange(…)IwmEvents::StatusChange(…)等,但它不会使用相应的dispid调用IDispatch::Invoke
如果您想要IDispatch事件,只需删除第一个查找到的连接点,或同时调用这两个连接点。请花点时间思考中的“最小值”。它是控制台应用程序吗?如果是,您可能需要发送windows消息,以便事件到达。@SimonMourier这是Win32应用程序,上面代码中的
parentHWND
是顶部窗口。您有完整的复制示例吗?@SimonMourier是的,请参阅我编辑的问题末尾。