Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

C++ and Flash: Send or get data from/to a SWF using C++ and ActiveX in Win32

4.59/5 (23 votes)
24 Oct 2011CPOL4 min read 84.9K   4.7K  
Embed flash to your applications and communicate with it with C++.

Introduction

Flash is nice, but it is mainly used in the Web. How about embedding flash into your own applications AND transfer data from/to them?

I've found out that many have discussed this subject, but sometimes their method will mysteriously fail for a reason. Here is a fully functional and very simple project.

1.png

Background

This article assumes you are familiar with C++ and COM. Make sure you review these topics and also review my Win32 ActiveX article. You can also use MFC or ATL to insert the ActiveX control without messing with the truly messy COM implementations. This article also assumes that you know the mechanisms of hosting an ActiveX control and connecting to it for notifications, and although my AX.CPP code includes all functions required, these functions are not discussed in this article in detail.

Also, ActionScript 3.0 knowledge is required.

Creating the ActiveX Control

You may have already been implementing your own methods to insert an ActiveX control in your application, and if so, you do not need to use my AX.CPP to get an IShockwaveFlash pointer. To insert the "Shockwave.Flash" ActiveX control, I use the Win32 ActiveX article discussion and AX.CPP, which merely implements an IOleClientSite and allows me to use the class ID in the resource file:

CONTROL "{D27CDB6E-AE6D-11CF-96B8-444553540000}", 888, 
	"AX", WS_CHILD | WS_VISIBLE, 10, 9, 399, 206 

in order to create an "AX" control (which accepts as the Window title the class ID of the requested ActiveX control). Once we have a HWND, I can send it an AX_QUERYINTERFACE to get a pointer to an IShockwaveFlash:

C++
CLSID iidx = __uuidof(IShockwaveFlash);
IShockwaveFlash* p = 0;
HRESULT hr = (HRESULT)SendMessage(hX,AX_QUERYINTERFACE,(WPARAM)&iidx,(LPARAM)&p);

Of course, your method might have been ATL or similar. The last thing to do is to activate the control in place:

C++
SendMessage(hX,AX_INPLACE,1,0);

Loading the SWF

I simply extract "1.swf" from the resource to a temporary file and load it (along with a white bg color):

C++
_bstr_t x(df);
p->put_BackgroundColor(RGB(255,255,255));
p->put_Movie(x); 

Sending Data to the SWF

Registering the ActionScript Function

Many methods are suggested, and I will use the simplest and the most efficient: The way to call an ActionScript 3.0 function from your C++ code. First, let's define (in frame 1) an ActionScript function in the .FLA file:

C++
import flash.external.ExternalInterface; 
// The following is called from our host 
function TestFunction1(he:String) 
	{
	this.gotoAndPlay(2);
	}
// Register TestFunction1 to be called
flash.external.ExternalInterface.addCallback("foo1",TestFunction1); 

What do we have here? Simply a function called "TestFunction1" which accepts a String parameter (This function merely goes to frame 2, leaving the passed string unused, but it is passed so you understand how you would pass arguments to the function).

After that, we must call flash.external.ExternalInterface.addCallback and register the "TestFunction1" as a function that may be called by our container. This function will be visible with the "foo1" name. You can think of a similar thing in DEF file "EXPORTS" section.

Calling the Function

IShockwaveFlash* has a CallFunction member which we can call. It's simple: Flash expects the entity of the call to be passed as a XML Element with the "name" "foo1" and the arguments in XML format. You can learn more on the XML format that Flash expects in this Adobe Help link.

The WM_COMMAND handler in my code demonstrates all this, and the call is shown below:

C++
_bstr_t fu(L"<invoke name=\"foo1\" returntype=\"xml\">
	<arguments><string>Hello</string></arguments></invoke>");
_bstr_t rs = p->CallFunction(fu);

Getting Notified of Events

OK, we have called an AS 3.0 function, but how could an AS 3.0 function call us? Simply - yes you have guessed it already - via IDispatch.

First, we use standard ActiveX advise mechanism to register for a notification - see AX.CPP and the call to AXConnectObject (you might use your own MFC/ATL methods to connect as well). We pass to it our own IDispatch implementation which, apart from the usual IUnknown and IDispatch methods, implements IDispatch::Invoke as follows:

C++
HRESULT _stdcall Invoke(DISPID d,REFIID ,LCID ,WORD ,DISPPARAMS* p,
			VARIANT FAR*,EXCEPINFO FAR* ,unsigned int FAR*)
{
	if (d != 0xC5) // DISPID for "Flash Call"
		return S_OK;
	if (!p)
		return E_POINTER;
	if (p->cArgs != 1)
		return E_INVALIDARG;
	if (p->rgvarg[0].vt != VT_BSTR)
		return E_INVALIDARG;

	wstring w = p->rgvarg[0].bstrVal;
	MessageBox(0,w.c_str(),L"Message",MB_ICONINFORMATION);

	return S_OK;
}

Let's explain this. We check the dispid for 0xC5, the "FlashCall" function. This function is called from ActionScript through our IDispatch, passing a BSTR with the calling parameters. This as you might have already guessed has the same XML format we used earlier and in my code. I simply display the result in a MessageBox - of course, you want to use my XML library to parse it and handle the function call.

And here is how we call our function from ActionScript 3.0:

C++
// Listener for b2
function Act2(et:Event):void
{
	flash.external.ExternalInterface.call("ext2",2);
}

This is the listener for the second button we have created. In this case, the "ext2" will be passed as the "name" variable in the <invoke> element, and the number '2' will be passed as a <number> element in <arguments>.

x64 Compatibility

If you have Flash x64 ActiveX installed (for Internet Explorer), this will also work. Flash support in x64 is really new and for complex AS functions you may run into problems, but eventually everything will work.

The Code

Somewhat dirty (as in all my CodeProject articles ;) but it works. The zip contains:

  • Project files SLN and VCPROJ for Visual Studio 2008 or later
  • 1.FLA and 1.SWF flash source and movie
  • AX.H / AX.CPP ActiveX Win32 interfaces
  • MAIN.CPP which demonstrates all we have said so far.
  • Other solution files like MAIN.RC, X86.MANIFEST and FUNC.H.
  • The executable, in case you get bored to open Visual Studio to compile the sample.

GOOD LUCK.

History

  • 21-10-2011: Typos, some additions
  • 17-10-2011: First release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)