用了好几天的时间,从从未接触com到知道用oleobject嵌入 flash ocx的过程。应该要注意下面几点:
1.实现ole 接口
* IOleClientSite
* IOleInPlaceSiteWindowless
* IOleInPlaceFrame
* IStorage
2.用#import 加载 flash ocx
#import "c:\\windows\\system32\\macromed\\flash\\flash.ocx" named_guids
3.flash自行交互(IOleObject::DoVerb())
要实现IOleInPlaceSiteWindowless接口,如果实现IOleInPlaceObject是不能进行交互的
4.guru代码例子中,应在draw中加入:if(g_flashmain!=this) retrun;
整理的代码是:
FlashWindow.h
#ifndef FlashWindow_h__
#define FlashWindow_h__
#pragma once
#import "c:\\windows\\system32\\macromed\\flash\\flash10c.ocx" named_guids
//ShockwaveFlashObjects::IShockwaveFlash
class CFlashWindow : public CWindowImpl<CFlashWindow>,
virtual public IOleClientSite,
virtual public IOleInPlaceSiteWindowless,
virtual public IOleInPlaceFrame,
virtual public IOleInPlaceObject,
virtual public IStorage,
public ShockwaveFlashObjects::_IShockwaveFlashEvents
{
public:
CFlashWindow(GUID clsid);
~CFlashWindow(void);
public:
DECLARE_WND_CLASS(TEXT("MyOleControl"))
BOOL PreTranslateMessage(MSG* pMsg);
BEGIN_MSG_MAP(CFlashWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate);
MESSAGE_HANDLER(WM_PAINT, OnPaint);
MESSAGE_HANDLER(WM_SIZE, OnSize);
MESSAGE_HANDLER(WM_NCHITTEST,OnNchittest);
MESSAGE_RANGE_HANDLER(WM_MOUSEMOVE,WM_MOUSEWHEEL,OnMouseEvent)
MESSAGE_RANGE_HANDLER(WM_KEYDOWN,WM_CHAR,OnMouseEvent)
MESSAGE_HANDLER(WM_SETCURSOR,OnMouseEvent);
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/);
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/);
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/);
LRESULT OnNchittest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/);
LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/);
void Draw(HDC hdcDraw, const RECT *rcDraw, BOOL bErase);
// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
//IOleClientSite
virtual HRESULT STDMETHODCALLTYPE SaveObject( void)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetMoniker(
/* [in] */ DWORD dwAssign,
/* [in] */ DWORD dwWhichMoniker,
/* [out] */ IMoniker **ppmk)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetContainer(
/* [out] */ IOleContainer **ppContainer)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE ShowObject( void)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE OnShowWindow(
/* [in] */ BOOL fShow)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout( void)
{
return E_NOTIMPL;
}
//IOleInPlaceSiteWindowless
virtual HRESULT STDMETHODCALLTYPE CanWindowlessActivate( void)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE GetCapture( void)
{
return S_FALSE;
}
virtual HRESULT STDMETHODCALLTYPE SetCapture(
/* [in] */ BOOL fCapture)
{
return S_FALSE;
}
virtual HRESULT STDMETHODCALLTYPE GetFocus( void)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE SetFocus(
/* [in] */ BOOL fFocus)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE GetDC(
/* [in] */ LPCRECT pRect,
/* [in] */ DWORD grfFlags,
/* [out] */ HDC *phDC)
{
return S_FALSE;
}
virtual HRESULT STDMETHODCALLTYPE ReleaseDC(
/* [in] */ HDC hDC)
{
return S_FALSE;
}
virtual HRESULT STDMETHODCALLTYPE InvalidateRect(
/* [in] */ LPCRECT pRect,
/* [in] */ BOOL fErase)
{
Draw(NULL, pRect, TRUE);
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE InvalidateRgn(
/* [in] */ HRGN hRGN,
/* [in] */ BOOL fErase)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE ScrollRect(
/* [in] */ INT dx,
/* [in] */ INT dy,
/* [in] */ LPCRECT pRectScroll,
/* [in] */ LPCRECT pRectClip)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE AdjustRect(
/* [out][in] */ LPRECT prc)
{
return S_FALSE;
}
virtual HRESULT STDMETHODCALLTYPE OnDefWindowMessage(
/* [in] */ UINT msg,
/* [in] */ WPARAM wParam,
/* [in] */ LPARAM lParam,
/* [out] */ LRESULT *plResult)
{
return S_FALSE;
}
//IOleInPlaceSiteEx
virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx(
/* [out] */ BOOL *pfNoRedraw,
/* [in] */ DWORD dwFlags)
{
if(pfNoRedraw)
*pfNoRedraw = FALSE;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(
/* [in] */ BOOL fNoRedraw)
{
return S_FALSE;
}
virtual HRESULT STDMETHODCALLTYPE RequestUIActivate( void)
{
return S_FALSE;
}
//IOleInPlaceUIWindow : public IOleWindow
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetBorder(
/* [out] */ LPRECT lprectBorder)
{
return S_OK;
}
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE RequestBorderSpace(
/* [unique][in] */ LPCBORDERWIDTHS pborderwidths)
{
return S_OK;
}
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetBorderSpace(
/* [unique][in] */ LPCBORDERWIDTHS pborderwidths)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE SetActiveObject(
/* [unique][in] */ IOleInPlaceActiveObject *pActiveObject,
/* [unique][string][in] */ LPCOLESTR pszObjName)
{
return S_OK;
}
//IOleInPlaceFrame
virtual HRESULT STDMETHODCALLTYPE InsertMenus(
/* [in] */ HMENU hmenuShared,
/* [out][in] */ LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
return S_OK;
}
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetMenu(
/* [in] */ HMENU hmenuShared,
/* [in] */ HOLEMENU holemenu,
/* [in] */ HWND hwndActiveObject)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE RemoveMenus(
/* [in] */ HMENU hmenuShared)
{
return S_OK;
}
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetStatusText(
/* [unique][in] */ LPCOLESTR pszStatusText)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE EnableModeless(
/* [in] */ BOOL fEnable)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(
/* [in] */ LPMSG lpmsg,
/* [in] */ WORD wID)
{
return S_OK;
}
//IStorage
virtual HRESULT STDMETHODCALLTYPE CreateStream(
/* [string][in] */ const OLECHAR *pwcsName,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved1,
/* [in] */ DWORD reserved2,
/* [out] */ IStream **ppstm)
{
return E_NOTIMPL;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE OpenStream(
/* [string][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ void *reserved1,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved2,
/* [out] */ IStream **ppstm)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE CreateStorage(
/* [string][in] */ const OLECHAR *pwcsName,
/* [in] */ DWORD grfMode,
/* [in] */ DWORD reserved1,
/* [in] */ DWORD reserved2,
/* [out] */ IStorage **ppstg)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OpenStorage(
/* [string][unique][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ IStorage *pstgPriority,
/* [in] */ DWORD grfMode,
/* [unique][in] */ SNB snbExclude,
/* [in] */ DWORD reserved,
/* [out] */ IStorage **ppstg)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE CopyTo(
/* [in] */ DWORD ciidExclude,
/* [size_is][unique][in] */ const IID *rgiidExclude,
/* [unique][in] */ SNB snbExclude,
/* [unique][in] */ IStorage *pstgDest)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE MoveElementTo(
/* [string][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ IStorage *pstgDest,
/* [string][in] */ const OLECHAR *pwcsNewName,
/* [in] */ DWORD grfFlags)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Commit(
/* [in] */ DWORD grfCommitFlags)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Revert( void)
{
return S_OK;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE EnumElements(
/* [in] */ DWORD reserved1,
/* [size_is][unique][in] */ void *reserved2,
/* [in] */ DWORD reserved3,
/* [out] */ IEnumSTATSTG **ppenum)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE DestroyElement(
/* [string][in] */ const OLECHAR *pwcsName)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE RenameElement(
/* [string][in] */ const OLECHAR *pwcsOldName,
/* [string][in] */ const OLECHAR *pwcsNewName)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE SetElementTimes(
/* [string][unique][in] */ const OLECHAR *pwcsName,
/* [unique][in] */ const FILETIME *pctime,
/* [unique][in] */ const FILETIME *patime,
/* [unique][in] */ const FILETIME *pmtime)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE SetClass(
/* [in] */ REFCLSID clsid)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE SetStateBits(
/* [in] */ DWORD grfStateBits,
/* [in] */ DWORD grfMask)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Stat(
/* [out] */ STATSTG *pstatstg,
/* [in] */ DWORD grfStatFlag)
{
return S_OK;
}
// IOleWindow
virtual HRESULT STDMETHODCALLTYPE CanInPlaceActivate( void)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivate( void)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE OnUIActivate( void)
{
return S_OK;
}
//OLECONTAINER(HRESULT STDMETHODCALLTYPE)::GetWindowContext(
//LPOLEINPLACEFRAME FAR* lplpFrame,
//LPOLEINPLACEUIWINDOW FAR* lplpDoc,
//LPRECT lprcPosRect,
//LPRECT lprcClipRect,
//LPOLEINPLACEFRAMEINFO lpFrameInfo)
virtual HRESULT STDMETHODCALLTYPE GetWindowContext(
/* [out] */ IOleInPlaceFrame **ppFrame,
/* [out] */ IOleInPlaceUIWindow **ppDoc,
/* [out] */ LPRECT lprcPosRect,
/* [out] */ LPRECT lprcClipRect,
/* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
*ppFrame = (LPOLEINPLACEFRAME)(this);
*ppDoc = 0;
lpFrameInfo->fMDIApp = FALSE;
lpFrameInfo->hwndFrame = m_hWnd;
lpFrameInfo->haccel = 0;
lpFrameInfo->cAccelEntries = 0;
RECT r;
GetClientRect(&r);
*lprcPosRect = r;
*lprcClipRect = r;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Scroll(
/* [in] */ SIZE scrollExtant)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnUIDeactivate(
/* [in] */ BOOL fUndoable)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate( void)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE DiscardUndoState( void)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE DeactivateAndUndo( void)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnPosRectChange(
/* [in] */ LPCRECT lprcPosRect)
{
return S_OK;
}
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetWindow(
/* [out] */ HWND *phwnd)
{
*phwnd = m_hWnd;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(
/* [in] */ BOOL fEnterMode)
{
return E_NOTIMPL;
}
//IOleInPlaceObject
virtual HRESULT STDMETHODCALLTYPE InPlaceDeactivate( void)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE UIDeactivate( void)
{
return S_OK;
}
virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetObjectRects(
/* [in] */ LPCRECT lprcPosRect,
/* [in] */ LPCRECT lprcClipRect)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE ReactivateAndUndo( void)
{
return S_OK;
}
//FlashWindos fun
public:
virtual void OnErrorClassNotReg();
virtual BOOL OnBeforeShowingContent();
virtual BOOL OnAfterShowingContent();
public:
//IUnknow
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppvObject);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
//IDispatch
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
UINT __RPC_FAR * pctinfo);
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(
UINT iTInfo,
LCID lcid,
ITypeInfo __RPC_FAR * __RPC_FAR * ppTInfo);
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(
REFIID riid,
LPOLESTR __RPC_FAR *rgszNames,
UINT cNames,
LCID lcid,
DISPID __RPC_FAR *rgDispId);
virtual HRESULT STDMETHODCALLTYPE Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS __RPC_FAR *pDispParams,
VARIANT __RPC_FAR *pVarResult,
EXCEPINFO __RPC_FAR * pExcepInfo,
UINT __RPC_FAR *puArgErr);
//_IShockwaveFlashEvents
public:
HRESULT OnReadyStateChange (
long newState );
HRESULT OnProgress (
long percentDone );
HRESULT FSCommand (
_bstr_t command,
_bstr_t args );
HRESULT FlashCall (
_bstr_t request );
public:
void CallFunction(WCHAR *arr)
{
m_lpControl->CallFunction(arr);
}
void OpenSwf(WCHAR *file)
{
WCHAR *fsc = m_lpControl->GetAllowFullScreen();
long frnum = m_lpControl->GetFrameNum();
WCHAR *gmv = m_lpControl->GetMovie();
WCHAR *gmvd =m_lpControl->GetMovieData();
WCHAR *gmvsta = m_lpControl->GetScale();
WCHAR *gswfro = m_lpControl->GetSWRemote();
WCHAR *gwmod = m_lpControl->GetWMode();
long gtfms = m_lpControl->GetTotalFrames();
m_lpControl->FlashVars;
gwmod = m_lpControl->GetVariable(TEXT("_x"));
gwmod = m_lpControl->GetVariable(TEXT("_y"));
gwmod = m_lpControl->GetVariable(TEXT("_alpha"));
m_lpControl->LoadMovie(0, file);
fsc = m_lpControl->GetAllowFullScreen();
m_lpControl->SetVariable(TEXT("_alpha"), TEXT("50"));
//m_lpControl->SetVariable(TEXT("_rotation"), TEXT("20"));
}
private:
long m_lVersion;
private:
int m_iRef;
private:
GUID m_CLSID;
ShockwaveFlashObjects::IShockwaveFlash * m_lpControl;
IOleObject *m_lpO;
IViewObjectEx *m_lpViewObject;
IViewObjectEx *m_lpViewObjectEx;
IOleInPlaceObject *m_lpInPlaceObj;
IOleInPlaceObjectWindowless *m_lpInPlaceObjWindowless;
IConnectionPointContainer *m_lpConCont;
IConnectionPoint *m_lpConPoint;
//HWND m_hWnd, m_hWndParent;
HWND m_hWndParent;
HINSTANCE m_hInst;
BOOL m_bChild;
BOOL m_bTransparent;
BOOL m_bFixTransparency;
DWORD m_dwConPointID;
HDC m_hdcBack;
HBITMAP m_bmpBack;
RECT m_rcBounds;
BYTE *m_lpBitsOnly;
int m_iBPP;
HDC m_hdcBackW;
HBITMAP m_bmpBackW;
BYTE *m_lpBitsOnlyW;
};
#endif // FlashWindow_h__
FlashWindow.cpp
#include "StdAfx.h"
#include "FlashWindow.h"
BOOL CFlashWindow::PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}
CFlashWindow::CFlashWindow(GUID clsid):m_CLSID(clsid)
{
m_lVersion = 0;
m_lpControl = NULL;
m_lpO = NULL;
m_lpViewObjectEx = NULL;
m_lpViewObject = NULL;
m_lpInPlaceObj = NULL;
m_lpInPlaceObjWindowless = NULL;
m_lpConCont = NULL;
m_lpConPoint = NULL;
m_hdcBack = NULL;
m_bmpBack = NULL;
m_hdcBackW = NULL;
m_bmpBackW = NULL;
m_rcBounds.left = m_rcBounds.top = m_rcBounds.right = m_rcBounds.bottom = 0;
m_lpBitsOnly = NULL;
m_lpBitsOnlyW = NULL;
m_iBPP = 0;
m_dwConPointID = 0;
m_bTransparent = TRUE;
m_bFixTransparency = FALSE;
m_iRef = 0;
}
CFlashWindow::~CFlashWindow(void)
{
if (m_lpControl)
{
if(m_lpConPoint)
{
if (m_dwConPointID)
m_lpConPoint->Unadvise(m_dwConPointID);
m_lpConPoint->Release();
}
if (m_lpConCont)
m_lpConCont->Release();
//m_lpO->Close(OLECLOSE_NOSAVE);
if(m_lpViewObject)
m_lpViewObject->Release();
if(m_lpViewObjectEx)
m_lpViewObjectEx->Release();
if(m_lpInPlaceObjWindowless)
m_lpInPlaceObjWindowless->Release();
if(m_lpInPlaceObj)
m_lpInPlaceObj->Release();
if(m_lpO)
m_lpO->Release();
m_lpControl->Release();
}
if(m_hdcBack)
::DeleteDC(m_hdcBack);
if(m_bmpBack)
::DeleteObject(m_bmpBack);
if(m_hdcBackW)
::DeleteDC(m_hdcBackW);
if(m_bmpBackW)
::DeleteObject(m_bmpBackW);
}
LRESULT CFlashWindow::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/)
{
m_hInst = _AtlBaseModule.GetModuleInstance();
//::SetWindowPos(GetParent(), HWND_TOP, 0, 0, 0,0, SWP_NOSIZE | SWP_NOMOVE);
HRESULT hr;
hr = OleCreate(m_CLSID, IID_IOleObject, OLERENDER_DRAW,
0, (IOleClientSite *) this, (IStorage *)this, (void **) &m_lpO);
if (FAILED(hr))
{
// E_OUTOFMEMORY
if (hr == REGDB_E_CLASSNOTREG)
{
OnErrorClassNotReg();
}
return FALSE;
}
hr = OleSetContainedObject(m_lpO, TRUE);
if(FAILED(hr))
return FALSE;
hr = m_lpO->QueryInterface(__uuidof(ShockwaveFlashObjects::IShockwaveFlash), (void **)&m_lpControl);
if(FAILED(hr))
return FALSE;
hr = m_lpO->QueryInterface(IID_IViewObjectEx, (void **) &m_lpViewObjectEx);
if(FAILED(hr))
{
m_lpViewObjectEx = NULL;
hr = m_lpO->QueryInterface(IID_IViewObject, (void **)&m_lpViewObject);
if(FAILED(hr))
return FALSE;
}
if(m_bTransparent)
{
hr = m_lpO->QueryInterface(IID_IOleInPlaceObjectWindowless, (void **) & m_lpInPlaceObjWindowless);
if (FAILED(hr))
{
hr = m_lpO->QueryInterface(IID_IOleInPlaceObject, (void**) &m_lpInPlaceObj);
if (FAILED(hr))
{
return FALSE;
}
m_bTransparent = FALSE;
}
}
else
{
hr = m_lpO->QueryInterface(IID_IOleInPlaceObject, (void **)&m_lpInPlaceObj);
if (FAILED(hr))
{
return FALSE;
}
}
if (!OnBeforeShowingContent())
{
return FALSE;
}
m_bTransparent = FALSE;
hr = m_lpO ->DoVerb(OLEIVERB_SHOW , NULL, (IOleClientSite *) this, 0,NULL, NULL);
if (FAILED(hr))
return FALSE;
if (!OnAfterShowingContent())
return FALSE;
return FALSE;
}
LRESULT CFlashWindow::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/)
{
CPaintDC dc(m_hWnd);
RECT r;
GetClientRect(&r);
Draw(dc, &r, TRUE);
return FALSE;
}
void CFlashWindow::Draw(HDC hdcDraw, const RECT *rcDraw, BOOL bErase)
{
HWND hwnd = m_hWnd;
HRESULT hr;
RECT r = {0};
IOleObject *lpO = m_lpO;
IViewObject *lpV = m_lpViewObjectEx ?(IViewObject *) m_lpViewObjectEx:m_lpViewObject;
if (!m_bTransparent)
{
RECT rTotal;
GetClientRect(&rTotal);
if (lpV)
{
if( !hdcDraw)
{
hdcDraw = ::GetDC(hwnd);
hr = OleDraw(lpV, DVASPECT_CONTENT, hdcDraw, &rTotal);
::ReleaseDC(hwnd, hdcDraw);
}
else
{
hr = OleDraw(lpV, DVASPECT_CONTENT, hdcDraw, &rTotal);
}
}
return;
}
GetClientRect(&r);
if (!m_hdcBack || EqualRect(&r, &m_rcBounds))
{
if(m_hdcBack)
::DeleteDC(m_hdcBack);
if(m_bmpBack)
::DeleteObject(m_bmpBack);
if(m_hdcBackW)
::DeleteObject(m_bmpBackW);
m_rcBounds = r;
HDC hdc = ::GetDC(hwnd);
BITMAPINFOHEADER bih = {0};
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biBitCount = 32;
bih.biClrImportant = BI_RGB;
bih.biPlanes = 1;
bih.biWidth = r.right - r.left;
bih.biHeight = (r.bottom - r.top);
m_hdcBack = CreateCompatibleDC(hdc);
m_bmpBack = CreateDIBSection(hdc, (BITMAPINFO*) &bih, DIB_RGB_COLORS, (void **)&m_lpBitsOnly,NULL,0x0);
SelectObject(m_hdcBack, m_bmpBack);
if(m_bFixTransparency)
{
m_hdcBackW = CreateCompatibleDC(hdc);
m_bmpBackW = CreateDIBSection(hdc, (BITMAPINFO*) &bih, DIB_RGB_COLORS, (void **)&m_lpBitsOnly, NULL, 0x0);
SelectObject(m_hdcBackW, m_bmpBackW);
}
::ReleaseDC(hwnd, hdc);
if(m_iBPP == 0)
m_iBPP = GetDeviceCaps(m_hdcBack, BITSPIXEL);
}
POINT p = {r.left, r.top};
POINT p2 = {0,0};
SIZE sz = {r.right - r.left, r.bottom - r.top};
if(lpO && lpV)
{
RECT rTotal;
GetClientRect(&rTotal);
RECTL rcBounds = {rTotal.left, rTotal.top, rTotal.right, rTotal.bottom};
BYTE *dst = m_lpBitsOnly, *dstW;
if (m_iBPP == 32)
{
if(!m_bFixTransparency)
{
memset(m_lpBitsOnly, 0, sz.cx * sz.cy * 4);
hr = OleDraw(lpV, DVASPECT_TRANSPARENT, m_hdcBack, &rTotal);
}
else
{
memset(m_lpBitsOnly, 0, sz.cx * sz.cy * 4);
memset(m_lpBitsOnlyW, 255, sz.cx * sz.cy * 4);
hr = OleDraw(lpV, DVASPECT_TRANSPARENT, m_hdcBack, &rTotal);
hr = OleDraw(lpV, DVASPECT_TRANSPARENT, m_hdcBackW, &rTotal);
dst = m_lpBitsOnly;
dstW = m_lpBitsOnlyW;
BYTE r, g, b, a, rw, gw, bw, aw, alpha_r, alpha_g, alpha_b, alpha;
for (int y = 0; y < sz.cy; y++)
{
for (int x = 0; x <sz.cx; x++)
{
r = *dst++;
g = *dst++;
b = *dst++;
a = *dst++;
rw = *dstW++;
gw = *dstW++;
bw = *dstW++;
aw = *dstW++;
alpha_r = rw - r;
alpha_g = gw - g;
alpha_b = bw - b;
alpha = (alpha_r + alpha_g + alpha_b) / 3;
*(dst - 1) = 255 - alpha;
}
}
}
}
else
{
HDC hdcParent = ::GetWindowDC(GetParent());
BOOL bRet = BitBlt(m_hdcBack, 0, 0, rTotal.right, rTotal.bottom, hdcParent, 0, 0, SRCCOPY);
::ReleaseDC(GetParent(), hdcParent);
hr = OleDraw(lpV, DVASPECT_TRANSPARENT,m_hdcBack, &rTotal);
dst = m_lpBitsOnly;
}
}
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.AlphaFormat = AC_SRC_ALPHA;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
BOOL bRet = UpdateLayeredWindow(hwnd, NULL, &p, &sz, m_hdcBack, &p2, 0, &bf, m_iBPP==32?ULW_ALPHA:ULW_OPAQUE);
}
LRESULT CFlashWindow::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/)
{
HRESULT hr;
RECT rPos;
GetClientRect(&rPos);
RECT rClip = rPos;
if(m_lpInPlaceObjWindowless)
hr = m_lpInPlaceObjWindowless->SetObjectRects(&rPos, &rClip);
else if (m_lpInPlaceObj)
hr = m_lpInPlaceObj->SetObjectRects(&rPos, &rClip);
return FALSE;
}
LRESULT CFlashWindow::OnNchittest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/)
{
int x = LOWORD(lParam), y = HIWORD(lParam);
if (m_lpO && m_lpViewObjectEx)
{
IViewObjectEx *lpV = m_lpViewObjectEx;
POINT p = {x, y};
DWORD dwRes;
RECT rTotal;
GetWindowRect(&rTotal);
HRESULT hr = lpV->QueryHitPoint(DVASPECT_DOCPRINT, &rTotal, p, 1, &dwRes);
if (hr == S_OK)
{
if (dwRes == HITRESULT_OUTSIDE)
return HTTRANSPARENT;
else
return HTCLIENT;
}
}
return TRUE;
}
LRESULT CFlashWindow::OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&/* bHandled*/)
{
if (uMsg == WM_RBUTTONDBLCLK || uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
{
return TRUE;
}
if(m_lpInPlaceObjWindowless)
{
HRESULT hr;
LRESULT res;
hr = m_lpInPlaceObjWindowless->OnWindowMessage(uMsg,wParam,lParam, &res);
if(hr == S_OK)
{
return res;
}
}
return FALSE;
}
void CFlashWindow::OnErrorClassNotReg()
{
}
HRESULT STDMETHODCALLTYPE CFlashWindow::QueryInterface(REFIID riid, void ** ppvObject)
{
if (IsEqualGUID(riid, IID_IUnknown))
*ppvObject = (void*)this;
else if (IsEqualGUID(riid, IID_IOleInPlaceSite))
*ppvObject = (void*)dynamic_cast<IOleInPlaceSite*>(this);
else if(IsEqualGUID(riid, IID_IOleInPlaceSiteEx))
*ppvObject = (void *)dynamic_cast<IOleInPlaceSiteEx*> (this);
else if (IsEqualGUID(riid, IID_IOleInPlaceSiteWindowless))
*ppvObject = (void *)dynamic_cast<IOleInPlaceSiteWindowless*>(this);
else if(IsEqualGUID(riid, IID_IOleInPlaceFrame))
*ppvObject = (void *)dynamic_cast<IOleInPlaceObject *>(this);
else if(IsEqualGUID(riid, IID_IOleInPlaceFrame))
*ppvObject = (void *)dynamic_cast<IOleInPlaceFrame *>(this);
else if (IsEqualGUID(riid, IID_IStorage))
*ppvObject = (void*)dynamic_cast<IStorage*>(this);
else if (IsEqualGUID(riid, ShockwaveFlashObjects::DIID__IShockwaveFlashEvents))
*ppvObject = (void*)dynamic_cast<ShockwaveFlashObjects::_IShockwaveFlashEvents *>(this);
else
{
*ppvObject = 0;
return E_NOINTERFACE;
}
if (!(*ppvObject))
return E_NOINTERFACE;
m_iRef ++;
return S_OK;
}
BOOL CFlashWindow::OnBeforeShowingContent()
{
m_lVersion = m_lpControl->FlashVersion();
if ((m_lVersion & 0x00FF0000) == 0x00080000)
m_bFixTransparency = TRUE;
else
m_bFixTransparency = FALSE;
HRESULT hr;
hr = m_lpControl->QueryInterface(IID_IConnectionPointContainer, (void**)&m_lpConCont);
if ( FAILED(hr))
return FALSE;
hr = m_lpConCont->FindConnectionPoint(ShockwaveFlashObjects::DIID__IShockwaveFlashEvents, &m_lpConPoint);
if ( FAILED(hr))
return FALSE;
hr = m_lpConPoint->Advise((ShockwaveFlashObjects::_IShockwaveFlashEvents*) this, & m_dwConPointID);
if ( FAILED(hr))
return FALSE;
if (m_bTransparent)
m_lpControl->PutWMode(TEXT("transparent"));
m_lpControl->PutScale(TEXT("showAll"));
m_lpControl->PutBackgroundColor(0x00000000);
m_lpControl->PutEmbedMovie(FALSE);
return TRUE;
}
BOOL CFlashWindow::OnAfterShowingContent()
{
HRESULT hr;
m_lpControl->PutEmbedMovie(TRUE);
hr = m_lpControl->LoadMovie(0, TEXT("e:\\test.swf"));
if (FAILED(hr))
return FALSE;
hr = m_lpControl->Play();
if (FAILED(hr))
return FALSE;
return TRUE;
}
ULONG STDMETHODCALLTYPE CFlashWindow::AddRef()
{
m_iRef ++;
return m_iRef;
}
ULONG STDMETHODCALLTYPE CFlashWindow::Release()
{
m_iRef--;
return m_iRef;
}
//IDispatch
HRESULT STDMETHODCALLTYPE CFlashWindow::GetTypeInfoCount(UINT __RPC_FAR *pctinfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CFlashWindow::GetTypeInfo(
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CFlashWindow::GetIDsOfNames(
/* [in] */ REFIID riid,
/* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
/* [in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CFlashWindow::Invoke(
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
/* [out] */ VARIANT __RPC_FAR *pVarResult,
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
/* [out] */ UINT __RPC_FAR *puArgErr)
{
if(dispIdMember > 0)
{
CString str;
str.Format(TEXT("%s"),pDispParams->rgvarg->bstrVal);
ATLTRACE(str);
ATLTRACE("\r\n");
}
/* switch (dispIdMember)
{
default:
return S_OK;
}*/
return S_OK;
}
//ShockwaveFlashObjects::_IShockwaveFlashEvents
HRESULT CFlashWindow::OnReadyStateChange (
long newState )
{
return S_OK;
}
HRESULT CFlashWindow::OnProgress (
long percentDone )
{
return S_OK;
}
HRESULT CFlashWindow::FSCommand (
_bstr_t command,
_bstr_t args )
{
return S_OK;
}
HRESULT CFlashWindow::FlashCall (
_bstr_t request )
{
return S_OK;
}
在mainfram创建代码:
RECT r = {0,0,800,480};
CFlashWindow m_flash;
m_flash.Create(m_hWnd, r, TEXT("MyOleControlWindow"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS/*,WS_EX_LAYERED*/);
This article illustrates the implementation of a simple OLE container that is used to host a transparent or windowed Flash Player Object.
Part 1. OLE Interfaces
The simplest OLE control implementation for an ActiveX object should consist of several interfaces:
* IOleClientSite
* IOleInPlaceSiteWindowless
* IOleInPlaceFrame
* IStorage
My implementation of the OLE container is called COleContainerWnd. It is declared as in the following:
template<class TObj> class COleContainerWnd :
virtual public IOleClientSite,
virtual public IOleInPlaceSiteWindowless,
virtual public IOleInPlaceFrame,
virtual public IStorage
* Post a comment
* Email Article
* Print Article
* Share Articles
o Digg
o del.icio.us
o Newsvine
o Facebook
o Google
o LinkedIn
o MySpace
o Reddit
o Slashdot
o StumbleUpon
o Technorati
o Twitter
o Windows Live
o YahooBuzz
o FriendFeed
where TObj is the desired interface of an ActiveX object.
Part 2. Flash Object
Importing the Flash Object into VC++ is done by using the #import command:
#import "c:\\windows\\system32\\macromed\\flash\\flash.ocx" named_guids
The named_guids directive is used to generate a CLSID_ShockwaveFlash class ID.
If you are running under Windows 2000, change the system folder to "winnt".
As a result of the #import command, the compiler will generate the flash.tli and flash.tlh files. They contain your Flash Player interface declarations.
Part 3. CFlashWnd Derivative Class
This class is based on COleContainer and uses ShockwaveFlashObjects:IShockwaveFlash as the template parameter:
class CFlashWnd :
public COleContainerWnd<ShockwaveFlashObjects::IShockwaveFlash>,
public ShockwaveFlashObjects::_IShockwaveFlashEvents
It also implements the _IShockwaveFlashEvents interface to receive fscommand() events from the Flash movie.
The creation of CFlashWnd object:
g_flashWnd = new CFlashWnd;
g_flashWnd->Create(ShockwaveFlashObjects::CLSID_ShockwaveFlash,
WS_EX_LAYERED, WS_POPUP | WS_VISIBLE |
WS_CLIPSIBLINGS, g_hWnd, g_hInst);
The first parameter is the class ID of the Flash Player Object. The second parameter is the extended window style; it should be set to WS_EX_LAYERED for transparent Flash control and 0 for non-transparent. The third is the window style, followed by the owner window and application instance.
The HWND handle for the OLE container can be retrieved by using the GetHWND() function.
Part 4. Inside CFlashWnd::Create()
First, the window class is registered. Then, the window with your specified styles is created.
The OleCreate function creates an instance of an IOleObject object. It passes COleContainer's IOleClientSite and IStorage to the IOleObject object. Then, the OleSetContainedObject is called to inform the object of its embedded state. TheIShockwaveFlash interface is obtained from IOleObject by using QueryInterface. IViewObjectEx is obtained in the same way.
If a windowless control is created, the container needs the IOleInPlaceObjectWindowless interface to dispatch messages to the object because the object does not have its own window. In another case, the IOleInPlaceObject interface is required to draw the object.
IOleObject::DoVerb() is used to show the object and switch it to its running state.
hr = m_lpO->DoVerb(OLEIVERB_SHOW, NULL, (IOleClientSite *)this,
0, NULL, NULL);
Now, the Flash Player object is fully created.
Part 5. Transparent Window Drawing
It is not quite trivial to draw semitransparent translucent windows. The algorithm is the following:
1. Create a WS_POPUP window with WS_EX_LAYERED style.
2. Create a 32-bit DIB Section using the CreateDIBSection() function and select it to any compatible DC. It will be an offscreen plain to render window contents to.
3. Render window contents, preserving the alpha channel.
4. Call the UpdateLayeredWindow() function to draw the window to the screen.
To render Flash player contents, I use the OleDraw helper function. It internally calls the IViewObject::Draw() method:
hr = OleDraw(lpV, DVASPECT_TRANSPARENT, hdcDraw, &rTotal);
* lpV: IViewObject interface of flash player control
* hdcDraw: Offscreen plain
* rTotal: Client rectangle of the container window
The DVASPECT_TRANSPARENT drawing aspect tells the object to draw its content using alpha blending.
When implementing this, I met a serious bug in Flash Player Control 8. This bug is only in this version. Players 7 and 9 are free of it. The bug is in the way Flash Control fills the alpha channel of a 32-bit device context. If at least 1 of 255 alpha values is applied to a pixel, the colors are mixed correctly, but the resulting alpha channel is set to 255, even if it was initially zero. This makes it impossible to create semitransparent windows. So, I had to develop a solution to fix this bug. The solution is quite simple. These equations are used by the Flash Player Control for alpha blending:
* R' = Rdst * (1 - alpha) + Rsrc * alpha
* G' = Gdst * (1 - alpha) + Gsrc * alpha
* B' = Bdst * (1 - alpha) + Bsrc * alpha
If I draw the contents of Flash onto a black surface, I get the following:
* R'black = Rsrc * alpha
* G'black = Gsrc * alpha
* B'black = Bsrc * alpha
If I draw the contents of Flash onto a white surface, I get this:
* R'white = 255 * (1 - alpha) + Rsrc * alpha
* G'white = 255 * (1 - alpha) + Rsrc * alpha
* B'white = 255 * (1 - alpha) + Rsrc * alpha
Here is the system of equations:
* R'black = Rsrc * alpha
* R'white = 255 * (1 - alpha) + Rsrc * alpha
where alpha and Rsrc are unknown. After solving it, you will get:
* (255-Alpha) = R'white - R'black
* Alpha = 255 - (R'white - R'black)
So, the solution is found. Now, you can draw the contents of the Flash player twice and then correct the spoiled alpha channel.
Part 6. Events
Flash Control Events are handled by using IDispatch. After the Flash control is created, you retrieve a IConnectionPointContainer and try to find DIID__IShockwaveFlashEvents' connection point:
hr = m_lpControl->QueryInterface(IID_IConnectionPointContainer,
(void**)&m_lpConCont);
if (FAILED(hr))
return FALSE;
hr = m_lpConCont->FindConnectionPoint(
ShockwaveFlashObjects::DIID__IShockwaveFlashEvents, &m_lpConPoint);
if (FAILED(hr))
return FALSE;
hr = m_lpConPoint->Advise((ShockwaveFlashObjects::
_IShockwaveFlashEvents *)this,
&m_dwConPointID);
if (FAILED(hr))
return FALSE;
After a successful Advise(), you will receive events in the IDispatch::Invoke method.