Click here to Skip to main content
6,594,932 members and growing! (15,322 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » COM / COM+ » General     Advanced

Transparent Flash Control in plain C++

By Makarov Igor

OLE container implementation for hosting Transparent Flash Player Control using plain C++. No ATL, MFC or other libraries are used.
C++, Windows, Visual Studio, COM, Dev
Posted:4 Jul 2006
Views:94,025
Bookmarked:53 times
Unedited contribution
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
34 votes for this article.
Popularity: 6.27 Rating: 4.09 out of 5
3 votes, 8.8%
1
1 vote, 2.9%
2
1 vote, 2.9%
3
4 votes, 11.8%
4
25 votes, 73.5%
5

This article illustrates the implementation of a simple OLE container, used for hosting 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 OLE container is called COleContainerWnd. It is declared as following:

template<CLASS TObj> class COleContainerWnd :
virtual public IOleClientSite,
virtual public IOleInPlaceSiteWindowless,
virtual public IOleInPlaceFrame,
virtual public IStorage


where TObj is the desired interface of an ActiveX object.

Part 2. Flash Object.

Importing the Flash Object into VC++ is done by #import command:

#import "c:\\windows\\system32\\macromed\\flash\\flash.ocx" named_guids

named_guids directive is used to generate CLSID_ShockwaveFlash class ID.
If you are running under Windows 2000, change the system folder to "winnt".

As a result of #import command compiler will generate flash.tli and flash.tlh files, containing 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<?XML:NAMESPACE PREFIX = ShockwaveFlashObjects /><ShockwaveFlashObjects::IShockwaveFlash>,
public ShockwaveFlashObjects::_IShockwaveFlashEvents


It also implements _IShockwaveFlashEvents interface to receive fscommand() events from 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 class ID of Flash Player Object. The second parameter is extended window style, which should be set to WS_EX_LAYERED for transparent flash control and 0 for non-transparent. The third is window style, then goes owner window and application instance.

HWND handle for the OLE container can be retrieved by using GetHWND() function.

Part 4. Inside CFlashWnd::Create().

First window class is registered. Then, window with specified styles is created.

OleCreate function is used to create an instance of IOleObject object. It passes COleContainer's IOleClientSite and IStorage to IOleObject object.

Then OleSetContainedObject is called to inform the object of its embedded state.

IShockwaveFlash interface is obtained from IOleObject using QueryInterface. IViewObjectEx is obtained in the same way.

If a windowless control is created, then the container needs IOleInPlaceObjectWindowless interface to dispatch messages to the object since the object does not have it's own window. In other case, IOleInPlaceObject interface is required to draw the object.

IOleObject::DoVerb() is used to show the object and switch it to 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 following:

1. Create WS_POPUP window with WS_EX_LAYERED style.
2. Create a 32 bit DIB Section using 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 UpdateLayeredWindow() function to draw the window to screen.

To render flash player contents, I use OleDraw helper function, which internally calls 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

DVASPECT_TRANSPARENT drawing aspect tells the object to draw it's content using alpha blending.

While implementing this, I have 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 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 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 black surface I get

R'black = Rsrc * alpha
G'black = Gsrc * alpha
B'black = Bsrc * alpha

If I draw the contents of Flash onto white surface I get

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, we can draw contents of flash player twice and then correct the corrupted alpha channel.

Part 6. Events.

Flash Control Events are handled using IDispatch. After flash control is created we 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 successful Advise() we will receive events in IDispatch::Invoke method.

Part 7. DirectDraw (Updated).

Flash Control can slightly improve drawing performance by using DirectDraw3 interface. Flash object queries it through ShockwaveFlashObjects::IServiceProvider::raw_RemoteQueryService method. It passes IID_IDirectDraw3 guid as guidService and riid parameters. The implementation looks like this:

//include direct draw header (do not link ddraw.lib)

#include <ddraw.h>

//declare required GUIDs

#ifndef DEFINE_GUID2

#define DEFINE_GUID2(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \

const GUID name \

= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }

#endif

DEFINE_GUID2(CLSID_DirectDraw,0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35);

DEFINE_GUID2(CLSID_DirectDraw7,0x3c305196,0x50db,0x11d3,0x9c,0xfe,0x00,0xc0,0x4f,0xd9,0x30,0xc5);

DEFINE_GUID2(IID_IDirectDraw,0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);

