Game Development Community

Maybe the best solution for embeding Flash (I am wrong)

by Huan Li · 05/08/2009 (2:00 am) · 1 comments

There's good flash-embeding resource found from GameDev.net.
The original link is:
www.gamedev.net/community/forums/topic.asp?topic_id=503535
That post had been retired,so i post it here for discussing.
/********************************************************************
	created:	2008/08/02
	created:	2:8:2008   17:18
	filename: 	e:Visual Studio 2005ProjectsSamplesSwfViewerDxFlashViewer.h
	file path:	e:Visual Studio 2005ProjectsSamplesSwfViewer
	file base:	DxFlashViewer
	file ext:	h
	author:		xoyojank
	
	purpose:	A DirectX Flash Viewer
*********************************************************************/
#pragma once
#include <d3dx9.h>

#include <atlbase.h>
#include <atlcom.h>
#include <atlwin.h>
#pragma comment(lib,"atl")

#import "flash.ocx"
using namespace ShockwaveFlashObjects; 


class DxFlashViewer
{
public:
	DxFlashViewer(void);
	~DxFlashViewer(void);

	bool Init( IDirect3DDevice9* pDevice, HWND hWnd, int width, int height );

	void OpenFlash(const char* filename);

	void UpdateTexture();

	IDirect3DTexture9* GetTexturePtr();

	int GetViewerWidth() const;
	int GetViewerHeight() const;
	int GetTextureWidth() const;
	int GetTextureHeight() const;

	void OnWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam);

private:
	int mViewerWidth;
	int mViewerHeight;
	int mTextureWidth;
	int mTextureHeight;
	IDirect3DTexture9* mTexture;
	IDirect3DDevice9* mDevice;

	HWND mViewerWnd;
	IShockwaveFlash* mFlashCtrl;
	IOleInPlaceObjectWindowless* mWndlessObject;
};
/********************************************************************
	created:	2008/08/02
	created:	2:8:2008   17:19
	filename: 	e:Visual Studio 2005ProjectsSamplesSwfViewerDxFlashViewer.cpp
	file path:	e:Visual Studio 2005ProjectsSamplesSwfViewer
	file base:	DxFlashViewer
	file ext:	cpp
	author:		xoyojank
	
	purpose:	A DirectX Flash Viewer
*********************************************************************/
#include "StdAfx.h"
#include "DxFlashViewer.h"


DxFlashViewer::DxFlashViewer(void)
: mViewerWidth(0)
, mViewerHeight(0)
, mTextureWidth(0)
, mTextureHeight(0)
, mTexture(NULL)
, mDevice(NULL)
, mViewerWnd(0)
, mFlashCtrl(NULL)
, mWndlessObject(NULL)
{
}

DxFlashViewer::~DxFlashViewer(void)
{
	DestroyWindow(this->mViewerWnd);
	if (NULL != this->mTexture)
	{
		this->mTexture->Release();
		this->mTexture = NULL;
	}
	if (NULL != this->mFlashCtrl)
	{
		this->mFlashCtrl->Release();
		this->mFlashCtrl = NULL;
	}
	if (NULL != this->mWndlessObject)
	{
		this->mWndlessObject->Release();
		this->mWndlessObject = NULL;
	}
}

