[置顶] c++播放Flash文件

最近由于需要在程序中使用Flash播放,所以学习了下如何播放Flash,这里使用atl库中的CAxWindow来处理我们要播放的Flash!由于Flash的很多接口我们都不知道,所以可以参考前一篇文章http://blog.csdn.net/xueyunf/article/details/9160657,这篇文章中介绍了如何导出Flash的接口,这篇文章主要介绍一下,Flash的时间的通知,以及如何利用windows的API,进行两个Flash的混合播放!新建一个默认的 win32窗口程序,然后加入后面的头文件,这里主要是加入atl库文件,以及adobe公司的flash的ocx控件。

#include <atlbase.h>
extern CComModule _Module;
#include <atlwin.h>
#include <comdef.h>
#include "flash32_11_7_700_224.tlh"
#include <string>
using namespace std;
using namespace ShockwaveFlashObjects;
CComModule _Module;


然后我们建立个Flash事件的处理类:
class FlashSink : public ShockwaveFlashObjects::_IShockwaveFlashEvents   
{   
public:    
	LPCONNECTIONPOINT       m_ConnectionPoint;     
	DWORD                   m_dwCookie;   
	int                     m_nRefCount;

public:   
	FlashSink()   
	{          
		m_dwCookie = 0;   
		m_ConnectionPoint = NULL;   
		m_nRefCount = 0;   
	}   

	virtual ~FlashSink()   
	{   

	}   

	HRESULT Init(CComPtr<IShockwaveFlash> ptrFlash)   
	{   
		HRESULT aResult = NOERROR;   
		LPCONNECTIONPOINTCONTAINER aConnectionPoint = NULL;   
		if ((ptrFlash->QueryInterface(IID_IConnectionPointContainer, (void**) &aConnectionPoint) == S_OK) &&   
			(aConnectionPoint->FindConnectionPoint(__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents), &m_ConnectionPoint) == S_OK))               
		{   
			IDispatch* aDispatch = NULL;   
			QueryInterface(__uuidof(IDispatch), (void**) &aDispatch);   
			if (aDispatch != NULL)   
			{   
				aResult = m_ConnectionPoint->Advise((LPUNKNOWN)aDispatch, &m_dwCookie);   
				aDispatch->Release();   
			}   
		}   

		if (aConnectionPoint != NULL)    
			aConnectionPoint->Release();   

		return aResult;   
	}   

	HRESULT Shutdown()   
	{   
		HRESULT aResult = S_OK;   

		if (m_ConnectionPoint)   
		{   
			if (m_dwCookie)   
			{   
				aResult = m_ConnectionPoint->Unadvise(m_dwCookie);   
				m_dwCookie = 0;   
			}   

			m_ConnectionPoint->Release();   
			m_ConnectionPoint = NULL;   
		}   

		return aResult;   
	}   

	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppv)   
	{   
		*ppv = NULL;   

		if (riid == IID_IUnknown)   
		{   
			*ppv = (LPUNKNOWN)this;   
			AddRef();   
			return S_OK;   
		}   
		else if (riid == IID_IDispatch)   
		{   
			*ppv = (IDispatch*)this;   
			AddRef();   
			return S_OK;   
		}   
		else if (riid == __uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents))   
		{   
			*ppv = (ShockwaveFlashObjects::_IShockwaveFlashEvents*) this;   
			AddRef();   
			return S_OK;   
		}   
		else   
		{      
			return E_NOTIMPL;   
		}   
	}   

	ULONG STDMETHODCALLTYPE AddRef()   
	{     
		return ++m_nRefCount;   
	}   

	ULONG STDMETHODCALLTYPE Release()   
	{     
		int aRefCount = --m_nRefCount;   
		if (aRefCount == 0)        
			delete this;           

		return aRefCount;   
	}   

	// IDispatch method   
	virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo)   
	{   
		return E_NOTIMPL;   
	}   

	virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)   
	{   
		return E_NOTIMPL;    
	}   

	virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,   
		UINT cNames, LCID lcid,DISPID* rgDispId)   
	{   
		return E_NOTIMPL;    
	}   

	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)   
	{   
		switch(dispIdMember)   
		{   
		case 0x7a6:            
			break;   
		case 0x96:             
			if ((pDispParams->cArgs == 2) &&   
				(pDispParams->rgvarg[0].vt == VT_BSTR) &&   
				(pDispParams->rgvarg[1].vt == VT_BSTR))   
			{   
				FSCommand(pDispParams->rgvarg[1].bstrVal, pDispParams->rgvarg[0].bstrVal);   
			}   
			break;   
		case DISPID_READYSTATECHANGE:                      
			break;   
		default:               
			return DISP_E_MEMBERNOTFOUND;   
		}    

		return NOERROR;   
	}   

	HRESULT OnReadyStateChange (long newState)   
	{   
		MessageBox(NULL,L"",L"Read",MB_OK);
		return S_OK;   
	}   

	HRESULT OnProgress(long percentDone )   
	{   
		MessageBox(NULL,L"",L"Done",MB_OK);
		return S_OK;   
	}   

	HRESULT FSCommand (_bstr_t command, _bstr_t args)   
	{   
		//         if (m_pFlashWidget != NULL)   
		//             m_pFlashWidget->FlashCommand((char*) command, (char*) args);   
		return S_OK;   
	}      
};   