DEFINE_GUID2(IID_IDirectDraw3,0x618f8ad4,0x8b7a,0x11d0,0x8f,0xcc,0x0,0xc0,0x4f,0xd9,0x18,0x9d);

DEFINE_GUID2(IID_IDirectDraw4,0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5);

DEFINE_GUID2(IID_IDirectDraw7,0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b);

//declare smart pointer type for IDirectDraw4 interface

_COM_SMARTPTR_TYPEDEF(IDirectDraw4, IID_IDirectDraw4);

//the implementation of IServiceProvider interface

HRESULT __stdcall CFlashWnd::raw_RemoteQueryService (

GUID * guidService,

GUID * riid,

IUnknown * * ppvObject )

{

HRESULT hr;

if (IsEqualGUID(*guidService, IID_IDirectDraw3))

{

if (!m_lpDD4)

{

m_lpDD4 = new IDirectDraw4Ptr;

hr = m_lpDD4->CreateInstance(CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER);

if (FAILED(hr))

{

delete m_lpDD4;

m_lpDD4 = NULL;

return E_NOINTERFACE;

}

}

if (m_lpDD4 && m_lpDD4->GetInterfacePtr())

{

*ppvObject = m_lpDD4->GetInterfacePtr();

m_lpDD4->AddRef();

return S_OK;

}

}

return E_NOINTERFACE;

}


Download source code - 16.1 Kb

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Makarov Igor


Member
Visual C++ developer, team leader (mailto: mak_test@mail.ru)
Occupation: Web Developer
Location: Russian Federation Russian Federation

Other popular COM / COM+ articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 164 (Total in Forum: 164) (Refresh)FirstPrevNext
GeneralMemory hogging when ActionScript is added PinmemberBoris Epelbaum5:11 30 Sep '09  
Questionpuzzle on CreateWindowEx() Pinmemberxins012317:42 9 Jul '09  
QuestionRe: puzzle on CreateWindowEx() Pinmemberxins012318:35 9 Jul '09  
QuestionWhy the flash window can't move automatically follow its parent? [modified] Pinmemberxins012323:39 8 Jul '09  
GeneralCrash with Adobe Flash Player 10b (10.0.22.87) PinmemberMad_Gandalf0:16 14 May '09  
GeneralRe: Crash with Adobe Flash Player 10b (10.0.22.87) PinmemberRaPit14:28 16 May '09  
GeneralRe: Crash with Adobe Flash Player 10b (10.0.22.87) PinmemberAttila F22:55 22 Jul '09  
Generalproblem with flash have action script [modified] Pinmemberthuong10127721:50 10 May '09  
Generalperform performance Pinmemberthuong1012770:39 6 May '09  
GeneralWhen enter into OLECONTAINER(void)::Draw() function the program crashed PinmemberMember 461199317:22 5 May '09  
GeneralIn the Draw(..) function, GetHWND() return dummy handle. PinmemberMember 303867421:02 21 Apr '09  
GeneralTransparency problem in 16 bpp display mode Pinmemberbmk_shepherd7:29 21 Apr '09  
GeneralCan not play flash in thread Pinmemberbmk_shepherd19:20 8 Apr '09  
GeneralRe: Can not play flash in thread Pinmemberbmk_shepherd18:28 16 Apr '09  
GeneralRe: Can not play flash in thread PinmemberKaSA12:44 21 Apr '09  
GeneralRe: Can not play flash in thread Pinmemberbmk_shepherd5:36 21 Apr '09  
GeneralRe: Can not play flash in thread PinmemberKaSA16:42 21 Apr '09  
GeneralRe: Can not play flash in thread Pinmemberthuong10127721:57 10 May '09  
QuestionNo blinking cursor PinmemberMugdha Jain13:53 7 Apr '09  
Questionhow to detect the flash movie have been finished ? Pinmembere_ilite23:38 19 Aug '07  
AnswerRe: how to detect the flash movie have been finished ? PinmemberSun(#)3:50 26 Aug '07  
QuestionHow to add support for ExternalInterface.addCallback? Pinmembervian250:51 19 Aug '07  
GeneralDid anybody try to do the same with MSHTML? Pinmemberdude15316:14 17 Aug '07  
QuestionA twinkle problem with DirectShow. PinmemberTead20:08 12 Aug '07  
Generalbuilding in vs2003 Pinmember_xmind_0:27 1 Aug '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 4 Jul 2006
Editor:
Copyright 2006 by Makarov Igor
Everything else Copyright © CodeProject, 1999-2009
Web17 | Advertise on the Code Project