EternalWindows
ActiveX コントロール / Flash再生サンプル

ActiveXコントロールのコンテナの実装例を示します。対象となるコントロールはFlashを想定しています。

#include <windows.h>
#include <olectl.h>

class CActiveXContainer : public IOleClientSite, public IOleInPlaceSite, public IOleControlSite, public IDispatch
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();
	
	STDMETHODIMP SaveObject();
	STDMETHODIMP GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
	STDMETHODIMP GetContainer(IOleContainer **ppContainer);
	STDMETHODIMP ShowObject();
	STDMETHODIMP OnShowWindow(BOOL fShow);
	STDMETHODIMP RequestNewObjectLayout();
	
	STDMETHODIMP GetWindow(HWND *phwnd);
	STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
	STDMETHODIMP CanInPlaceActivate();
	STDMETHODIMP OnInPlaceActivate();
	STDMETHODIMP OnUIActivate();
	STDMETHODIMP GetWindowContext(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
	STDMETHODIMP Scroll(SIZE scrollExtant);
	STDMETHODIMP OnUIDeactivate(BOOL fUndoable);
	STDMETHODIMP OnInPlaceDeactivate();
	STDMETHODIMP DiscardUndoState();
	STDMETHODIMP DeactivateAndUndo();
	STDMETHODIMP OnPosRectChange(LPCRECT lprcPosRect);
	
	STDMETHODIMP OnControlInfoChanged();
	STDMETHODIMP LockInPlaceActive(BOOL fLock);
	STDMETHODIMP GetExtendedControl(IDispatch **ppDisp);
	STDMETHODIMP TransformCoords(POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags);
	STDMETHODIMP TranslateAccelerator(MSG *pMsg, DWORD grfModifiers);
	STDMETHODIMP OnFocus(BOOL fGotFocus);
	STDMETHODIMP ShowPropertyFrame();
	
	STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);
	STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
	STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
	STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);

	CActiveXContainer();
	~CActiveXContainer();
	int Run(HINSTANCE hinst, int nCmdShow);
	LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
	BOOL Create();
	BOOL InitNew();
	BOOL QuickActivate();
	BOOL SetEventSink();
	HRESULT PlayMovie(BSTR bstr);
	HRESULT Invoke(IDispatch *pDispatch, LPOLESTR lpszName, WORD wFlags, VARIANT *pVarArray, int nArgs, VARIANT *pVarResult);

private:
	LONG             m_cRef;
	HWND             m_hwnd;
	DWORD            m_dwEventCookie;
	DWORD            m_dwMiscStatus;
	IOleObject       *m_pOleObject;
	IDispatch        *m_pEventSink;
	IConnectionPoint *m_pConnectionPoint;
};

class CEventSink : public IDispatch
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();
	
	STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);
	STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
	STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
	STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);

	CEventSink();

private:
	LONG m_cRef;
};

const CLSID CLSID_ShockwaveFlash = {0xD27CDB6E, 0xAE6D, 0x11cf, {0x96, 0xB8, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
const IID IID_IShockwaveFlashEvents = {0xD27CDB6D, 0xAE6D, 0x11CF, {0x96, 0xB8, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

CActiveXContainer *g_pActiveXContainer = NULL;

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	int nResult = 0;

	OleInitialize(NULL);
	
	g_pActiveXContainer = new CActiveXContainer;
	if (g_pActiveXContainer != NULL) {
		nResult = g_pActiveXContainer->Run(hinst, nCmdShow);
		g_pActiveXContainer->Release();
	}

	OleUninitialize();

	return nResult;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return g_pActiveXContainer->WindowProc(hwnd, uMsg, wParam, lParam);
}


// CActiveXContainer


CActiveXContainer::CActiveXContainer()
{
	m_cRef = 1;
	m_hwnd = NULL;
	m_dwEventCookie = 0;
	m_dwMiscStatus = 0;
	m_pEventSink = NULL;
	m_pOleObject = NULL;
	m_pConnectionPoint = NULL;
}

CActiveXContainer::~CActiveXContainer()
{
}

STDMETHODIMP CActiveXContainer::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;
	
	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IOleClientSite))
		*ppvObject = static_cast<IOleClientSite *>(this);
	else if (IsEqualIID(riid, IID_IOleWindow) || IsEqualIID(riid, IID_IOleInPlaceSite))
		*ppvObject = static_cast<IOleInPlaceSite *>(this);
	else if (IsEqualIID(riid, IID_IOleControlSite))
		*ppvObject = static_cast<IOleControlSite *>(this);
	else if (IsEqualIID(riid, IID_IDispatch))
		*ppvObject = static_cast<IDispatch *>(this);
	else
		return E_NOINTERFACE;

	AddRef();
	
	return S_OK;
}

