简体   繁体   English

Flash ActiveX:如何从内存,资源或流加载影片?

[英]Flash ActiveX: How to Load Movie from memory or resource or stream?

I'm embedding a Flash ActiveX control in my C++ app (Flash.ocx, Flash10a.ocx, etc depending on your Flash version). 我将Flash ActiveX控件嵌入到我的C ++应用程序中(Flash.ocx,Flash10a.ocx等,具体取决于您的Flash版本)。

I can load an SWF file by calling LoadMovie(0, filename), but the file needs to physically reside in the disk. 我可以通过调用LoadMovie(0,filename)来加载SWF文件,但是该文件实际上需要驻留在磁盘中。 How to load the SWF from memory (or resource, or stream)? 如何从内存(或资源或流)加载SWF? I'm sure there must be a way, because commercial solutions like f-in-box 's feature Load flash movies from memory directly also uses Flash ActiveX control. 我肯定一定有办法,因为像f-in-box的功能那样的商业解决方案直接从内存加载Flash电影也使用Flash ActiveX控件。

Appearantly I a going to need to supply details for a vote 'up'.. OK. 显然,我将需要提供详细信息以进行投票。

The internal flash buffer when first initiailized indicates if a movie is loaded or if the buffer hold properties in the buffer fisrt four bytes. 内部闪存缓冲区在首次初始化时指示是否加载了影片或该缓冲区是否在缓冲区第四个字节中保留了属性。

gUfU -- no movie loaded. gUfU-未加载电影。 properties to follow .... 要遵循的属性..

fUfU -- .. [4bytes] size as integer. fUfU-.. [4bytes]大小为整数。

then the UNCOMPRESSED movie or SWF as it were. 然后是未压缩的电影或SWF。 Write a IStream class. 编写一个IStream类。 fill with above. 用上面填充。 save as szFile 另存为szFile

TFlashStream *fStream = new TFlashStream(szFile);
// QI flash player

IPersistStreamInit * psStreamInit = 0;
shock->QueryInterface(::IID_IPersistStreamInit,  
                     (LPVOID*)&psStreamInit);
if(psStreamInit)
{
    psStreamInit->InitNew();
    psStreamInit->Load(fStream);
    psStreamInit->Release();
}
delete fStream;

Things to note : When psStreamInit->Load(fStream); 注意事项:psStreamInit-> Load(fStream); will call IStream::Read looking for the header 'fUfU'. 将调用IStream :: Read查找标题'fUfU'。

if the return is correct psStreamInit then calls IStream::Read for the buffer size. 如果返回正确,则psStreamInit会调用IStream :: Read来获取缓冲区大小。

If everthing looks good so far, psStreamInit then reads in 1024 byte chunks until the read is exhausted. 如果到目前为止一切正常,则psStreamInit会读取1024个字节的块,直到读取结束。 However. 然而。 for the header and file size. 标头和文件大小。

STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead)

pcbRead is invalid. pcbRead无效。 you may want to use something like IsBadReadPtr 您可能想要使用IsBadReadPtr之类的东西

-- -

Michael 迈克尔

To spare you some typing. 为您节省一些打字时间。 It works for me in this way (just works not extensively tested): 它以这种方式为我工作(只是未经广泛测试的工作):

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;
    };

MS VC ATL sample (have built with VS 2010 SP1 + Windows SDK 7.1 and tested on Windows 7 SP1 64-bit with Flash64_11_3_300_257.ocx / Flash32_11_3_300_257.ocx and on Windows XP SP3 32-bit with Flash32_11_3_300_257.ocx): MS VC ATL示例(已使用VS 2010 SP1 + Windows SDK 7.1构建,并已在64位Windows 7 SP1和Flash64_11_3_300_257.ocx / Flash32_11_3_300_257.ocx上以及在Windows XP SP3 32位和Flash32_11_3_300_257.ocx上进行了测试):

#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;
}

This method don't work when you try to load a movie via the MovieclipLoader or LoadMovie from another movie!!! 当您尝试通过MovieclipLoader或LoadMovie从另一部电影加载电影时,此方法不起作用!

The result is to replace the calling SWF file!! 结果是替换了调用SWF文件! ...so this method work only for loading the base file. ...因此此方法仅适用于加载基本文件。

Someone know a better method that work also with MovieClipLoader and LoadMovie? 有人知道也可以与MovieClipLoader和LoadMovie一起使用的更好的方法吗? Thanks. 谢谢。

Being a flash guy I don't know any details on the C++ side, but if you made a request on the Flash side to a fake protocol, on the C side can you intercept that request and answer it with a data stream? 作为一名Flash专家,我在C ++方面一无所知,但是如果您在Flash方面向虚假协议提出请求,那么在C方面可以拦截该请求并使用数据流进行答复吗? I mean something like: 我的意思是:

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

As long as the response looks (to Flash) like an HTTP stream, that ought to work. 只要响应(对于Flash)看起来像HTTP流,它就应该起作用。 (Apologies in advance if the "intercept the request and return a data stream" is the part you're asking for help with.) (如果您要“帮助”部分,则在此先表示歉意。)

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

.. in theory. .. 理论上。

Sorry for the above.. I intended to post Flash player promotes IPersistStreamInit. 抱歉以上。我打算在Flash Player中推广IPersistStreamInit。 flash.QI IPersistStreamInit pStream.load (my_stream) flash.QI IPersistStreamInit pStream.load(my_stream)

Michael 迈克尔

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM