Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > alexcon314

Оценить эту запись

Пишем свою оболочку для FP под Windows. Шаг 2.

Запись от alexcon314 размещена 17.05.2011 в 17:43
Обновил(-а) alexcon314 30.06.2011 в 11:43

Как и обещал, сегодня рассмотрим альтернативные способы подключения плеера к приложениию. Эти способы будут работать даже если плеер не установален (не зарегистрирован) на целевой машине.

Загрузка с диска.

Файл плеера Flash.ocx (версия не имеет значения) представляет из себя обычный PE-файл.
Проще говоря, это обычная DLL, которая экспортирует ряд функций. Однако есть и отличие: в этой библиотеке сидят не просто функции, там зашит класс, класс плеера.
Библиотека спроектирована таким образом, что любое приложение может обратитившись к ней когда нужно, создать экземпляр этого класса и использовать. Как и все ActiveX длл-ки
Flash.ocx экспортирует четыре функции:

DllCanUnloadNow()
DllGetClassObject()
DllRegisterServer()
DllUnregisterServer()

Последние две используются как раз при регистрации/отмене регистрации контрола в системе и для наших целей они, вобщем-то, не нужны.
А вот DllGetClassObject() - то что нужно. Эта функция позволит получить нам указатель
на «фабрику», которая и породит для нас экземпляр контрола.
Сигнатура это функции стандартна:

DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv);

Что мы сделаем: загрузим либу, найдем эту функцию и вызовем ее с соответствующими параметрами:
Код AS3:
// определяем тип будущего указателя на DllGetClassObject()
typedef VOID	(WINAPI *LPGetClassObject )(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
// загружаем либу 
HMODULE hModule = LoadLibrary(szFileOCX);
// получаем указатель на DllGetClassObject()
LPGetClassObject fLPGetClassObject = (LPGetClassObject)GetProcAddress(hModule, "DllGetClassObject");
// вызываем
IClassFactory* clf = NULL;
IShockwaveFlash* flash = NULL;
fLPGetClassObject(CLSID_ShockwaveFlash, IID_IClassFactory, (LPVOID*)&clf);
// фабрика создет для нас экземпляр плеера и сохраняет указатель на него в  flash
HRESULT hr = clf->CreateInstance(NULL, __uuidof(IShockwaveFlash),(void**)&flash);
clf->Release();
Включим этот механизм в базовый класс CFlashWnd, перегрузив уже имеющуюся CreateInstence():
Код AS3:
HRESULT CFlashWnd::CreateInstance(WCHAR* szFileOCX)
{
	if(isInit)
		return S_FALSE;
 
	HMODULE hModule = LoadLibrary(szFileOCX);
	if(!hModule)
		return S_FALSE;
 
	LPGetClassObject fLPGetClassObject = (LPGetClassObject)GetProcAddress(hModule, "DllGetClassObject");
	if(!fLPGetClassObject )
		return S_FALSE;
 
	IClassFactory* clf = NULL;
	fLPGetClassObject(CLSID_ShockwaveFlash, IID_IClassFactory, (LPVOID*)&clf);
	if(!clf )
		return S_FALSE;
 
	HRESULT hr = clf->CreateInstance(NULL, __uuidof(IShockwaveFlash),(void**)&flash);
	clf->Release();
	isInit = hr == S_OK;
	return hr;
}
Использование:
Код AS3:
CreateInstance(L"C:\\Flash10a.ocx");
Загрузка из ресурсов.

Сначала, собственно, включим Flash.ocx в ресурсы приложеения.
Для этого добавим по строчке в файлы Resource.h и test.rc:
Код AS3:
//  test.rc 
ID_OCX	BIN	"Flash10o.ocx"
// Resource.h
#define ID_OCX	1000
В директорию проекта (рядом с test.vcproj) положим Flash10o.ocx. Если в названии присутствует другая версия, внесите соответственно правки.

Компилируем (F7). Чувствуете, как вырос размер .ехе? Воот.
Далее логика мало отличается от предыдущего случая. За исключением вопроса: как загрузить длл из ресурсов? MS не предоставляет такого функционала на уровне Win API.
Но, как я уже говорил, интернет не без добрых людей:
http://www.joachim-bauch.de/tutorial...l-from-memory/
Здесь лежит то, что нам нужно — MemoryModule, код для загрузки длл из памяти.
(Патриотически замечу, что и наши программеры реализовали такую фичу, жаль ссылку потерял.)
Подключаем к проекту MemoryModule.c и MemoryModule.h (Правый клик по проекту->Добавить->Существующий элемент). Прописываем MemoryModule.h в инклудах базового класса.
Ну, теперь дело техники:
Код AS3:
HRESULT CFlashWnd::CreateInstance(UINT id, WCHAR* resType)
{
	if(hInst == NULL)
		return S_FALSE;
	if(isInit)
		return S_FALSE;
 
	IClassFactory* clf = NULL;
	HRSRC hResInfo = ::FindResource(hInst, MAKEINTRESOURCE(id), resType);
	if(!hResInfo)
		return S_FALSE;
 
	DWORD dwFlashOCXCodeSize = ::SizeofResource(hInst, hResInfo);
	if(dwFlashOCXCodeSize == 0)
		return S_FALSE;
 
	HGLOBAL data = ::LoadResource(hInst, hResInfo);
	if(!data)
		return S_FALSE;
 
	LPVOID lpFlashOCXCode = ::LockResource(data);
	if(!lpFlashOCXCode)
		return S_FALSE;
 
	HMEMORYMODULE hMem = MemoryLoadLibrary(lpFlashOCXCode);
	if(!hMem )
		return S_FALSE;
 
	LPGetClassObject fLPGetClassObject = (LPGetClassObject)MemoryGetProcAddress(hMem, "DllGetClassObject");
	if(!fLPGetClassObject )
		return S_FALSE;
 
	fLPGetClassObject(CLSID_ShockwaveFlash, IID_IClassFactory, (LPVOID*)&clf);
	if(!clf )
		return S_FALSE;
 
	HRESULT hr = clf->CreateInstance(NULL, __uuidof(IShockwaveFlash),(void**)&flash);
	clf->Release();
	isInit = hr == S_OK;
	return hr;
 
}
Пояснение: ищем ресурс по ID и типу, загружаем в память. По lpFlashOCXCode (это адрес модуля в памяти) с помощью MemoryLoadLibrary() ищем DllGetClassObject().
Дальше — по накатанной. Получаем «фабрику», потом инстанс плеера.
Использование:
Код AS3:
CreateInstance(ID_OCX, L"BIN");
Вот и все.

... ан нет. Не все. Случайно обнаружил такую вот непонятную багу.
Совершенно произвольно я длительное время использовал для эмбеда Flash10a.ocx (10.0.12.36) и не замечал, что он не грузит AVM2-ролики. Так уж вышло, что забот было других и я пользовал для тестов AVM1-ролик. Причем при загрузке этого .осх с диска и штатно — все ок.
Подсунул ему AVM2-ролик - и тут такой облом...
10.1.85.3 и 10.2.153.1 работают как ни в чем не бывало во всех трех режимах инициализации и с AVM2-роликами, и AVM1-роликами. Так что имейте в виду.
В тестовом проекте я прописал в #import и в .rc Flash10o.ocx (10.2.153.1). Не забудьте
положить его в директорию проекта.

На следующем шаге будем грузить swf из ресурсов приложения.
Вложения
Тип файла: zip test2.zip (33.1 Кб, 329 просмотров)
Всего комментариев 0

Комментарии

 

 


Часовой пояс GMT +4, время: 07:55.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.