STDMETHODIMP_(ULONG) CActiveXContainer::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) CActiveXContainer::Release()
{
	if (InterlockedDecrement(&m_cRef) == 0) {
		delete this;
		return 0;
	}

	return m_cRef;
}

STDMETHODIMP CActiveXContainer::SaveObject()
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::GetContainer(IOleContainer **ppContainer)
{
	*ppContainer = NULL;

	return E_NOINTERFACE;
}

STDMETHODIMP CActiveXContainer::ShowObject()
{
	return S_OK;
}

STDMETHODIMP CActiveXContainer::OnShowWindow(BOOL fShow)
{
	return S_OK;
}

STDMETHODIMP CActiveXContainer::RequestNewObjectLayout()
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::GetWindow(HWND *phwnd)
{
	*phwnd = m_hwnd;

	return S_OK;
}

STDMETHODIMP CActiveXContainer::ContextSensitiveHelp(BOOL fEnterMode)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::CanInPlaceActivate()
{
	return S_OK;
}

STDMETHODIMP CActiveXContainer::OnInPlaceActivate()
{
	return S_OK;
}

STDMETHODIMP CActiveXContainer::OnUIActivate()
{
	return S_OK;
}

STDMETHODIMP CActiveXContainer::GetWindowContext(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
	*ppFrame = NULL;
	*ppDoc = NULL;
	
	GetClientRect(m_hwnd, lprcPosRect);
	GetClientRect(m_hwnd, lprcClipRect);

	return S_OK;
}

STDMETHODIMP CActiveXContainer::Scroll(SIZE scrollExtant)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::OnUIDeactivate(BOOL fUndoable)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::OnInPlaceDeactivate()
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::DiscardUndoState()
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::DeactivateAndUndo()
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::OnPosRectChange(LPCRECT lprcPosRect)
{
	return S_OK;
}

STDMETHODIMP CActiveXContainer::OnControlInfoChanged()
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::LockInPlaceActive(BOOL fLock)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::GetExtendedControl(IDispatch **ppDisp)
{
	*ppDisp = NULL;
	
	return E_NOINTERFACE;
}

STDMETHODIMP CActiveXContainer::TransformCoords(POINTL *pPtlHimetric, POINTF *pPtfContainer, DWORD dwFlags)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::TranslateAccelerator(MSG *pMsg, DWORD grfModifiers)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::OnFocus(BOOL fGotFocus)
{
	return S_OK;
}

STDMETHODIMP CActiveXContainer::ShowPropertyFrame()
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::GetTypeInfoCount(UINT *pctinfo)
{
	*pctinfo = 0;
	
	return S_OK;
}

STDMETHODIMP CActiveXContainer::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXContainer::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
	if (dispIdMember == DISPID_AMBIENT_LOCALEID) {
		pVarResult->vt = VT_I4;
		pVarResult->lVal = (SHORT)GetThreadLocale();
	}
	else if (dispIdMember == DISPID_AMBIENT_USERMODE) {
		pVarResult->vt = VT_BOOL;
		pVarResult->boolVal = VARIANT_TRUE;	
	}
	else if (dispIdMember == DISPID_AMBIENT_DISPLAYASDEFAULT) {
		pVarResult->vt = VT_BOOL;
		pVarResult->boolVal = VARIANT_FALSE;	
	}
	else
		return DISP_E_MEMBERNOTFOUND;

	return S_OK;
}

int CActiveXContainer::Run(HINSTANCE hinst, int nCmdShow)
{
	TCHAR      szAppName[] = TEXT("sample");
	HWND       hwnd;
	MSG        msg;
	WNDCLASSEX wc;

	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	wc.lpfnWndProc   = ::WindowProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hinst;
	wc.hIcon         = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	wc.hCursor       = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = szAppName;
	wc.hIconSm       = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	
	if (RegisterClassEx(&wc) == 0)
		return 0;

	hwnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL);
	if (hwnd == NULL)
		return 0;

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	
	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return (int)msg.wParam;
}