bool DxFlashViewer::Init( IDirect3DDevice9* pDevice, HWND hWnd, int width, int height )
{
	if (NULL == pDevice || width <= 0 || height <= 0)
		return false;

	this->mDevice = pDevice;
	this->mViewerWidth = width;
	this->mViewerHeight = height;

	// calculate texture size required (next power of two above browser window size)
	for ( mTextureWidth = 1; mTextureWidth < mViewerWidth; mTextureWidth <<= 1 );
	for ( mTextureHeight = 1; mTextureHeight < mViewerHeight; mTextureHeight <<= 1 );

	// create the browser window in the background
	WNDCLASSEX wc;
	ZeroMemory(&wc, sizeof(WNDCLASSEX));
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.lpfnWndProc = DefWindowProc;
	wc.lpszClassName = "FlashViewer";
	RegisterClassEx(&wc);

	this->mViewerWnd = CreateWindowEx(0, "FlashViewer", "FlashViewer", WS_POPUP
		, 0, 0, width, height, hWnd, NULL, NULL, 0);

	if (!this->mViewerWnd)
		return false;

	//embed the player in the window
	HRESULT hr;
	hr = CoCreateInstance(__uuidof(ShockwaveFlash), 0, CLSCTX_ALL, __uuidof(IShockwaveFlash), (void **)&(this->mFlashCtrl)); 
	if (FAILED(hr))
		return false;
	hr = this->mFlashCtrl->put_WMode(L"transparent");
	hr = AtlAxAttachControl(this->mFlashCtrl, this->mViewerWnd, NULL);
	if (FAILED(hr))
		return false;
	hr = this->mFlashCtrl->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (void**)&this->mWndlessObject);
	if (FAILED(hr))
		return false;

	// create the render texture for Direct3D
	hr =  this->mDevice->CreateTexture(this->mTextureWidth, this->mTextureHeight
		, 0, NULL, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &this->mTexture, NULL);

	if (FAILED(hr))
		return false;

	return true;
}

void DxFlashViewer::OpenFlash( const char* filename )
{
	this->mFlashCtrl->put_Movie(_bstr_t(filename));
}

IDirect3DTexture9* DxFlashViewer::GetTexturePtr()
{
	return this->mTexture;
}

int DxFlashViewer::GetViewerWidth() const
{
	return this->mViewerWidth;
}

int DxFlashViewer::GetViewerHeight() const
{
	return this->mViewerHeight;
}

int DxFlashViewer::GetTextureWidth() const
{
	return this->mTextureWidth;
}

int DxFlashViewer::GetTextureHeight() const
{
	return this->mTextureHeight;
}

void DxFlashViewer::UpdateTexture()
{
	if(NULL == this->mViewerWnd)
		return;
	RECT rect = {0, 0, this->mViewerWidth, this->mViewerHeight};
	IDirect3DSurface9* pSurface = NULL;
	this->mTexture->GetSurfaceLevel(0, &pSurface);
	if (NULL != pSurface)
	{
		HDC hdcTexture;
		HRESULT hr = pSurface->GetDC(&hdcTexture);
		if(FAILED(hr)) return;
		::SetMapMode(hdcTexture, MM_TEXT);
		::OleDraw(this->mFlashCtrl, DVASPECT_CONTENT, hdcTexture, &rect);
		pSurface->ReleaseDC(hdcTexture);
		pSurface->Release();
	}
}

void DxFlashViewer::OnWindowMessage( UINT msg, WPARAM wParam, LPARAM lParam )
{
	LRESULT lr;
	if (NULL != mWndlessObject)
	{
		mWndlessObject->OnWindowMessage(msg, wParam, lParam, &lr);
	}
}
/********************************************************************
	created:	2008/08/02
	created:	2:8:2008   17:21
	filename: 	e:Visual Studio 2005ProjectsSamplesSwfViewerSwfViewer.cpp
	file path:	e:Visual Studio 2005ProjectsSamplesSwfViewer
	file base:	SwfViewer
	file ext:	cpp
	author:		xoyojank
	
	purpose:	Test flash in DirectX app
*********************************************************************/
#include "stdafx.h"
#include <d3d9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning 
#include <strsafe.h>
#pragma warning( default : 4996 ) 

#include "DxFlashViewer.h"

// A structure for our custom vertex type
struct CUSTOMVERTEX
{
	float x, y, z, rhw;	// The transformed position for the vertex
	float u, v;			// The texcoord
};
CUSTOMVERTEX ScreenQuadVertex[] =
{
	{   0.0f,   0.0f, 0.5f, 1.0f, 0.0f, 0.0f, }, // x, y, z, rhw, u, v
	{ 800.0f,   0.0f, 0.5f, 1.0f, 800.0f/1024, 0.0f, },
	{   0.0f, 600.0f, 0.5f, 1.0f, 0.0f, 600.0f/1024, },
	{ 800.0f, 600.0f, 0.5f, 1.0f, 800.0f/1024, 600.0f/1024, },
};
// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1)

CComModule _Module;


//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D       = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device
IDirect3DVertexBuffer9* g_pVertexBuffer = NULL;

