Флэш-активатор:Как загрузить фильм из памяти, ресурса или потока?
Вопрос
Я встраиваю элемент управления Flash ActiveX в свое приложение на C ++ (Flash.ocx, Flash10a.ocx и т.д. В зависимости от вашей версии Flash).
Я могу загрузить SWF-файл, вызвав loadMovie (0, имя файла), но файл должен физически находиться на диске.Как загрузить SWF-файл из памяти (или ресурса, или потока)?Я уверен, что должен быть какой-то способ, потому что коммерческие решения, такие как f-в-коробкеособенность Загружайте flash-фильмы непосредственно из памяти также использует элемент управления Flash ActiveX.
Решение
По-видимому, мне нужно будет предоставить детали для голосования "за"..ОК.
Внутренний флэш-буфер при первой инициализации указывает, загружен ли фильм или свойства буфера хранятся в буфере длиной до четырех байт.
гУфУ - фильм не загружен.свойства , которым следует следовать ....
Фуфу ... ..размер [4 байта] как целое число.
затем как бы НЕСЖАТЫЙ фильм или SWF-файл.Напишите класс IStream.заполните вышеперечисленным.сохранить как szFile
TFlashStream *fStream = new TFlashStream(szFile); // QI flash playerIPersistStreamInit * psStreamInit = 0; shock->QueryInterface(::IID_IPersistStreamInit, (LPVOID*)&psStreamInit); if(psStreamInit) { psStreamInit->InitNew(); psStreamInit->Load(fStream); psStreamInit->Release(); } delete fStream;
На что следует обратить внимание :Когда psStreamInit-> Загрузить(fStream);вызовет IStream::Read в поисках заголовка 'fUfU'.
если возвращаемое значение правильное, psStreamInit затем вызывает IStream::Read для определения размера буфера.
Если пока все выглядит хорошо, psStreamInit затем выполняет чтение фрагментами по 1024 байта, пока не будет исчерпано время чтения.Однако.для заголовка и размера файла.
STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead)
pcbRead недействителен.возможно, вы захотите использовать что-то вроде IsBadReadPtr
--
Майкл
Другие советы
Чтобы избавить вас от набора текста. Это работает для меня таким образом (только работает, не проверено):
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;
};
Будучи флеш-парнем, я не знаю каких-либо подробностей на стороне C ++, но если вы сделали запрос на стороне Flash на поддельный протокол, на стороне C вы можете перехватить этот запрос и ответить на него потоком данных. ? Я имею в виду что-то вроде:
var mc:MovieClip = createEmptyMovieClip( "mc", 0 );
mc.loadMovie( "fakeprotocol://"+filename )
Пока ответ выглядит (для Flash) как поток HTTP, это должно работать. (Заранее извиняюсь, если «перехватить запрос и вернуть поток данных» - это та часть, с которой вы обращаетесь за помощью.)
в дополнение....Flash player продвигает IPersistStorage.flash.QI IPersistStorage pStorage.загрузить (mystorage_as_stream)
..в теории.
Извините за вышесказанное..Я намеревался опубликовать Flash Player продвигает IPersistStreamInit.flash.QI IPersistStreamInit pStream.load (my_stream)
Майкл
Этот метод не работает, когда вы пытаетесь загрузить фильм через MovieclipLoader или LoadMovie из другого фильма !!!
Результатом является замена вызывающего SWF-файла !! ... так что этот метод работает только для загрузки базового файла.
Кто-нибудь знает лучший метод, который работает также с MovieClipLoader и LoadMovie? Спасибо.
Образец 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 и 32-разрядной в Windows XP SP3 с 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;
}