LRESULT CActiveXContainer::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) {

	case WM_CREATE:
		m_hwnd = hwnd;
		if (!Create())
			return -1;
		return 0;

	case WM_SIZE: {
		RECT              rc = {0, 0, LOWORD(lParam), HIWORD(lParam)};
		IOleInPlaceObject *pOleInPlaceObject;
		
		if (m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)
			return 0;

		m_pOleObject->QueryInterface(IID_PPV_ARGS(&pOleInPlaceObject));
		pOleInPlaceObject->SetObjectRects(&rc, &rc);
		pOleInPlaceObject->Release();
		return 0;
	}

	case WM_DESTROY:
		if (m_pConnectionPoint != NULL) {
			m_pConnectionPoint->Unadvise(m_dwEventCookie);
			m_pConnectionPoint->Release();
		}
		
		if (m_pEventSink != NULL)
			m_pEventSink->Release();
		
		if (m_pOleObject != NULL) {
			RECT rc;
			SetRectEmpty(&rc);
			m_pOleObject->DoVerb(OLEIVERB_HIDE, NULL, NULL, 0, m_hwnd, &rc);
			m_pOleObject->Close(OLECLOSE_NOSAVE);
			m_pOleObject->SetClientSite(NULL);
			m_pOleObject->Release();
		}
		PostQuitMessage(0);
		return 0;

	default:
		break;

	}

	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

BOOL CActiveXContainer::Create()
{
	RECT            rc;
	BSTR            bstr;
	HRESULT         hr;
	BOOL            bQuickActivate;
	IRunnableObject *pRunnableObject;

	hr = CoCreateInstance(CLSID_ShockwaveFlash, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pOleObject));
	if (FAILED(hr))
		return FALSE;
	
	m_pEventSink = new CEventSink();
	
	bQuickActivate = QuickActivate();

	if (!bQuickActivate) {
		m_pOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);
		if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
			m_pOleObject->SetClientSite(static_cast<IOleClientSite *>(this));
	}

	InitNew();

	if (!bQuickActivate) {
		if (!(m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
			m_pOleObject->SetClientSite(static_cast<IOleClientSite *>(this));
		SetEventSink();
	}
	
	if (m_dwMiscStatus & OLEMISC_ALWAYSRUN) {
		m_pOleObject->QueryInterface(IID_PPV_ARGS(&pRunnableObject));
		if (pRunnableObject != NULL) {
			pRunnableObject->Run(NULL);
			pRunnableObject->Release();
		}
	}

	SetRectEmpty(&rc);
	hr = m_pOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, static_cast<IOleClientSite *>(this), 0, m_hwnd, &rc);
	if (FAILED(hr))
		return FALSE;

	bstr = SysAllocString(L"C:\\sample.swf");
	PlayMovie(bstr);
	SysFreeString(bstr);

	return TRUE;
}

BOOL CActiveXContainer::InitNew()
{
	BOOL                bResult = TRUE;
	IPersistStreamInit  *pPersistStreamInit;
	IPersistStorage     *pPersistStorage;
	IPersistMemory      *pPersistMemory;
	IPersistPropertyBag *pPersistPropertyBag;

	if (m_pOleObject->QueryInterface(IID_PPV_ARGS(&pPersistStreamInit)) == S_OK) {
		pPersistStreamInit->InitNew();
		pPersistStreamInit->Release();
	}
	else if (m_pOleObject->QueryInterface(IID_PPV_ARGS(&pPersistStorage)) == S_OK) {
		pPersistStorage->InitNew(NULL);
		pPersistStorage->Release();
	}
	else if (m_pOleObject->QueryInterface(IID_PPV_ARGS(&pPersistMemory)) == S_OK) {
		pPersistMemory->InitNew();
		pPersistMemory->Release();
	}
	else if (m_pOleObject->QueryInterface(IID_PPV_ARGS(&pPersistPropertyBag)) == S_OK) {
		pPersistPropertyBag->InitNew();
		pPersistPropertyBag->Release();
	}
	else
		bResult = FALSE;

	return bResult;
}