DxFlashViewer* g_pViewer = NULL;


//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
	// Create the D3D object.
	if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
		return E_FAIL;

	// Set up the structure used to create the D3DDevice
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory( &d3dpp, sizeof(d3dpp) );
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

	// Create the D3DDevice
	if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp, &g_pd3dDevice ) ) )
	{
		return E_FAIL;
	}

	// Create the vertex buffer.
	return g_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX),0, D3DFVF_CUSTOMVERTEX
		, D3DPOOL_DEFAULT, &(g_pVertexBuffer), NULL );
}


//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
	if (NULL != g_pViewer)
	{
		delete g_pViewer;
	}
	if( g_pd3dDevice != NULL ) 
		g_pd3dDevice->Release();

	if( g_pD3D != NULL )       
		g_pD3D->Release();
}




//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
	// Clear the backbuffer to a blue color
	g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );

	if (NULL != g_pViewer)
	{
		g_pViewer->UpdateTexture();
	}

	// Begin the scene
	if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
	{

		// Now we fill the vertex buffer.
		VOID* pVertexBuffer;
		if( FAILED(g_pVertexBuffer->Lock( 0, sizeof(ScreenQuadVertex), (void**)&pVertexBuffer, 0 ) ) )
			return;
		memcpy( pVertexBuffer, ScreenQuadVertex, sizeof(ScreenQuadVertex) );
		g_pVertexBuffer->Unlock();

		// use the browser texture
		g_pd3dDevice->SetTexture( 0, g_pViewer->GetTexturePtr() );
		// draw the single quad full screen (orthographic)
		g_pd3dDevice->SetStreamSource( 0, g_pVertexBuffer, 0, sizeof(CUSTOMVERTEX) );
		g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

		// End the scene
		g_pd3dDevice->EndScene();
	}

	// Present the backbuffer contents to the display
	g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}




//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
	case WM_MOUSEACTIVATE:
	case WM_MOUSEMOVE:
	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
		g_pViewer->OnWindowMessage(msg, wParam, lParam);
		return 0;
	case WM_DESTROY:
		Cleanup();
		PostQuitMessage( 0 );
		return 0;
	}
	return DefWindowProc( hWnd, msg, wParam, lParam );
}




//-----------------------------------------------------------------------------
// Name: wWinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR     lpCmdLine,
					 int       nCmdShow)
{
	// Register the window class
	WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
		TEXT("DxFlashViewer"), NULL };
	RegisterClassEx( &wc );
	CoInitialize(NULL);  
	AtlAxWinInit();  

	// Create the application's window
	HWND hWnd = CreateWindow( TEXT("DxFlashViewer"), TEXT("DxFlashViewer"),
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
		NULL, NULL, wc.hInstance, NULL );

	// Initialize Direct3D
	if( SUCCEEDED(InitD3D(hWnd)) )
	{
		g_pViewer = new DxFlashViewer();
		// Show the window
		ShowWindow( hWnd, SW_SHOWDEFAULT );
		UpdateWindow( hWnd );
		if (!g_pViewer->Init(g_pd3dDevice, hWnd, 800, 600))
		{
			MessageBox(NULL, "Failed to init.", NULL, 0);
			return 0;
		}

		g_pViewer->OpenFlash("E:My VideosTestGame.swf");
		// Enter the message loop
		MSG msg;
		ZeroMemory( &msg, sizeof(msg) );
		while( msg.message!=WM_QUIT )
		{
			if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
			{
				TranslateMessage( &msg );
				DispatchMessage( &msg );
			}
			else
			{
				Render();
			}
		}
	}
	CoUninitialize();

	UnregisterClass( TEXT("DxFlashViewer"), wc.hInstance );
	return 0;
}

you guys, please discussing this:)

#1
05/16/2009 (4:16 pm)
::OleDraw(this->mFlashCtrl, DVASPECT_CONTENT, hdcTexture, &rect);

The code above contains an OCX api OleDraw(...) which is very low performance.

In the example given in this resource, it's a 800*600 swf file. OleDraw(...) needs 60 or more ms to render one frame.

So i think i am wrong, this is not a suitable solution for completely embeding flash.