当然这也很简单,我们只要明白Flash的机制就可以了。后边是Flash播放的一些简单的处理
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: 在此放置代码。
	HRESULT hr =  CoInitialize(NULL);
	AtlAxWinInit();

	MSG msg;
	HACCEL hAccelTable;

	// 初始化全局字符串
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_WIN32PROJECT7, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// 执行应用程序初始化:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT7));

	// 主消息循环:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	CoUninitialize();
	return (int) msg.wParam;
}



//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32PROJECT7));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_WIN32PROJECT7);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 将实例句柄存储在全局变量中
  

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND	- 处理应用程序菜单
//  WM_PAINT	- 绘制主窗口
//  WM_DESTROY	- 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	RECT rc = {0, 0, 300, 300 };
	RECT rc1 = {0, 0, 600, 300 };
	HWND hwnd_tmp= NULL;
	HWND hwnd_tmp1= NULL;
	CAxWindow    m_pWinContainer;
	static CComPtr<IShockwaveFlash> pFlash;
	static FlashSink    flashSink;

	CAxWindow    m_pWinContainer1;
	static CComPtr<IShockwaveFlash> pFlash1;
	static FlashSink    flashSink1;

	switch (message)
	{		
	case WM_CREATE:
		AllocConsole();
		freopen("CONOUT$","w+t", stdout);
		SetWindowPos(hWnd,NULL,0,0,1024,768,SWP_NOMOVE);
		GetClientRect(hWnd,&rc);
		GetWindowRect(hWnd,&rc1);
		POINT tmpPoint;
		tmpPoint.x = rc1.left;
		tmpPoint.y = rc1.top;
		ScreenToClient(hWnd,&tmpPoint);

		rc1.left -= tmpPoint.x;
		rc1.top  -= tmpPoint.y;

		tmpPoint.x = rc.right;
		tmpPoint.y = rc.bottom;
		ClientToScreen(hWnd,&tmpPoint);

		rc1.right = tmpPoint.x;
		rc1.bottom = tmpPoint.y;

		hwnd_tmp=m_pWinContainer.Create(hWnd,rc,TEXT("ShockwaveFlash.ShockwaveFlash"),WS_CHILD|WS_VISIBLE);
		hwnd_tmp1=m_pWinContainer1.Create(hWnd,rc1,TEXT("ShockwaveFlash.ShockwaveFlash"),WS_POPUPWINDOW|WS_VISIBLE,WS_EX_LAYERED);
		SetLayeredWindowAttributes(hwnd_tmp1, 0, 123, LWA_ALPHA);
		printf("%d",GetLastError());

		if (NULL == hwnd_tmp)
		{
			printf("%s","句柄为空");
		}
		if (NULL == hwnd_tmp1)
		{
			printf("%s","窗口2句柄失败!");
		}
		
	
		HRESULT hr;
		hr=m_pWinContainer.QueryControl(__uuidof(IShockwaveFlash),(void**)&pFlash);
		m_pWinContainer1.QueryControl(__uuidof(IShockwaveFlash),(void**)&pFlash1);
		if(FAILED(hr)) 
		{
			return -1L;
		}
		else
		{
			flashSink.Init(pFlash);

			wchar_t sst[1024];
			GetCurrentDirectory(1000,sst);
			
			wprintf(L"%s",sst);
			wstring tmppath;
			tmppath = sst;
			wstring tmppath1;
			tmppath1 = tmppath+L"/f146.swf";
			wstring tmppath2;
			tmppath2 =tmppath+ L"/flash1920.swf";

			hr=pFlash->put_Movie((BSTR)tmppath1.c_str());

			pFlash1->put_Movie((BSTR)tmppath2.c_str());
			if(SUCCEEDED(hr)) 
			{
				pFlash->Play();
				printf("开始播放!");
			}
			pFlash1->Play();
		}
		
		
		break;
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// 分析菜单选择:
		switch (wmId)
		{
		case IDM_ABOUT:
			//DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			//VARIANT_BOOL isPlayIng;
			//pFlash->get_Playing(&isPlayIng);
			if (pFlash->IsPlaying())
			{
				pFlash->Stop();
			}
			else
			{
				pFlash->Play();
			}
			
			
			break;
		case IDM_EXIT:
			if (pFlash1->IsPlaying())
			{
				pFlash1->Stop();
			}
			else
			{
				pFlash1->Play();
			}

			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此添加任意绘图代码...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		FreeConsole();
		pFlash.Release();
		//m_pWinContainer.DestroyWindow();
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}
可以看到红色部分是被我修改过的地方,这些东西虽然不难,但是自己做起来没有资料的时候也挺不方便的!这样Flash的播放就好了,但是不知道为什么停止和开始播放按钮对某些Flash动画不起作用。好了就说这么多!因为有些童鞋可能比较没有时间,所以直接附上源码在最后方便修改和使用!http://download.csdn.net/detail/xueyunf/5658183当然也同样给出一个运行的结果截图:
原文地址:https://www.cnblogs.com/snake-hand/p/3159700.html