BOOL CActiveXContainer::QuickActivate()
{
	HRESULT        hr;
	QACONTAINER    qaContainer;
	QACONTROL      qaControl;
	IQuickActivate *pQuickActivate;

	hr = m_pOleObject->QueryInterface(IID_PPV_ARGS(&pQuickActivate));
	if (FAILED(hr))
		return FALSE;

	ZeroMemory(&qaContainer, sizeof(QACONTAINER));
	qaContainer.cbSize        = sizeof(QACONTAINER);
	qaContainer.pClientSite   = static_cast<IOleClientSite *>(this);
	qaContainer.pUnkEventSink = m_pEventSink;
	
	qaControl.cbSize = sizeof(QACONTROL);

	hr = pQuickActivate->QuickActivate(&qaContainer, &qaControl);
	if (FAILED(hr)) {
		pQuickActivate->Release();
		return FALSE;
	}
	
	m_dwMiscStatus = qaControl.dwMiscStatus;
	m_dwEventCookie = qaControl.dwEventCookie;

	pQuickActivate->Release();

	return TRUE;
}

BOOL CActiveXContainer::SetEventSink()
{
	IConnectionPointContainer *pConnectionPointContainer;
	IConnectionPoint          *pConnectionPoint;
	HRESULT                   hr;
	
	hr = m_pOleObject->QueryInterface(IID_PPV_ARGS(&pConnectionPointContainer));
	if (FAILED(hr))	
		return FALSE;

	hr = pConnectionPointContainer->FindConnectionPoint(IID_IShockwaveFlashEvents, &pConnectionPoint);
	pConnectionPointContainer->Release();
	if (FAILED(hr))	
		return FALSE;

	hr = pConnectionPoint->Advise(m_pEventSink, &m_dwEventCookie);
	m_pConnectionPoint = pConnectionPoint;
	
	return TRUE;
}

HRESULT CActiveXContainer::PlayMovie(BSTR bstr)
{
	HRESULT   hr;
	VARIANT   var;
	IDispatch *pDispatch;
	
	m_pOleObject->QueryInterface(IID_PPV_ARGS(&pDispatch));
	
	var.vt = VT_BSTR;
	var.bstrVal = bstr;
	hr = Invoke(pDispatch, L"Movie", DISPATCH_PROPERTYPUT, &var, 1, NULL);
	if (FAILED(hr)) {
		pDispatch->Release();
		return hr;
	}

	hr = Invoke(pDispatch, L"Play", DISPATCH_METHOD, NULL, 0, NULL);

	pDispatch->Release();

	return hr;
}

HRESULT CActiveXContainer::Invoke(IDispatch *pDispatch, LPOLESTR lpszName, WORD wFlags, VARIANT *pVarArray, int nArgs, VARIANT *pVarResult)
{
	DISPPARAMS dispParams;
	DISPID     dispid;
	DISPID     dispidName = DISPID_PROPERTYPUT;
	HRESULT    hr;
	
	hr = pDispatch->GetIDsOfNames(IID_NULL, &lpszName, 1, LOCALE_USER_DEFAULT, &dispid);
	if (FAILED(hr))
		return hr;
	
	dispParams.cArgs = nArgs;
	dispParams.rgvarg = pVarArray;
	if (wFlags & DISPATCH_PROPERTYPUT) {
		dispParams.cNamedArgs = 1;
		dispParams.rgdispidNamedArgs = &dispidName;
	}
	else {
		dispParams.cNamedArgs = 0;
		dispParams.rgdispidNamedArgs = NULL;
	}

	hr = pDispatch->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, &dispParams, pVarResult, NULL, NULL);

	return hr;
}


// CEventSink


CEventSink::CEventSink()
{
	m_cRef = 1;
}

STDMETHODIMP CEventSink::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;

	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDispatch) || IsEqualIID(riid, IID_IShockwaveFlashEvents))
		*ppvObject = static_cast<IDispatch *>(this);
	else
		return E_NOINTERFACE;

	AddRef();
	
	return S_OK;
}

STDMETHODIMP_(ULONG) CEventSink::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) CEventSink::Release()
{
	if (InterlockedDecrement(&m_cRef) == 0) {	
		delete this;
		return 0;
	}

	return m_cRef;
}

STDMETHODIMP CEventSink::GetTypeInfoCount(UINT *pctinfo)
{
	*pctinfo = 0;
	
	return S_OK;
}

STDMETHODIMP CEventSink::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
	return E_NOTIMPL;
}

STDMETHODIMP CEventSink::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
	return E_NOTIMPL;
}

STDMETHODIMP CEventSink::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
	if (dispIdMember != DISPID_READYSTATECHANGE) {
		TCHAR szBuf[256];
		wsprintf(szBuf, TEXT("%d"), dispIdMember);
		MessageBox(NULL, szBuf, TEXT("CEventSink::Invoke"), MB_OK);
	}

	return S_OK;
}

戻る