Flash ActiveX:如何从内存或资源或流中加载电影?
Posted
技术标签:
【中文标题】Flash ActiveX:如何从内存或资源或流中加载电影?【英文标题】:Flash ActiveX: How to Load Movie from memory or resource or stream? 【发布时间】:2010-09-30 04:55:54 【问题描述】:我在我的 C++ 应用程序中嵌入了一个 Flash ActiveX 控件(Flash.ocx、Flash10a.ocx 等,具体取决于您的 Flash 版本)。
我可以通过调用 LoadMovie(0, filename) 来加载 SWF 文件,但该文件需要物理上驻留在磁盘中。如何从内存(或资源或流)加载 SWF?我相信一定有办法,因为像 f-in-box 的功能 Load flash movies from memory directly 这样的商业解决方案也使用 Flash ActiveX 控件。
【问题讨论】:
我不敢相信我之前找不到这个。感谢您的提问! 【参考方案1】:显然我需要提供投票“赞成”的详细信息.. 好的。
第一次初始化时的内部闪存缓冲区指示是否加载了电影,或者缓冲区是否在缓冲区的前四个字节中保存属性。
gUfU -- 没有加载电影。要遵循的属性 ....
fUfU -- .. [4bytes] 大小为整数。
然后是未压缩的电影或 SWF。 编写一个 IStream 类。 填写以上。 另存为 szFile
TFlashStream *fStream = new TFlashStream(szFile); // QI Flash 播放器IPersistStreamInit * psStreamInit = 0;
shock->QueryInterface(::IID_IPersistStreamInit,
(LPVOID*)&psStreamInit);
if(psStreamInit)
psStreamInit->InitNew();
psStreamInit->Load(fStream);
psStreamInit->Release();
delete fStream;
注意事项: 当 psStreamInit->Load(fStream); 将调用 IStream::Read 查找标头“fUfU”。
如果返回正确 psStreamInit 则调用 IStream::Read 获取缓冲区大小。
如果到目前为止一切看起来都不错,psStreamInit 然后读取 1024 字节块,直到读取用尽。 然而。对于标题和文件大小。
STDMETHOD(读取)(void *pv, ULONG cb, ULONG *pcbRead)pcbRead 无效。你可能想使用类似的东西 IsBadReadPtr
--
迈克尔
【讨论】:
【参考方案2】:为了节省您的打字时间。它以这种方式对我有用(只是没有经过广泛测试):
void flash_load_memory(FlashWidget* w, void* data, ULONG size)
FlashMemoryStream fStream = FlashMemoryStream(data, size);
IPersistStreamInit* psStreamInit = NULL;
w->mFlashInterface->QueryInterface(IID_IPersistStreamInit,(LPVOID*) &psStreamInit);
if(psStreamInit)
psStreamInit->InitNew();
psStreamInit->Load((LPSTREAM)&fStream);
psStreamInit->Release();
class FlashMemoryStream : IStream
public:
FlashMemoryStream(void* data,ULONG size)
this->data = data;
this->size = size;
this->pos = 0;
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppv)
return E_NOTIMPL;
ULONG STDMETHODCALLTYPE AddRef()
return E_NOTIMPL;
ULONG STDMETHODCALLTYPE Release()
return E_NOTIMPL;
// IStream methods
STDMETHOD(Read) (void *pv,ULONG cb,ULONG *pcbRead)
if(pos == 0 && cb == 4)
memcpy(pv,"fUfU",4);
pos += 4;
return S_OK;
else if(pos == 4 && cb == 4)
memcpy(pv,&size,4);
size += 8;
pos += 4;
return S_OK;
else
if(pos + cb > size) cb = size - pos;
if(cb == 0) return S_FALSE;
memcpy(pv,(char*)data + pos - 8,cb);
if(pcbRead) (*pcbRead) = cb;
pos += cb;
return S_OK;
STDMETHOD(Write) (void const *pv,ULONG cb,ULONG *pcbWritten) return E_NOTIMPL;
STDMETHOD(Seek) (LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition) return E_NOTIMPL;
STDMETHOD(SetSize) (ULARGE_INTEGER libNewSize) return E_NOTIMPL;
STDMETHOD(CopyTo) (IStream *pstm,ULARGE_INTEGER cb,ULARGE_INTEGER *pcbRead,ULARGE_INTEGER *pcbWritten) return E_NOTIMPL;
STDMETHOD(Commit) (DWORD grfCommitFlags) return E_NOTIMPL;
STDMETHOD(Revert) (void) return E_NOTIMPL;
STDMETHOD(LockRegion) (ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType) return E_NOTIMPL;
STDMETHOD(UnlockRegion) (ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType) return E_NOTIMPL;
STDMETHOD(Stat) (STATSTG *pstatstg,DWORD grfStatFlag) return E_NOTIMPL;
STDMETHOD(Clone) (IStream **ppstm) return E_NOTIMPL;
void* data;
ULONG size;
ULONG pos;
;
【讨论】:
【参考方案3】:作为一名 Flash 专家,我不知道 C++ 端的任何细节,但如果你在 Flash 端向虚假协议发出请求,在 C 端你可以拦截该请求并用数据流回答它?我的意思是:
var mc:MovieClip = createEmptyMovieClip( "mc", 0 );
mc.loadMovie( "fakeprotocol://"+filename )
只要响应(对于 Flash)看起来像 HTTP 流,就应该可以工作。 (如果“拦截请求并返回数据流”是您寻求帮助的部分,请提前道歉。)
【讨论】:
是的,我的部分问题是如何拦截它。【参考方案4】:另外...... Flash 播放器推广 IPersistStorage。 flash.QI IPersistStorage pStorage.load (mystorage_as_stream)
..理论上。
对以上内容感到抱歉..我打算发帖 Flash 播放器提升 IPersistStreamInit。 flash.QI IPersistStreamInit pStream.load (my_stream)
迈克尔
【讨论】:
【参考方案5】:当您尝试通过 MovieclipLoader 或 LoadMovie 从另一部电影加载电影时,此方法不起作用!!!
结果是替换调用的 SWF 文件!! ...所以此方法仅适用于加载基础文件。
有人知道一种更适用于 MovieClipLoader 和 LoadMovie 的方法吗? 谢谢。
【讨论】:
【参考方案6】:MS VC ATL 示例(使用 VS 2010 SP1 + Windows SDK 7.1 构建,并在带有 Flash64_11_3_300_257.ocx / Flash32_11_3_300_257.ocx 的 Windows 7 SP1 64 位和带有 Flash32_11_3_300_257.ocx 的 Windows XP SP3 32 位上测试):
#pragma pack(push, 1)
typedef struct _FLASH_STREAM_HEADER
DWORD m_dwSignature;
DWORD m_dwDataSize;
FLASH_STREAM_HEADER, *PFLASH_STREAM_HEADER;
#pragma pack(pop)
static HRESULT LoadFlashMovieFromResource(ATL::CComPtr<IShockwaveFlash>& spShockwaveFlash,
UINT nResourceID, LPCTSTR pszResourceType = RT_RCDATA)
HMODULE hModule = ATL::_AtlBaseModule.GetModuleInstance();
ATLASSUME(hModule != NULL);
//HINSTANCE hResourceInstance = ATL::AtlFindResourceInstance(nResourceID, pszResourceType);
//HRSRC hResource = ::FindResource(hResourceInstance, MAKEINTRESOURCE(nResourceID),
// pszResourceType);
HRSRC hResource = ::FindResource(hModule, MAKEINTRESOURCE(nResourceID), pszResourceType);
if (hResource == NULL)
return HRESULT_FROM_WIN32(::GetLastError());
DWORD dwResourceDataSize = ::SizeofResource(hModule, hResource);
if (dwResourceDataSize == 0)
return HRESULT_FROM_WIN32(::GetLastError());
HGLOBAL hResourceLoaded = ::LoadResource(hModule, hResource);
if (hResourceLoaded == NULL)
return HRESULT_FROM_WIN32(::GetLastError());
ATL::CComPtr<IStream> spStream;
HRESULT hResult = ::CreateStreamOnHGlobal(NULL, TRUE, &spStream);
if (FAILED(hResult))
return hResult;
FLASH_STREAM_HEADER fsh = 0x55665566, dwResourceDataSize;
ULARGE_INTEGER uli = sizeof (fsh) + dwResourceDataSize;
hResult = spStream->SetSize(uli);
if (FAILED(hResult))
return hResult;
hResult = spStream->Write(&fsh, sizeof (fsh), NULL);
if (FAILED(hResult))
return hResult;
hResult = spStream->Write(reinterpret_cast<void*>(hResourceLoaded), dwResourceDataSize, NULL);
if (FAILED(hResult))
return hResult;
uli.QuadPart = 0;
hResult = spStream->Seek(*reinterpret_cast<PLARGE_INTEGER>(&uli), STREAM_SEEK_SET, NULL);
if (FAILED(hResult))
return hResult;
ATL::CComPtr<IPersistStreamInit> spPersistStreamInit;
hResult = spShockwaveFlash.QueryInterface(&spPersistStreamInit);
if (SUCCEEDED(hResult))
hResult = spPersistStreamInit->Load(spStream);
return hResult;
【讨论】:
以上是关于Flash ActiveX:如何从内存或资源或流中加载电影?的主要内容,如果未能解决你的问题,请参考以下文章
当activex与flash player在同一个页面时不能调用activex方法