1

我在我的 C++ 应用程序中嵌入了一个 Flash ActiveX 控件(Flash.ocx、Flash10a.ocx 等,具体取决于您的 Flash 版本)。

我可以通过调用 LoadMovie(0, filename) 来加载 SWF 文件,但该文件需要物理上驻留在磁盘中。如何从内存(或资源或流)加载 SWF?我确信一定有办法,因为像f-in-box的功能这样的商业解决方案直接从内存中加载 Flash 电影也使用 Flash ActiveX 控件。

4

6 回答 6

2

显然,我需要提供“支持”投票的详细信息……好吧。

首次初始化时,内部闪存缓冲区指示是否加载了电影,或者缓冲区是否在缓冲区的前四个字节中保存了属性。

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 字节块,直到读取耗尽。然而。对于标题和文件大小。

标准方法(读取)(无效 *pv,ULONG cb,ULONG *pcbRead)

pcbRead 无效。你可能想使用类似 IsBadReadPtr

--

迈克尔

于 2009-01-26T16:26:00.753 回答
1

为您节省一些打字时间。它以这种方式对我有用(只是没有经过广泛测试):

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;
    };
于 2010-04-25T15:58:21.407 回答
0

作为一个 Flash 人,我不知道 C++ 端的任何细节,但如果你在 Flash 端向虚假协议发出请求,在 C 端你能拦截该请求并用数据流回答它吗?我的意思是:

var mc:MovieClip = createEmptyMovieClip( "mc", 0 );
mc.loadMovie( "fakeprotocol://"+filename )

只要响应看起来(对 Flash 来说)像一个 HTTP 流,就应该可以工作。(如果“拦截请求并返回数据流”是您寻求帮助的部分,请提前道歉。)

于 2009-01-08T04:13:30.240 回答
0

此外.... Flash 播放器推广 IPersistStorage。flash.QI IPersistStorage pStorage.load (mystorage_as_stream)

.. 理论上。

抱歉以上内容.. 我打算发布 Flash 播放器推广 IPersistStreamInit。flash.QI IPersistStreamInit pStream.load (my_stream)

迈克尔

于 2009-01-21T18:12:16.137 回答
0

当您尝试通过 MovieclipLoader 或 LoadMovie 从另一部电影加载电影时,此方法不起作用!!!

结果是替换调用的 SWF 文件!!...因此此方法仅适用于加载基本文件。

有人知道与 MovieClipLoader 和 LoadMovie 一起使用的更好方法吗?谢谢。

于 2009-08-29T22:24:39.810 回答
0

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;
}
于 2012-06-20T17:09:27.007 回答