Clickteam Fusion 2.5 Extension Developement Kit |
Добавил(а) microsin |
Этот Extension Developement Kit (далее для краткости EDK, он же SDK, что одно и то же) позволит Вам создавать свои собственные индивидуальные объекты (расширения), которые можно будет использовать вместе в CF 2.5. Каждый объект может иметь свое собственное поведение и специализированные условия событий (conditions) и действия (actions). Для того, чтобы начать создавать свои расширения, Вам понадобится Visual C++ 2005 (или более свежая версия) и хорошие знания языка C. Примечание: здесь приведен перевод документации из Clickteam Fusion 2.5 Extension Developement Kit, файл Extensions\Help\ExtSdk.chm из архива Fusion25SDK.zip [1]. Команда CF 2.5 разработала файл шаблона, чтобы ускорить и упростить для Вас создание первого объекта расширения. Все, что Вам нужно - заполнить пустые места в шаблоне для настройки своего объекта. Этот файл шаблона разработан так, что он быстро скомпилируется на Вашей рабочей станции. Предлагаемый EDK очень мощный инструмент, поставляемый с обширной документацией. Рекомендуется уделить время для обстоятельного изучения содержимого EDK, шаг за шагом, чтобы полностью понять его. Хороший кандидат на первую попытку создания объекта - сделать невидимый объект, который просто генерирует звуковой сигнал BEEP или печатает слово "Hello!" на экране. После того, как освоите базовые техники по созданию простых объектов, добавьте к ним больше действий, и создайте более сложные объекты. Попробуйте добавить подпрограмму, которая нарисует во фреймах объект, который Вы создали. Команда Clickteam определенно хотела бы видеть Ваши расширения доступными в магазине Clickstore [2], что в перспективе может Вам предоставить шанс дополнительного заработка на разработанных объектах. [Папка Template] В этой папке содержится готовый для сборки шаблон нового объекта с примерами условий событий (example conditions), действий (actions) и выражений (expressions). Шаблон состоит из нескольких файлов: Common.h. Общий заголовочный файл, который нужно подключить ко всем Вашим файлам исходного кода. Содержит несколько определений, которые позволят ограничить Ваше расширение для определенных версий и определенных сборок CF. Edittime.cpp. Содержит функции, вызываемые редакторами фрейма (Frame editor) и событий (Event editor). Ext.def. Файл определения экспорта для линкера (export definition file). Этот файл очень важен: здесь перечислены все функции, к которым нужно получить доступ из CF. Если Вы включите функцию, вызываемую из CF, то убедитесь, что она также включена и в файле .def (удалите точку с запятой перед именем функции), поскольку CF знает только те имена, которые находятся в файле .def, и не осуществляет доступ к функциям через их декорированные имена. Ext.rc. Файл ресурсов для Вашего проекта. Содержит все строки, рисунки, окна диалога объекта. General.cpp. Содержит подпрограммы, которые вызываются во время редактирования (edit time) и во время выполнения (run time). Main.cpp. Содержит действия (actions), условия (conditions) и выражения (expressions) для Вашего объекта. Main.h. Файл определения для Вашего расширения, содержит структуры EDITDATA и RUNDATA, необходимые для редактирования и запуска объекта. Runtime.cpp. Содержит функции, необходимые для запуска объекта, которые работают только во время выполнения (run time). Включает подпрограммы для отладчика, подпрограммы для отображения Вашего объекта во время выполнения приложения, и т. д. Resource.h. Файл определения для ресурсов. Содержит идентификаторы разных элементов в файле ресурсов. Template.sln. Файл решения (Solution file) для использования в среде разработки MS Visual C++ 2005 (или более новой версии). Template.vcproj. Файл проекта для использования в среде разработки MS Visual C++ 2005 (или более новой версии). Res\ExtIcon.bmp. Иконка для объекта: эта картинка используется для отображения объекта в окне объекта редактора фрейма и редактора событий. Удалите этот файл, если Вы рисуете свою иконку вручную с помощью функции MakeIconEx. Res\ExtImg.bmp. Картинка объекта: будет использоваться для отображения объекта в редакторе фрейма. Удалите этот файл, если Вы рисуете объект вручную с помощью функции EditorDisplay. [Папка Inc] Папка Inc содержит все подключаемый файлы, необходимые для компиляции Вашего расширения. Ccx.h. Этот файл содержит определения, используемые расширением и компилятором ресурсов. Вы должны подключить его в начало своего кода. Ccxhdr.h. Этот файл сразу подключает все необходимые файлы. Вы должны подключить его в начало своего кода. CfcError.h. Содержит некоторые коды ошибки, возвращаемые функциями из mmfs2.dll и в фильтрах. CfcFile.h. Содержит декларации файловых функций в mmfs2.dll. Cncf.h. Этот файл содержит основное определение для выполняемого кода (runtime). Содержит все структуры, объекты, действия и условия, используемые во время работы объекта. Он автоматически подключается из файла Ccxhdr.h. Cncy.h. Содержит другие структуры для работы приложения (runtime) и среды CF (edittime). Он автоматически подключается из файла Ccxhdr.h. Cncr.h. Маленький файл, который подключает все другие файлы. Он автоматически подключается из файла Ccxhdr.h. Cnpdll.h. Содержит основную часть определений для mmfs2.dll. Он автоматически подключается из файла Ccxhdr.h. Colors.h. Маленький файл, который содержит определения базовых цветов, используемых в программах (таких как BLACK, к примеру). Он автоматически подключается из файла Ccxhdr.h. EvtCcx.h. Этот файл определяет структуры информации события, используемые в главном исходном коде расширения, чтобы определить действия (actions) и условия (conditions) событий. Он автоматически подключается из файла Ccxhdr.h. Fill.h. Содержит структуры, используемые для функций заливки (Rectangle, Ellipse, и т. д.) в классе cSurface. FilterMgr.h. Содержит базовый класс для менеджеров фильтров изображения и звука. ImageFlt.h. Содержит менеджер фильтра изображения (image filter manager) и классы фильтра изображений (image filter classes). ImageDefs.h. Игнорируйте этот файл, он присутствует только для поддержки совместимости с внутренними подключаемыми файлами Clickteam. Palet.h. Содержит функции палитры в mmfs2.dll. PictEdDefs.h. Содержит определения для редактора изображений (picture editor). Для использования в функциях mvEditImage и mvEditAnimation. Props.h. Этот файл содержит определения новой системы свойств CF. Он автоматически подключается из файла Ccxhdr.h. PType.h. Этот файл содержит определения некоторых типов переменных, используемых программой. Он автоматически подключается из файла Ccxhdr.h. SndDefs.h. Игнорируйте этот файл, он присутствует только для поддержки совместимости с внутренними подключаемыми файлами Clickteam. SoundFilter.h. Содержит класс фильтра звука (sound filter class). SoundFilterMgr.h. Содержит класс менеджера фильтра звука (sound filter manager class). StdDefs.h. Игнорируйте этот файл, он присутствует только для поддержки совместимости с внутренними подключаемыми файлами Clickteam. Surface.h. Содержит класс cSurface class. Подключается файлом Common.h в шаблоне расширения (Extension template). SurfaceDefs.h. Игнорируйте этот файл, он присутствует только для поддержки совместимости с внутренними подключаемыми файлами Clickteam. TigsExt.hpp. Содержит некоторые полезные макросы, созданные для старого SDK стороннего производителя. WinMacro.h. Набор макросов, определенных для Win32. [Папка Lib] Папка Lib содержит только один файл: Mmfs2.Lib. Он используется для линковки CF DLL к расширению, если это необходимо. [Примеры объектов (расширений)] Разработчики добавили в EDK полнофункциональные объекты в качестве примеров, чтобы Вы могли научиться делать объекты, исследуя готовый код. Simple Data Buffer. Это пример объекта, у которого нет вывода во фрейм. Он используется только для сохранения данных, и может также загружать или сохранять файлы. Simple Text. Это пример объекта, который отображает простой текст. Оп показывает, как отображать что-то во фрейме с использованием функции DisplayRunObject. Simple Picture. Это пример объекта, который загружает и отображает файлы картинок. Он демонстрирует, как загружать файлы, используя фильтры графики (CF graphic filters), как отображать их с использованием функции GetRunObjectSurface, и как точно обрабатывать коллизии объектов с использованием функции GetRunObjectCollisionMask. Simple Control. Этот пример объекта управления Windows (Windows control object), например объект, отображаемый в своем собственном окне (в действительности этот объект работает как окно редактирования, edit box). Он показывает, как работать с подклассами окон управления и как перехватывать основные оконные сообщения. Дополнительно показывается разница между обычными условиями и "событийными" условиями ("event" conditions) в системе CF. Замечание: если Вы используете один из этих примеров как базу для своих собственных объектов, например если Вы повторно используете исходный код и файл проекта для своих собственных расширений, то не забудьте поменять этот идентификатор в файле Main.h. [Поддержка Unicode] CF 2.5 работает как Unicode-приложение, обрабатывает текст в формате Unicode (UTF16). Формат Unicode позволяет сохранять в строке любые символы, например греческие (Greek) или китайские (Chinese). Строка UTF16 состоит из 2-байтных символов, вместо 1-байтных символов для обычной строки, не Unicode (например, в кодировке ASCII или ANSI). CF 2.5 поддерживает оба вида расширений, расширения не-Unicode (наподобие старых расширений, сделанных для MMF2) и расширения Unicode. В этом SDK предоставляется шаблон (Template), который сконфигурирован по умолчанию для поддержки Unicode. Он использует следующие макросы: TCHAR заменяется на WCHAR в режиме Unicode (и на char в режиме не-Unicode). и так далее ... Замечание: эти макросы позволяют Вам собрать не-Unicode расширение, если Вы действительно не можете собрать расширение Unicode (например, если Ваше расширение использует какую-то не-Unicode библиотеку). Если Вы хотите собрать не-Unicode расширение, удалите определения для препроцессора UNICODE и _UNICODE, установите набор символов на MBCS в настройках проекта и установите Ваше расширение в папки Extensions и Data\Runtime каталога установки CF (вместо папок Extensions\Unicode и Data\Runtime\Unicode). Когда CF передает текст в не-Unicode расширение (или принимает от него текст), то текст преобразуется в кодировку ANSI (или из кодировки ANSI) с использованием языка текущего пользователя. CF 2.5 может загрузить расширения Unicode или расширения не-Unicode, однако конечно же символы Unicode поддерживаются только расширениями Unicode, поэтому если Ваши расширения используют текст, то Вы должны портировать их для поддержки Unicode. [Как преобразовать расширение, чтобы оно поддерживало Unicode] Чтобы скомпилировать расширение Unicode, добавьте определения препроцессора _UNICODE и UNICODE в настройки своего проекта расширения. Если Вы не определите эти символы, то расширение будет скомпилировано в режиме не-Unicode. Первое, что нужно сделать, это папку расширения MMF2 (extension folder) в папку Fusion25SDK/Extensions, и затем нужно: • Отредактировать этот проект. Замечание 1: расширения Unicode устанавливаются в папки и Extensions\Unicode и Data\Runtime\Unicode, находящиеся в каталоге установки CF. Замечание 2: если Вы используете MSVC++ 2005 или более новую версию этой системы разработки, то установите опцию "Threat wchar_t as Built-in Type" в значение "No" раздела "C++ / Language" настроек проекта, иначе будут появляться ошибки линковки, если Вы используете функции в DLL с текстовыми параметрами. [Что делают символы _UNICODE и UNICODE] Все структуры и функции Windows, которые используют текст, как и все структуры CF, существуют в 2 версиях: без поддержки Unicode и с поддержкой Unicode. Когда определены макросы _UNICODE и UNICODE, используется Unicode-версия структур, а когда эти макросы не определены, то используется non-Unicode версия. Например, на самом деле Windows-функция DrawText не существует, и Windows содержит 2 функции DrawTextA и DrawTextW, и DrawText на самом деле макрос, который устанавливается на функцию DrawTextW, если определены _UNICODE/UNICODE, и устанавливается на DrawTextA, если _UNICODE/UNICODE не определены. Структуры наподобие LOGFONT также макросы, и реальные структуры для него это LOGFONTA и LOGFONTW. Такие функции и структуры не используют типы char или char*, они также используют вместо них макросы, поэтому для определения строк нужно соблюдать определенные правила, если хотите, чтобы расширение могло компилироваться и для поддержки Unicode, и без поддержки Unicode, если это необходимо. Поэтому замените определения символов и строк следующим образом: char замените на TCHAR Замечание: Вы все еще можете использовать char для символов, которые всегда не Unicode, или WCHAR для символов, которые всегда Unicode. Функции из библиотеки C++ runtime также заменяются на макросы (это определено в tchar.h): strlen заменяется на _tcslen ... и так далее. Для строк констант используйте макрос _T: "это строка" замените на _T("это строка") Если Ваше расширение компилируется в режиме Unicode, то _T("это строка") будет заменено на L"это строка", иначе это будет заменено на "это строка". [Изменения в Main.h] Структура EDITDATA. Эта наиболее проблематичная часть в преобразовании расширений. Если расширение не содержит и не использует никакого текста, то ничего делать не нужно. Если же текст используется, то нужно обеспечить поддержку 2 версий этой структуры: • Структура EDITDATAA, non-Unicode, со значениями типа char (например, char array[2], LOGFONTA lfnt, и т. д.). И еще сделайте следующее определение: #ifdef _UNICODE
#define EDITDATA EDITDATAW
#define LPEDATA LPEDATAW
#else
#define EDITDATA EDITDATAA
#define LPEDATA LPEDATAA
#endif
Внимание: не используйте в EDITDATA тип TCHAR. Вы также также должны конвертировать Вашу структуру EDITDATA в Unicode и из Unicode в функции UpdateEditStructure, находящейся в модуле General.cpp: если Вы уже не используете функцию UpdateEditStructure в своем приложении, то реализуйте её так, чтобы она могла конвертировать не-Unicode EDITDATA из не-Unicode приложений в Unicode. Вы можете проверить, загружен ли файл приложения как Unicode, вызовом функции mvIsUnicodeApp(pMV, pMV->mvEditApp). Если Вам не нужно преобразовывать текст из Unicode и в Unicode, то используйте функции MultiByteToWideChar и WideCharToMultiByte, и используйте в качестве кодовой страницы mvGetAppCodePage(pMV, pMV->mvEditApp). Как все это делается, можно подсмотреть в примере Simple Control. И не забудьте разрешить эту функцию в файле .DEF! Если уже используете UpdateEditStructure для обновления EDITDATA старых версий Вашего объекта, то это немного более сложнее: сначала Вам нужно обновить старую структуру EDITDATAA, и затем преобразовать обновленную структуру EDITDATAA в Unicode. Структура RUNDATA. С ней ничего делать не нужно, просто используйте типы TCHAR, LPTSTR, и т. д. [Изменения в других модулях исходного кода] EditTime.cpp. Замените LPSTR (или LPCSTR) на LPTSTR (или LPCTSTR) в заголовочных файлах следующих функций: GetObjInfos И замените функцию menucpy на следующий код: void menucpy(HMENU hTargetMenu, HMENU hSourceMenu) { #ifndef RUN_ONLY int n, id, nMn; LPTSTR strBuf; HMENU hSubMenu; nMn = GetMenuItemCount(hSourceMenu); strBuf = (LPTSTR)calloc(80, sizeof(TCHAR)); for (n = 0; n < nMn; n++) { if (0 == (id = GetMenuItemID(hSourceMenu, n))) AppendMenu(hTargetMenu, MF_SEPARATOR, 0, 0L); else { GetMenuString(hSourceMenu, n, strBuf, 80, MF_BYPOSITION); if (id != -1) AppendMenu(hTargetMenu, GetMenuState(hSourceMenu, n, MF_BYPOSITION), id, strBuf); else { hSubMenu = CreatePopupMenu(); AppendMenu(hTargetMenu, MF_POPUP | MF_STRING, (uint)hSubMenu, strBuf); menucpy(hSubMenu, GetSubMenu(hSourceMenu, n)); } } } free(strBuf); #endif
}
Свойства (Properties). Не нужно делать изменений в свойствах, кроме строковых свойств. Вы использовали ранее CPropDataValue, чтобы передать/получить строки в/из менеджера свойств (CF property manager). Теперь здесь новый класс CPropStringValue. В функции GetPropValue: // Было раньше так: case PROPID_MYSTRING: return new CPropDataValue((LPCSTR)edPtr->myString); // Теперь стало так: case PROPID_MYSTRING: return new CPropStringValue(edPtr->myString); В функции SetPropValue: // Было раньше так: case PROPID_MYSTRING: LPSTR ps = (LPSTR)((CPropDataValue*)pValue)->m_pData; // Теперь стало так: case PROPID_MYSTRING: LPCTSTR ps = ((CPropStringValue*)pValue)->GetString(); Runtime.cpp. Замените заголовочный файл функции GetDebugItem: void WINAPI DLLExport GetDebugItem(LPTSTR pBuffer, LPRDATA rdPtr, int id) General.cpp. Добавьте в функции GetInfos: case KGI_UNICODE:
#ifdef _UNICODE return TRUE; #else return FALSE; #endif
Это позволит системе CF узнать, каким является Ваше расширение: Unicode или non-Unicode. Тогда CF преобразует эти строки, если это необходимо, перед передачей из в функции Вашего расширения, или после получения строк из Вашего расширения. Замените LPCSTR на LPCTSTR в функции GetDependencies() и в таблице, которую она возвращает, если это нужно (и добавьте _T() в имена dll в этой таблице). Замените LPSTR на LPTSTR в заголовочном файле функции UpdateFileNames. Реализуйте структуру UpdateEditStructure, если это необходимо, так как это было описано выше. Main.cpp. Действия/условия/выражения (Actions/Conditions/Expressions): если Ваше расширение Unicode, то оно будет принимать строковые параметры в формате Unicode (и будет возвращать строковые параметры в формате Unicode). Если Ваше расширение не Unicode, то оно будет получать/возвращать строки non-Unicode. Замечание: параметр size в функциях RFUNCTION_GETSTRINGSPACE и RFUNCTION_GETSTRINGSPACE_EX указывается в байтах. Умножьте длину строки на sizeof(TCHAR), чтобы получить size байтах. Изменения в runtime-структурах. Есть несколько изменений в некоторых внутренних структурах, особенно в структуре objInfoList. Теоретически Вам нужно заботиться о них только если Ваше расширение не Unicode, и Вы хотите получить прямой доступ к этим структурам. 1. Сделайте копию директории исходного кода Вашего расширения в папку MMF2SDK\Extensions. 2. Откройте Ваш файл проекта в Visual Studio, отредактируйте настройки проекта, выберите All Configurations. 2a. В combo-боксе Settings For выберите закладку C/C++, Preprocessor и введите ..\..\inc как дополнительную директорию для подключаемых файлов (Additional Include directory). Если Вы используете Visual Studio 2005 или Visual Studio 2005 Express, то не должны использовать "Multithreaded DLL", так как файлы VS2005 runtime пока не присутствуют на некоторых машинах, и от пользователя может потребоваться загрузить и установить эти файлы runtime библиотек (2.5 мегабайта) с сайта microsoft.com. Чтобы узнать, какие DLL требуются для Вашего расширения, запустите утилиту MS "Dependency Viewer", и загрузите Ваш файл .MFX. 3. Отредактируйте Ваш файл Common.h, сохранив свои определения (если они есть) и перезапишите остальную часть Common.h новым шаблоном. Также, если есть файл TigsExt.hpp в Вашей директории, то удалите его. Обновленная версия этого файла подключается из директории Inc. 4. Важно: функции UsesFile и CreateFromFile (модуль EditTime.cpp) теперь в качестве первого параметра имеют LPMV mV. В должны добавить его, иначе MMF упадет, если Вы бросите файл в редактор фрейма. BOOL WINAPI DLLExport UsesFile (LPMV mV, LPCTSTR fileName) void WINAPI DLLExport CreateFromFile (LPMV mV, LPCTSTR fileName, LPEDATA edPtr)
5. Важно: если используете RFUNCTION_SUBCLASSWINDOW, то количество окон, которое Вы передаете в эту функцию, теперь int вместо short int. Вы должны модифицировать свою структуру RUNDATA, чтобы она получила соответствующее изменение. 6. Менее важно: • Некоторые функции MMFireSDK не находились в правильных файлах исходного кода. EnumElts, LoadObject, UnloadObject, Initialize, Free, UpdateEditStructure, UpdateFileNames должны быть перемещены в модуль General.cpp, так как они тоже вызываются из runtime, и их пустые клоны должны быть удалены из RunOnly.cpp. 7. Отредактируйте Ваши строки ресурсов, поменяйте значение строки KPX_MARK на "MF2", и удалите строку KPX_CREATETITLE. Вы также можете удалить M_DESC, если не используете это, так как это не используется в MMF2. 8. Скомпилируйте Ваше расширение. Ниже см. описание и способы устранения возможных ошибок компиляции и линковки. [Возможные ошибки линковки] "Cannot find unique match for symbol xxx". ("Не получается найти уникальное совпадение для символа xxx"). Обычно эта проблема происходит с функциями Initialize и Free. Чтобы исправить их, либо добавьте extern "C" перед заголовком функции, например так: extern "C" int WINAPI DLLExport Initialize(mv _far *knpV, int quiet) Или замените определения Initialize и Free в своем файле .def: Initialize = ?Initialize@@YGHPAVmv@@H@Z @25 Free = ?Free@@YGHPAVmv@@@Z @26 [Возможные ошибки компиляции] "error C2664: 'DialogBoxParamA': cannot convert parameter 4 from etc." ("ошибка C2664: 'DialogBoxParamA': не могу преобразовать параметр 4 из ..."). Функция DialOpen теперь простой макрос (переопределение для DialogBoxParam). Удалите приведение типа FARPROC перед параметром оконной процедуры (window proc), чтобы избежать этой ошибки компиляции (также Вы можете напрямую использовать DialogBoxParam). Ошибка в RunOnly.cpp, "loOiNum not a member of 'LO'" ("loOiNum не член 'LO'"). Удалите строку "loPtr->loOiNum = 0". Структура rhy больше не существует. Как теперь получить доступ к переменным, которые были раньше членами этой структуры: ryPtr->ryHmainWin замените на rhPtr->rhHMainWin DibToImage и AddImage теперь не возвращают DWORD, но старшее слово всегда равно 0 в MMF2, так что Вы можете безопасно использовать приведение типа результата к WORD. oiHFran больше не является членом ObjInfo. Вам не нужен этот параметр в MMF2, можно просто удалить все ссылки на него. Члены oiEffect и oiEffectParam структуры ObjInfo теперь oiHdr.oiInkEffect и oiHdr.oiInkEffectParam. Если Вы их используете, то убедитесь, что наложили маску EFFECT_MASK на oiInkEffect. GetKnpPalette был переименован в GetPaletteAppli. Изменен параметр AntiA функций cSurface::Blit. Если используете этот параметр, то просто замените TRUE на BLTF_ANTIA для blit с анти-алиасингом. Изменены параметры по умолчанию Blit и Stretch, так что это иногда может привести к ошибкам компиляции, или даже с проблемами компилятора, который ошибется с 2 функциями и не выдаст какое-либо предупреждение. Если встретитесь с любой ошибкой компиляции, просто добавьте параметры по умолчанию к функции (BMODE_OPAQUE, BOP_COPY, и т. д.). Изменены параметры функции cSurface::DrawText. Вставьте счетчик символов (или -1) перед вторым параметром. cSurface::BeginRaster и EndRaster заменены на LPBYTE cSurface::LockBuffer() и void cSurface::UnlockBuffer(LPBYTE spBuffer). mvKncHelp была заменена на mvHelp. Изменена функция mvEditImage. Редактор изображений (Picture Editor) теперь работает как диалоговое окно (dialog box), наподобие TGF, так что больше не нужно закрывать Ваше окно настройки (setup box) для редактирования изображения. Вы можете редактировать свою картинку примерно так: EditImageParams eip; eip.m_dwSize = sizeof(EditImageParams); eip.m_pWindowTitle = NULL; eip.m_dwImage = edPtr->nImage; eip.m_dwOptions = PICTEDOPT_NOALPHACHANNEL | PICTEDOPT_CANBETRANSPARENT; eip.m_dwFixedWidth = 32; eip.m_dwFixedHeight = 32; if ( spa->kv->mvEditImage(edPtr, &eip, hDlg) ) { edPtr->nImage = (WORD)eip.m_dwImage; } Символы PICTEDOPT_ определены в PicEdDefs.h. Применение функции mvEditAnimation. Вы можете редактировать анимацию примерно так: EditAnimationParams eap; eap.m_dwSize = sizeof(EditAnimationParams); eap.m_pWindowTitle = NULL; eap.m_nImages = number_of_images; eap.m_nMaxImages = max_number_of_images_in_image_list; eap.m_nStartIndex = 0; eap.m_pImages = image_list; // LPWORD eap.m_pImageTitles = NULL; eap.m_dwOptions = PICTEDOPT_etc.; eap.m_dwFixedWidth = 32; eap.m_dwFixedHeight = 32; if ( spa->kv->mvEditAnimation(edPtr, &eap, hDlg) ) { number_of_images = eap.m_nImages; } [Как реализовать новые функции MMF2 в Вашем расширении] Функция MakeIcon все еще вызывается, если в Вашем расширении она есть, но это устарело. Если эта функции только загружает EXO_ICON bitmap из своих ресурсов, то Вы можете удалить её, MMF2 теперь загружает эту растровую картинку по умолчанию, и берет цвет первой точки как цвет прозрачности (transparent color). Иначе Вы можете заменить это функцией MakeIconEx, которая использует параметр cSurface и она проще для применения (и может поддерживать большее количество цветов). Функция EditorDisplay теперь не обязательна. Если эта функция отсутствует, то MMF загружает и отображает EXO_IMAGE bitmap из ресурсов расширения. Цвет первой точки этой картинки считается цветом прозрачности (transparent). Устарели функции AppendPopup, SelectPopup, ModifyObject, RebuildExt и EndModifyObject: - Функции AppendPopup, RebuiltExt и EndModifyObject больше не вызываются. Если Вы хотите использовать новую систему свойств, то реализуйте следующие функции: - GetProperties Также определите идентификаторы свойств и определения в файле Edittime.cpp. Если Вы хотите отобразить значения в отладчике (Debugger) для своего объекта, то реализуйте следующие функции: - GetDebugTree Также задайте идентификаторы элемента и определения в Runtime.cpp. Реализуйте функцию GetHelpFileName в Edittime.cpp, с ней MMF может отобразить Ваш файл подсказки (help file), когда пользователь кликает на кнопку Help в меню свойств About объекта. Замечание: окне диалога настройки (setup dialog box), если Вы все еще его используете, вызовите mV->mhHelp для отображения своего файла подсказки, например: mV->mvHelp(GetHelpFileName(), HH_DISPLAY_TOPIC, (LPARAM)"index.html"); Если Вашему расширению для работы нужны внешние DLL (bass.dll и т. п.), то реализуйте функцию GetDependencies, и установите эти DLL в папку Data\Runtime системы MMF, чтобы они были включены в автономные приложения. Если Вы хотите, чтобы Ваш объект поддерживал переходы (transitions), то можно это реализовать. Добавьте OEPREFS_TRANSITIONS к флагам OEPREFS в своем файле .h, и затем реализуйте GetRunObjectSurface. Если эта функция имеется, то она будет вызвана вместо DisplayRunObject, и возвратит поверхность (surface), которая отображается на экране. Замечание: если Вы хотите, чтобы расширение использовало эффекты чернил (ink effects), то это можно реализовать вручную в DisplayRunObject, или Вы можете позволить системе MMF делать это автоматически, если реализуете GetRunObjectSurface, описанную ранее. Примечание: Вы также должны добавить опцию OEPREFS_INKEFFECT к своим опциям OEPREFS. Если хотите реализовать для своего объекта точное детектирование коллизий, то Вам нужно реализовать функцию GetRunObjectCollisionMask. Эта функция должна вернуть маску монохромной коллизии. Для получения дополнительной информации обратитесь к документации по этой функции. Если Ваш объект отображает текст, и Вы хотите поддерживать автоматические текстовые функции MMF: - edittime (во время редактирования приложения): реализуйте функции GetTextCaps, GetTextFont, и т. д. (обратите внимание: они такие же в MMF 1.5). Если Вы хотите ограничить использование расширения для некоторых версий или сборок MMF2, то добавьте следующий код к GetInfos: case KGI_PRODUCT: return PRODUCT_VERSION_STANDARD; // Стандартная систем MMF, или более новая case KGI_BUILD: return 219; // Сборка 219 или более новая Если Ваше расширение загружает файлы, и Вы хотите реализовать поддержку новых двоичных встроенных файлов MMF2, то рассмотрите callback-функции mvOpenHFile, mvCloseHFile, mvGetFile, mvReleaseFile в Help-файле SDK [1]. [Пошаговый процесс создания расширения] EDK содержит шаблон, который Вы можете использовать для создания собственных объектов расширения. В этой главе будет показаны следующие шаги процесса разработки: • Компиляция. Компиляция. EDK поставляется с готовым к компиляции шаблоном расширения. Этот шаблон генерирует пустое расширение с двумя примерами для действий, условий и выражений, которые в основном не делают ничего. Ваша задача - заполнить пустоты в этом шаблоне для определения в исходном коде своих собственных подпрограмм. Первая задача состоит в правильной компиляции этого шаблона. • Распакуйте архив EDK (Fusion25SDK.zip) в произвольную папку на диске. Предположим, что это будет папка Fusion25Sdk. В ней появятся 3 папки: Extensions, Inc, Lib. Примечание: если у Вас IDE более новой версии, чем Microsoft Visual C++ 2005, то запустится мастер преобразования решения и проекта. Выполните все шаги, необходимые для этого преобразования (Далее -> Резервную копию не создавать, далее -> Готово -> Закрыть). • Выберите конфигурацию отладки (Debug Unicode), скомпилируйте, компиляция должна пройти успешно. Если все прошло хорошо, то в результате получится файл "Template.mfx" в папке Obj\Unicode\Debug. Примечание: у меня при компиляции появлялись предупреждения MSB8012, сообщающие о том, что цель компиляции TargetPath (c:\..\Debug\Template.dll) не соответствует значению свойства выходного файла (c:\..\Template.mfx) для Linker. Это может привести к неправильному построению проекта. Чтобы исправить это, убедитесь, что значения свойств $(OutDir), $(TargetName) и $(TargetExt) соответствуют значению, указанному в %(Link.OutputFile). Насколько я понял, это предупреждение не критично, и связано с тем, что в командной строке линкера выходной файл указан с расширением .mfx вместо традиционного расширения .dll (опция линкера /OUT:). • Теперь мы поменяем имя расширения. Откройте диалог настроек проекта (Project Settings, открывается выбором свойств в контекстном меню, если сделать правый клик на имени проекта), убедитесь, что выбрана конфигурация Debug Unicode. Перейдите в раздел Link (Компоновщик -> Общие), и поменяйте настройку "Output file name" (Выходной файл). Цель изменения - чтобы выходной файл после компиляции оказался в каталоге Extensions\Unicode текущей копии Вашей системы CF 2.5, тогда сразу после компиляции расширение будет доступно в среде CF. И конечно, переименуйте "Template.mfx" в то имя, которое хотите. Как вариант, для этой цели можно использовать событие построения (Post-build event), чтобы сделать копию Template.mfx в то имя и тот каталог, которые Вам нужны. Важное замечание: объект MFX это стандартный DLL-файл. Если CF работает, и приложение использует Ваше загруженное расширение, то линкер не сможет поместить выходной файл в директорию Extensions\Unicode. Вы должны закрыть приложение, загруженное в CF, которое использует Ваше расширение, перед тем, как выполнить компиляцию расширения. Примечание: не нужно закрывать саму среду CF, просто обновите список объектов и убедитесь сначала в наличие Вашего расширения в списке, если среда CF уже открыта. Должно быть закрыто приложение, использующее это расширение, и должны быть закрыты окна редакторов, где вставлено это расширение. Изменение имени и иконок. Когда создается объект расширения, то первое, что Вы захотите сделать - определить свой идентификатор для объекта, иконки и имена. Каждое расширение должно иметь свой собственный идентификатор. Этот идентификатор используется, например, когда Вы копируете (copy) / вставляете (paste) действия или условия (actions, conditions), связанные с объектами расширения. Если 2 расширения используют одинаковый идентификатор, то CF не будет знать, с каким расширением связать вставленные события. Таким образом первое, что Вам нужно сделать при создании своего расширения, это дать ему уникальный идентификатор. Идентификатор определяется в файле Main.h. Идентификатор по умолчанию следующий: #define IDENTIFIER MAKEID(S,A,M,2)
Просто поменяйте буквы в макросе MAKEID. Когда это будет сделано, удалите перед ним директиву #pragma message, чтобы удалить предупреждающее сообщение. Иконки определены как растровые картинки (bitmaps), находящиеся во внешних файлах в формате BMP. EXO_ICON (файл Exticon.bmp): иконка объекта, как он выглядит в окне "Object" редактора фрейма (Frame editor) и редактора событий (Event editor). Цвет первой точки картинки считается цветом прозрачности (transparent color). Если Вы хотите поменять цвет прозрачности, то реализуйте функцию MakeIconEx, загрузите свою иконку в параметр поверхности (surface) и поменяйте её цвет прозрачности функцией cSurface::SetTransparentColor. EXO_IMAGE (файл Extimg.bmp): картинка объекта, отображаемая в игровом поле редактора фрейма. Вы должны сделать трехмерный вид этой иконки, чтобы её было проще идентифицировать на игровом поле. Цвет первой точки дает цвет прозрачности. Если Вы не хотите использовать цвет прозрачности, или хотите нарисовать свою иконку вручную (программно), то реализуйте функцию EditorDisplay. В файле Ext.rc Вы найдете разные строки, описывающие объект, отображаемые в свойствах закладки About объекта (окно Property системы CF). KPX_NAME и IDST_OBJNAME: содержат имя объекта. Также Вы должны поменять информацию, содержащуюся в части "Version" ресурсов, просто отредактируйте эти поля и введите корректную информацию. Замечание: Вы должны увеличить номер версии каждый раз, когда выпускаете новый релиз своего расширения. Выбор флагов объекта (object flags). Когда определяется объект, важно решить, должен ли Ваш объект двигаться, быть анимированным, открывать окно поверх фрейма, открывать элемент управления, или просто быть невидимым. Сейчас нужно принять все эти решения. Как только Вы определили свойства своего объекта, прочитайте содержимое врезки "Определение флагов объекта", введите правильные описания OEFLAGS и OEPREFS в своем файле Main.h. Перед тем, как перейти к непосредственному кодированию поведения расширения, Вы должны уделить время для того, чтобы определить, какие свойства должны быть у объекта. Например, должен ли он двигаться, использовать анимацию наподобие активного объект, должен ли использовать свои собственное окно, и т. д. В должны сообщить системе CF о всех свойствах Вашего объекта. В подпрограмме GetRunObjectInfos расширение должно заполнить 2 поля флагов: infoPtr->editFlags=OEFLAGS; infoPtr->editPrefs=OEPREFS; Первое поле флагов содержит текущие флаги для объекта (объект создается с использованием этих флагов, когда Вы бросаете его в игровое поле). Эти флаги могут быть изменены позже с использованием настройки расширения (extension setup). Второе поле содержит флаги редактирования, и позволяет редактировать определенные свойства расширения таким образом, как нужно расширению. OEFLAGS и OEPREFS определены в конце файла MAIN.H. [OEFLAGS] OEFLAGS очень важны для Вашего объекта расширения. CF использует эти флаги, чтобы определить, как обрабатывать объект - как спрайт или фон (backdrop object), должны ли быть добавлены свойства движения и т. д. Главные свойства OEFLAGS OEFLAG_MOVEMENTS. Флаг OEFLAG_MOVEMENTS добавляет объекту свойство передвижения (movement property). Если Вы используете этот флаг, то должны подключить структуры rCom и rMov к структуре RUNDATA объекта. OEFLAG_ANIMATIONS. Флаг OEFLAG_ANIMATIONS добавляет объекту свойство анимации (animation property), основанное на спрайтах (sprite-based). Если используете этот флаг, то должны подключить структуры rCom и rAni к структуре RUNDATA объекта. Если у объекта есть оба флага OEFLAG_ANIMATIONS и OEFLAG_SPRITE, то отображение будет автоматически выполняться системой CF. Таким образом, Вам не нужно определять подпрограмму рисования в своем расширении. OEFLAG_VALUES. Флаг OEFLAG_VALUES добавляет объекту свойство значения (value property), которое содержит 26 изменяемых значений и 10 изменяемых строк. Если используете этот флаг, то должны добавить структуру rVal в структуру RUNDATA объекта. Свойства отображения OEFLAGS OEFLAG_BACKGROUND. OEFLAG_BACKGROUND говорит CF отображать этот объект посередине объектов фона (background objects). Замечание: этот флаг должен использоваться с осторожностью. Используйте его для объектов, которые не обновляются очень часто, и которые не перемещаются. Всякий раз, когда объект перемещается, перерисовывается весь экран. Объект Picture является примером объекта, который использует подпрограмму OEFLAG_BACKGROUND. Этот флаг не должен использоваться вместе с OEFLAG_SPRITES и OEFLAG_QUICKDISPLAY, и т. п. OEFLAG_SPRITES. OEFLAG_SPRITES говорит CF обрабатывать этот объект расширения как спрайт. Если также установлен флаг OEFLAG_ANIMATIONS, то CF будет использовать реальные спрайты для отображения этого объекта, и Вам не нужно для этого писать ни одной строки кода. Будет иметь эффект только OEFLAG_BACKSAVE. OEFLAG_BACKSAVE. CF будет сохранять фон объекта, если этот флаг установлен, и не будет сохранять этот фон, если флаг не установлен. Сохраняемая зона вычисляется по координатам объекта и полям hoImgXHot, hoImgYHot, hoImgWidth, hoImgHeight, возвращаемым подпрограммой HandleRunObject. OEFLAG_INTERNALBACKSAVE. Если установлен флаг OEFLAG_INTERNALBACKSAVE, и также установлен флаг OEFLAG_BACKSAVE, то CF будет вызывать подпрограммы сохранения фона расширения (extension background saving routines, которые должны быть определены). SaveBackground должна сохранять background в буфер, и RestoreBackground должна восстанавливать сохраненный буфер по тем же самым координатам. KillBackground должна очищать буфер из памяти. Если Вы используете функции SaveRect / RestoreRect / KillRect из mmfs2.dll, то можете использовать поле hoBackSave структуры headerObject. Или Вы можете использовать поверхность (surface) для сохранения фона. OEFLAG_QUICKDISPLAY. Отображение объекта как реальных спрайтов может значительно замедлить Ваше приложение. Если Ваш объект отображается медленно (например, Вы создали большой текстовый объект с использованием многих текстовых функций Windows), то каждый раз, когда другой спрайт отображается спереди этого объекта, то объект должен быть очищен и перерисован. Это приведет к тому, что Ваше приложение будет работать очень медленно. Чтобы не перерисовывать объект все время, используйте флаг QUICKDISPLAY. Этот флаг можно использовать только совместно с флагом OEFLAG_SPRITE. Такой спрайт удаляется из главного списка спрайтов, но рисуется только поверх фона. Когда спрайт поступает на верх, он не перерисовывается. Таким образом, Вы можете отобразить большой текст при движущихся спрайтах на полной скорости. Объекты QUICKDISPLAY могут или не могут сохранить фон в зависимости от флагов OEFLAG_BACKSAVE и OEFLAG_INTERNALBACKSAVE. Одна из вещей, которые эти флаги не делают правильно, это обработка сохранения фона, при пересечении друг друга. Некоторые часть второго объекта могут или не могут быть сохранены как часть фоновой сохраняемой области, и наоборот. В результате не помещайте объекты quickdisplay один поверх другого. Не использование OEFLAG_SPRITE или OEFLAG_BACKGROUND. Если не используете флаг OEFLAG_SPRITE или OEFLAG_BACKGROUND, то Вы не можете получить прямой доступ к экрану CF. Это не означает, что Вы не можете ничего отображать, Ваша подпрограмма DisplayRunObject может использоваться для открытия (open), перемещения (move) или изменения размера окна поверх экрана CF. Разработчики реально используют эту технику для объектов AVI, QuickTime, Button, List, Edit, Combo, и всех объектов с окном. Другие флаги OEFLAG_TEXT. Флаг OEFLAG_TEXT добавляет меню "Text" в действия (actions), условия (conditions) и выражения (expressions). Этот пункт меню содержит условия наподобие "IsBold", "IsItalic" и т. д., действия наподобие "Set font name" (установить имя шрифта), "Set italic" (установить наклонный вид шрифта), "Set bold" (установить толстый вид шрифта) и т. д. Если хотите реализовать этот флаг (если Ваш объект текстовый), то нужно определить 4 функции в исходном коде Вашего расширения: "GetRunObjectFont", "SetRunObjectFont", "GetRunObjectTextColor" и "SetRunObjectTextColor". Эти функции вызываются основным кодом работающего приложения (main runtime) для изменения/запроса данных шрифта и цвета шрифта, используемого в Вашем объекте. Этот флаг сейчас используется в объектах Button, Clock, Edit, List, ListView и других. OEFLAG_DISPLAYINFRONT. Если Вы установили флаг OEFLAG_DISPLAYINFRONT, то объект будет отображен спереди всех других объектов в редакторе. Вы должны использовать этот флаг, когда Ваш объект отображается как окно, так чтобы редактор учитывал отображение, которое Вы получаете в приложении. OEFLAG_WINDOWPROC. Если Ваш объект нуждается в перехвате оконных сообщений CF, то Вы должны установить флаг OEFLAG_WINDOWPROC. CF будет вызывать подпрограмму "WindowProc" в объекте расширения. См. раздел "How to control a window from an extension". OEFLAG_TABSTOP. Элементы управления интерфейса пользователя (Controls), такие как объект Edit или объект List, нуждаются в активизации клавишей TAB. Используйте флаг OEFLAG_TABSTOP, если хотите, чтобы Ваш объект перехватывал команды табуляции. OEFLAG_SCROLLINGINDEPENDANT. Если установлен флаг OEFLAG_SCROLLINGINDEPENDANT, то объект не будет следовать игровому полю, когда оно прокручивается. Таким образом, объект останется статическим на экране, наподобие объекта Score (очки игрока) или объекта Lives (жизни игрока). OEFLAG_NEVERKILL. Установите флаг OEFLAG_NEVERKILL, чтобы предотвратить удаление объекта, если он уйдет далего от границ игрового поля. OEFLAG_RUNBEFOREFADEIN. Этот флаг позволяет объекту расширения быть созданным перед переходом постепенного появления изображения (fade-in transition). Этот флаг устанавливается пользователем через свойство Create Before Fade-In Transition. OEFLAG_MANUALSLEEP. Обычно объект деактивируется, если он уходит слишком далеко из окна отображения - он все еще существует, но удаляется из окна отображения. Принятие решения о том, должен ли быть деактивирован этот объект, обычно осуществляет CF. Если объект не управляется игроком, и не является частью детектирования столкновения (collision detection), то он может быть деактивирован. Если нет, то он будет оставаться активным, даже если уйдет за границы области отображения. OEFLAG_MANUALSLEEP меняет этот процесс на ручной режим. В этом случае флаг OEFLAG_NEVERSLEEP используется как триггер, и если этот флаг установлен, то объект никогда не деактивируется. Изменения флагов. Какой флаг можно изменить в диалоге настройки (setup dialog)? Окно диалога настройки (или подпрограммы свойства SetPropValue/SetPropCheck) Вашего объекта расширения можно использовать для изменения любого из флагов, кроме следующих: OEFLAG_MOVEMENTS Эти флаги устанавливаются только один раз для каждого объекта. Так что пожалуйста обратите внимание, что некоторые из этих флагов сохранены в файле MFA, так что если Вы поменяете их, то возможно придется удалить и заново создать эти экземпляры Вашего объекта, чтобы эти изменения были учтены. В соответствии с флагами, которые используете, Вы должны задать определенные структуры в своей структуре RUNDATA. Для дополнительной информации см. "Важные структуры". Важные структуры. Эти структуры Вы должны использовать в своей структуре RUNDATA. Базовая структура RUNDATA должна содержать структуру headerObject в качестве первого элемента: typedef struct tagRDATA { headerObject rHo; } RUNDATA; Если установлены флаги OEFLAG_MOVEMENTS, OEFLAG_ANIMATIONS или OEFLAG_SPRITES, то Вы должны добавить структуру rCom после структуры rHo: typedef struc tagRDATA
{
headerObject rHo;
rCom rc;
} RUNDATA;
Если также установлен флаг OEFLAG_MOVEMENTS, то Вы должны добавить структуру rMvt сразу после структуры rCom. typedef struc tagRDATA
{
headerObject rHo;
rCom rc;
rMvt rm;
} RUNDATA;
Вот различные случаи: OEFLAG_MOVEMENTS headerObject rHo; rCom rc; rMvt rm; OEFLAG_ANIMATIONS headerObject rHo; rCom rc; rAni ra; OEFLAG_SPRITE headerObject rHo; rCom rc; rSpr rs; OEFLAG_VALUE headerObject rHo; rVal rv; OEFLAG_MOVEMENTS | OEFLAG_ANIMATIONS headerObject rHo; rCom rc; rMvt rm; rAni ra; OEFLAG_MOVEMENTS | OEFLAG_ANIMATIONS|OEFLAG_SPRITE headerObject rHo; rCom rc; rMvt rm; rAni ra; rSpr rs; Если вышеуказанные комбинации включают OEFLAG_VALUE, то Вы должны поместить rVal как последний элемент. Помните: • Должен быть представлен элемент rCom, если используются флаги OEFLAG_MOVEMENTS, OEFLAG_ANIMATIONS или OEFLAG_SPRITES. [OEPREFS] Флаги OEPREFS управляют некоторыми свойствами, отображаемыми CF в окне редактора свойств (Property window). Каждая опция управляется соответствующей опцией OEFLAG_ в поле hoOEFlag. OEPREFS_BACKSAVE. OEPREFS_BACKSAVE разрешит опцию "Save background", сохранить задний фон (OEFLAG_BACKSAVE). OEPREFS_BACKEFFECTS. OEPREFS_BACKEFFECTS разрешит опцию эффектов очистки фона, если установлен флагOEPREFS_BACKSAVE. OEPREFS_QUICKDISPLAY. OEPREFS_QUICKDISPLAY разрешит опцию быстрого отображения (OEFLAG_QUICKDISPLAY). OEPREFS_SCROLLINGINDEPENDANT. OEPREFS_SCROLLINGINDEPENDANT разрешит опцию следования за игровым полем (Follow the playfield, OEFLAG_SCROLLINGINDEPENDANT). OEPREFS_LOADONCALL. OEPREFS_LOADONCALL разрешит опцию "load on call" (загрузка при вызове). Имейте в виду, что эта опция не имеет эффекта на объектах расширений. OEPREFS_GLOBAL. OEPREFS_GLOBAL разрешит опцию "global object" (глобальный объект). Имейте в виду, что эта опция не имеет эффекта на объектах расширений. OEPREFS_SLEEP. OEPREFS_SLEEP разрешит опции ручного входа в сон (manual sleep, OEFLAG_MANUALSLEEP). OEPREFS_KILL. OEPREFS_KILL разрешит уничтожение (Destroy), если объект далеко от игрового поля (OEFLAG_NEVERKILL). OEPREFS_INKEFFECTS. OEPREFS_INKEFFECTS разрешит свойства эффекта чернил (Ink Effect). OEPREFS_TRANSITIONS. OEPREFS_TRANSITIONS разрешит свойства переходов (Transitions). Вы должны реализовать в своем объекте функцию GetRunObjectSurface. OEPREFS_FINECOLLISIONS. OEPREFS_FINECOLLISIONS разрешит опцию точного детектирования столкновений (Collisions / Use Fine Detection). Вы должны реализовать в своем объекте функцию GetRunObjectCollisionMask. [Примеры объектов и флагов] Без вывода на экран: Ini object • OEFLAG_DISPLAYINFRONT MCI object • OEFLAG_DISPLAYINFRONT Window control object • OEFLAG_DISPLAYINFRONT CD Audio object • OEFLAG_DISPLAYINFRONT Print object • OEFLAG_DISPLAYINFRONT Mixer object • OEFLAG_DISPLAYINFRONT ODBC object • OEFLAG_DISPLAYINFRONT SEARCH object • OEFLAG_DISPLAYINFRONT Открытие элемента управления. Объекты, открывающие элемент управления интерфейса пользователя (control) в окне фрейма: Button object • OEFLAG_WINDOWPROC | OEFLAG_DISPLAYINFRONT | OEFLAG_TABSTOP | OEFLAG_MOVEMENT | OEFLAG_TEXT List object • OEFLAG_WINDOWPROC | OEFLAG_DISPLAYINFRONT | OEFLAG_TABSTOP | OEFLAG_MOVEMENT | OEFLAG_TEXT Combo object • OEFLAG_WINDOWPROC | OEFLAG_DISPLAYINFRONT | OEFLAG_TABSTOP | OEFLAG_MOVEMENT | OEFLAG_TEXT Открытие окна. Объекты, открывающие окно в окне фрейма: AVI object • OEFLAG_MOVEMENTS | OEFLAG_WINDOWPROC | OEFLAG_DISPLAYINFRONT QT3 object • OEFLAG_MOVEMENTS | OEFLAG_DISPLAYINFRONT | OEFLAG_WINDOWPROC Рисование на экране. Объекты, непосредственно рисующие в окне фрейма: Anim object • OEFLAG_SPRITES | OEFLAG_BACKSAVE | OEFLAG_MOVEMENTS | OEFLAG_VALUES Hiscore object • OEFLAG_SPRITES | OEFLAG_QUICKDISPLAY | OEFLAG_BACKSAVE | OEFLAG_TEXT Date & Time object • OEFLAG_SPRITES | OEFLAG_MOVEMENTS | OEFLAG_QUICKDISPLAY | OEFLAG_BACKSAVE | OEFLAG_SCROLLINGINDEPENDANT | OEFLAG_TEXT Создание подпрограмм, работающих во время выполнения приложения (run-time routines). Если Вы скомпилировали шаблон, поменяли имя и иконки, выбрали флаги объекта, создали диалог настройки или свойства, то Вы теперь готовы бросить Ваш объект во фрейм и вызвать диалог настройки (или свойства в редакторе свойств CF). Следующий шаг состоит в том, чтобы объект работал во время выполнения приложения (run-time). Для разработки объекта расширения абсолютно критично наличие двух подпрограмм: CreateRunObject Подпрограмма CreateRunObject вызывается, когда создается объект. В этой подпрограмме Вы должны инициализировать структуру RUNDATA из информации, находящейся в структуре EDITDATA. Обычно структура RUNDATA отражает структуру EDITDATA, и имеет больше полей, чтобы хранить данные времени выполнения (run-time data). CreateRunObject только мостик между EDITDATA и RUNDATA, и поэтому Вам здесь нужно сделать копию всей необходимой информации. DestroyRunObject вызывается, когда объект уничтожается. Эта подпрограмма должна освобождать любую выделенную память, открытые окна, или ресурсы, которые были загружены за время жизни объекта. Другая важная подпрограмма это HandleRunObject. Она вызывается в каждой прокрутке цикла приложения. Пожалуйста сделайте время работы этой подпрограммы как можно меньше: медленная подпрограмма будет замедлять работу всего приложения. Например, объект поиска просматривает только 100 строк текста на каждой прокрутке цикла приложения. Если подпрограмма HandleRunObject быстрая, то пользователь все еще может использовать анимации во время работы объекта, в то время как объект осуществляет поиск запрошенного текста. Если Ваш объект невидимый, то перейдите к главе "Определение условий, действий и выражений". Если видимый, то Вам нужно заполнить подпрограмму DisplayRunObject своим кодом. Запомните 2 вещи: • Только в подпрограмме DisplayRunObject можно записывать данные в экран, чтобы работал процесс сохранения и восстановления фона. Определение условий, действий и выражений. Условия (conditions), действия (actions) и выражения (expressions) являются основными частями Вашего объекта расширения. Следующий пример покажет, как создать новое условие. Используйте ту же самую технику для создания для создания действий и выражений для своего объекта. 1. Подумайте, какие условия должны быть для объекта, подберите хорошие имена для них в всплывающем меню и отображении в редакторе событий (Event Editor). Нужны ли для них параметры, какие они должны быть, и т. п.? Здесь мы создадим условие, которое будет запрашивать числовой параметр. 2. Определите в файле MAIN.H код для условия, и найдите значение CND_LAST. Замените имя (name) на имя в коде для своего расширения, например CND_MINE, и определите CND_LAST для своего последнего условия плюс 1 (CND_LAST должно быть всегда последним определенным, плюс единица). 3. Отредактируйте файл EXT.RC в редакторе ресурсов Visual Studio. Определите новую запись в MN_CONDITIONS для своего условия. Убедитесь, что Вы дали новой опции меню понятный идентификатор, например IDMN_CND_MINE, так как он понадобится Вам позже. 4. В файле EXT.RC определите новую строку для отображения своего условия в редакторе событий. Например: "%o: какое хорошее условие %0". Убедитесь, что идентификатор этой строки также понятен, например IDS_CND_MINE, Вам он позже понадобится. 5. Закройте редактор ресурсов, и загрузите файл "Resource.h" в редакторе кода Visual Studio. Найдите идентификатор опции меню, и поменяйте его значение так, чтобы оно лежало в диапазоне 26000 .. 26999. Это важно сделать, если хотите, чтобы система CF распознавала опцию меню, когда она выбрана. Просто имейте в виду: для действий (actions) идентификатор должен лежать в диапазоне 25000 .. 25999, и для выражений (expressions) между 27000 .. 27999. 6. Откройте файл MAIN.CPP, и найдите массив conditionsInfos. Введите новые определения, которые будут содержать информацию для CF. Для нашего примера строка должна быть такой: [IDMN_CND_MINE, IDS_CND_MINE, CND_MINE, EVFLAGS_ALWAYS, 1, PARAM_EXPRESSION, IDS_PARAM]. Порядок следующий: идентификатор опции меню, идентификатор отображаемой строки, код условия, флаги условия, количество параметров, идентификатор параметра и строка для отображения, когда вводится параметр. 7. В файле EXT.CPP определите новую подпрограмму для обработки Вашего нового условия. Например, short WINAPI DLLExport ConditionOfMine(LPRDATA rdPtr, long param1, long param2). Подробнее см. главу "List of run-time routines" для получения информации о подпрограммах обработки условий (condition routines). 8. Теперь найдите массив ConditionJumps, и в точно определенном месте, как было задано кодом CND_MINE, вставьте имя для своей новой подпрограммы. В этом примере вставленное имя будет "ConditionOfMine". Отладка объекта. Отладка кода для Вашего расширения очень важны шаг в процессе разработки. Вам определенно понадобится пошаговое выполнение кода, чтобы решить проблемы и исправлять ошибки. В следующих секциях содержатся процедуры, описывающие доступ к исходному коду Вашего расширения в отладчике. 1. С среде Visual C++ откройте настройки проекта. 2. Убедитесь, что выбрана конфигурация отладки (Debug Unicode), и выбрана секция отладки (Debugging) настроек. 3. Введите путь до копии установки CF в поле ввода Command. 4. Введите директорию копии установки CF в поле ввода Working directory. 5. В разделе настроек линкера (Linker) введите в качестве пути до выходного файла (Output File) путь до файла расширения в каталоге Extensions\Unicode Вашей копии каталога установки CF. Измените права на запись в этот файл, если на Вашем компьютере разрешена работа системы UAC, чтобы Вы могли осуществить сборку этого файла. Теперь у Вас должна быть возможность ставить точку останова непосредственно в исходный код своего расширения, чтобы можно было выполнять пошаговую отладку кода. Отладка расширения во время выполнения приложения, где используется расширение, несколько сложнее, так как CF запускает процесс runtime как внешнюю программу, но это важный шаг для отладки условий и действий. Выполните следующие шаги: 1. Откройте папку Extensions \ Help \ Misc Documentation в SDK, и сделайте копию файла CopyRun.Bat в корневую папку CF, где находится файл MMF2U.EXE. 2. Если папка C:\Temp еще не существует, то создайте её в корне диска C:. В этой директории создайте папку Rt. Примечание: также можно отредактировать файл CopyRun.bat, и поменять имя директории, см. далее. 3. Загрузите файл проекта Вашего расширения в Visual C++, откройте настройки проекта (Project Settings), перейдите в раздел отладки (Debugging). В опции командной строки (Command line), введите путь до файла EdRt.exe, который находится в папке Data\Runtime\Unicode каталога установки системы CF. 4. В строке опции аргумента приложения (Program argument) введите "/fC:\Temp\Rt\App0.ccn". Как отлаживать? • Загрузите CF и создайте приложение с Вашим объектом, который хотите отладить. Через некоторое время эти операции станут для Вас привычными. Замечание: если Вы не хотите создавать папку C:\Temp\Rt folder, то можете поменять её на любую, какую пожелаете: для этого нужно поменять CopyRun.Bat и поменять опции командной строки (command line options) в настройках отладки проекта (Debugging settings). Добавление файла помощи (Help) для Вашего расширения. Файл подсказки (help file) рекомендуется создавать, в формате Microsoft HTML Help (*.CHM). Шаблон для этого предоставлен в подкаталоге Help каталога Template шаблона. Просто поменяйте имя расширения в файле .HHP, отредактируйте файлы HTML и затем скомпилируйте файл CHM с помощью утилиты Microsoft HTML Help Workshop. Файл CHM будет собран в подкаталоге ToInstall\Files\Help каталога Template. Вы можете загрузить Microsoft HTML Help Workshop [3] (установщик htmlhelp.exe). Пожалуйста установите свой файл CHM в папку Help системы CF, и убедитесь, что у файла уникальное имя. Примечание: не меняйте позицию и имя индекса, он должен быть в файле htm\index.htm. Как реализовать Help в Вашем расширении. Свойства объекта (Properties) имеют кнопку Help на закладке About. Если кликнуть на эту кнопку, то будет вызвана функция GetHelpFileName. Убедитесь, что эта функция определена в Вашем исходном коде, и разрешена в файле .DEF. Если Ваш объект имеет диалог настройки (setup dialog box), то Вы должны вызвать функцию mvHelp. Подробнее см. описание функции mvHelp в разделе "Callback-функции". Создание релиза Вашего объекта. Чтобы можно было распространять Ваше расширение, сначала скомпилируйте "редактируемую" (editable) версию релиза и версию релиза "только для запуска" (run only). Editable-версия должна быть скопирована в директорию Extensions\Unicode системы CF и run-only-версия должна быть скопирована в директорию Data\Runtime\Unicode системы CF. Почему надо создавать 2 версии своего расширения? Есть 2 причины для этого: во-первых, подпрограммы и ресурсы, используемые в редакторе, не нужны для исполняемых приложений, где используется расширение. Во-вторых, когда CF создает автономное исполняемое приложение (stand-alone application), то расширение из каталога Data\Runtime\Unicode встраивается в файл EXE. Когда исполняемое приложение запускается, эти расширения распаковываются во временную папку, таким образом, из может получить любой. Путем предоставления "non editable" версии Вашего расширения можно защититься от того, что кто угодно может получить расширение из исполняемого приложения и будет использовать его в среде CF. Конфигурации релиза (Release). Когда Вы просмотрите конфигурации в настройках проекта, то увидите там следующие готовые конфигурации: Release Unicode: компилируется editable-версия Вашего расширения, для копирования / установки в папку Extensions\Unicode системы CF. EDITOR определяется в опциях препроцессора в разделе настроек ресурсов (Resource). Run_Only Unicode: компилируется run-only-версия Вашего расширения, для копирования / установки в папку Data\Runtime\Unicode системы CF. RUN_ONLY определяется в опциях препроцессора C/C++ и в разделе настроек ресурсов. Вы наверное заметили, что некоторые части исходного кода подключаются в секции условной компиляции между директивами #ifndef RUN_ONLY и #endif, чтобы выкинуть это из версии "run only". Также некоторые ресурсы имеют условие EDITOR, чтобы предотвратить их подключение в версию "run only". Установка Вашего расширения. Для установки расширения самый простой путь это использование бесплатной версии Clickteam Install Creator (или любую другую версию инсталлятора). Шаблон для Install Creator предоставлен в подкаталоге ToInstall директории Template. Сделайте копию своей "run only" версии в папку ToInstall\Files\Data\Runtime\Unicode, "editable" версию в папку ToInstall\Files\Extensions\Unicode, файл подсказки (help file, если он есть) в папку ToInstall\Files\Help, любые примеры в специальный подкаталог папки ToInstall\Files\Examples, и затем запустите Install Creator, загрузите файл .iit, поменяйте заголовок продукта и выполните сборку своего инсталлятора. Если Вы не используйте предоставленный шаблон для Install Creator, и хотите автоматически детектировать директорию инсталляции CF, то эту информацию можно получить из следующего ключа реестра: Key = HKEY_CLASSES_ROOT\MMF2.Document\DefaultIcon Этот ключ используется вышеупомянутым шаблоном Install Creator. Он содержит путь последней версии Clickteam Fusion, работающей на машине. Замечание: Вы должны удалить ",1" в конце строки - это делается автоматически утилитой Install Creator. Key = HKEY_LOCAL_MACHINE\Software\Clickteam\Fusion 2.5\Settings, Value = InstallPath Этот ключ содержит путь установки стандартной версии CF (Standard version). Key = HKEY_LOCAL_MACHINE\Software\Clickteam\Fusion Developer 2.5\Settings, Value = InstallPath Этот ключ содержит путь установки версии разработчика CF (Developer version). [Действия, условия и выражения] Действия (actions), условия (conditions) и расширения (expressions) ключевые составляющие для качественной работы Вашего объекта расширения. Действия, условия и выражения дают пользователю полное управление над объектом, который Вы создали. Тщательно выбирайте условия и действия, и тогда Вы умножите возможности использования Вашего объекта. long WINAPI DLLExport Condition(LPRDATA rdPtr, long param1, long param2) Каждое условие, которое Вы определяете, должно иметь свою подпрограмму. Эта подпрограмма вызывается системой CF, когда условие требует анализа. Параметры: LPRDATA rdPtr указатель на run-time структуру объекта. Возвращаемое значение: FALSE, если условие не удовлетворяется, TRUE если удовлетворяется. Если один из параметров PARAM_COMPARAISON или PARAM_CMPSTRING, то возвращаемое значение должно быть результатом сравнения. Замечания: - Эта подпрограмма должна быть как можно более быстрой, потому что она может вызываться довольно часто при работе приложения. Пример, условие без параметров: long WINAPI DLLExport Condition(LPRDATA rdPtr, long param1, long param2) { return TRUE; // это условие всегда верное } Пример, условие с одним параметром: long WINAPI DLLExport Condition(LPRDATA rdPtr, long param1, long param2) { return (param != 0); // это условие верно, если параметр не равен 0 } Пример, условие с двумя параметрами: long WINAPI DLLExport Condition(LPRDATA rdPtr, long param1, long param2) { return (param1==param2); // это условие верно, если параметры идентичны } Пример, условие с тремя параметрами: long WINAPI DLLExport Condition(LPRDATA rdPtr, long param1, long param2) { int p1 = CNC_GetIntParameter(rdPtr); int p2 = CNC_GetIntParameter(rdPtr); int p3 = CNC_GetIntParameter(rdPtr); return (p1==p2 && p1==p3); // это условие верно, если параметры идентичны } short WINAPI DLLExport Action(LPRDATA rdPtr, long param1, long param2) Каждое действие, которое Вы определяете, должно иметь свою подпрограмму. Эта подпрограмма вызывается системой CF, когда действие запускается приложением. Параметры: LPRDATA rdPtr указатель на run-time структуру объекта Возвращаемое значение: должен быть возвращен 0. Замечания: - Делайте Вашу подпрограмму обработки действия максимально быстрой, насколько это возможно, потому что она может вызываться довольно часто при работе приложения. Пример, действие без параметров: short WINAPI DLLExport Action(LPRDATA rdPtr, long param1, long param2) { Beep(); return 0; } Пример, действие с одним параметром: short WINAPI DLLExport Action(LPRDATA rdPtr, long param1, long param2) { if ( param1 == 0 ) Beep(0); else Beep(1); return 0; } Пример, действие с двумя параметрами: short WINAPI DLLExport Action(LPRDATA rdPtr, long param1, long param2) { Beep(param1, param2); return 0; } Пример, действие с тремя параметрами: short WINAPI DLLExport Action(LPRDATA rdPtr, long param1, long param2) { int p1 = CNC_GetIntParameter(rdPtr); int p2 = CNC_GetIntParameter(rdPtr); int p3 = CNC_GetIntParameter(rdPtr); Beep(p1, p2, p3); return 0; } long WINAPI DLLExport Expression(LPRDATA rdPtr,long param1) Каждое выражение (expression), которое Вы задаете для своего расширения, должно иметь собственную подпрограмму обработки выражения. Эта подпрограмма вызывается системой CF, когда это выражение нуждается в вычислении. Параметры: LPRDATA rdPtr указатель на run-time структуру объекта. Возвращаемое значение: если выражение числовое, то подпрограмма выражения должна возвратить вычисленное значение типа long. Если выражение строковое, то подпрограмма должна вернуть указатель на вычисленную строку. Важный момент: если выражение возвращает строку, то оно должно также установить флаг HOF_STRING в поле rdPtr->rHo.hoFlags, вот так: rdPtr->rHo.hoFlags |= HOF_STRING; Вы должны сделать это перед возвратом из функции выражения (это должно быть после захвата параметров). Установите флаг HOF_FLOAT, если выражение возвращает float (предупреждение: не делайте приведение типа float к long, см. пример ниже). Замечания: - Делайте Вашу подпрограмму обработки выражения максимально быстрой, насколько это возможно, потому что она может вызываться довольно часто при работе приложения. Пример, выражение с 1 параметром: long WINAPI DLLExport Expression(LPRDATA rdPtr,long param1) { long p1 = CNC_GetFirstExpressionParameter(rdPtr, param1, TYPE_INT); // В этом месте выполняется вычисление выражения: return p1 * 2; } Пример, выражение с 2 параметрами: long WINAPI DLLExport Expression(LPRDATA rdPtr,long param1) { long p1 = CNC_GetFirstExpressionParameter(rdPtr, param1, TYPE_INT); long p2 = CNC_GetNextExpressionParameter(rdPtr, param1, TYPE_INT); // В этом месте выполняется вычисление выражения: return p1+p2; } Пример, выражение с 3 параметрами: long WINAPI DLLExport Expression(LPRDATA rdPtr,long param1) { long p1 = CNC_GetFirstExpressionParameter(rdPtr, param1, TYPE_INT); long p2 = CNC_GetNextExpressionParameter(rdPtr, param1, TYPE_INT); long p3 = CNC_GetNextExpressionParameter(rdPtr, param1, TYPE_INT); // В этом месте выполняется вычисление выражения: return p1+p2+p3; } Пример, выражение, которое возвращает строку: long WINAPI DLLExport Expression(LPRDATA rdPtr,long param1) { long p1 = CNC_GetFirstExpressionParameter(rdPtr, param1, TYPE_INT); // тут может быть получение других параметров // Установка флага строки: rdPtr->rHo.hoFlags |= HOF_STRING; // Возврат строки: return (long)_T("Hello world"); } Пример, выражение, которое возвращает float: long WINAPI DLLExport Expression(LPRDATA rdPtr,long param1) { long p1 = CNC_GetFirstExpressionParameter(rdPtr, param1, TYPE_INT); // тут может быть получение других параметров // Установка флага "Float": rdPtr->rHo.hoFlags |= HOF_FLOAT; // Возврат float: float fResult = 1.0f; // Не возвращайте fResult напрямую, так как это значение должно // быть преобразовано в long: return *((long*)&fResult); } Для каждого действия или условия, которые Вы назначаете своему объекту расширения, Вы должны определить следующее: • Пункт меню для всплывающего меню действий условия. Довольно просто добавить пункт меню во всплывающее меню действий условия. Используйте обычную опцию меню для нормального всплывающего меню Windows. Важное замечание: определение строки это одна из вещей, однако Вы должны редактировать файл ресурса для изменения идентификатора для новой опции меню: CF сравнивает этот идентификатор выбранной опции с граничными значениями и детектирует, чем является последняя выбранная опция с этим методом - действием или условием. Обратите внимание: Вы также можете делать это напрямую в редакторе ресурсов Visual C, когда Вы вводите новый идентификатор, например вводите IDMN_YOURACTION = 25011 для присваивания значения идентификатора. Идентификаторы меню действий должны лежать между 25000 и 25999. Идентификаторы меню условий должны лежать между 26000 и 26999. Если Вы не меняете идентификаторы, то Ваша опция меню не будет детектироваться системой CF. Строка отображения. Это строка, которую CF может показать для действий или событий в списке редактора событий. Отображение несколько более сложное, потому что CF должна вставить параметры и иконку объекта, когда отображает строку в редакторе событий. Система CF была разработана, чтобы справиться со всеми комбинациями одной строки (строка условия/действия), имени объекта и параметров. Эти строки кодируются с символами %, каждый из этих символов заменяется строкой, либо именем объекта, либо параметрами: %o заменяется именем объекта и т. д. Пример 1: "Number of objects in %0=%1" С первым параметром как параметром zone и вторым параметром сравнения, будет отображено: "Number of objects in zone(0,0) to (10,10)=15" Пример 2: "%o is facing a direction %0" Оригинальная строка в программе выдает: Romeo is facing a direction south Пример 3: "Number of %o in %0=%1" Number of Romeo in zone () to () = 10 Выражения, как и условия и действия, нуждаются в 2 строках, находящихся в файле ресурсов: • Пункт меню во всплывающем меню выражения. Добавить пункт меню во всплывающем меню выражений довольно просто. Используйте обычную опцию меню в нормальном всплывающем меню Windows, и в меню максимально кратко опишите, что возвращает Ваше выражение. Важное замечание: определение строки это одна из вещей, однако Вы должны отредактировать файл resource.h для смены идентификатора в новой опции меню: CF сравнивает этот идентификатор выбранной опции с границей значений, и определяет этим методом, является ли последняя выбранная опция выражением. Обратите внимание: Вы также можете делать это напрямую в редакторе ресурсов Visual C, когда вводите новый идентификатор, например введите IDMN_YOUREXPRESSION = 27005 чтобы определить значение для этого идентификатора. Идентификаторы меню выражения должны лежать между 27000 и 27999. Если Вы не меняете идентификаторы, то Ваша опция меню не будет детектироваться системой CF. Строка отображения. Для отображения строки, которой CF может показать выражение, имеется токен выражения. Он должен быть уникальным для этого объекта, потому что вычислитель выражения сравнивает строку, введенную пользователем, и строки, найденные в различных ресурсах объектов, пока не найдет корректную. Строка не должна содержать больше 20 символов, и должна завершаться открывающей скобкой. Примеры из объекта Clock: "seconds of(" Все показанные выше выражения возвратят числовое значение. Чтобы показать, что выражение возвращает строку, Вы должны поместить знак доллара перед скобкой. Пример строки выражения из объекта system: "str$(" Вставка знака доллара перед скобкой всего лишь показывает, что Ваше выражение возвращает строку. Если Вы просматривали исходный код объектов примеров, то наверное заметили, что некоторые флаги в массивах conditionsInfos и actionsInfos в начале файла EVFLAGS_ALWAYS или EVFLAGS_NOTABLE. Эти флаги очень важны, потому что они определяют поведение каждого условия (condition). Условия событий, управляемые true и false event-driven. CF может обработать 2 разных типа условий: событийные и не событийные условия. Действительно событийные условия полагаются на реальное событие, такое как клик мышью, столкновение (collision), нажатие кнопки клавиатуры или выбранная опция меню. Возьмем например клик мышью: пользователь кликает где-нибудь во фрейме, CF получает сообщение клика, и затем просматривает список событий, чтобы увидеть, существует ли условие, работающее с кликом, как первое условие в группе событий. Если да, то условие оценивается, и если результат оценки TRUE, то вычисляются другие (событийные) условия этой группе событий. Условие, которое реально событийное, и первое условие в группе условий, вычисляется по-настоящему быстро, потому что вычисление происходит только когда событие реально происходит. Не событийные условия обычно вовлекают сравнение, такое как Global Value 1 < 10, и оно не срабатывает по реальному событию. CF вычисляет эти условия на каждом цикле приложения. Условие также может быть не событийным, когда реально событийное условие находится в позиции 2 (или с большим номером по списку) группы списка условий. В этом случае CF вызывает подпрограмму оценки, когда это необходимо. Что Вам следует делать? Если Ваше условие отвечает за клик мышью или другое очень специфичное событие, то Вы должны сделать его реально событийным. Если нет, то оно должно вычисляться на каждой итерации цикла приложения. Флаги, которые можно использовать, следующие: EVFLAGS_ALWAYS: говорит CF, что условие должно вычисляться на каждой прокрутке цикла. Если Вы просмотрите исходный код, то увидите, что это случай для большинства условий в примерах объектов. Нет флага EVFLAGS_ALWAYS: говорит CF, что Ваше условие будет вычисляться только если генерируется событие (для Вас это может быть реализовано функциями RFUNCTION_GENERATEEVENT, RFUNCTION_PUSHEVENT), если оно первое в группе событий, или когда необходимо, если оно не первое в группе событий. В случае не событийных условий Вы также можете добавить флаг: EVFLAGS_NOTABLE: показывает, что Ваше условие может быть инвертировано. В этом случае будет доступна опция Negate, когда Вы кликаете на условии правой кнопкой мыши. Параметры действия и условия. Действия (actions) и условия (conditions) могут запрашивать у пользователя некоторое количество параметров. эти параметры могут быть числовыми выражениями, строками или указателями на другие объекты или зоны, и т. д. Вы должны указать, что у одного действия или одного условия есть параметр в массивах actionsinfos и conditionsInfos Вашего расширения. Просто укажите код параметра для использования в поле param структуры. PARAM_CLICK. Что запрашивается у пользователя: он должен выбрать левый, средний или правый клик, и должен ли клик быть одиночным или двойным. Значение, вводимое в подпрограмму действия/условия: младший байт представляет тип клика (left 0, middle 1, right 2), и старший байт флагом PARAMCLICK_DOUBLE (0x0100) показывает двойной клик. PARAM_COLOUR. Что запрашивается у пользователя: он должен выбрать цвет из палитры. Значение, вводимое в подпрограмму действия/условия: значение long представляет значение RGB выбранного цвета. PARAM_EXPRESSION. Что запрашивается у пользователя: он должен ввести числовое выражение. Значение, вводимое в подпрограмму действия/условия: значение long представляет введенное значение. PARAM_EXPSTRING. Что запрашивается у пользователя: он должен ввести строку или строковое выражение. Значение, вводимое в подпрограмму действия/условия: указатель на строку, оканчивающуюся нулем. PARAM_FILENAME. Что запрашивается у пользователя: он выбирает файл, используя диалог селектора файла. Примечание: этот параметр сейчас устарел. В новых действиях Вы должны вместо него использовать PARAM_FILENAME2. Значение, вводимое в подпрограмму действия/условия: указатель на имя файла (pathname) со свойством перемещения (поддержка относительного пути), если приложение было перенесено в другой каталог и если файл был в директории приложения или в её подкаталоге. Замечания: если Вы хотите, то можете определить фильтр для использования в селекторе файлов. Чтобы сделать это, определите параметр null после Вашего параметра PARAM_FILENAME, и введите строку фильтра в качестве заголовка этого параметра. Имейте в виду, что новый параметр PARAM_FILENAME2 позволяет Вам вставить и заголовок, и фильтр в одной строке, и Вы должны использовать этот новый параметр для новых действий. Пример: определение действия "Загрузка текста": {IDMN_ACTLOADTEXT, IDST_ACTLOADTEXT, ACT_LOADTEXT, 0, 2, PARAM_FILENAME,0,M_LOADTEXTTITLE,M_LOADTEXTFILTER}, со строками: M_LOADTEXTTITLE,"Please select a text file" M_LOADTEXTFILTER,"Text files|*.txt|All files|*.*|" Примечание: сепаратор, используемый в строке фильтра, должен быть символом |, вместо нуля. PARAM_FILENAME2. Что запрашивается у пользователя: он должен выбрать файл с использованием селектора файлов. Этот параметр был определен взамен параметра PARAM_FILENAME, так что Вы можете определить заголовок и фильтр в одной строке вместо двух. Вы должны использовать этот параметр вместо PARAM_FILENAME. Значение, вводимое в подпрограмму действия/условия: указатель на имя файла (pathname) со свойством произвольного перемещения приложения, если путь был указан относительно каталога приложения. Замечания: если Вы хотите, то можете определить заголовок и фильтр для использования в селекторе файлов. Чтобы сделать это, Вам нужно определить Ваш заголовок как часть строки с префиксом #Title" перед заголовком, и фильтр как часть строки, перед которым находится тег #Filter#. Пример: здесь задан селектор файла с заголовком "Выберите картинку" и фильтром "*.bmp": {IDMN_ ACTLOADIMAGE, IDST_ACTLOADIMAGE, ACT_LOADIMAGE, 0, 1, PARAM_FILENAME2, M_IMAGETITLE}, со строками: M_IMAGETITLE,"#Title#Выберите картинку...#Filter #Windows Bitmap Files|*.bmp|All files|*.*|" Примечание: сепаратор, используемый в строке фильтра, должен быть символом |, вместо нуля. PARAM_JOYDIRECTION. Что запрашивается у пользователя: направление и/или кнопка огня при использовании джойстика. Значение, вводимое в подпрограмму действия/условия: значение long, отражающее состояние джойстика: JOYSTICK_UP: север PARAM_KEY. Что запрашивается у пользователя: нажатая клавиша. Значение, вводимое в подпрограмму действия/условия: значение long, содержащее виртуальный код клавиши. PARAM_NEWDIRECTION. Что запрашивается у пользователя: направление из 32 возможных. Значение, вводимое в подпрограмму действия/условия: значение long, которое состоит из 32 бит, отражающих выбранные в селекторе направления (селектор выглядит как набор стрелочек). Бит 0 означает запад, бит 8 север, бит 16 восток, и бит 24 юг. PARAM_PLAYER. Что запрашивается у пользователя: выбор игрока от 0 до 3. Значение, вводимое в подпрограмму действия/условия: значение long от 0 до 3, где 0 представляет player 1, и 3 представляет player 4. PARAM_POSITION. Что запрашивается у пользователя: позиция на фрейме, либо абсолютная, либо относительно другого объекта, с использованием селектора позиции. Значение, вводимое в подпрограмму действия/условия: значение long, где старшее слово содержит позицию X на фрейме, и младшее слово содержит позицию Y на фрейме. PARAM_SPEED. Что запрашивается у пользователя: значение скорости. Значение, вводимое в подпрограмму действия/условия: значение long содержащее скорость, от 0 до 100. PARAM_TIME. Что запрашивается у пользователя: ввод времени с использованием селектора секунд/минут. Значение, вводимое в подпрограмму действия/условия: значение long, представляющее время в единицах 1/1000 секунды. PARAM_ZONE. Что запрашивается у пользователя: определение зоны фрейма. Значение, вводимое в подпрограмму действия/условия: указатель на короткую структуру прямоугольника, содержащую зону в координатах фрейма: typedef { short left; short top; short right; short bottom; } SRECT; CF содержит функции, позволяющие Вам определить свои собственные параметры действия. Это новые параметры находятся в зоне памяти, в которой Вы можете сохранить то, что хотите (строки, цвета, и т. д.). Вам нужно только определить 3 функции для создания своего нового параметра. Что нужно для этого сделать: сначала в файле main.h определяется новое значение параметра: первый должен быть PARAM_EXTBASE, следующий PARAM_EXTBASE+1 и так далее. Пример: #define PARAM_MYPARAM (PARAM_EXTBASE)
В файле EditTime.cpp Вы должны определить 3 функции: InitParameter, EditParameter и GetParameterString. Пожалуйста обратитесь к описанию функции в главе "Список необходимых функций / Edit time". В файле Main.cpp, в записи Вашего действия (таблица actionsInfos), используйте свой пользовательский параметр в качестве типа параметра (PARAM_MYPARAM в примере выше). Когда будет вызвана Ваша подпрограмма действия, Вы получите в качестве параметра адрес начала Вашей новой структуры параметра: указатель на структуру paramExt. Интересующее Вас поле это paramData, где должны лежать Ваши пользовательские данные. Параметры только для условия. Следующие параметры допустимы только для условий. PARAM_COMPARAISON. Что запрашивается у пользователя: ввод сравнения, состоящего из выражения и оператора сравнения. Значение, вводимое в подпрограмму условия: Ваше условие не должно делать сравнение само, CF обрабатывает сравнение автоматически. Эта подпрограмма должна вернуть значение true или false, вместо этого должно быть возвращено значение long для сравнения со значением, введенным пользователем. Таким образом, у значения параметра, который Вы получаете, нет назначения. PARAM_CMPSTRING. Что запрашивается у пользователя: ввод строки или строки расширения и процесса сравнения. Значение, вводимое в подпрограмму условия: Ваше условие не должно делать сравнение само, CF обрабатывает сравнение автоматически. Эта подпрограмма не должна возвращать значение true или false, но вместо этого значение long для сравнения со значением, введенным пользователем. Эта функция должна вернуть указатель на строку. Таким образом, у значения параметра, который Вы получаете, нет назначения. PARAM_CMPTIME. Что запрашивается у пользователя: ввод значения времени и выбор процесса сравнения. Значение, вводимое в подпрограмму условия: Ваше условие не должно делать сравнение само, CF обрабатывает сравнение автоматически. Эта подпрограмма не должна возвращать значение true или false, но вместо этого значение long для сравнения со значением, введенным пользователем. Это значение должно быть временем, указанным в миллисекундах. Таким образом, у значения параметра, который Вы получаете, нет назначения. Параметры выражения. CF предлагает только 2 типа параметров для расширений. EXPPARAM_LONG. Что запрашивается у пользователя: числовое выражение в вычислителе выражения. Это выражение может состоять из простого числа или из сложного выражения со скобками и функциями. Значение, вводимое в подпрограмму условия: значение long, содержащее результат выражения. EXPPARAM_STRING. Что запрашивается у пользователя: строковое выражение в вычислителе выражения. Это выражение может состоять из простой строки или сложного выражения со скобками и функциями. Значение, вводимое в подпрограмму условия: указатель на начало строки, заканчивающейся нулем. [Реализация свойств] CF поставляется с новой системой свойств, чтобы заменить диалог настройки (setup box) объекта. Вы определенно заходите подключить эту систему к своему объекту, потому что у ней много достоинств: • Стандартизованный интерфейс во всем приложении. Реализация поддержки новой системы свойств проста, просто выполните шаги, рассмотренные в этой главе. Шаг 1. Определите значения для редактирования. На этом первом шаге нужно подготовить список всех редактируемых значений в Вашей структуре EDITDATA. Для каждого из значений найдите, какой интерфейс нужен для его редактирования: будет ли это простая галочка (checkbox), строка для редактирования, значение типа float и т. д. Определитесь, должны ли быть некоторые значения сгруппированы, или вставлены одно в другое, и т. п. Другими словами, спланируйте интерфейс редактора свойств объекта. Шаг 2. Таблица PropData. Следующее, что нужно сделать - создать таблицу, которая будет содержать все свойства, показывая для CF вид каждого свойства, и как его отображать. это осуществляется с помощью определения таблицы PropData. Сначала нужно определить идентификатор для каждого из свойств, которые Вы намереваетесь реализовать. Это делается через простое перечисление (enum). Поместите её в начало файла EDITTIME.CPP. Пример: // Это перечисление определяет идентификаторы свойств:
enum { PROPID_SETTINGS = PROPID_EXTITEM_CUSTOM_FIRST, PROPID_TEXTTITLE, PROPID_TEXT, PROPID_CHECK, PROPID_COMBO, PROPID_COLOR, }; Обратите внимание, что Ваши идентификаторы свойств должны быть в диапазоне от PROPID_EXTITEM_CUSTOM_FIRST до PROPID_EXTITEM_CUSTOM_LAST. Другие значения используются CF для других свойств объекта. Вы должны дать понятные имена для идентификаторов, потому что будете потом использовать их в своем коде. Таблица PropData это список макросов, которые определяют для каждого свойства его тип и связанные отображаемые строки. Эти макросы определены в файле Props.h находящемся в каталоге Inc EDK. Определено множество макросов, по одному для каждой возможной конфигурации свойства. Например, макрос PropData_CheckBox будет отображать простую галочку для двоичного выбора (разрешено или запрещено, check box). Макрос PropData_ComboBox_Check отобразит checkbox (галочка), связанный с combobox (выпадающий список для выбора), и т. д. Для дополнительной информации см. раздел "Макросы PropData" в этой главе. Каждому макросу нужно указать параметры: - Первый параметр это идентификатор свойства, который Вы определили на шаге 1. Эта таблица должна заканчиваться макросом PropData_End. Пример массива PropData: // Определение дерева свойств. PropData Properties[] = { PropData_Group (PROPID_TEXTTITLE, IDS_PROP_TEXTTITLE, IDS_PROP_TEXTTITLE), PropData_EditString (PROPID_TEXT, IDS_PROP_TEXT, IDS_PROP_TEXT_INFO), PropData_CheckBox (PROPID_CHECK, IDS_PROP_CHECK, IDS_PROP_CHECK_INFO), PropData_ComboBox (PROPID_COMBO, IDS_PROP_COMBO, IDS_PROP_COMBO, ComboList), PropData_Color (PROPID_COLOR, IDS_PROP_COLOR, IDS_PROP_COLOR_INFO), PropData_End() }; Первый элемент массива показывает группу заголовка, простой разделитель в списке. Его параметрами являются идентификатор свойства, затем идентификатор строки в ресурсах, где содержится текстовый заголовок свойства, и снова та же самая строка (для этого случая строка информации не должна нести дополнительной информации). Второй элемент показывает редактируемую строку. Здесь также 2 параметра: заголовок и информационная строка. Третий элемент показывает простой check box, со строкой заголовка и строкой информации. Четвертый элемент представляет combo box, с заголовком и строкой информации, плюс дополнительный параметр, который указывает на таблицу, содержащую строки для этого combo box: // Список вариантов выбора для combo box: LPCSTR ComboList[] = { 0, // зарезервировано MAKEINTRESOURCE(IDS_FIRSTOPTION), MAKEINTRESOURCE(IDS_SECONDOPTION), MAKEINTRESOURCE(IDS_THIRDOPTION), NULL }; Как Вы можете видеть, это список содержит простой макрос MAKEINTRESOURCE для каждого идентификатора строки. Эта таблица завершается NULL (и начинается с 0). Пятый элемент определяет свойство цвета, здесь также есть текст заголовка и строка информации. Таблица заканчивается макросом PropData_End(). Шаг 3. Функция GetProperties. Функция GetProperties вызывается системой CF, когда ей нужно вставить свойства объекта в список отображаемых свойств. Это очень простая функция, она должна вызывать callback-функцию, передавая ей в параметрах адрес таблицы PropData. BOOL WINAPI DLLExport GetProperties(LPMV mV, LPEDATA edPtr, BOOL bMasterItem) { mvInsertProps(mV, edPtr, Properties, PROPID_TAB_GENERAL, TRUE); return TRUE; } В зависимости от Вашего объекта можно иметь разные таблицы свойств для вставки: просто поменяйте адрес соответствующим образом адрес таблицы PropData. Также Вы можете добавить свойства к другой закладки свойств, кроме закладки General Options, или даже удалить стандартные параметры с помощью callback-функции mvRemoveProps. Для дополнительной информации по функции GetProperties обратитесь к главе "Список необходимых функций / Edit time". Шаг 4. Возврат значений в CF. Когда CF отображает каждое свойство, она должна знать отображаемое значение. Тогда она вызывает функцию объекта, которая возвращает значение для отображения, в соответствии с идентификатором свойства. Вот эта функция: LPVOID WINAPI DLLExport GetPropValue(LPMV mV, LPEDATA edPtr, UINT nPropID) Параметры, передаваемые в GetPropValue: • Указатель на структуру mv, содержащую информацию о системе CF. Сама функция должна быть очень простой. Она должны быть основана на простом операторе switch / case на базе идентификатора свойства, и для каждого случая эта функция должна выбирать из структуры EDITDATA нужное значение и возвращать его. Возвращаемое значение это сами данные, а класс C++, содержащий данные. Определено несколько классов для разных видов возвращаемых значений. Например: CPropDWordValue: когда нужно вернуть значение типа DWORD, наподобие цвета, числа. В функции нужно вернуть значение следующим образом: для каждого варианта создается объект нужного типа: return new CPropDWordValue( myValue ); или return new CPropStringValue( myString ); или return new CPropFloatValue( myFloat ); и так далее. Пример: LPVOID WINAPI DLLExport GetPropValue(LPMV mV, LPEDATA edPtr, UINT nPropID) { switch (nPropID) { case PROPID_COLOR: // Возврат цвета: return new CPropDWordValue(edPtr->dwColor); case PROPID_TEXT: // Возврат текста: return new CPropStringValue(edPtr->szText); case PROPID_COMBO: // Возврат значения из combo box: return new CPropDWordValue(edPtr->nComboIndex); } return NULL; } Объект CPropXXXValue является автоудаляемым, т. е. он будет удален системой CF, когда больше не нужен. Обратите внимание, что функция GetPropValue вызывается только для свойств, которые имеют свое значение. Свойства простого чекбокса не имеют других значений, кроме как свое установленное значение (checked/unchecked state), которое возвращается функцией GetPropCheck, что будет рассмотрено на следующем шаге 5. Для дополнительной информации по функции GetPropValue см. ниже главу "Список необходимых функций / Edit time". Шаг 5. Возврат состояния чекбокса. Если в Вашем списке свойств есть чекбоксы, то нужно реализовать функцию GetPropCheck: она специально вызывается из CF, чтобы узнать состояние чекбоксов в списке свойств. Замечание: любое свойство может иметь чекбокс, не только простые свойства с чекбоксом. Вот прототип этой функции: BOOL WINAPI DLLExport GetPropCheck(LPMV mV, LPEDATA edPtr, UINT nPropID) Параметры функции GetPropCheck: • Указатель на структуру mv, содержащую информацию о системе CF. Возвращаемое значение: состояние галочки чекбокса (0 если галочка не стоит или 1 если галочка стоит), в зависимости от состояния свойства на момент вызова функции. Эта подпрограмма, как и GetPropValue, должна быть основана на операторе switch / case на базе идентификатора свойства. Для каждого идентификатора Вы опрашиваете структуру EDITDATA, выбирая оттуда состояние нужного чекбокса, и возвращаете его простым оператором return. Пример: BOOL WINAPI DLLExport GetPropCheck(LPMV mV, LPEDATA edPtr, UINT nPropID) { switch (nPropID) { case PROPID_CHECK: // Возврат 0 (unchecked) или 1 (checked): return edPtr->nCheck; } return 0; // по умолчанию возвращается 0 (unchecked) } Для дополнительной информации по функции GetPropCheck см. главу "Список необходимых функций / Edit time". Шаг 6. Изменение значения свойства. Когда пользователь меняет значение свойства в списке, отображаемом на экране, система CF вызывает функцию объекта, чтобы изменить соответствующее значение свойства во внутренней структуре EDITDATA объекта. Вот эта функция: void WINAPI DLLExport SetPropValue(LPMV mV, LPEDATA edPtr, UINT nPropID, LPVOID lParam)
Параметры функции SetPropValue: • Указатель на структуру mv, содержащую информацию о системе CF. Эта подпрограмма должна быть также основана на операторе switch / case на базе идентификатора свойства. Для каждого идентификатора свойства функция должна восстановить данные и записать их в структуру EDITDATA объекта. Чтобы получить данные, Вам нужно сделать приведение типа (cast) параметра lParam в один из классов CPropValue. Например: DWORD myDWordValue = ((CPropDWordValue*)lParam)->m_dwValue; float myFloatValue = ((CPropFloatValue*)lParam)->m_fValue; LPCTSTR myStringPointer = ((CPropStringValue*)pValue)->GetString(); Обратите внимание, что для свойств чекбокса CF вызывает специальную функцию, а не SetPropValue, что будет рассмотрено отдельно на шаге 7. Для дополнительной информации о функции SetPropValue см. главу "Список необходимых функций / Edit time". Пример: void WINAPI DLLExport SetPropValue(LPMV mV, LPEDATA edPtr, UINT nPropID, LPVOID lParam) { // Получение указателя на структуру CPropValue: CPropValue* pValue = (CPropValue*)lParam; switch (nPropID) { case PROPID_COMBO: // Простая выборка значения: edPtr->nComboIndex = ((CPropDWordValue*)pValue)->m_dwValue; break; case PROPID_COLOR: // Здесь то же самое, выборка значения: edPtr->dwColor = ((CPropDWordValue*)pValue)->m_dwValue; break; case PROPID_TEXT: // Получение строки: LPCTSTR pStr = ((CPropStringValue*)pValue)->GetString(); // Вы можете просто сделать копию строки, если структура // EDITDATA имеет фиксированный размер. Либо она может // иметь адаптивный размер, как показано ниже. // Если длина отличается: if (_tcslen(pStr)!=_tcslen(edPtr->text)) { // Запрос к CF для изменения размера структуры в памяти: LPEDATA pNewPtr=(LPEDATA)mvReAllocEditData(mV, edPtr, sizeof(EDITDATA)+_tcslen(pStr)*sizeof(TCHAR)); if (pNewPtr!=NULL) { // Если повторное выделение структуры сработало, // делаем копию строки: edPtr=pNewPtr; _tcscpy(edPtr->text, pStr); } } else { // Тот же размер: простое копирование: _tcscpy(edPtr->text, pStr); } break; } // Вы можете захотеть перерисовать свой объект в редакторе фрейма // после изменений, в этом случае просто вызовите эту функцию: mvInvalidateObject(mV, edPtr); } Шаг 7. Изменение свойства чекбокса. Когда пользователь меняет состояние чекбокса в списке свойств, система CF вызывает подпрограмму объекта, чтобы отразить соответствующие изменения в структуре EDITDATA объекта. Вот эта функция: void WINAPI DLLExport SetPropCheck(LPMV mV, LPEDATA edPtr, UINT nPropID, BOOL nCheck)
Параметры SetPropCheck: • Указатель на информационную структуру mv. Эта функция также должна быть основана на операторе switch / case по базе идентификатора свойства. Для каждого идентификатора функция должна записать текущее состояние в нужную ячейку структуры EDITDATA. Пример: void WINAPI DLLExport SetPropCheck(LPMV mV, LPEDATA edPtr, UINT nPropID, BOOL nCheck) { switch (nPropID) { case PROPID_CHECK: edPtr->nCheck = nCheck; // Перерисовать объект в редакторе фрейма:
mvInvalidateObject(mV, edPtr);
// Указать свойство PROPID_COMBO для перерисовки: mvRefreshProp(mV, edPtr, PROPID_COMBO); break; } } Для дополнительной информации о функции SetPropCheck см. главу "Список необходимых функций / Edit time". Макросы PropData. В этом разделе документации содержится список макросов для таблицы свойств PropData с описанием каждого макроса в отдельной врезке. Эти макросы должны использоваться в массиве PropData, который перечисляет свойства Вашего объекта. Обратите внимание, что каждый макрос обычно бывает 3 версий: PropData_xxxx (id, name, info[, param]) PropData_xxxx_Check (id, name, info[, param]) PropData_xxxx_Opt (id, name, info, options[, param]) - Первый макрос задает определение по умолчанию. PROPOPT_CHECKBOX к свойству добавляется чекбокс. PROPOPT_BOLD заголовок свойства должен быть показан жирным шрифтом. PROPOPT_PARAMREQUIRED требуется параметр инициализации, и он не может быть NULL (полезно, если Вы определяете свои собственные свойства). PROPOPT_SINGLESEL это свойство не отображается, когда в редакторе фрейма выделено несколько объектов. Замечание: просто для информации, PropData_xxxx_Check ( id, title, info, param ) является эквивалентом PropData_xxxx_Opt ( id, title, info, PROPOPT_CHECKBOX, param). Параметры макросов: id идентификатор свойства. Замечание по поводу: если свойство требует параметра инициализации, и param == NULL в макросе PropData, то система CF вызовет функцию GetPropCreateParam, когда создается свойство (или когда оно обновляется функцией mvRefreshProp с параметром ReInit, установленным в TRUE). Функция GetPropCreateParam должна возвратить параметр инициализации. Этот механизм позволяет Вам динамически создавать содержимое свойства (например, список элементов в combo box), соответствующее данным объекта. Когда свойство инициализировано, система CF вызывает функцию ReleasePropCreateParam, так что Вы можете освободить память, если Вы выделяете параметр динамически. Для дополнительной информации см. описание функций GetPropCreateParam и ReleasePropCreateParam в главе "Список необходимых функций / Edit time". PropData_Button( id, name, info, text ) PropData_Button_Check( id, name, info, text ) PropData_Button_Opt( id, name, info, options, text ) Отображает кликабельную кнопку. Когда пользователь кликает на ней, CF вызывает функцию EditProp, реализованную в Вашем расширении. Для получения подробностей обратитесь к документации по этой функции в главе "Список необходимых функций / Edit time". Даже если это свойство не отображает реальное свое содержимое, в зависимости от содержимого этого свойства Вы должны реализовать функции GetPropValue и SetPropValue, так что когда пользователь выбирает несколько объектов, и кликает на кнопку Edit, это свойство копировалось во все другие выделенные объекты. CPropValue, возвращенное GetPropValue, и переданное в SetPropValue не определено, Вы можете использовать то, что хотите. Параметры: id идентификатор свойства. PropData_CheckBox( id, name, info ) PropData_CheckBox_Opt( id, name, info, options ) Отобразит чекбокс. Система CF вызовет функцию GetPropCheck в Вашем расширении, чтобы получить состояние чекбокса, и вызовет функцию SetpropCheck, когда пользователь кликает на чекбоксе. Вызов GetPropValue или SetPropValue не осуществляется. Параметры: id идентификатор свойства. Примечание: здесь нет макроса PropData_CheckBox_Check, так как свойство CheckBox в основном "пустое" свойство для чекбокса. PropData_Color( id, name, info ) PropData_Color_Check( id, name, info ) PropData_Color_Opt( id, name, info, options ) Отображает свойство цвета: цвет и селектор цвета. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое из GetPropValue, и передаваемое в SetPropValue, это CPropDWordValue, которое содержит значение COLORREF. PropData_ComboBox( id, name, info, list ) PropData_ComboBox_Check( id, name, info, list ) PropData_ComboBox_Opt( id, name, info, options, list ) Отображает список выбора, содержащий строки. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое из GetPropValue, и передаваемое в SetPropValue, является значением CPropDWordValue, которое содержит индекс выбранного элемента в combo box (-1 = ничего не выбрано, 0 = выбран первый элемент, и т. д.). Замечания: Параметр list может быть равен NULL. В этом случае система CF вызовет функцию GetPropCreateParam, когда создается свойство combo box (или когда оно обновляется функцией mvRefreshProp с параметром ReInit, установленным в TRUE). Функция GetPropCreateParam должна возвратить ненулевой указатель (не равный null) на массив строк (наподобие статического параметра). Когда свойство combo box инициализировано, CF вызовет функцию ReleasePropCreateParam, так что Вы можете освободить память, если Вы её динамически выделили для указателя на массив строк. Для дополнительной информации см. описание функций GetPropCreateParam и ReleasePropCreateParam в главе "Список необходимых функций / Edit time". Пример: LPCTSTR ComboList[] = { 0, // зарезервировано MAKEINTRESOURCE(IDS_FIRSTOPTION), MAKEINTRESOURCE(IDS_SECONDOPTION), MAKEINTRESOURCE(IDS_THIRDOPTION), NULL }; PropData_ComboBox (PROPID_COMBO, IDS_PROP_COMBO, IDS_PROP_COMBO, ComboList); PropData_ComboBoxBtn( id, name, info, list ) PropData_ComboBoxBtn_Check( id, name, info, list ) PropData_ComboBoxBtn_Opt( id, name, info, options, list ) Отображает кнопку "+/-" и список выбора, содержащий строки. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое из GetPropValue, и передаваемое в SetPropValue, является значением CPropDWordValue, которое содержит индекс выбранного элемента в combo box (-1 = ничего не выбрано, 0 = выбран первый элемент, и т. д.). Замечания: Параметр list может быть равен NULL. В этом случае система CF вызовет функцию GetPropCreateParam, когда создается свойство combo box (или когда оно обновляется функцией mvRefreshProp с параметром ReInit, установленным в TRUE). Функция GetPropCreateParam должна возвратить ненулевой указатель (не равный null) на массив строк (наподобие статического параметра). Когда свойство combo box инициализировано, CF вызовет функцию ReleasePropCreateParam, так что Вы можете освободить память, если Вы её динамически выделили для указателя на массив строк. Для дополнительной информации см. описание функций GetPropCreateParam и ReleasePropCreateParam в главе "Список необходимых функций / Edit time". Пример: LPCTSTR ComboList[] = { 0, // зарезервировано MAKEINTRESOURCE(IDS_FIRSTOPTION), MAKEINTRESOURCE(IDS_SECONDOPTION), MAKEINTRESOURCE(IDS_THIRDOPTION), NULL }; PropData_ComboBoxBtn (PROPID_COMBO, IDS_PROP_COMBO, IDS_PROP_COMBO, ComboList); PropData_Custom( id, name, info, param ) PropData_Custom_Check( id, name, info, param ) PropData_Custom_Opt( id, name, info, options, param ) Это свойство позволяет Вам создавать свои собственные свойства. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое из GetPropValue, и передаваемое в SetPropValue, должно быть таким же, как и значение, используемое в функциях GetPropValue и SetPropValue Вашего объекта CCustomProp (см. описание ниже). Пример: CustomPropCreateStruct initStruct = { CreateMyCustomPropProc, 0 }; PropData_Custom( PROPID_MYPROP, IDS_MYPROP, IDS_MYPROP_INFO, &initStruct ); Структура CustomPropCreateStruct. Эта структура содержит значения для создания элемента свойства в новом окне, и инициализирует его. typedef struct CustomPropCreateStruct { CP_CREATEINSTANCE m_pCreateCustomPropFnc; LPARAM m_lCreateParam; } CustomPropCreateStruct; m_lCreateParam это параметр инициализации, который соответствует lParam, обычно передаваемые в свойства наподобие ComboBox. Поместите в этот член структуры значение, специфичное для Вашего идентификатора свойства. m_pCreateCustomPropFnc это callback-функция, которую CF вызовет для создания свойства, она имеет следующий формат: CCustomProp* CALLBACK CreateMyCustomPropProc() { // Эта функция должна возвратить объектCCustomProp: return new CMyCustomProp; } Класс CCustomProp. Базовый класс CCustomProp, определенный в Props.h, представляет Ваш элемент свойства в окне редактора свойств (property window). Вы должны создать на его основе свой новый класс, например CMyCustomProp, производный от CCustomProp. Базовый класс CCustomProp имеет следующие функции: void Initialize(HINSTANCE hInst, LPARAM lCreateParam, BOOL bReInit); Вызывается системой CF для инициализации элемента свойства. hInst это указатель HINSTANCE на программу, lCreateParam это член m_lCreateParam структуры CustomPropCreateStruct (в PropData) и bReInit будет TRUE, когда эта функция вызывается для повторной инициализации свойства, если оно уже было создано (когда запрашивается обновление с параметром reinit, равным TRUE). void Delete(); Вы не должны изменять эту функцию. void Draw(HDC hDC, LPRECT pRc, HFONT hFont, COLORREF textColor); Позволяет Вам нарисовать элемент свойства в окне редактора свойств. hDC это контекст устройства (windows device context) окна свойств, pRc это прямоугольник, в котором Вам нужно нарисовать элемент свойства, hFont и textColor должны использоваться для отображения некоторого текста. CPropValue* GetPropValue(); Вы должны вернуть значение свойства, которое отображается в настоящий момент окном редактора свойств (property window). void SetPropValue(CPropValue* pValue); Эта функция вызывается CF для установки значения элемента свойства. void Activate(HWND hParent, LPRECT pRc, HFONT hFont); Эта функция вызывается, когда пользователь делает клик на элементе свойства в редакторе свойств. Например, в этой функции Вы можете создать или показать окно combo box, кнопку, и т. п. hParent это хендл окна редактора свойств, pRc это координаты прямоугольника элемента свойства относительно родительского окна. void Deactivate(); Эта функция вызывается для деактивации элемента свойств. Например, в этой функции Вы можете скрыть элемент управления (control), который был создан функцией Activate. void Refresh(); Эта функция вызывается системой CF после изменения значения. void Move(LPRECT pRc); Эта функция вызывается, если элемент свойства был перемещен или у него был изменен размер. Например, Вы можете обновить позицию элементов управления пользовательского интерфейса, созданные при активации окна (Activate). pRc это новый прямоугольник области элемента свойств. BOOL UpdateData();
В этой функции Вы должны получить редактируемое значение для любого открытого элемента управления пользовательского интерфейса (control), если оно есть, и сохранить его в данные объекта CCustomProp. Эта функция обычно вызывается непосредственно перед вызовом функции Deactivate. PropData_DirCtrl( id, name, info, param ) PropData_DirCtrl_Check( id, name, info, param ) PropData_DirCtrl_Opt( id, name, info, options, param ) Отобразит селектор для 32 возможных направлений, наподобие используемого в свойствах перемещения (movement properties). Параметры: id идентификатор свойства. typedef struct { BOOL bMultiSel; // TRUE для множественного выбора, FALSE для одиночного выбора int numDirs; // количество направлений 4, 8, 16 или 32 DWORD style; // стиль } DirCtrlCreateParam; Поле style может содержать один или большее количество флагов: DCS_FLAT плоское отображение (Flat). Пример: DirCtrlCreateParam initDirParam32 = { TRUE, 32, DST_3D | DST_SETALL_BTNS }; PropData_DirCtrl(PROPID_INITDIR, IDS_INITDIR, IDS_INITDIR_INFO, &initDirParam32); CPropValue: значение, возвращаемое GetPropValue, и передаваемое в SetPropValue, должно быть CPropDataValue, которое содержит структуру PropDirValue. typedef struct { int selDir; // выбранное направление (индекс одиночного выбора направления) DWORD selDir32; // выбранные направления (32-битная маска направлений, // для множественного выбора) int numDirs; // количество направлений int reserved; // не используется } PropDirValue; Пример: PropDirValue pv; memset(&pv, 0, sizeof(PropDirValue)); pv.selDir32 = m_pMvtData->mvDirAtStart; pv.numDirs = 32; return new CPropDataValue(sizeof(PropDirValue), (LPBYTE)&pv); PropData_EditButton( id, name, info ) PropData_EditButton_Check( id, name, info ) PropData_EditButton_Opt( id, name, info, options ) Отображает кнопку, на которой имеется текст "Edit". Это тот же PropData_Button, к которого нельзя поменять текст на кнопке. Когда пользователь кликает на этой кнопке, CF вызовет функцию EditProp, реализованную в Вашем расширении. Для получения подробностей обратитесь к документации по этой функции в главе "Список необходимых функций / Edit time". Даже если это свойство не отображает реальное свое содержимое, в зависимости от содержимого этого свойства Вы должны реализовать функции GetPropValue и SetPropValue, так что когда пользователь выбирает несколько объектов, и кликает на кнопку Edit, это свойство копировалось во все другие выделенные объекты. CPropValue, возвращенное GetPropValue, и переданное в SetPropValue не определено, Вы можете использовать то, что хотите. Параметры: id идентификатор свойства. PropData_EditFloat ( id, name, info ) PropData_EditFloat_Check ( id, name, info ) PropData_EditFloat_Opt ( id, name, info, options ) Отображает окошко редактирования для ввода числа с плавающей запятой. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое GetPropValue, и передаваемое в SetPropValue, то тип CPropFloatValue. PropData_EditMultiLine ( id, name, info ) PropData_EditMultiLine_Check ( id, name, info ) PropData_EditMultiLine_Opt ( id, name, info, options ) Отображает окошко редактирования с кнопкой Edit, которая открывает окно диалога с многострочным вводом (multi-line edit box). Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropStringValue, оно содержит многострочный текст: каждая строка заканчивается на последовательность символов CR/LF (0x0D, 0x0A), и весь многострочный текст заканчивается нулевым символом (символ с кодом 0). PropData_EditNumber ( id, name, info ) PropData_EditNumber_Check ( id, name, info ) PropData_EditNumber_Opt ( id, name, info, options ) Отображает бокс ввода для редактирования числа. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropDWordValue. PropData_EditString ( id, name, info ) PropData_EditString_Check ( id, name, info ) PropData_EditString_Opt ( id, name, info, options ) Отображает бокс для ввода и редактирования строки. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropStringValue, это значение содержит строку. Пример: return new CPropDataValue(pStr); LPCTSTR pStr = ((CPropStringValue*)lParam)->GetString(); PropData_End( ) Показывает конец списка PropData. PropData_Filename ( id, name, info, param ) PropData_Filename_Check ( id, name, info, param ) PropData_Filename_Opt ( id, name, info, options, param ) Отображает свойство имени файла: имя файла в строке редактирования пути, и кнопка browse, которая открывает браузер/селектор файла. Параметры: id идентификатор свойства. typedef struct { // Строка фильтра для диалога GetOpenFilename // (например "All Files (*.*)|*.*|"): LPCTSTR extFilter; // Опции для диалога GetOpenFilename (OFN_FILEMUSTEXIST, // OFN_PATHMUSTEXIST, OFN_HIDEREADONLY, и т. д.): DWORD options; } FilenameCreateParam; Пример: FilenameCreateParam fcp = { MAKEINTRESOURCE(IDS_TXTFILTER), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY }; PropData_Filename(PROPID_FILENAME, IDS_PROP_FILENAME, IDS_PROP_FILENAME_INFO, &fcp); CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropStringValue, это значение содержит имя файла. PropData_Folder( id, name, info ) Инициализирует папку, содержащую другие свойства. Параметры: id идентификатор свойства. Замечания: все свойства, которые перечислены после этого макроса, будут содержаться в закрываемой папке. Вы должны показать конец этой папки макросом PropData_Folder_End. PropData_Folder_End() Показывает окончание папки для свойств. Замечания: этот макрос нужно использовать в паре с макросом PropData_Folder, чтобы показать границы свойств, содержащихся в отдельной папке редактора свойств. PropData_Font ( id, name, info, param ) Отображает свойство шрифта: имя шрифта и кнопку его выбора (Choose Font), которая открывает селектор шрифта. Параметры: id идентификатор свойства. Пример: PropData_Font(PROPID_TEXT_FONT, IDS_TEXTPROP_FONT,
IDS_TEXTPROP_FONT_INFO, (CF_EFFECTS | CF_SCREENFONTS));
CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropDataValue, это значение содержит структуру LOGFONT. Пример: return new CPropDataValue(sizeof(LOGFONT), (LPBYTE)&lf); LOGFONT* plf = (LOGFONT*)((CPropDataValue*)lParam)->m_pData; PropData_Group( id, name, info) Отображает заголовок группы. Параметры: id идентификатор свойства. Замечания: группу используются в подавляющем большинстве объектов: они упрощают список и позволяют составить его в организованном порядке. PropData_IconComboBox( id, name, info, list ) PropData_IconComboBox_Check( id, name, info, list ) PropData_IconComboBox_Opt( id, name, info, options, list ) Отображает окно списка (list box), содержащее строки, в начале которых содержаться иконки. Параметры: id идентификатор свойства. - Значение NULL, зарезервированное для будущего использования. Пример: LPCTSTR iconComboList[] = { (LPCTSTR)0, // зарезервировано (LPCTSTR)24, // размер иконки MAKEINTRESOURCE(IDS_LINE1), hIcon1, MAKEINTRESOURCE(IDS_LINE2), hIcon2, MAKEINTRESOURCE(IDS_LINE3), hIcon3, MAKEINTRESOURCE(IDS_LINE4), hIcon3, NULL // показывает конец списка }; PropData_IconComboBox (PROPID_COMBO, IDS_PROP_COMBO, IDS_PROP_COMBO, iconComboList); CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropDWordValue, это значение содержит индекс выбранного элемента в combo box (-1 = ничего не выбрано, 0 = первый элемент). Замечания: Вы можете установить параметр list в значение NULL, когда используете макрос в PropData, создайте его в функции GetPropCreateParam function и освободите в функции ReleasePropCreateParam. Это самый простой способ загрузить иконки. Внимание: не уничтожайте иконки созданного списка, они будут уничтожены, когда завершится программа (CF). PropData_ImageList ( id, name, info ) PropData_ImageList_Check ( id, name, info ) PropData_ImageList_Opt ( id, name, info, options ) Отображает список картинок с кнопкой редактирования (Edit). Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropDataValue, это значение содержит количество изображений (WORD), за которым идет список значений WORD, содержащий идентификаторы изображений. Замечания: когда пользователь делает клик на кнопке Edit, CF вызывает функцию EditProp, реализованную в Вашем расширении. Например, в функции EditProp Вы можете открыть редактор списка картинок CF (image list editor) вызовом mvEditAnimation (или редактор картинки, picture editor, с помощью вызова mvEditImage, если это только одна картинка). Пример: GetPropValue: CPropDataValue* pv = new CPropDataValue((nImages + 1) * sizeof(WORD), NULL); if ( pv != NULL ) { if ( pv->m_pData != NULL ) { LPWORD pw = (LPWORD)pv->m_pData; *pw++ = nImages; for (WORD w=0; w < nImages; w++) *pw++ = edPtr->images[w]; return pv; } pv->Delete(); } SetPropValue: if ( ((CPropDataValue*)pValue)->m_pData != NULL ) { LPWORD pw = (LPWORD)((CPropDataValue*)pValue)->m_pData; nImages = *pw++; // и т. д. } EditProp: BOOL WINAPI DLLExport EditProp(LPMV mV, LPEDATA edPtr, UINT nPropID) { if ( nPropID == PROPID_IMAGES ) { EditAnimationParams eap; eap.m_dwSize = sizeof(EditAnimationParams); eap.m_pWindowTitle = NULL; eap.m_nImages = edPtr->nImages; eap.m_nMaxImages = edPtr->nImages; eap.m_nStartIndex = 0; eap.m_pImages = edPtr->images; eap.m_pImageTitles = NULL; eap.m_dwOptions = PICTEDOPT_FIXEDNFRAMES; eap.m_dwFixedWidth = 100; eap.m_dwFixedHeight = 100; if ( mV->mvEditAnimation(edPtr, &eap, NULL) ) { mvRefreshProp(mV, edPtr, PROPID_IMAGES, FALSE); mvInvalidateObject(mV, edPtr); return TRUE; } } return FALSE;
}
PropData_PictureFilename ( id, name, info, param ) PropData_PictureFilename_Check ( id, name, info, param ) PropData_PictureFilename_Opt ( id, name, info, options, param ) Отображает свойство имени файла картинки: имя файла к строке редактирования (edit box), и кнопка browse, которая открывает селектор файла картинки. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropStringValue, это значение содержит имя файла. Пример: PropData_PictureFilename(PROPID_FILENAME, IDS_PROP_FILENAME, IDS_PROP_FILENAME_INFO); PropData_Size ( id, name, info, tab ) PropData_Size_Check ( id, name, info, tab ) PropData_Size_Options ( id, name, info, options, tab ) Отображает свойство размера (size): две поля ввода (edit box), одна для горизонтального размера, другая для вертикального. Параметры: id идентификатор свойства. Пример: int tabPredefinedSizes[] = { 320, 200, 320, 240, 640, 480, 800, 600, 1024, 768, 1280, 1024, 1400, 1050, 1600, 1200, 0, 0 }; PropData_Size(PROPID_WINDOWSIZE, IDS_WINDOWSIZE, IDS_WINDOWSIZE_INFO, (LPARAM)tabPredefinedSizes); CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropSizeValue. PropData_SpinEdit ( id, name, info, minmax) PropData_SpinEdit_Check ( id, name, info, minmax) PropData_SpinEdit_Opt ( id, name, info, options, minmax) Отображает spinbox (регулятор), связанный с полем редактирования (edit box), чтобы проще редактировать целые числа. Параметры: id идентификатор свойства. Пример: int MinMaxAngle[] = { 0, 359 }; PropData_SpinEdit(PROPID_FII_ANGLE, IDS_FIIPROP_ANGLE, IDS_FIIPROP_ANGLE_INFO, &MinMaxAngle); CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropDWordValue. PropData_SliderEdit ( id, name, info, minmax) PropData_SliderEdit_Check ( id, name, info, minmax) PropData_SliderEdit_Opt ( id, name, info, options, minmax) Отображает слайдер, связанный с полем редактирования (edit box), чтобы проще редактировать целые числа. Параметры: id идентификатор свойства. Пример: int MinMaxAngle[] = { 0, 359 }; PropData_SliderEdit(PROPID_FII_ANGLE, IDS_FIIPROP_ANGLE, IDS_FIIPROP_ANGLE_INFO, &MinMaxAngle); CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropDWordValue. PropData_StaticString ( id, name, info ) PropData_StaticString_Check ( id, name, info ) PropData_StaticString_Options ( id, name, info, options ) Отображает простую статическую строку текста. Параметры: id идентификатор свойства. CPropValue: значение, возвращаемое GetPropValue, и передаваемое SetPropValue, имеет тип CPropStringValue, здесь содержится строка. [Реализация поддержки отладчика] CF содержит инструментарий, чтобы помочь отлаживать Ваше приложение: debugger. Этот инструмент поставляется в форме окна, в котором Вы можете, когда отлаживаемая программа работает (runtime), отобразить важную информацию об объектах, которые можно найти в приложении. Эта часть документации будет покажет Вам, как пошагово реализовать обмен отладочной информацией, касающейся Вашего объекта, чтобы она отображалась в окне отладчика. Шаг 1. Определение значений для отображения. Первое, что Вам нужно сделать для реализации отладчика в объекте - определить, что Вы хотите показывать в окне отладки. Составьте список из всех этих значений. Обратите внимание, что по умолчанию в окне отладки будут показаны параметры X и Y позиции объекта, а также его ширина (width) и высота (height). Шаг 2. Создание таблицы DebugTree. Для каждого значения, которое хотите отобразить, Вам нужно определить идентификатор. Сделайте это в начале файла EXT.CPP, с помощью простой структуры перечисления: // Определение отлаживаемых элементов:enum { DB_CURRENTSTRING, DB_CURRENTVALUE, DB_CURRENTCHECK, DB_CURRENTCOMBO }; В этом примере мы определили 4 идентификатора, поскольку хотим показывать 4 значения. Как только идентификатора определены, Вы должны составить таблицу DebugTree. Эта таблицу представляет простой список значений WORD, с идентификаторами: // Эта таблица определяет, что будет показано в отладчике: WORD DebugTree[] = { DB_CURRENTSTRING|DB_EDITABLE, DB_CURRENTVALUE|DB_EDITABLE, DB_CURRENTCHECK, DB_CURRENTCOMBO, DB_END }; Просто перечислите эти идентификаторы в том порядке, в каком хотите видеть их на экране, и завершите таблицу значением DB_END. Используйте значение DB_EDITABLE, чтобы показать, что это отображаемое значение можно изменять: тогда пользователь может двойным кликом на значении перейти к его редактированию. Шаг 3. Определение функции GetDebugTree. Функция GetDebugTree вызывается системой CF, чтобы получить адрес DebugTree. Она просто возвратит адрес этой таблицы. LPWORD WINAPI DLLExport GetDebugTree(LPRDATA rdPtr) { return DebugTree; } Шаг 4. Определение функции GetDebugItem. Функция GetDebugItem вызывается системой CF, чтобы получить текст элемента для отображения. void WINAPI DLLExport GetDebugItem(LPTSTR pBuffer, LPRDATA rdPtr, int id) На входе в функцию CF передает 3 параметра: • Адрес буфера с текстом, куда Вы будете копировать строку для отображения. У этого буфера длина равна DB_BUFFERSIZE. Эта подпрограмма должна просто состоять из оператора switch / case на базе идентификатора элемента. Тогда Вы загружаете строку из ресурса, описывающего элемент, используете wsprintf для обработки значения в строке и копируете результат по адресу pBuffer, уделяя внимание тому, чтобы не переполнить буфер. Как это делается, см. проект Template, поставляемый вместе с EDK. Шаг 5. Если необходимо определяется функция EditDebugItem. Если Вы добавили флаг DB_EDITABLE для некоторых значений DebugTree, то эта функция будет вызвана системой CF, когда пользователь выполнит двойной клик на элементе. void WINAPI DLLExport EditDebugItem(LPRDATA rdPtr, int id) В эту функцию передается 2 параметра: • Адрес структуры RUNDATA. Здесь также подпрограмма должна состоять из простого оператора simple switch / case на базе идентификатора. Для каждого передаваемого значения подпрограмма должна открыть для пользователя поле редактирования (edit box), чтобы он мог изменить значение элемента. Обратите внимание, что приложение будет приостановлено (как будто поставлено на паузу) перед вызовом этой функции: Вы можете тратить столько времени, сколько нужно, чтобы отредактировать значение. Для реализации редактирования нужно предоставить 2 callback-функции, одна для целого значения, другая для строкового: callRunTimeFunction(rdPtr, RFUNCTION_EDITINT, 0, (LPARAM)&dbi); и callRunTimeFunction(rdPtr, RFUNCTION_EDITTEXT, 0, (LPARAM)&dbi); Подробнее об этих callback-функциях см. главу "CallBack-функции" документации, секция "runtime / RFUNCTION". [Управление окном] Некоторые объекты нуждаются в открытии окна поверх фрейма CF. Это могут быть, например, органы управления, просмотрщики видео, интерфейс MCI (Media Control Interface) и т. д. Такого рода окна будут либо дочерним окном основного окна приложения, либо дочерним окно окна фрейма (последнее является дочерним для основного окна приложения). Вам нужно уметь принимать Windows-сообщения от Вашего окна, и перехватывать сообщения, которые отправляются в окно фрейма, такие как окна оповещения. CF предоставляет Вам все инструменты, которые нужны для тонкого управления Вашим окном. Пожалуйста просмотрите исходный код объекта StaticText для получения информации по следующим функциям: CreateRunObject, WindowProc, DestroyRunObject и в файле ext.h определение для OEFLAGS. Далее идет описание, как реализовать управление окном из расширения. Перехват оповещающих сообщений окна фрейма. Можно очень просто реализовать перехват каждое сообщение Windows, которое посылается в окно фрейма. Такие сообщения могут быть сообщениями палитры, кодом оповещения, и т. д. Нужно реализовать 2 вещи: • Установка OEFLAG_WINDOWPROC в поле OEFLAGS расширения. Вы также можете определить приоритет для Вашей подпрограммы, если хотите, чтобы она была вызвана первой: #define WINDOWPROC_PRIORITY 100. 100 соответствует среднему уровню приоритета, 0 самому низкому приоритету и 255 самому высокому приоритету. Открытие нового окна. Обычно окна открываются подпрограммой CreateRunObject, и удаляется в подпрограмме DestroyRunObject. Используйте обычную подпрограмму Windows, такую как CreateWindow, чтобы открыть окно, и сохраните указатель на него (хендл, handle) в структуре RUNDATA. Рекомендуется сделать Вашего окно дочерним для окна фрейма. Преобразования координат. Координаты объекта находятся в подструктуре headerObject, находящейся в начале Вашей структуры RUNDATA. В этой подструктуре содержатся координаты фрейма для Вашего объекта. Вы должны преобразовать эти координаты в координаты клиентского окна фрейма. Это осуществляется простым вычитанием полей rhWindowX и rhWindowY, содержащихся в структуре RunHeader. Пример открытия окна управления: // Для получения rhPtr: rhPtr = rdPtr->rHo.hoAdRunHeader; // Создание окна: rdPtr->hWnd = CreateWindow(_T("EDIT"), NULL, dwStyle, rdPtr->rHo.hoX - rhPtr->rhWindowX, rdPtr->rHo.hoY - rhPtr->rhWindowY, rdPtr->rHo.hoImgWidth, rdPtr->rHo.hoImgHeight, rhPtr->rhHEditWin, NULL, rhPtr->rh4.rh4Instance, NULL); Пояснения параметров, передаваемых в функцию CreateWindow: dwStyle стиль окна, содержащий WS_CHILD, если Ваше окно будет дочерним по отношению к окну фрейма. Теперь Вы открыли окно поверх фрейма, но пока не получили управление над ним. Ниже показано, как перехватывать оповещающие сообщения родительского окна, и сообщения самого открытого окна. Подкласс окна. Если Ваше окно это объект управления пользовательского интерфейса (объект control, такой как кнопка, list box, и т. д.), то вы должны быть в состоянии обрабатывать сообщения оповещения, относящиеся к этому окну. Для этой цели Вы определите флаг OEFLAG_WINDOWPROC и определите процедуру WindowProc. Однако этого недостаточно. Оповещающее сообщение содержит только хендл окна (window handle, HWND), но в нем нет указателя на структуру RUNDATA, связанную с окном. Multimedia Fusion (MMF) предоставляет простую систему подкласса, чтобы было проще получить указатель на RUNDATA. Чтобы сделать хендл окна доступным для CF, Вы должны вставить следующие поля данных в свою структуру RUNDATA (это 2 поля должны следовать одно за другим): #define MAX_WINDOWS xxx
int rWindowNumber;
HWND hwnd[MAX_WINDOWS];
MAX_WINDOWS содержит количество окон, которое планируется открывать из объекта. Перед вызовом hook-функции Вы должны установить указатель в поле rWindowNumber подструктуры headerObject, которая находится в Вашей структуре RUNDATA: rdPtr->hwnd[0]=my_window_handle; rdPtr->rWindowNumber = MAX_WINDOWS; rdPtr->rHo.hoOffsetToWindows = (int)((LPBYTE)&rdPtr->rWindowNumber - (LPBYTE)rdPtr); callRunTimeFunction(rdPtr, RFUNCTION_SUBCLASSWINDOW, 0, 0); Вот пример подпрограммы WindowProc, которая восстанавливает адрес структуры RUNDATA: LRESULT CALLBACK DLLExport WindowProc(fprh rhPtr, HWND hWnd, UINT msgType,
WPARAM wParam, LPARAM lParam)
{
LPRDATA rdPtr;
// Если пауза, то выход: if (rhPtr->rh2.rh2PauseCompteur != 0) return 0; // Обработка типа сообщения: switch (msgType) { case WM_COMMAND: // Обработка сообщений, которые мне нужно перехватить... switch (wmCommandNotif) { case BN_CLICKED: // Это для меня? if ((rdPtr = GetRdPtr((HWND)lParam, rhPtr, &n)) != NULL && (IDENTIFIER == rdPtr->rHo.hoIdentifier)) { // ... тут делается требуемая обработка сообщения ... ... // Сигнал от том, что сообщение было обработано: return REFLAG_MSGHANDLED; } break; default: break; }// switch (wmCommandNotif) return 0; default: // Не для меня ... return 0; }// switch (msgType) } Первое, что нужно сделать - определить, что мы не находимся в режиме паузы приложения (pause mode). Если сейчас pause mode, то объект расширения не должен реагировать на действия пользователя. Затем Вы должны получить адрес структуры RUNDATA, соответствующей этому окну. Когда окно было "подклассом" с callback-функцией RFUNCTION_SUBCLASSWINDOW, система CF сохраняет адрес структуры RUNDATA в структуру окна. Следующая подпрограмма GetRdPtr позволяет Вам получить этот адрес из Вашего окна управления: LPRDATA GetRdPtr(HWND hWnd, LPRH rhPtr) { return (LPRDATA)GetProp(hWnd, (LPCTSTR)rhPtr->rh4.rh4AtomRd); } Однако одного получения адреса недостаточно, у Вас в одно и то же время может быть больше одного объекта с окном поверх фрейма. Поэтому очень важно проверить идентификатор объекта, и убедиться, что он соответствует нужному идентификатору. if ((rdPtr = GetRdPtr((HWND)lParam, rhPtr, &n)) != NULL && rdPtr->rHo.hoIdentifier == IDENTIFIER) { // OK, это для меня: } Ваша главная оконная процедура. Для окон, не являющихся окнами управления интерфейса, Вам нужно определить реальную процедуру окна. Вы должны определить hook в своем окне, чтобы привязаться к обработке окон системы CF. Здесь показано, как реализована оконная процедура в объекте QTVR: сначала мы регистрируем класс окна в подпрограмме Initialize: // Регистрация класса окна QTVR: wcMov.style = 0; wcMov.lpfnWndProc = (WNDPROC)WndProc; wcMov.cbClsExtra = 0; wcMov.cbWndExtra = 0; wcMov.hInstance = hInstLib; wcMov.hIcon = NULL; wcMov.hCursor = LoadCursor(NULL, IDC_ARROW); wcMov.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcMov.lpszMenuName = NULL; wcMov.lpszClassName = szMovClass;if (RegisterClass(&wcMov) != 0) QuickTimeInit++; В подпрограмме CreateRunObject мы создаем окно для этого класса: rdPtr->hwndMov = CreateWindow(szMovClass, NULL, WS_CHILDWINDOW, rdPtr->rHo.hoX - rhPtr->rhWindowX, rdPtr->rHo.hoY - rhPtr->rhWindowY, rdPtr->rHo.hoImgWidth, rdPtr->rHo.hoImgHeight, rhPtr->rhHEditWin, NULL, hInstLib, NULL); Теперь установим hook: // Ветка hook: rdPtr->raviWindowNumber = 1; rdPtr->rHo.hoOffsetToWindows = (int)((LPBYTE)&rdPtr->raviWindowNumber - (LPBYTE)rdPtr); callRunTimeFunction(rdPtr, RFUNCTION_SUBCLASSWINDOW, 0, (DWORD)WndHookProc); Обратите внимание, что мы передаем адрес hook-подпрограммы как последний параметр подпрограммы callRunTimeFunction. Теперь реальная подпрограмма окна, которая ничего не делает: LRESULT CALLBACK DLLExport WndProc(HWND hWnd, uint msgType, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hWnd, msgType, wParam, lParam); } Hook-процедура, выполняющая нужную работу: LRESULT CALLBACK DLLExport WndHookProc(fprh rhPtr, HWND hWnd, uint msgType,
WPARAM wParam, LPARAM lParam)
{
LPRDATA rdPtr;
// Обработка сообщений: rdPtr=GetRdPtr(hWnd, rhPtr); if (rdPtr!=0) { // Сюда вставляется необходимый код ... ... // Отправка сообщения в контроллер изображения (movie controller) с возвратом: return MCIsPlayerMessage(rdPtr->mcController, hWnd, msgType, wParam, lParam); } return 0; } Hook-процедура вызывается перед реальной процедурой окна. Она должна вернуть значение, отличающееся от 0, чтобы показать, что сообщение было обработано. В этом случае WndProc не будет вызвана. Как обработать сообщения палитры. Хотя 256 цветов приложения теперь устарели, Вы можете захотеть обработать сообщения палитры для своих окон. Когда приложение работает в 256 цветах, дочернее окно должно правильно реагировать на сообщения палитры (palette messages). Как это можно реализовать: LRESULT CALLBACK DLLExport WindowProc(LPRH rhPtr, HWND hWnd, UINT msgType,
WPARAM wParam, LPARAM lParam)
{
LPRDATA rdPtr;
HWND hwndT;
HWND hwndNewPal;
// Это для меня? switch (msgType) { // Сообщения палитры: case WM_PALETTECHANGED: case WM_QUERYNEWPALETTE: // Поиск окон AVI со своей собственной палитрой: if ( NULL == rhPtr->rhHEditWin || rhPtr->rhHMainWin != hWnd ) break; rdPtr = NULL; hwndNewPal = NULL; hwndT = GetWindow(rhPtr->rhHEditWin, GW_CHILD); while (hwndT) { // Получение указателя на структуру avi: rdPtr = GetRdPtr(hwndT, rhPtr); if ((rdPtr != 0) && (IDENTIFIER == rdPtr->rHo.hoIdentifier)) { if (msgType == WM_PALETTECHANGED) SendMessage (hwndT, WM_PALETTECHANGED, wParam, lParam); else { // Отправка сообщения WM_QUERYNEWPALETTE к AVI // и WM_PALETTECHANGED в окно фрейма: if (NULL == hwndNewPal) SendMessage(hwndNewPal = hwndT, WM_QUERYNEWPALETTE, 0, 0); else SendMessage(hwndT, WM_PALETTECHANGED, (WPARAM)hwndNewPal, 0); } break; } hwndT = GetWindow(hwndT, GW_HWNDNEXT); } if ( hwndNewPal != NULL ) { SendMessage(ryPtr->ryHeditWin, WM_PALETTECHANGED, (WPARAM)hwndNewPal, 0); // Показывает, что сообщение было обработано: return REFLAG_MSGHANDLED; } break; } return 0L; } Как Вы можете видеть, эта подпрограмма детектирует сообщения палитры. Когда появляется сообщение палитры, оно проходит через список дочерних окон AVI. Когда одно из них детектировано, то окну отправляется сообщение QUERYNEWPALETTE, и сообщение PALETTECHANGED в окно фрейма. Даже если такой объект реально не рисуется во фрейме, Вы должны только модифицировать позицию и размер окна в подпрограмме DisplayRunObject. Это гарантирует, что все модификации, осуществляемые по действиям, произойдут одновременно, синхронно с главным процессом перерисовки окна приложения. [Используемые структуры] В этой главе перечислены самые важные структуры, которые Вы должны знать и использовать, чтобы запрограммировать Ваш объект расширения. Некоторые из этих структур являются частью исходного кода расширения, и некоторые частью исходного кода CF (определены в cncf.h, cncr.h и cncy.h). Определена в CNCR.H, часть основных структур CF. Используется только во время работы приложения runtime. Назначение: содержит всю нужную информацию о текущем приложении. Замечание: как и все runtime-структуры, возможно разработчики будут вынуждены поменять её содержимое в будущих обновлениях CF. Если так, то придется обновить SDK. Вы должны избегать прямого использования этих структур, конечно за исключением случаев, когда нет другого способа получить доступ к нужной информации. Полезные поля: m_hdr - gaNewFlags: содержит флаги GANF_xxx, в которых находятся настройки. m_name: имя приложения. m_appFileName: имя файла приложения (оно может находиться во временной директории, см. структуру mV, если Вам требуется имя исполняемого файла EXE). m_copyright: сообщение копирайта. m_aboutText: текст для отображения в окошке About. m_doc: файл подсказки (help). m_nbKpx: количество расширений, используемых в приложении. m_kpxTab и m_kpxDataTable: информация о расширениях (HINSTANCE и функции). m_nbMvx: количество расширений перемещения (movement extensions). m_mvxTable: информация о расширениях перемещения (HINSTANCE и функции). m_oiMaxIndex: количество объектов. m_ois: таблица объектов. m_pParentApp: родительское приложение (если текущее приложение работает как дочернее, sub-application). m_Frame: текущий фрейм (см. структуру CRunFrame для дополнительной информации). m_nCurrentFrame: индекс текущего фрейма. m_pGlobalValues: глобальные значения (предупреждение: если m_bShareGlobalValues == TRUE, используйте m_pGlobalValues из родительского приложения, или выше). m_pGlobalStrings: глобальные строки (предупреждение: если m_bShareGlobalStrings == TRUE, используйте m_pGlobalStrings из родительского приложения, или выше). Определена в CNCR.H, часть основных структур CF. Назначение: содержит всю необходимую информацию по текущему фрейму во время выполнения приложения (runtime). Замечание: как и все runtime-структуры, возможно разработчики будут вынуждены поменять её содержимое в будущих обновлениях CF. Если так, то придется обновить SDK. Вы должны избегать прямого использования этих структур, конечно за исключением случаев, когда нет другого способа получить доступ к нужной информации. Полезные поля: m_hdr - leWidth: ширина игрового поля. m_name: имя фрейма. m_loMaxIndex: количество экземпляров объекта. m_los: экземпляры объекта во фрейме. m_rhPtr: указатель на структуру RunHeader. Определена в MAIN.H, часть кода расширения. Назначение: хранит настройки времени редактирования (edit-time) объекта, определенные в диалоге настройки и свойствах объекта. Эта структура должна быть полностью определена Вами! EDITDATA должен начинаться с дочерней структуры extheader, которая содержит информацию для CF. Замечания: здесь показан минимум для структуры EDITDATA: typedef struct { extHeader eHeader; } EDITDATA; Структура extheader: typedef struct tagEditExtension { DWORD extSize; // размер структуры EDITDATA DWORD extMaxSize; // максимальный размер DWORD extVersion; // номер версии LPVOID extID; // идентификатор объекта LPVOID extPrivateData; // приватные данные } extHeader; Замечание: Вы не должны менять эту структуру. Если Вам нужно повторно выделить структуру EDITDATA, используйте callback-функцию mvReAllocEditData в структуре mv. Определена в CNCF.H, часть основных структур CF. Назначение: хранит run-time информацию, не зависящую от объекта. Структура HeaderObject должна всегда быть в начале структуры RUNDATA. Предупреждение: обращайтесь только к "полезным полям", изменения в любых других областях могут полностью нарушить работу приложения! Полезные поля: short hoNumber; // Номер объекта в списке объектов CF LPRH hoAdRunHeader; // Адрес структуры RunHeader short hoX; // Координата X объекта short hoY; // Координата Y объекта int hoImgXSpot; // Позиция X активной области (hot spot) текущей картинки int hoImgYSpot; // Позиция Y активной области (hot spot) текущей картинки int hoImgWidth; // Текущая ширина объекта int hoImgHeight; // Текущая высота объекта short hoOEFlags; // Флаги OEFLAGS объекта Определена в CNPY.H, часть основного кода CF. Назначение: хранит информацию о каждом отдельном объекте во фрейме. Имеется один экземпляр структуры LO на каждый объект во фрейме. Дублированные объекты имеют одну и ту же структуру OI. Замечание: как и все runtime-структуры, возможно разработчики будут вынуждены поменять её содержимое в будущих обновлениях CF. Если так, то придется обновить SDK. Вы должны избегать прямого использования этих структур, конечно за исключением случаев, когда нет другого способа получить доступ к нужной информации. Полезные поля: loX: координата X объекта на игровом поле Обратите внимание, что поля этой структуры действительны только во время работы приложения (run time). Структура mv служит для коммуникации между CF и Вашим расширением. Она содержит глобальные данные наподобие хендлов окна, callback-функции, которые Ваше расширение может использовать. Для получения списка callback-функций см. раздел "Callback-функции" этой документации. Важные поля в структуре mv: mvHInst: HINSTANCE программы (CF или runtime-приложения). Другие поля структуры это callback-функции, подробнее о них см. раздел "Callback-функции" этой документации. Примечание: во время работы программы (runtime) Вы можете обращаться к структуре mv из структуры RunHeader: rhPtr->rh4.rh4Mv. Определена в CNCY.H, часть основного кода CF. Назначение: хранит информацию об объекте. Структура OI сохраняется в приложении. Экземпляры объекта имеют структуры LO, сохраненные в каждом фрейме. Замечание: как и все runtime-структуры, возможно разработчики будут вынуждены поменять её содержимое в будущих обновлениях CF. Если так, то придется обновить SDK. Вы должны избегать прямого использования этих структур, конечно за исключением случаев, когда нет другого способа получить доступ к нужной информации. Полезные поля: oiHdr - oiType: тип объекта. oiName: имя объекта. oiOC: указатель на структуру, которая содержит информацию времени редактирования (анимации, перемещения, данные расширения, и т. д.). Примечание: только поля эффекта чернил в этой структуры достоверны во время редактирования (edit time). Определена в MAIN.H, часть кода расширения. Назначение: хранит информацию об объекте во время выполнения приложения (run-time). Структура RUNDATA должна всегда начинаться с headerObject, за которым идут структуры movement, animation, common и value, в зависимости от флагов OEFLAG. Для получения дополнительной информации обратитесь к секции "Определение флагов объекта / важные структуры" этой документации. Как устроена структура RUNDATA. Во простейшая структура RUNDATA: typedef struct { headerObject rHo; } RUNDATA; Определена в CNCF.H, часть основного исходного кода CF. Назначение: хранит информацию приложения во время его выполнения (run-time). Обычно Вам нужно обращаться к этой структуре для получения хендла окон. Предупреждение: обращайтесь только к "полезным полям", изменения в любых других полях могут полностью нарушить работу приложения! Полезные поля: npWin rhIdEditWin; // идентификатор MMFS окна приложения npWin rhIdMainWin; // идентификатор MMFS окна фрейма приложения npAppli rhIdAppli; // идентификатор MMFS приложения HWND rhHEditWin; // хендл Windows для окна приложения HWND rhHMainWin; // хендл Windows для окна фрейма CRunApp* rhApp; // указатель на информационную структуру приложения CRunFrame* rhFrame; // указатель на информационную структуру фрейма int rhLoopCount; // количество циклов от момента запуска фрейма UINT rhTimer; // таймер в единицах 1/1000 секунды от начала фрейма [Список необходимых функций] Режимы edit-time и run-time. Система CF работает в 2 главных режимах: edit-time mode (режим редактирования приложения, когда пользователь в визуальном интерфейсе проектирует внешний вид и поведение программы), и run-time mode (работа спроектированной программы в штатном или отлаживаемом режиме). Edit-time mode используется в редакторе фрейма (Frame Editor), редакторе событий (Event editor), редакторе пошагового выполнения (Step-through editor). Run-time mode вступает в силу, как только приложение начинает выполняться. Ваш объект расширения также должен следовать этой логике. Код для объекта расширения должен быть также поделен на 2 части: edit-time и run-time. Секция edit-time должна содержать диалог настройки (Setup), если это необходимо, свойства (поддержка окна Properties), отображение объекта в редакторе фрейма, создание нового объекта (описание процесса см. в [4]), и список доступных действий (actions) и условий (conditions). Секция run-time должна содержать все подпрограммы для создания, анимирования и удаления объекта, и все действия и условия. Разработчики CF поделили необходимые подпрограммы на 3 секции: • Список подпрограмм общего назначения. Важное замечание: чтобы быть доступными из основной программы, функции в DLL (объекты расширения это модули DLL) должны быть декларированы в файле DEF, так чтобы линкер знал, какие функции сделать общедоступными (public). Если Вы реализуете эти функции, или будут функции, которые не присутствуют в исходном коде, то Вы ДОЛЖНЫ декларировать их в файле EXT.DEF проекта. Все функции, перечисленные в этом разделе, которые не реализованы, должны быть закомментированы точкой с запятой. Для декларации функции просто удалите точку с запятой в начале имени новой функции. Если Вы так не сделаете, то даже реализованные Ваши функции расширения будут невидимы для CF или для кода runtime, и они не будут вызываться. Подпрограммы общего назначения. Насколько я понял, эти подпрограммы могут использоваться в обоих режимах: edit-time и run-time. BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) Эта подпрограмма основной реализации DLL. Обратитесь к документации Microsoft для получения полной информации об этой подпрограмме. Замечания: Вы не должны использовать эту подпрограмму для инициализации ресурсов или загрузки данных. Всю необходимую для Вас инициализацию делайте в подпрограмме Initialize. int WINAPI DLLExport Initialize(mv _far *mV, int quiet) Подпрограмма Initialize выполняет инициализации холодного старта. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: 0 если выполнение было успешным, -1 в случае ошибки (расширение не было загружено). Замечания: эта подпрограмма вызывается один раз для каждого объекта и каждого приложения, независимо от того, как много дублированных объектов было помещено в любой из фреймов. В этой подпрограмме Вы должны выполнить все основные инициализации наподобие регистрации классов окна, загрузки модулей DLL, и т. д. Установленный флаг quiet показывает, что не нужно сообщать об ошибках соответствующими сообщениями. int WINAPI DLLExport Free(mv _far *mV) Подпрограмма Free освобождает все ресурсы, которые были выделены в подпрограмме Initialize. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: всегда должна возвращать 0. Замечание: подпрограмма Free является комплементарной подпрограмме Initialize, т. е. они работают в паре. Эта подпрограмма вызывается только 1 раз для каждого объекта и каждого приложения, независимо от количества дубликатов объектов, размещенных в любом количестве фреймов. В этой подпрограмме Вы должны освободить все, что было выделено процессом холодного старта. DWORD WINAPI DLLExport GetInfos(int info)
GetInfos выдает номер версии расширения и другую полезную информацию для runtime. Параметры: info: запрашиваемое значение. Возвращаемое значение: зависит от запрашиваемого. Если параметр info равен константе KGI_PRODUCT, то Вы должны вернуть минимальную версию CF, с которой совместимо Ваше расширение: PRODUCT_VERSION_HOME = TGF или выше. Если info равен KGI_BUILD, то Вы должны вернуть минимальный номер сборки CF, с которой совместимо Ваше расширение: Не меняйте другие части этой подпрограммы. short WINAPI DLLExport GetRunObjectInfos(mv _far *mV, fpKpxRunInfos infoPtr) GetRunObjectInfos возвращает информацию о run-time флагах объекта, размере edit-time структур, условия и действия. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращает TRUE, если все в порядке, или FALSE в случае ошибки. Замечания: использование этой подпрограммы хорошо показано в проекте шаблона объекта (Template): можете копировать оттуда код, он работает корректно, и хорошо самодокументирован. LPCTSTR* WINAPI DLLExport GetDependencies()
Подпрограмма GetDependencies возвращает список специфичных DLL, которые требуются для запуска расширения. Здесь нужно просто вернуть дополнительные DLL, не возвращайте стандартные Windows DLL. Необходимые для расширения DLL должны быть скопированы в папку Data\Runtime системы CF, чтобы CF могла подключить их в независимые приложения. Они будут распакованы в ту же самую временную папку, как и расширение, когда запускается код runtime. Возвращает: список значений LPCTSTR и значение NULL, обозначающее конец этого списка. int WINAPI DLLExport EnumElts (mv __far *mV, LPEDATA edPtr, ENUMELTPROC enumProc, ENUMELTPROC undoProc, LPARAM lp1, LPARAM lp2) Подпрограмма EnumElts вызывается системой CF для перечисления картинок и шрифтов, используемых в объекте расширения. Она вызывается и системой CF, и кодом runtime. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: код ошибки или 0, если все в порядке. Не нулевое значение останавливает перечисление. Замечание: эта подпрограмма должна выполнять энумерацию (перечисление по списку) только картинок и шрифтов, которые были сохранены в приложении. Она не должна перечислять временные картинки и шрифты. Эта подпрограмма обычно вызывается, когда объект загружается или сохраняется, и показывает для CF, какие картинки и шрифты сохранять в файл приложения. Для каждой картинки и шрифта эта подпрограмма должна вызвать функцию enumProc со следующими параметрами: LPWORD eltPtr указатель на картинку или шрифт (созданную одной из следующих функций MMFS2: DibToImage, WinCreateFont, или функцией mvEditImage). Если enumProc вернет ошибку (не 0), то Вы должны вызвать функцию undoProc для каждой картинки и шрифта, уже переданных в enumProc. enumProc может менять номер картинки или шрифта, указанного через eltPtr. Пример: здесь показана энумерация 8 картинок и 4 шрифтов объекта. int WINAPI DLLExport EnumElts (mv __far *mV, fpedata edPtr, ENUMELTPROC enumProc, ENUMELTPROC undoProc, LPARAM lp1, LPARAM lp2) { int i, j, error = FALSE; // Перечисление шрифтов: for (i=0; i < 4; i++) { error = enumProc (&edPtr->nFont[i], FONT_TAB, lp1, lp2); if ( error ) { // Отмена перечисленных шрифтов: for (j=i-1; j>=0; j--) undoProc (&edPtr->nFont[j], FONT_TAB, lp1, lp2); break; } } // Перечисление картинок: if ( !error ) { for (i=0; i < 8; i++) { error = enumProc(&edPtr->nImg[i], IMG_TAB, lp1, lp2); if ( error ) { // Отмена перечисленных картинок: for (j=i-1; j>=0; j--) undoProc (&edPtr->nImg[j], IMG_TAB, lp1, lp2); // Отмена перечисленных шрифтов: for (j=3; j>=0; j--) undoProc (&edPtr->nFont, FONT_TAB, lp1, lp2); break; } } } return error; } int WINAPI DLLExport LoadObject(mv _far *mV, LPCTSTR fileName, LPEDATA edPtr, int reserved) Подпрограмма LoadObject вызывается, когда объект загружается в память, либо когда приложение загружается системой CF, или когда объект загружается кодом runtime. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: 0 если все в порядке, -1 в случае обнаруженной ошибки. Замечания: LoadObject вызывается один раз для каждого отличающегося объекта в каждом фрейме. Например, если Вы дублировали один объект путем вставки копии (paste) в фрейм, то эта функция будет вызвана только один раз. Указатель edPtr покажет на общую структуру EDITDATA для всех дублированных объектов. В этой подпрограмме Вы можете загрузить некоторые данные в зависимости от содержимого структуры EDITDATA, или сохранить указатели. void WINAPI DLLExport UnloadObject(mv _far *mV, LPEDATA edPtr, int reserved) Подпрограмма UnloadObject вызывается, когда последний объект определенного вида удаляется из памяти, либо в режиме edit-time, либо в режиме run-time. Параметры: mv _far *mV указатель на информационную структуру mv. Замечания: UnloadObject вызывается только один раз для каждого отличающегося объекта в каждом фрейме. Например, если Вы сделали дубликат объекта копированием/вставкой его во фрейм, то эта функция будет вызвана все равно только 1 раз. Указатель edPtr покажет на общую структуру EDITDATA для всех дублированных объектов. Эта подпрограмма освободит все ресурсы, которые были выделены подпрограммой LoadObject. HGLOBAL WINAPI DLLExport UpdateEditStructure(mv __far *mV, void __far * OldEdPtr) UpdateEditStructure позволяет Вам преобразовать предыдущую версию (версии) структуры EDITDATA. Она вызывается и в режиме edit-time, и в режиме run-time (поскольку файл подчиненного приложения, созданный в предыдущей версии, может быть загружен более новой версией кода runtime). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: 0, если структура EDITDATA не была изменена, либо глобальный хендл памяти, разблокированный, если это уместно. Замечания: структура EDITDATA каждого объекта сохраняется в файлах .MFA / .CCN. Вы можете захотеть добавить в них новые записи с сохранением совместимости с приложениями, сохраненными ранее, тогда нужно обновить эту структуру. Когда номер версии структуры EDITDATA не совпадает с текущим номером версии объекта, то система CF вызовет эту подпрограмму, чтобы Вы могли осуществить процесс обновления. Из старой структуры Вы можете заново создать новую структуру, совместимую с Вашей новой версией. Если Вы определили больше 2 версий, то не забудьте сделать инкрементальным процесс обновления, поскольку более новая версия ничего не знает о том, какая структура может находится в приложении. Таким образом, для трех разных версий сначала делается обновление от V0 к V1, затем от V1 к V2, и затем от V2 к V3. Если поступать таким образом, то независимо от версий конечная структура будет корректной. Пример: HGLOBAL WINAPI DLLExport UpdateEditStructure(mv __far *mV, void __far * OldEdPtr) { HGLOBAL hgNew = NULL; if (((fpedata)OldEdPtr)->eHeader.extVersion < KCX_VERSION_1) { fpedata_v1 newEdPtr; if ((hgNew = GlobalAlloc(GPTR, sizeof(editData_v1))) != NULL) { newEdPtr = (fpedata_v1)GlobalLock(hgNew); memcpy(&newEdPtr->eHeader, &((fpedata_v0)OldEdPtr)->eHeader, sizeof(extHeader)); // Обновление номера версии: newEdPtr->eHeader.extVersion = KCX_VERSION_1; // Обновление размера структуры EDITDATA: newEdPtr->eHeader.extSize = sizeof(editData_v1); newEdPtr->eaviIdApp = ((fpedata_v0)OldEdPtr)->eaviIdApp; newEdPtr->eaviImage = ((fpedata_v0)OldEdPtr)->eaviImage; newEdPtr->eaviSx = ((fpedata_v0)OldEdPtr)->eaviSx; newEdPtr->eaviSy = ((fpedata_v0)OldEdPtr)->eaviSy; newEdPtr->eaviFlags = ((fpedata_v0)OldEdPtr)->eaviFlags; _tcscpy(newEdPtr->eaviName, ((fpedata_v0)OldEdPtr)->eaviName); memcpy(newEdPtr->eaviSecu, ((fpedata_v0)OldEdPtr)->eaviSecu, 16); GlobalUnlock(hgNew);
}
}
return hgNew;
}
void WINAPI DLLExport UpdateFileNames(mv _far *mV, LPTSTR appName, LPEDATA edPtr, void (WINAPI * lpfnUpdate)(LPTSTR, LPTSTR)) Подпрограмма UpdateFileNames позволяет именам файла, содержащимся в структуре EDITDATA, быть перемещенными системой CF. Эта функция вызывается системой CF во время выполнения приложения (runtime). Параметры: mv _far *mV указатель на информационную структуру mv. Замечания: подпрограмма UpdateFileNames вызывается, когда каждый отличающийся объект загружается из каждого фрейма. Эта подпрограмма должна вызвать подпрограмму перемещения для для каждого пути до файла, содержащего в структуре EDITDATA. Подпрограмма UpdateFileNames гарантирует, что путь корректен для места расположения приложения. Буфер, содержащий путь, должен быть размером как минимум _MAX_PATH символов. Пример: // Обновление имени файла: if (edPtr->eaviName[0] != 0) lpfnUpdate(appName, edPtr->eaviName); Подпрограммы режима edit-time: int WINAPI DLLExport CreateObject(mv _far *mV, fpLevObj loPtr, LPEDATA edPtr) Подпрограмма CreateObject вызывается, когда Вы создаете новый объект в редакторе фрейма. Эта функция может открыть окно диалога настройки объекта (Setup dialog), если оно предусмотрено, и инициализировать структуру редактирования. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: ненулевое, если создание было неудачным, например если пользователь нажал "Отмена" (cancel) в окне диалога, и 0, если объект был создан. Замечания: некоторые объекты не нуждаются в окне диалога настройки, когда создается объект. В этих случаях подпрограмма CreateObject просто устанавливает инициализационные значения в структуре редактирования. Пример: здесь показан простой вызов окна настройки (setup dialog box), после чего в структуре EDITDATA инициализируются поля размера. int WINAPI DLLExport CreateObject(mv _far *mV, fpLevObj loPtr, LPEDATA edPtr) { // Установка для объекта значений по умолчанию: edPtr->swidth = 32; edPtr->sheight = 32; // Отображения диалога настройки: setupParams spa; spa.edpt = edPtr; spa.kv = mV; if ( DialogBoxParam(hInstLib, MAKEINTRESOURCE(DB_SETUP), mV->mvHEditWin, setupProc, (LPARAM)(LPBYTE)&spa) == IDOK ) { return 0; // нет ошибки } // Ошибка: return -1; } void WINAPI DLLExport CreateFromFile (mv _far *mV, LPCTSTR fileName, LPEDATA edPtr) Подпрограмма CreateFromFile вызывается, если UsesFile возвращает TRUE, когда пользователь бросает файл в окно редактора фрейма. Эта функция должна инициализировать структуру EDITDATA. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: для дополнительной информации обратитесь к описанию функции UsesFile. Пример: void WINAPI DLLExport CreateFromFile (LPMV mV, LPCTSTR fileName, LPEDATA edPtr) { _tcscpy(edPtr->myFileName, fileName); } void WINAPI DLLExport DuplicateObject(mv _far *mV, fpObjInfo oiPtr, LPEDATA edPtr) Подпрограмма DuplicateObject вызывается, когда объект клонируется в редакторе фрейма, например когда дублируется структура EDITDATA. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: эта подпрограмма позволяет Вам дублировать любую память, выделенную в структуре EDITDATA. BOOL WINAPI DLLExport EditObject(mv _far *mV, fpObjInfo oiPtr, fpLevObj loPtr, LPEDATA edPtr)
Подпрограмма EditObject вызывается системой CF, когда пользователь выбрал пункт Edit контекстного меню редактора фрейма, или сделал двойной клик на объекте. Вам не нужна эта функция, если Ваш объект использует только свойства (окно диалога настройки не предусмотрено). Однако в некоторых случаях хорошей идеей будет использовать и свойства, и окно диалога настройки. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: FALSE, если не сделано никаких модификаций, TRUE для проверки изменений. Пример: BOOL WINAPI EditObject (mv _far *mV, fpObjInfo oiPtr, fpLevObj loPtr, LPEDATA edPtr) { // Удалите это, если Ваш объект не имеет диалога настройки: setupParams spa; spa.edpt = edPtr; spa.kv = mV; if ( DialogBoxParam(hInstLib, MAKEINTRESOURCE(DB_SETUP), mV->mvHEditWin, setupProc, (LPARAM)(LPBYTE)&spa) == IDOK ) { return TRUE; } return FALSE; } void WINAPI DLLExport EditorDisplay(mv _far *mV, fpObjInfo oiPtr, fpLevObj loPtr, LPEDATA edPtr, RECT FAR *rc) Подпрограмма EditorDisplay отображает объект в окне редактора фрейма (Frame Editor). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: эта подпрограмма в действительности рисует объект в окне редактора фрейма. Вы не должны ничего рисовать вне пределов, ограниченных прямоугольником структуры rc. Вы не должны использовать GetDC и ReleaseDC для получения хендла окна фрейма. Чтобы нарисовать свой объект, Вы должны получить поверхность CF (surface), присоединенную к окну редактора фрейма для этого объекта, и рисовать по этой поверхности функциями cSurface. Пример: void WINAPI DLLExport EditorDisplay(mv _far *mV, fpObjInfo oiPtr, fpLevObj loPtr, LPEDATA edPtr, RECT FAR *rc) { // Это простой случай рисования картинки во окне редактора фрейма CF. // Сначала мы должны получить указатель на поверхность (surface), // используемую редактором фрейма: LPSURFACE ps = WinGetSurface((int)mV->mvIdEditWin); if ( ps != NULL ) // Если поверхность существует, ... { // ... то выполняем следующие действия: int x = rc->left; // получение наших границ int y = rc->top; int w = rc->right-rc->left; int h = rc->bottom-rc->top; cSurface is; // новая переменная поверхности, которую // мы будем использовать // Создание реализации поверхности из прототипа (выиграл редактор фрейма): is.Create(4, 4, ps); // Загрузка нашей растровой картинки (bitmap) из ресурсов, // и переназначение палитры, если это необходимо: is.LoadImage(hInstLib, EXO_IMAGE, LI_REMAP); // Копирование битового массива картинки (Blit) в поверхность редактора фрейма: is.Blit(*ps, x, y, BMODE_TRANSP, BOP_COPY, 0); // Это действительно копирует всю нашу поверхность в поверхность редактора // фрейма на указанное место. Мы могли использовать разные эффекты // для изображения при копировании, например инверсия, операции AND, OR, XOR, // blend (полупрозрачность, 6-й параметр задает величину прозрачности). // Вы можете выполнить антиалиасинг с помощью 7-го параметра (по умолчанию = 0, // или выключено). } } void WINAPI EditParameter(mv* mV, short code, paramExt* pExt) Редактирует пользовательский параметр. Параметры: mv* mV указатель на структуру mv, содержащую данные о приложении. Возвращаемое значение: отсутствует. Замечания: эта функция вызывается, когда пользователь редактирует параметры своего параметра. Это должно открыть окно диалога, или сделать необходимые действия для редактирования параметра, изменения структуры paramExt (особенно поля pExt->pextData), и записи нового размера этого параметра в поле pExt->pextSize. Общий размер, который Вы можете использовать, равен PARAM_EXTMAXSIZE. Система CF выдаст ошибку, если размер превысит это значение (и произойдет сбой, если Вы ДЕЙСТВИТЕЛЬНО превысите этот лимит). BOOL WINAPI DLLExport EditProp(LPMV mV, LPEDATA edPtr, UINT nPropID) Эта функция вызывается, когда пользователь кликнет на кнопку свойств (например на кнопке в свойстве Button, или на кнопке в свойстве ComboBoxBtn, или на кнопке в свойстве ImageList). Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: TRUE, если свойства обновлены, иначе FALSE. Замечания: если эта подпрограмма возвращает TRUE, то система CF вызовет GetPropertyValue, чтобы получить текущее значение свойства, и вызовет SetPropertyValue для других свойств выбранных объектов. short WINAPI DLLExport GetActionCodeFromMenu(mv _far *mV, short menuId) Подпрограмма GetActionCodeFromMenu преобразует идентификатор меню из всплывающих меню действий (action pop-up menu) в код действия (action code). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: код действия. Замечания: в предоставленном шаблоне идентификатор меню определен так, чтобы непосредственно отразить коды условий (condition codes). LPINFOEVENTSV2 WINAPI DLLExport GetActionInfos(mv _far *mV, short code) Подпрограмма GetActionInfos возвратит указатель для на структуру infoEventsV2 из кода действия. Указатель является относительным к этому коду. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: указатель на структуру infoEventsV2. Замечания: в предоставленном шаблоне функция ищет в массиве actionInfo код, и возвращает указатель на эту структуру. HMENU WINAPI DLLExport GetActionMenu(mv _far *mV, fpObjInfo oiPtr, LPEDATA edPtr)
Подпрограмма GetActionMenu возвратит всплывающее меню действий (action pop-up menu). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: меню для использования. Замечания: Вы можете скрыть или показать определенные опции, в зависимости от содержимого редактируемой структуры. void WINAPI DLLExport GetActionString(mv _far *mV, short code, LPTSTR strPtr, short maxLen) Подпрограмма GetActionString возвращает строку отображения из кода действия, для использования в редакторе событий (Event Editor). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. void WINAPI DLLExport GetActionTitle(mv _far *mV, short code, short param, LPTSTR strBuf, short maxLen) Подпрограмма GetActionTitle возвращает строку для отображения, когда вводятся параметры действия. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: подпрограмма GetActionTitle, предоставленная в шаблоне, автоматически загружает строку из ресурса, если Вы определили её в массиве. short WINAPI DLLExport GetConditionCodeFromMenu(mv _far *mV, short menuId) Подпрограмма GetConditionCodeFromMenu преобразует идентификатор меню из всплывающего меню условия (condition pop-up menu) в код условия (condition code). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: код условия. Замечания: в предоставленном шаблоне идентификатор меню определен так, чтобы непосредственно отражать коды условий. LPINFOEVENTSV2 WINAPI DLLExport GetConditionInfos(mv _far *mV, short code) Подпрограмма GetConditionInfos возвращает указатель на структуру InfoEventsV2 из кода условия (condition code). Этот указатель является относительным к этому коду. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: указатель на структуру infoEvents. Замечания: в предоставленном шаблоне эта функция ищет по массиву условий код, и возвращает часть информации. HMENU WINAPI DLLExport GetConditionMenu(mv _far *mV, fpObjInfo oiPtr, LPEDATA edPtr)
Подпрограмма GetConditionMenu возвращает всплывающее меню условия (condition pop-up menu). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: меню для использования. Замечания: Вы можете скрыть или показать определенные опции в зависимости от содержания редактируемой структуры. void WINAPI DLLExport GetConditionString(mv _far *mV, short code, LPTSTR strPtr, short maxLen) Подпрограмма GetConditionString возвратит строку отображения из кода условия (condition code), для использования в редакторе событий (Event Editor). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. void WINAPI DLLExport GetConditionTitle(mv _far *mV, short code, short param, LPTSTR strBuf, short maxLen) Подпрограмма GetConditionTitle возвратит строку для отображения, когда вводятся параметры условия. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: подпрограмма GetConditionTitle, предоставленная в шаблоне, автоматически загружает строку из ресурса, если Вы определите это в массиве. short WINAPI DLLExport GetExpressionCodeFromMenu(mv _far *mV, short menuId) Подпрограмма GetExpressionCodeFromMenu преобразует идентификатор меню из всплывающего меню выражения (expression pop-up menu) в код выражения (expression code). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: код выражения. Замечания: в предоставленном шаблоне идентификатор меню определен таким образом, чтобы непосредственно отражать коды выражений (expression codes). LPINFOEVENTSV2 WINAPI DLLExport GetExpressionInfos(mv _far *mV, short code) Подпрограмма GetExpressionInfos возвратит указатель на структуру infoEventsV2 из кода выражения (expression code). Этот указатель относителен к этому коду. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: указатель на структуру infoEventsV2. Замечания: в предоставленном шаблоне функция ищет код в массиве expressionInfo, и возвращает указатель. void WINAPI DLLExport GetExpressionParam(mv _far *mV, short code, short param, LPTSTR strBuf, short maxLen) Подпрограмма GetExpressionParam возвратит текст параметра выражения, полученный из кода выражения, для использования в редакторе событий (Event Editor). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. void WINAPI DLLExport GetExpressionString(mv _far *mV, short code, LPTSTR strPtr, short maxLen) Подпрограмма GetExpressionString вернет строку отображения, полученную из кода выражения (expression code), для использования в редакторе событий (Event Editor). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. void WINAPI DLLExport GetExpressionTitle(mv _far *mV, short code, short param, LPTSTR strBuf, short maxLen) Подпрограмма GetExpressionTitle возвратит строку для отображения, когда вводятся параметры выражения. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: подпрограмма GetExpressionTitle, предоставленная в шаблоне, автоматически загружает строку из ресурса, если Вы определили её в массиве. LPCTSTR WINAPI DLLExport GetHelpFileName() Подпрограмма GetHelpFileName возвращает имя файла подсказки расширения. Возвращаемое значение: имя Help-файла. Замечания: возвращается имя файла без пути до него, если к Вашему help-файлу происходит обращение в главном файле подсказки CF, например _T("MyExt.chm"), или будет возвращен путь до Вашего help-файла относительно директории системы CF, например _T("Help\\MyExt.chm"). Вы должны установить свои help-файлы в каталог Help системы CF. void WINAPI DLLExport GetObjectRect(mv _far *mV, RECT FAR *rc, fpLevObj loPtr, LPEDATA edPtr) Подпрограмма GetObjectRect вызывается системой CF, чтобы определить размеры объекта. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: на входе поля left и top структуры RECT устанавливаются в действительные координаты объекта. Вы должны добавить к ним размер Вашего объекта. void WINAPI DLLExport GetObjInfos (mv _far *mV, LPEDATA edPtr, LPTSTR ObjName, LPTSTR ObjAuthor, LPTSTR ObjCopyright, LPTSTR ObjComment, LPTSTR ObjHttp) Подпрограмма GetDesc возвратит строку, описывающую объект. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: эти строки текста отображаются в свойствах About объекта. Текст ObjComment отображается также в диалоге создания нового объекта (Create New Object). Пример: void WINAPI DLLExport GetObjInfos (mv _far *mV, LPEDATA edPtr, LPTSTR ObjName, LPTSTR ObjAuthor, LPTSTR ObjCopyright, LPTSTR ObjComment, LPTSTR ObjHttp) { // Имя: LoadString(hInstLib, IDST_OBJNAME, ObjName, 255); // Автор: LoadString(hInstLib, IDST_AUTHOR, ObjAuthor, 255); // Копирайт: LoadString(hInstLib, IDST_COPYRIGHT, ObjCopyright, 255); // Комментарий: LoadString(hInstLib, IDST_COMMENT, ObjComment, 1024); // Адрес в Интернете: LoadString(hInstLib, IDST_HTTP, ObjHttp, 255); } void WINAPI GetParameterString(mv* mV, short code, paramExt* pExt, LPTSTR pDest, short size) Возвратит строку, описывающую пользовательский параметр. Параметры: mv* mV указатель на структуру mv, содержащую данные о приложении. Возвращаемое значение: отсутствует. Замечания: эта функция вызывается, когда CF хочет отобразить параметр в редакторе событий. Вы должны создать строку, которая содержит описание Вашего параметра, не слишком длинную и не слишком короткую. Только такую, какую нужно. BOOL WINAPI DLLExport GetPropCheck(LPMV mV, LPEDATA edPtr, UINT nPropID) Эта функция вызывается системой CF, чтобы узнать состояние галочки (checkmark) свойства. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: TRUE (галочка стоит, checked), или FALSE (галочка снята, unchecked). Замечания: эта функция вызывается только для опций-галочек, так что если в списке Ваших свойств есть и галочки, и значения, то должны реализовать и GetPropValue и GetPropCheck. Пример: BOOL WINAPI DLLExport GetPropCheck(LPMV mV, LPEDATA edPtr, UINT nPropID) { switch (nPropID) { case PROPID_MYCHECKBOX: // Будет возвращено 0 (галочка снята, unchecked) // или 1 (галочка стоит, checked): return edPtr->nCheck; } return 0; // галочка снята, unchecked } LPARAM WINAPI DLLExport GetPropCreateParam(LPMV mV, LPEDATA edPtr, UINT nPropID) Эта функция вызывается системой CF, чтобы получить параметр, связанный со свойством, если параметр NULL в определении свойства. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: используемый параметр. Вы не должны возвратить NULL, за исключением случая, когда у свойства есть установка по умолчанию. Замечания: есть 2 способа передать инициализационные данные в свойство. Либо Вы вводите их непосредственно в макрос PropData таблицы свойств, либо Вы используете параметр NULL в макросе PropData и возвратить параметр в функции GetPropCreateParam. Второе решение позволяет Вам динамически менять содержимое свойства (например элемент списка свойства списка выбора, combo box property). Если Вы выделяете память в этой функции, то должны освободить её в функции ReleasePropCreateParam. Пример: LPARAM WINAPI DLLExport GetPropCreateParam(LPMV mV, LPEDATA edPtr, UINT nPropID) { if ( nPropID == PROPID_COMBO ) { switch (edPtr->sType) { case TYPE1: return (LPARAM)ComboList1; case TYPE2: return (LPARAM)ComboList2; } } return NULL; } BOOL WINAPI DLLExport GetProperties(LPMV mV, LPEDATA edPtr, BOOL bMasterItem) Вызывается системой CF для получения определений свойств объекта. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: TRUE, если все прошло хорошо. Замечания: эта подпрограмма должна сказать CF вставить список свойств путем использования следующей функции обратного вызова (callback): mvInsertProps(mV, edPtr, Properties, PROPID_TAB_GENERAL, TRUE); Здесь Properties указывает на массив PropData, определяющий свойства. Обратите внимание, что Ваш объект может иметь несколько массивов PropData, и GetProperties может выбрать правильный массив, определяющий состояние объекта. Вы можете также удалить предопределенные свойства макросом mvRemoveProperty, если это необходимо. Пример этой подпрограммы можно найти в проекте объекта Template (шаблон, где показана реализация объекта). LPVOID WINAPI DLLExport GetPropValue(LPMV mV, LPEDATA edPtr, UINT nPropID) Эта функция вызывается системой CF, чтобы получить значение свойства объекта. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: должно быть объектом CPropValue (объектом, являющимся производным от объекта CPropValue). Тип CPropValue зависит от типа свойства. Например, свойство EditNumber нуждается в CPropDWordValue, свойство EditString нуждается в CPropDataValue, инициализированном строкой, и т. д. Замечания: для возврата значения просто напишите следующую строку кода: return new CPropDWordValue( myValue); или return new CPropDataValue(buffer, size); или return new CPropStringValue(myString); или return new CPropSizeValue(width, height); ... и т. д. Примечание: GetPropValue не вызывается для простых чекбоксов (PropData_CheckBox), Вы должны реализовать функцию GetPropCheck для таких свойств. Пример: LPVOID WINAPI DLLExport GetPropValue(LPMV mV, LPEDATA edPtr, UINT nPropID) { switch (nPropID) { case PROPID_COLOR: // Возврат цвета: return new CPropDWordValue(edPtr->dwColor); case PROPID_TEXT: // Возврат строки: return new CPropStringValue(edPtr->szText); case PROPID_COMBO: // Возврат значения из выпадающего списка (combo box): return new CPropDWordValue(edPtr->nComboIndex); } return NULL; } DWORD WINAPI DLLExport GetTextAlignment(mv _far *mV, LPEDATA edPtr)
Функция GetTextAlignement вызывается системой CF для получения текущего выравнивания текста text. Параметры: mv _far *mV указатель на структуру mv. Возвращаемое значение: DWORD, содержащее текущие флаги выравнивания. Эти флаги должны быть следующими масками (одна или несколько масок, объединенных операцией ИЛИ): TEXT_ALIGN_LEFT Замечания: Вы должны сохранить эти флаги в своей структуре EDITDATA, и возвратить их в этой подпрограмме. Вы должны возвратить флаги выравнивания, поддерживаемые Вашим объектом, в функции GetTextCaps, когда эта функция была вызвана. DWORD WINAPI DLLExport GetTextCaps(mv _far *mV, LPEDATA edPtr)
Эта подпрограмма вызывается системой CF, чтобы узнать свойства шрифта, который ей нужно обработать. Параметры: mv _far *mV указатель на структуру mv. Возвращаемое значение: DWORD, содержащее флаги, показывающие обрабатываемые свойства. Эти флаги могут быть одним или несколькими из следующих значений (объединенными операцией ИЛИ): TEXT_FONT показывает, что возможен выбор шрифта. Вы должны будете реализовать функции GetTextFont и SetTextFont. TEXT_COLOR поддерживается цвет текста. Вы должны будете реализовать функции GetTextClr и SetTextClr. TEXT_ALIGN_LEFT Все вышеперечисленные флаги показывают поддержку выравнивания шрифта. Из значения понятны из названия флага. Вы должны будете реализовать в своем коде объекта функции GetTextAlignement и SetTextAlignement. Пример: проект Template содержит пример для такой функции. COLORREF WINAPI DLLExport GetTextClr(mv _far *mV, LPEDATA edPtr)
Эта функция вызывается системой CF, чтобы получить текущий цвет текста объекта. Параметры: mv _far *mV указатель на структуру mv. Возвращаемое значение: COLORREF, содержащее текущий цвет текста объекта. Пример: проект Template содержит пример для такой функции. Вы должны вернуть TEXT_COLOR в функции GetTextCaps, чтобы вызывалась функция GetTextClr. BOOL WINAPI DLLExport GetTextFont(mv _far *mV, LPEDATA edPtr,
LPLOGFONT plf, LPTSTR pStyle,
UINT cbSize)
Эта функция вызывается системой CF, чтобы получить текущий шрифт объекта. Параметры: mv _far *mV указатель на структуру mv. Возвращаемое значение: TRUE если все хорошо, иначе FALSE в случае ошибки. Замечание: Вы должны сохранить LOGFONT в своей структуре EDITDATA. Эта функция должна всего лишь копировать эту структуру из EDITDATA. Пример: проект шаблона содержит пример такой функции. Вы должны возвратить TEXT_FONT в функции GetTextCaps, чтобы вызывалась функция GetTextFont. void WINAPI InitParameter(mv* mV, short code, paramExt* pExt) Инициализирует новый параметр. Параметры: mv* mV указатель на структуру mv, содержащую данные о приложении. Возвращаемое значение: отсутствует. Замечания: эта функция вызывается, когда пользователь выбирает действие (action), содержащее Ваш новый параметр. Параметр pExt указывает на структуру paramExt, которая содержит Ваш новый параметр. Вы должны записать свои данные в поля pExt->pextData. И вы должны записать новый размер структуры в поле pExt->pextSize. Общий размер, который Вы можете использовать, равен PARAM_EXTMAXSIZE. Система CF выдаст ошибку, если Вы превысите это значение. BOOL WINAPI DLLExport IsPropEnabled(LPMV mV, LPEDATA edPtr, UINT nPropID) Эта функция вызывается системой CF, чтобы узнать, разрешено свойство или нет. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: TRUE, если свойство разрешено, иначе FALSE. Замечания: если Вы не реализуете эту функцию, то все свойства будут разрешены. BOOL WINAPI DLLExport IsTransparent(mv _far *mV, fpLevObj loPtr, LPEDATA edPtr, int dx, int dy) Подпрограмма IsTransparent вызывается системой CF, когда указатель мыши перемещается через одну из копий объекта расширения в редакторе фрейма. Эта подпрограмма показывает, является ли эта точка прозрачной. Если объект прозрачный, то клик мыши выберет объект, который лежит ниже прозрачного объекта. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: TRUE, если точка прозрачна, FALSE если непрозрачна. Замечания: используйте эту подпрограмму, если хотите создать очень точный объект. int WINAPI DLLExport MakeIconEx (mv _far *mV, cSurface* pIconSf, LPTSTR lpName, fpObjInfo oiPtr, LPEDATA edPtr) Подпрограмма MakeIconEx рисует на поверхности (surface) иконку, когда отображается объект в заголовочной полосе редактора событий. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: 0 если все в порядке, и любое не нулевое значение, показывающее, что произошла ошибка. Замечания: эта функция должна загрузить или нарисовать иконку объекта в поверхность pIconSf. Вы можете поменять размер поверхности, система CF уменьшит её до правильного размера, если это необходимо. CF использует иконки размером 32 x 32 точек. Старые версии этой функции могли поменять имя через параметр lpName. В этой версии такое не рекомендуется. Эта функция необязательна. По умолчанию она не реализована в шаблоне. Когда эта функция не существует, CF напрямую загружает иконку EXO_ICON из ресурсов расширения и считает, что первый пиксел иконки содержит цвет прозрачности (transparent color). void WINAPI DLLExport PrepareToWriteObject(mv _far *mV, LPEDATA edPtr, fpObjInfo oiPtr) Подпрограмма PrepareToWriteObject вызывается системой CF перед записью структуры редактирования (EDITDATA) на диск, когда сохраняется приложение. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: Вы можете захотеть очистить структуру перед её записью! Структура EDITDATA, которая передается в PrepareToWriteObject, является временной копией структуры EDITDATA объекта, так что Вы можете её очистить без сохранения изменений. void WINAPI DLLExport PutObject(mv _far *mV, fpLevObj loPtr, LPEDATA edPtr, WORD cpt) Подпрограмма PutObject вызывается каждый раз, когда объект бросается на игровое поле фрейма. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: каждый раз, когда один объект бросается на игровое поле, система CF вызывает подпрограмму PutObject. Параметр cpt отражает количество одинаковых объектов на фрейме (одинаковые объекты все указывают на одну и ту же структуру времени редактирования, edit-time structure, и одну и ту же структуру OI). Вам может потребоваться загрузить некоторые данные для первого объекта. Пример: в действительности разработчики CF нигде не использует эту подпрограмму! void WINAPI DLLExport ReleasePropCreateParam(LPMV mV, LPEDATA edPtr, UINT nPropID, LPARAM lCreateParam); Эта функция вызывается системой CF после завершения использования пользовательского параметра. Вы должны использовать эту функцию для освобождения памяти, если Вы выделили её в функции GetPropCreateParam. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: отсутствует. Замечания: реализуйте эту функцию только если Вы выделяете память в функции GetPropCreateParam. Эта функция позволяет Вам безопасно освободить память, когда она больше не используется. void WINAPI DLLExport ReleaseProperties(LPMV mV,
LPEDATA edPtr,
BOOL bMasterItem)
Система CF вызывает эту подпрограмму, когда свойства объекта удаляются из окна свойств (Property window). Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: отсутствует. Замечания: Вы можете использовать эту подпрограмму для освобождения любой памяти или чего-нибудь, что было выделено Вами в GetProperties. void WINAPI DLLExport RemoveObject(mv _far *mV, fpLevObj loPtr, LPEDATA edPtr, ushort cpt) Подпрограмма RemoveObject вызывается каждый раз, когда объект удаляется из фрейма. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: подпрограмма RemoveObject является антиподом PutObject. Каждый раз, когда объект удаляется из фрейма, CF вызывает подпрограмму RemoveObject. Параметр cpt отражает количество одинаковых объектов, оставшихся на фрейме (все одинаковые объекты указывают на одну и ту же структуру времени редактирования, edit-time structure, и одну и ту же структуру OI). Значение параметра cpt=1 означает, что Вы удаляете последний объект, так что может понадобиться освободить некоторые данные. Пример: в действительности разработчики CF никогда не используют эту подпрограмму! BOOL WINAPI DLLExport SetEditSize(LPMV mv, LPEDATA edPtr, int cx, int cy) Эта функция вызывается системой CF, когда модифицируется размер объекта в редакторе фрейма. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: TRUE, если размер был изменен. Замечание: эта функция заменяет старое значение MODIF_SIZE в подпрограмме ModifyObject предыдущих версий SDK. Если эта функция присутствует, то система CF подразумевает, что Ваш объект может менять размеры. Если этой функции нет, то соответственно CF подразумевает, что Ваш размер не может менять размеры. void WINAPI DLLExport SetPropCheck(LPMV mV, LPEDATA edPtr,
UINT nPropID, BOOL nCheck)
Эта функция вызывается системой CF, когда пользователь поменял галочку в свойствах объекта. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: отсутствует. Замечания: эта функция является антиподом GetPropCheck. Вам нужно сохранить состояние свойства в своей структуре EDITDATA. Пример: пример этой функции можно найти в проекте Template. void WINAPI DLLExport SetPropValue(LPMV mV, LPEDATA edPtr,
UINT nPropID, LPVOID lParam)
Эта функция вызывается системой CF для изменения значения свойства, когда пользователь изменил свойства на экране. Параметры: LPMV mV указатель на структуру mV. Возвращаемое значение: отсутствует. Замечания: тип CPropValue, сохраняемый в lParam, зависит от типа свойства. Чтобы получить эти данные, Вам нужно сделать приведение типа (cast) параметра lParam в один из классов CPropValue. Пример: DWORD myDWordValue = ((CPropDWordValue*)lParam)->m_dwValue; float myFloatValue = ((CPropFloatValue*)lParam)->m_fValue; LPCTSTR myStringPointer = ((CPropStringValue*)pValue)->GetString(); Пример: void WINAPI DLLExport SetPropValue(LPMV mV, LPEDATA edPtr, UINT nPropID, LPVOID lParam) { // Получение указателя на структуру CPropValue: CPropValue* pValue = (CPropValue*)lParam; LPEDATA pNewPtr; switch (nPropID) { case PROPID_COMBO: // Простая выборка значения: edPtr->nComboIndex = ((CPropDWordValue*)pValue)->m_dwValue; break; case PROPID_COLOR: // Здесь также просто берется значение: edPtr->dwColor = ((CPropDWordValue*)pValue)->m_dwValue; break; case PROPID_TEXT: // Получение строки: LPCTSTR pStr = ((CPropStringValue*)pValue)->GetString(); // Вы можете просто записать строку, если Ваша структура EDITDATA // имеет фиксированный размер, или Вам нужно использовать подстраиваемый // размер структуры, примерно как показано ниже. if (_tcslen(pStr)!=_tcslen(edPtr->text)) { // Если длина отличается, то у CF запрашивается переразмещение // (reallocate) структуры на новый размер: pNewPtr=(LPEDATA)mvReAllocEditData(mV, edPtr, sizeof(EDITDATA)+_tcslen(pStr)*sizeof(TCHAR)); if (pNewPtr!=NULL) { // Если переразмещение сработало, копируем строку: edPtr=pNewPtr; _tcscpy(edPtr->text, pStr); } } else { // Одинаковый размер: простое копирование: _tcscpy(edPtr->text, pStr); } break; } // Вы можете захотеть иметь перерисовку своего объекта в редакторе фрейма // после изменений. В нашем случае просто вызовем эту функцию: mvInvalidateObject(mV, edPtr); } void WINAPI DLLExport SetTextAlignment(mv _far *mV, LPEDATA edPtr, DWORD dwAlignFlags) CF вызывает эту функцию, когда у объекта изменяются флаги выравнивания текста. Параметры: mv _far *mV указатель на структуру mv. TEXT_ALIGN_LEFT Возвращаемое значение: отсутствует. Замечание: эта функция должна сохранить флаги в структуру EDITDATA объекта. Вы должны возвратить флаги выравнивания, поддерживаемые Вашим объектом, в функции GetTextCaps, чтобы функция SetTextAlignment могла быть вызвана. void WINAPI DLLExport SetTextClr(mv _far *mV, LPEDATA edPtr, COLORREF color) Эта функция вызывается системой CF, когда пользователь завершает модификацию цвета шрифта объекта. Параметры: mv _far *mV указатель на структуру mv. Возвращаемое значение: отсутствует. Замечание: эта функция должна просто сохранять цвет в структуре EDITDATA объекта. Пример: пример этой функции можно найти в проекте Template. Вы должны вернуть TEXT_COLOR в функции GetTextCaps, чтобы могла быть вызвана функция SetTextClr. BOOL WINAPI DLLExport SetTextFont(mv _far *mV, LPEDATA edPtr,
LPLOGFONT plf, LPCTSTR pStyle)
Эта функция вызывается системой CF, чтобы изменить шрифт объекта. Параметры: mv _far *mV указатель на структуру mv. Возвращаемое значение: эта функция должна вернуть TRUE, если шрифт был корректно скопирован. Замечания: эта подпрограмма должна просто скопировать LOGFONT в структуру EDITDATA объекта. Пример: проект Template содержит пример для такой функции. Вы должны возвратить TEXT_FONT в функции GetTextCaps, чтобы могла быть вызвана функция SetTextFont. BOOL WINAPI DLLExport UsesFile(mv _far *mV, LPCTSTR fileName)
Система CF вызывает подпрограмму UsesFile, когда пользователь бросает файл в редактор фрейма, чтобы узнать, поддерживает ли расширение этот файл. Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: TRUE, если расширение поддерживает этот файл. Замечания: если UsesFile вернет TRUE, то CF добавляет расширение в список объектов, которые можно создать из этого файла. Если пользователь выбирает это расширение, то CF вызывает функцию CreateFromFile для создания расширения. Функция CreateObject не вызывается, так что Вы должны дублировать любую инициализацию из CreateObject, если это необходимо. Пример: BOOL WINAPI DLLExport UsesFile (LPMV mV, LPCTSTR fileName) { BOOL r = FALSE; // Пример возвращает TRUE, если расширение файла ".txt". TCHAR ext[_MAX_EXT]; if ( fileName != NULL ) { _tsplitpath(fileName, NULL, NULL, NULL, ext); if ( _tcsicmp(ext, ".txt") == 0 ) r = TRUE; } return r; } Подпрограммы режима run-time: short WINAPI DLLExport ContinueRunObject(LPRDATA rdPtr)
Подпрограмма ContinueRunObject перезапускает объект после паузы. Параметры: LPRDATA rdPtr указатель на структуру run-time. Возвращаемое значение: функция должна вернуть 0. Замечания: подпрограмма ContinueRunObject вызывается, когда пользователь завершает режим паузы. Это должно перезапустить любой эффект, остановленный функцией PauseRunObject. short WINAPI DLLExport CreateRunObject(LPRDATA rdPtr, LPEDATA edPtr, fpcob cobPtr)
Подпрограмма CreateRunObject создает объект во время работы приложения (run-time). Параметры: LPRDATA rdPtr указатель на run-time структуру объекта, резервированную системой CF. Эта структура всегда обнуляется. Возвращаемое значение: 0, если объект создан успешно, !=0 если создание было неудачным. Замечания: эта подпрограмма вызывается только 1 раз для каждого объекта. Могут быть безопасно проведены выделения памяти, которые будут уничтожены в функции DestroyRunObject. CreateRunObject формирует связь между структурой редактирования EDITDATA и структурой кода реального времени (run-time structure) RUNDATA. В этой функции Вы должны скопировать все необходимые элементы из структуры редактирования в структуру run-time. У Вас не будет доступа к структуре редактирования, когда работает приложение (run-time). По большей части Вы свободны делать в этой функции все, что захотите. Однако Вы здесь не можете записывать в экран. Любые графические операции должны быть реализованы в подпрограмме DisplayRunObject. Если CreateRunObject терпит сбой, то все равно будет вызвана функция DestroyRunObject. Если Вы не определили подпрограмму GetZoneInfo, то должны установить поля rdPtr->rHo.hoImgWidth, rdPtr->rHo.hoImgHeight, rdPtr->rHo.hoImgXSpot и rdPtr->rHo.hoImgYSpot своего объекта, чтобы получить корректное отображение. short WINAPI DLLExport DestroyRunObject(LPRDATA rdPtr, long fast) Подпрограмма DestroyRunObject удаляет объект во время работы приложения (run-time). Параметры: LPRDATA rdPtr указатель на run-time структуру объекта. Возвращаемое значение: эта функция всегда должна возвращать 0. Замечания: не беспокойтесь по поводу флага fast, это автоматически обрабатывается системой CF. Эта подпрограмма должна удалить любые выделения памяти, произошедшие за время жизни объекта, и оставить место чистым, как все было в перед созданием объекта. Эта подпрограмма вызывается только 1 раз для каждого объекта. Она также вызывается, если CreateRunObject не может создать объект. short WINAPI DLLExport DisplayRunObject(LPRDATA rdPtr)
Подпрограмма DisplayRunObject рисует объект на экране. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: эта функция должна возвратить 0. Замечания: только подпрограмма DisplayRunObject рисует объекты на экране. В этой статье Вы найдете больше информации о том, как рисовать на экране CF с помощью функций MMFS2.DLL. Для этой цели Вы не можете использовать API-функции Windows GetDC и ReleaseDC, Вы должны использовать функции cSurface. Если Ваш объект в действительности не отрисовывается на экране, но является окном, например, то Вы должны использовать функцию DisplayRunObject для изменения размера и позиции окна. Эти параметры не должны быть изменены посередине подпрограмм действия (action routines), за исключением случаев, когда Вам реально требуется непосредственное перемещение. void WINAPI DLLExport EditDebugItem(LPRDATA rdPtr, int id) Эта функция вызывается во время работы программы (runtime), когда пользователь выбрал редактирование отлаживаемого элемента в окне отладки (debugging screen). Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: эта функция может решить открыть окно диалога для редактирования параметра, или сделать то, что хочет. Приложение ставится на паузу, когда вызывается эта функция, так что Вы можете не торопиться. Вы также можете использовать две callback-функции, которые будут редактировать это для Вас. Для текста: callRunTimeFunction(rdPtr, RFUNCTION_EDITTEXT, 0, (LPARAM)&dbi); И для числа: long ret=callRunTimeFunction(rdPtr, RFUNCTION_EDITINT, 0, (LPARAM)&dbi); Пример: Вы найдете пример реализации в проекте Template. void WINAPI DLLExport EndApp(mv *mV, CRunApp* pApp) Эта функция вызывается только 1 раз для каждого расширения, когда приложение закрывается. Параметры: mv *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: EndApp не вызывается, когда приложение перезапускается (действием Restart Application). Если Ваш объект использует глобальные данные, сохраненные в пользовательских данных расширения, то здесь Вы должны их освободить. Пример: CMyData* pData = (CMyData*)mV->mvGetExtUserData(pApp, hInstLib); if ( pData != NULL ) { delete pData; mV->mvSetExtUserData(pApp, hInstLib, NULL); } Здесь hInstLib это HINSTANCE расширения. void WINAPI DLLExport EndFrame(mv *mV, CRunApp* pApp, int nFrame) Эта функция вызывается только один раз для каждого расширения, когда завершается фрейм. Параметры: mv *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: EndFrame не вызывается, когда перезапускается фрейм (через действие Restart Frame). void WINAPI DLLExport GetDebugItem(LPTSTR pBuffer, LPRDATA rdPtr, int id) Эта функция вызывается во время работы приложения (runtime) чтобы узнать значение одного из отлаживаемых элементов. Параметры: LPTSTR pBuffer указатель на текстовый буфер длиной DB_BUFFERSIZE, в который Вам нужно поместить текст для отображения на экране отладчика (debugger screen). Замечания: просто вставьте строку для отображения, это может быть все что угодно от числа (в виде ASCII) до текста. Учитывайте размер буфера. LPWORD WINAPI DLLExport GetDebugTree(LPRDATA rdPtr) Эта подпрограмма вызывается во время работы приложения (runtime), чтобы получить список отлаживаемых элементов (debugger items). Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: указатель на массив, содержащий определение дерева отладчика (debugger tree). short WINAPI DLLExport GetZoneInfo(LPRDATA rdPtr)
Подпрограмма GetZoneInfo вычисляет текущий размер объекта для сохранения фона. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: должно быть возвращено TRUE. Замечания: нужно использовать эту подпрограмму только если меняются размер и горячие точки (hot spots) Вашего объекта. Если эта функция определена, то она вызывается непосредственно перед процессом сохранения фона, и Вы должны обновить поля rdPtr->rHo.hoImgWidth, rdPtr->rHo.hoImgHeight, rdPtr->rHo.hoImgXSpot и rdPtr->rHo.hoImgYSpot в зоне данных run-time объекта в текущий размер. Эти значения используются немедленно (как и rdPtr->rHo.hoX, rdPtr->rHo.hoY) для вычисления размера экрана для сохранения в буфер. WORD WINAPI DLLExport GetRunObjectDataSize(LPRH rhPtr, LPEDATA edPtr) Подпрограмма GetRunObjectDataSize возвращает размер run-time структуры. Параметры: LPRH rhPtr указатель главную run-time структуру CF. Возвращаемое значение: эта подпрограмма должна вернуть полный размер Вашего объекта, с которым он будет работать. Замечания: эта подпрограмма вызывается непосредственно перед тем, как объект будет создан. Обычно каждый возвращает размер run-time структуры RUNDATA, но Вам может понадобится другой размер для сохранения строк или массивов значений. void WINAPI GetRunObjectFont(LPRDATA rdPtr, LOGFONT* pLf) Функция GetRunObjectFont возвратит LOGFONT, содержащий текущий шрифт, используемый объектом. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: отсутствует. Замечания: эта подпрограмма вызывается только в том случае, когда установлен флаг OEFLAG_TEXT. Она должна скопировать LOGFONT текущего шрифта, используемого объектом, по указателю LOGFONT, который передан на входе через параметр. Если в Вашей структуре RUNDATA нет LOGFONT, то Вы можете использовать функцию GetObject из Windows API, чтобы преобразовать HFONT в LOGFONT. short WINAPI DLLExport GetRunObjectInfos(mv _far *mV, fpKpxRunInfos infoPtr) Подпрограмма GetRunOjbectInfos возвращает информацию о run-time флагах объекта, размер структур времени редактирования (edit-time structures), условия (conditions) и действия (actions). Параметры: mv _far *mV указатель на информационную структуру mv. Возвращаемое значение: TRUE если все хорошо, FALSE если обнаружена ошибка. Замечания: как использовать эту подпрограмму показано в проекте Template, Вы можете скопировать её целиком, она работает нормально, и код интуитивно понятен. COLORREF WINAPI GetRunObjectTextColor( LPRDATA rdPtr) Функция GetRunObjectTextColor возвращает текущий цвет шрифта, используемого в объекте. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: значение RGB, содержащее текущий цвет текста. Замечания: эта подпрограмма вызывается только тогда, когда установлен флаг OEFLAG_TEXT. Просто возвратите текущий цвет текста, используемого в Вашем объекте, как значение COLORREF. short WINAPI DLLExport HandleRunObject(LPRDATA rdPtr)
Подпрограмма HandleRunObject вызывается каждые 1/50 секунды, когда работает приложение (если в Вашем приложении есть скорость обновления фреймов 50 fps). Эта подпрограмма обрабатывает каждую задачу, которую выполняет объект. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: может быть возвращено значение, состоящее из одного или большего количества следующих флагов (объединенных операцией ИЛИ): REFLAG_ONESHOT показывает, что подпрограмма больше не может быть вызвана. Замечания: флаг REFLAG_ONESHOT обычно используется для объектов, где HandleRunObject ничего не делает, и это экономит процессорное время приложения. Вы не должны использовать этот флаг с объектом, определенным с флагом OEFLAG_MOVEMENT (т. е. с объектом, у которого есть перемещение). Будучи удаленной из списка вызовов, подпрограмма HandleRunObject может быть вставлена туда повторно (например, действием, которое модифицирует объект) с использованием последовательности: callRunTimeFunction(rdPtr, RFUNCTION_REHANDLE, 0, 0); HandleRunObject не должна ничего рисовать на экране. Чтобы записать что-либо в экран, Вы должны использовать подпрограмму DisplayRunObject. Используйте HandleRunObject, чтобы показать для CF, что подпрограмма Display должна быть вызвана с использованием флага REFLAG_DISPLAY. Если Вы не используете этот флаг, и если объект не перемещается, то подпрограмма отображения никогда не будет вызвана. Вы можете захотеть использовать эту возможность для объектов, которые ничего не отображают, наподобие объекта INI. Другой способ для принудительной перерисовки из подпрограммы действия, это вызов: callRunTimeFunction(rdPtr, RFUNCTION_REDRAW, 0, 0); short WINAPI DLLExport KillBackground ( LPRDATA rdPtr )
Подпрограмма KillBackground уничтожает буфер памяти, используемый для сохранения области экрана, находящейся за объектом. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: должен быть возвращен 0. Замечания: эта подпрограмма должна вызываться только если установлены флаги OEFLAG_BACKSAVE и OEFLAG_INTERNALBACKSAVE. Эта подпрограмма должна проверять, что область памяти действительно была зарезервирована, и только в этом случае область памяти должна быть уничтожена. BOOL WINAPI DLLExport LoadRunObject(LPRDATA rdPtr, HANDLE hf) Подпрограмма LoadRunObject вызывается системой CF из действия Load Frame Position или Load Application Position ("загрузить позицию фрейма" или "загрузить позицию приложения"). Загружаемые данные сохранены в SaveRunObject, чтобы восстановить состояние объекта. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: возвратит TRUE, если функция успешно загрузила данные, или FALSE, если произошла ошибка. Ниже показан пример простых подпрограмм загрузки и сохранения (Load & Save routines): // -----------------
// SaveRunObject
// -----------------
// Сохраняет объект на диск
//
// Это номер версии, он должен быть изменен, если содержимое структуры поменялось:
#define SAVEVERSION_CURRENT 1
// Структура для сохранения на диск:
typedef struct tagSaveCB { DWORD dwVersion; DWORD dwFlags; }SaveCB; BOOL WINAPI SaveRunObject(LPRDATA rdPtr, HANDLE hf)
{
BOOL bOK = FALSE;
#ifndef VITALIZE SaveCB save; DWORD written; while(TRUE) { save.dwVersion = SAVEVERSION_CURRENT; save.dwFlags = rdPtr->dwFlags; if ( WriteFile(hf, &save, sizeof(SaveCB), &written, NULL) == 0 ) break; bOK = TRUE; break; } #endif // VITALIZE return bOK;
}
// -----------------
// LoadRunObject
// -----------------
// Загружает объект с диска
// BOOL WINAPI LoadRunObject(LPRDATA rdPtr, HANDLE hf) { BOOL bOK = FALSE; SaveCB save; DWORD read; while(TRUE) { if (ReadFile(hf, &save, sizeof(SaveCB), &read, NULL) == 0 || read < sizeof(SaveCB)) break; if (save.dwVersion != SAVEVERSION_CURRENT) break; rdPtr->dwFlags = save.dwFlags; bOK = TRUE; break; } return bOK;
}
short WINAPI DLLExport PauseRunObject(LPRDATA rdPtr)
Подпрограмма PauseRunObject временно останавливает объект, когда приложение входит в режим паузы (pause mode). Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: должен быть возвращен 0. Замечания: если Ваш объект выполняет задачу, основанную на таймере, или выводит какой-то звук, то Вы должны приостановить это действие в подпрограмме PauseRunObject. Есть несколько способов войти в pause mode: • Пользователь нажал CONTROL + P. short WINAPI DLLExport RestoreBackground ( LPRDATA rdPtr )
Подпрограмма RestoreBackground восстанавливает экран, который был заблокирован наподобие ситуации перед отрисовкой объекта. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: должен быть возвращен 0. Замечания: эта подпрограмма вызывается только если были установлены флаги OEFLAG_BACKSAVE и OEFLAG_INTERNALBACKSAVE. Она должна проверять, что буфер памяти был зарезервирован в предыдущем цикле. Если это произошло, то сохраненная на предыдущем цикле часть экрана должна быть восстановлена. Предупреждение: не используйте hoX и hoY для восстановления области экрана, hoX и hoY содержат новые координаты объекта. Поэтому Вы должны сохранить эти координаты (в SaveBackground), как и порцию экрана, и использовать эти сохраненные координаты, когда восстанавливаете фон. short WINAPI DLLExport SaveBackground ( LPRDATA rdPtr )
Подпрограмма SaveBackground сохраняет область экрана объекта в буфер памяти. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: должен быть сохранен 0. Замечания: эта подпрограмм вызывается только если установлены флаги OEFLAG_BACKSAVE и OEFLAG_INTERNALBACKSAVE. Если установлены эти 2 флага, то перед любым вызовом DisplayRunObject система CF вызывает подпрограмму SaveBackground. В этой подпрограмме Вы должны зарезервировать буфер памяти достаточного размера, чтобы он мог содержать порцию экрана, покрываемую объектом, и копировать содержимое этой области в эту подпрограмму. BOOL WINAPI DLLExport SaveRunObject(LPRDATA rdPtr, HANDLE hf) Подпрограмм SaveRunObject вызывается системой CF из действия Save Frame Position (сохранение позиции фрейма). Сохраните данные объекта, чтобы его состояние могло быть восстановлено из действия Load Frame/Application Position. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: TRUE, если функция успешно сохранила данные, или FALSE, если произошла ошибка. Ниже показан простой пример подпрограмм загрузки и сохранения (Load & Save): // -----------------
// SaveRunObject
// -----------------
// Сохраняет объект на диск
//
// Это номер версии, он должен быть изменен, если содержимое структуры поменялось:
#define SAVEVERSION_CURRENT 1
// Структура для сохранения на диск:
typedef struct tagSaveCB { DWORD dwVersion; DWORD dwFlags; }SaveCB; BOOL WINAPI SaveRunObject(LPRDATA rdPtr, HANDLE hf) { BOOL bOK = FALSE; #ifndef VITALIZE
SaveCB save;
DWORD written;
while(TRUE) { save.dwVersion = SAVEVERSION_CURRENT; save.dwFlags = rdPtr->dwFlags; if ( WriteFile(hf, &save, sizeof(SaveCB), &written, NULL) == 0 ) break; bOK = TRUE; break; } #endif // VITALIZE return bOK; } // -----------------
// LoadRunObject
// -----------------
// Загружает объект с диска
// BOOL WINAPI LoadRunObject(LPRDATA rdPtr, HANDLE hf) { BOOL bOK = FALSE; SaveCB save; DWORD read; while(TRUE) { if ( ReadFile(hf, &save, sizeof(SaveCB), &read, NULL) == 0 || read < sizeof(SaveCB)) break; if ( save.dwVersion != SAVEVERSION_CURRENT ) break; rdPtr->dwFlags = save.dwFlags; bOK = TRUE; break; } return bOK; } void WINAPI SetRunObjectFont( LPRDATA rdPtr, LOGFONT* pLf, RECT* pRect) Функция SetRunObjectFont вызывается, когда приложение хочет поменять шрифт объекта. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: отсутствует. Замечания: эта подпрограмма вызывается, только если установлен флаг OEFLAG_TEXT. Эта подпрограмма вызывается, когда приложение хочет изменить аспект шрифта, используемого объектом. Эта функция должна использовать LOGFONT, переданный как параметр, для изменения шрифта, используемого объектом, принудительной перерисовки объекта. Параметр pRect вызывается, когда визуальный элемент управления меняет размер, когда поменялся размер шрифта. Он может быть NULL, в таком случае не будет осуществляться изменение размера. Если он не NULL, то поля pRect->right и pRect->bottom содержат новый размер объекта. Ваш объект тогда должен поменять следующие поля в структуре headerObject: hoImgWidth, hoImgHeight, hoRect.right, hoRect.bottom, и конечно поменять размер окна, если объектом является элемент управления. COLORREF WINAPI SetRunObjectTextColor( LPRDATA rdPtr, COLORREF rgb) Функция GetRunObjectTextColor вызывается, когда пользователь хочет поменять цвет текста, отображаемого объектом. Параметры: LPRDATA rdPtr указатель на run-time структуру. Возвращаемое значение: отсутствует. Замечания: эта подпрограмма вызывается только если установлен флаг OEFLAG_TEXT. Просто поменяйте цвет Вашего текста в соответствии со значением rgb. void WINAPI DLLExport StartApp(mv *mV, CRunApp* pApp) Функция StartApp вызывается только один раз для каждого расширения, когда приложение запускается и перезапускается. Параметры: mv* mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: если Ваш объект использует глобальные данные, сохраненные в пользовательских данных расширения в приложении, то Вы должны здесь инициализировать их или освободить. Пример: CMyData* pData = (CMyData*)mV->mvGetExtUserData(pApp, hInstLib); if ( pData != NULL ) { delete pData; mV->mvSetExtUserData(pApp, hInstLib, NULL); } Здесь hInstLib это HINSTANCE расширения. void WINAPI DLLExport StartFrame(mv *mV, CRunApp* pApp, int nFrame) Эта функция вызывается только 1 раз для каждого расширения, когда фрейм запускается или перезапускается. Параметры: mv *mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: если Ваш объект использует глобальные данные, сохраненные по пользовательских данных расширения в приложении, то Вы должны сделать здесь их копию, так чтобы смогли потом восстановить эти данные, если фрейм перезапустится. LRESULT CALLBACK DLLExport WindowProc(LPRH rhPtr, HWND hWnd, UINT msgType, WPARAM wParam, LPARAM lParam) Когда флаг OEFLAG_WINDOWPROC установлен, и код runtime получает сообщение для основного окна или дочернего окна, система CF вызывает подпрограмму WindowProc перед вызовом оконной процедуры основного или дочернего окна. Параметры: LPRH rhPtr указатель главную run-time структуру RunHeader системы CF. Возвращаемое значение: если 0, то сообщение не было обработано, и должно быть передано оконной процедуре фрейма. Другие значения: REFLAG_MSGHANDLED сообщение немедленно остановлено, и в Windows возвращено 0L. Замечания: подпрограмма WindowProc вызывается, только когда установлен флаг OEFLAG_WINDOWPROC. Если Вы открываете окно управления как дочерний объект окна фрейма, и хотите обработать оповещающие сообщения в процедуре WindowProc, мы советуем установить хук (см. "How to control a window from an extension"), чтобы Вы могли проще восстановить адрес структуры RUNDATA, контролирующей это окно из хендла. Эта функция должна проверить статус паузы и не должна отвечать на каждое сообщение, если приложение поставлено на паузу: // Если пауза, то выход:
if (rhPtr->rh2.rh2PauseCompteur != 0) return 0; Например, в режиме паузы расширение должно отвечать на сообщения палитры, если это необходимо, но не на сообщения WM_COMMAND или CLICK. Примеры: Вы найдете много примеров подпрограммы WindowProc в исходных кодах EDIT и StaticText этого extension kit. [Callback-функции] Система CF предоставляет для расширения способ вызова своей собственной внутренней функции. Эти функции называются функциями обратного вызова, "Callback-функции". Система CF предлагает набор полезных функций как для edit-time, так и для run-time. Эта глава документации поделена на 2 соответствующих раздела: • Список подпрограмм edit-time Функции обратного вызова edit-time. Эти callback-функции доступны через указатель на структуру mv, которая передается почти каждой edit-time функции. Пожалуйста обратитесь к описанию структуры mv для получения дополнительной информации. BOOL (CALLBACK * mvEditAnimation) (LPVOID edPtr, LPEDITANIMATIONPARAMS pParams,
HWND hParent)
Эта функция откроет редактор изображения (CF picture editor), чтобы редактировать список изображений, содержащихся в банке картинок приложения. Параметры: LPVOID edPtr указатель на структуру EDITDATA. typedef struct EditAnimationParams { DWORD m_dwSize; // sizeof(EditImageParams) LPTSTR m_pWindowTitle; // заголовок Picture Editor (NULL заголовок по умолчанию) int m_nImages; // количество изображений в списке int m_nMaxImages; // максимальное количество изображений в списке int m_nStartIndex; // индекс первого изображения для изменения в редакторе LPWORD m_pImages; // список изображений (по одному слову WORD на изображение) LPTSTR* m_pImageTitles; // заголовки к изображениям (может быть NULL) DWORD m_dwOptions; // опции, см. PictEdDefs.h DWORD m_dwFixedWidth; // ширина по умолчанию или фиксированная ширина // (если используется PICTEDOPT_FIXEDIMGSIZE) DWORD m_dwFixedHeight; // высота по умолчанию или фиксированная высота // (если используется PICTEDOPT_FIXEDIMGSIZE) } EditAnimationParams; m_dwOptions могут быть одной или большим количеством одновременно указанных опций: PICTEDOPT_FIXEDIMGSIZE // пользователь не может поменять размер изображения PICTEDOPT_HOTSPOT // пользователь может редактировать горячую точку (hot spot) PICTEDOPT_ACTIONPOINT // пользователь может редактировать точку действия (action point) PICTEDOPT_16COLORS // 16-цветное изображения, палитра Windows PICTEDOPT_FIXEDNFRAMES // пользователь не может добавлять / удалять фреймы PICTEDOPT_NOTRANSPARENCY // нет цвета прозрачности PICTEDOPT_NOALPHACHANNEL // нет канала альфа PICTEDOPT_CANBETRANSPARENT // анимация может быть пуста (только прозрачные изображения). // Если эта опция не указана, то CF отклоняет закрытие picture // editor, если анимация пуста. Возвращаемое значение: TRUE, если список изображений был изменен, иначе FALSE. Если список изображений изменен, то m_pImages содержит новые идентификаторы изображений и m_nImages содержит новое количество изображений. Замечания: если Ваша структура EDITDATA содержит изображения, то Вы должны реализовать функцию EnumElts. Пожалуйста обратитесь к главе "Библиотека MMFS2" в этой документации для получения дополнительной информации про изображения. Пример: LPTSTR imageTitles[] = { _T("Normal"), _T("Disabled") NULL }; EditAnimationParams eip; eip.m_dwSize = sizeof(EditAnimationParams); eip.m_pWindowTitle = NULL; eip.m_nImages = 2; eip.m_nMaxImages = 2; eip.m_nStartIndex = 0; eip.m_pImages = &edPtr->wImage[0]; eip.m_pImageTitles = imageTitles; eip.m_dwImage = edPtr->wImage; eip.m_dwOptions = PICTEDOPT_FIXEDNFRAMES | PICTEDOPT_FIXEDIMGSIZE; eip.m_dwFixedWidth = 24; eip.m_dwFixedHeight = 20;if ( mV->mvEditImage(edPtr, &eip, mV->mvHEditWin) ) { ; } BOOL (CALLBACK * mvEditImage) (LPVOID edPtr, LPEDITIMAGEPARAMS pParams,
HWND hParent)
Эта функция открывает редактор изображений (CF picture editor) для редактирования картинки, содержащейся в банке изображений приложения. Параметры: LPVOID edPtr указатель на структуру EDITDATA. typedef struct EditImageParams { DWORD m_dwSize; // sizeof(EditImageParams) LPTSTR m_pWindowTitle; // заголовок Picture Editor (NULL заголовок по умолчанию) DWORD m_dwImage; // картинка для редактирования. Замечание: в этой версии // используется только LOWORD (младшее слово). DWORD m_dwOptions; // опции, см. PictEdDefs.h DWORD m_dwFixedWidth; // ширина по умолчанию или фиксированная ширина // (если используется PICTEDOPT_FIXEDIMGSIZE) DWORD m_dwFixedHeight; // высота по умолчанию или фиксированная высота // (если используется PICTEDOPT_FIXEDIMGSIZE) } EditImageParams; m_dwOptions могут быть одной или большим количеством одновременно указанных опций: PICTEDOPT_FIXEDIMGSIZE // пользователь не может поменять размер изображения PICTEDOPT_HOTSPOT // у изображения есть горячая точка (hot spot) PICTEDOPT_ACTIONPOINT // у изображения есть точка действия (action point) PICTEDOPT_16COLORS // 16-цветное изображения, палитра Windows PICTEDOPT_NOTRANSPARENCY // нет цвета прозрачности PICTEDOPT_NOALPHACHANNEL // нет канала альфа PICTEDOPT_CANBETRANSPARENT // анимация может быть пуста. Если эта опция не указана, // то CF отклоняет закрытие picture editor, // если анимация пуста. Возвращаемое значение: TRUE, если изображение было изменено, иначе FALSE. Если изображение было изменено, то m_dwImage содержит новый идентификатор изображения. Замечания: если Ваша структура EDITDATA содержит картинки, то Вы должны реализовать функцию EnumElts. Чтобы добавить картинку в банк изображений (CF image bank), Вы можете использовать функции DibToImage и DibToImageEx. Пожалуйста обратитесь к главе "Библиотека MMFS2" в этой документации для получения дополнительной информации по поводу картинок. Пример: EditImageParams eip; eip.m_dwSize = sizeof(EditImageParams); eip.m_pWindowTitle = NULL; eip.m_dwImage = edPtr->wImage; eip.m_dwOptions = 0; eip.m_dwFixedWidth = 100; eip.m_dwFixedHeight = 100;if ( mV->mvEditImage(edPtr, &eip, mV->mvHEditWin) ) { edPtr->wImage = LOWORD(eip.m_dwImage); } BOOL (CALLBACK * mvEditSurface) (LPVOID edPtr, LPEDITSURFACEPARAMS pParams,
HWND hParent)
Эта функция открывает редактор изображений (CF picture editor) для редактирования поверхности (surface). Параметры: LPVOID edPtr указатель на структуру EDITDATA. typedef struct EditSurfaceParams { DWORD m_dwSize; // sizeof(EditImageParams) LPTSTR m_pWindowTitle; // заголовок Picture Editor (NULL заголовок по умолчанию) cSurface* m_pSf; // поверхность для редактирования DWORD m_dwOptions; // опции, см. PictEdDefs.h DWORD m_dwFixedWidth; // ширина по умолчанию или фиксированная ширина // (если используется PICTEDOPT_FIXEDIMGSIZE) DWORD m_dwFixedHeight; // высота по умолчанию или фиксированная высота // (если используется PICTEDOPT_FIXEDIMGSIZE) POINT m_hotSpot; // координаты горячей точки POINT m_actionPoint; // координаты точки действия } EditSurfaceParams; m_dwOptions могут быть одной или большим количеством одновременно указанных опций: PICTEDOPT_FIXEDIMGSIZE // пользователь не может поменять размер изображения PICTEDOPT_HOTSPOT // у изображения есть горячая точка (hot spot) PICTEDOPT_ACTIONPOINT // у изображения есть точка действия (action point) PICTEDOPT_16COLORS // 16-цветная поверхность, палитра Windows // (фактически 256-цветная поверхность с 16x16 // цветовой палитрой) PICTEDOPT_NOTRANSPARENCY // нет цвета прозрачности PICTEDOPT_NOALPHACHANNEL // нет канала альфа PICTEDOPT_CANBETRANSPARENT // поверхность может быть пуста (иначе CF будет отклонять // закрытие picture editor) Возвращаемое значение: TRUE, если изображение было изменено, иначе FALSE. Указатель m_pSf не поменяется (если функция возвратит TRUE, то только содержимое поверхности было изменено). Пример: EditSurfaceParams eip; eip.m_dwSize = sizeof(EditSurfaceParams); eip.m_pWindowTitle = NULL; eip.m_pSf = pSf; eip.m_dwOptions = 0; eip.m_dwFixedWidth = 100; eip.m_dwFixedHeight = 100; eip.m_hotSpot.x = 0; eip.m_hotspot.y = 0; eip.m_actionPoint.x = 0; eip.m_actionPoint.y = 0;if ( mV->mvEditSurface(edPtr, &eip, mV->mvHEditWin) ) { ; } BOOL (CALLBACK * mvGetDefaultFont) (LPLOGFONT pLogFont, LPTSTR pStyle, int size) Эта функция возвращает информацию о шрифте по умолчанию, используемому в редакторе фрейма (frame editor). Параметры: LPLOGFONT pLogFont указатель на структуру LOGFONT, где будет скопирована информация. Возвращаемое значение: эта функция вернет TRUE, если информация достоверна, иначе FALSE. Замечание: эта функция должна использоваться для инициализации Вашего объекта в функции CreateObject, если Ваш объект содержит текст. DWORD (CALLBACK * mvGetVersion) ()
Эта функция возвращает текущую версию системы CF. Возвращаемое значение: DWORD, содержащее номер версии CF. Пример: DWORD dwVersion = mV->mvGetVersion(); if ( (dwVersion & MMFVERSION_MASK) == MMFVERSION_25 ) ; // CF 2.5 if ( (dwVersion & MMFVERSION_PRO) != 0 ) ; // CF 2.5 Developer int nBuildNumber = (dwVersion & MMFBUILD_MASK); void ( CALLBACK * mvHelp) (LPCTSTR hlpFileName, UINT contextId, LPARAM lParam); Используйте эту функцию для открытия Вашего файла подсказки, например из диалога настройки (setup dialog box) Вашего объекта. Параметры: LPCTSTR hlpFileName имя фала подсказки расширения (extension help file). Возвращаемое значение: отсутствует. Замечание: если на Ваш help-файл ссылаются в основном файле справки CF, просто передайте заголовок файла в эту функцию. Пример: mV->mvHelp("MyExt.chm", HH_DISPLAY_TOPIC, (LPARAM)"index.html"); Иначе передайте путь до help-файла относительно директории CF. Пример: mV->mvHelp("Help\\MyExt.chm", HH_DISPLAY_TOPIC, (LPARAM)"index.html"); LRESULT (CALLBACK * mvCallFunction) (LPVOID edPtr, int nFnc, LPARAM lParam1=0, LPARAM lParam2=0, LPARAM lParam3=0) Эта функция фактически набор подпрограмм. Вы можете вызывать эти подпрограммы передачей в подпрограмму mvCallFunction индекса нужной подпрограммы (nFnc) и её параметры (lParam1, и т. д.). Для упрощения этой задачи и для того, чтобы сделать исходный код понятнее, разработчики CF определили по одному макросу на функцию. Параметры: LPVOID edPtr указатель на структуру EDITDATA объекта. Индексы функций: // Только редактор EF_INSERTPROPS, // Вставка свойств в окно Property EF_REMOVEPROP, // Удаление свойства EF_REMOVEPROPS, // Удаление свойств EF_REFRESHPROP, // Обновление свойства EF_REALLOCEDITDATA, // Переразмещение edPtr EF_GETPROPVALUE, // Получение значения свойства объекта EF_GETAPPPROPVALUE, // Получение значения свойства приложения EF_GETFRAMEPROPVALUE, // Получение значения свойства фрейма EF_SETPROPVALUE, // Установка значения свойства объекта EF_SETAPPPROPVALUE, // Установка значения свойства приложения EF_SETFRAMEPROPVALUE, // Установка значения свойства фрейма EF_GETPROPCHECK, // Получение состояния галочки свойства объекта EF_GETAPPPROPCHECK, // Получение состояния галочки свойства приложения EF_GETFRAMEPROPCHECK, // Получение состояния галочки свойства фрейма EF_SETPROPCHECK, // Установка значения свойства галочки объекта EF_SETAPPPROPCHECK, // Установка значения свойства галочки приложения EF_SETFRAMEPROPCHECK, // Установка значения свойства галочки фрейма EF_INVALIDATEOBJECT, // Обновление объекта в редакторе фрейма EF_RECALCLAYOUT, // Перерасчет размещения окон во время работы программы // (recalc runtime layout, докинг) // Редактор и runtime EF_MALLOC, // Выделение памяти EF_CALLOC, // Выделение памяти и установка её в 0 EF_REALLOC, // Перераспределение памяти EF_FREE, // Освобождение памяти Макросы: // Только редактор
mvInsertProps
mvRemoveProp
mvRemoveProps
mvRefreshProp
mvReAllocEditData
mvGetPropValue
mvGetAppPropValue
mvGetFramePropValue
mvSetPropValue
mvSetAppPropValue
mvSetFramePropValue
mvGetPropCheck
mvGetAppPropCheck
mvGetFramePropCheck
mvSetPropCheck
mvSetAppPropCheck
mvSetFramePropCheck
mvInvalidateObject
// Редактор и runtime
mvMalloc
mvCalloc
mvReAlloc
mvFree
Как использовать. Вы можете вызвать нужную функцию вот так: mV->mvCallFunction(edPtr, EF_REFRESHPROP, PROPID_MYPROP, FALSE, 0); или так (mv это указатель на структуру mv): mvRefreshProp(mV, edPtr, PROPID_MYPROP, FALSE); LPVOID mvCalloc(LPMV mV, int nSize)
Выделяет буфер в памяти и устанавливает его содержимое в 0. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на выделенный буфер, NULL если произошла ошибка. Замечание: используйте эту подпрограмму, если нужно выделить буфер в памяти, который будет освобожден впоследствии системой CF runtime, например если Вы должны заново выделить буфер, выделенный системой CF, и сохраненный в одной из runtime-структур CF. Используйте обычную функцию calloc для других своих выделений памяти. void mvFree(LPMV mV, LPVOID ptr)
Освобождает буфер памяти, выделенный mvMalloc, mvCalloc или mvReAlloc. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечание: используйте эту подпрограмму, если Вам нужно освободить буфер в памяти, выделенный системой CF runtime или через mvMalloc, mvCalloc или mvReAlloc. Используйте обычную функцию free для других своих выделений памяти. mvGetAppPropCheck(LPMV mV, LPVOID edPtr, UINT nPropID) Вернет состояние галочки (checked state) свойства приложения, TRUE или FALSE. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: TRUE или FALSE, в зависимости от того, стоит ли галочка на свойстве или нет. Замечание: идентификаторы свойств приложения перечислены в Props.h. Например, если Вы хотите узнать, установлена ли опция "Hidden at start" приложения, выполните следующее: mvGetAppPropCheck(mV, edPtr, PROPID_APP_HIDDENATSTART); mvGetAppPropValue(LPMV mV, LPVOID edPtr, UINT nPropID) Вернет значение свойства приложения. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на класс CPropValue, где содержится значение свойства. Замечание: идентификаторы свойств приложения перечислены в Props.h. Например, если Вы хотите узнать размер окна приложения, выполните следующее: CPropSizeValue* psv = (CPropSizeValue*)mvGetAppPropValue(mV, edPtr, PROPID_APP_WINDOWSIZE); int nWidth = psv->m_cx; int nHeight = psv->m_cy; mvGetFramePropCheck(LPMV mV, LPVOID edPtr, UINT nPropID) Вернет состояние галочки (checked state) свойства фрейма, TRUE или FALSE. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: TRUE или FALSE, в зависимости от того, стоит ли галочка на свойстве или нет. Замечание: идентификаторы свойств фрейма перечислены в Props.h. Например, если Вы хотите узнать состояние галочки опции фрейма "Handle collisions out of window", то выполните следующее: mvGetFramePropCheck(mV, edPtr, PROPID_FRAME_TOTALCOLMASK); mvGetFramePropValue(LPMV mV, LPVOID edPtr, UINT nPropID) Вернет значение свойства фрейма, который содержит этот объект. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на класс CPropValue, где содержится значение свойства. Замечание: идентификаторы свойств фрейма содержатся в Props.h. Например, если Вы хотите узнать цвет фона фрейма, выполните следующее: CPropDWordValue* pv = (CPropDWordValue*)mvGetFramePropValue(mV, edPtr, PROPID_FRAME_BACKGROUNDCOLOR); COLORREF color = pv->m_dwValue; mvGetPropCheck(LPMV mV, LPVOID edPtr, UINT nPropID) Вернет состояние галочки (checked state) свойства объекта, TRUE или FALSE. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: TRUE или FALSE, в зависимости от того, стоит ли галочка на свойстве или нет. Замечание: идентификаторы свойств перечислены в Props.h. Например, если хотите узнать состояние галочки опции "Create before fade-in transition", то выполните следующее: mvGetPropCheck(mV, edPtr, PROPID_DYNITEM_CREATEBEFOREFADEIN); mvGetPropValue(LPMV mV, LPVOID edPtr, UINT nPropID) Вернет значение свойства объекта. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на класс CPropValue, где содержится значение свойства. Замечание: идентификаторы свойств перечислены в файле Props.h. Например, если хотите узнать имя объекта, то выполните следующее: CPropDataValue* pv = (CPropDataValue*)mvGetPropValue(mV, edPtr, PROPID_ITEM_NAME); LPSTR pName = (LPSTR)pv->m_pData; mvInsertProps(LPMV mV, LPVOID edPtr, PropData* pProperties,
UINT nInsertPropID, BOOL bAfter)
Вставляет список свойств в главные свойства объекта. Параметры: LPMV mV указатель на информационную структуру mv. Если nInsertPropID это идентификатор закладки: если bAfter == TRUE, то свойства добавляются в конец закладки, иначе они добавляются в начало. Если nInsertPropID обычный идентификатор: если bAfter == TRUE, то элемент будет вставлен после nInsertPropID, иначе перед nInsertPropID. Возвращаемое значение: отсутствует. Замечания: эта функция обычно вызывается в функции GetProperties объекта, но может быть также вызвана позже, если Вы хотите динамически менять содержимое окна свойств. Например, свойства перемещения (movement) изменяются, когда Вы меняете тип перемещения. Пример: PropData Properties[] =
{
PropData_PictureFilename(PROPID_FILENAME, IDS_PROP_FILENAME,
IDS_PROP_FILENAME_INFO, FALSE),
PropData_ComboBox(PROPID_RESIZE, IDS_PROP_RESIZE,
IDS_PROP_RESIZE_INFO, ResizeList),
PropData_End()
};
PropData TranspProps[] =
{
PropData_Group(PROPID_TRANSPCOLORGROUP,
IDS_PROP_TRANSPCOLORGROUP,
IDS_PROP_TRANSPCOLORGROUP_INFO),
PropData_CheckBox(PROPID_TRANSPFIRSTPIXEL,
IDS_PROP_TRANSPFIRSTPIXEL,
IDS_PROP_TRANSPFIRSTPIXEL_INFO),
PropData_Color_Check(PROPID_TRANSPCOLORCUSTOM,
IDS_PROP_TRANSPCOLORCUSTOM,
IDS_PROP_TRANSPCOLORCUSTOM_INFO),
PropData_End()
};
BOOL WINAPI GetProperties(LPMV mV, LPEDATA edPtr, BOOL bMasterItem) { mvInsertProps(mV, edPtr, Properties, PROPID_TAB_GENERAL, TRUE); mvInsertProps(mV, edPtr, TranspProps, PROPID_TAB_DISPLAY, TRUE); return TRUE; } mvInvalidateObject(LPMV mV, LPVOID edPtr) Принуждает к перерисовке объект в редакторе фрейма и обновляет его иконку. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечание: обычно Вы вызываете эту функцию, когда меняете свойство, влияющее на отображение объекта в редакторе фрейма. LPVOID mvMalloc(LPMV mV, int nSize)
Выделяет буфер памяти. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на выделенный буфер, иначе NULL, если произошла ошибка. Замечание: используйте эту подпрограмму, если Вам нужно выделить буфер в памяти, который будет освобожден системой CF runtime, например если Вы должны перераспределить буфер, выделенный системой CF, и сохраненный в одной из runtime структур CF. Используйте обычную функцию malloc для своих других выделений в памяти. LPVOID mvReAlloc(LPMV mV, LPVOID ptr, int nNewSize)
Меняет размер буфера памяти, ранее выделенного mvMalloc, mvCalloc или mvReAlloc. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на новый буфер. Если произошла ошибка, то эта функция вернет NULL, и оригинальный буфер не будет изменен. Работает наподобие стандартной библиотечной функции realloc языка C. Замечание: используйте эту подпрограмму, если Вам нужно выделить буфер в памяти, который будет освобожден системой CF runtime, например если Вы должны перераспределить буфер, выделенный системой CF, и сохраненный в одной из runtime структур CF. Используйте обычную функцию realloc для своих других повторных выделений в памяти. LPVOID mvReAllocEditData(LPMV mV, LPVOID edPtr, DWORD dwNewSize) Заново размещает в памяти структуру EDITDATA. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: адрес переразмещенной структуры (может отличаться от оригинального EDITDATA, переданного в эту функцию). Замечания: если размер Вашей структуры EDITDATA зависит от одного или большего количества свойств (к примеру, строк, которые могут менять размер), то Вы должны иметь возможность поменять размер структуры, когда модифицируется свойство. Для этой цели просто вызовите функцию mvReAllocEditData. mvRefreshProp(LPMV mV, LPVOID edPtr, UINT nPropID, BOOL bReInit) Обновляет отображение свойства. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: иногда изменение значения свойства влияет на другие свойства. Вам нужен способ побудить повторное отображения других свойств с их новым значением. Как раз для этого и нужна функция mvRefreshProp. Вы обычно используете её в функциях SetPropValue или SetPropCheck своего объекта. mvRemoveProp(LPMV mV, LPVOID edPtr, UINT nPropID) Удаляет одно свойство из отображаемого списка. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечание: вызовите эту функцию, когда хотите удалить свойство из списка. Это позволит Вам изменять отображение свойств в зависимости от ввода пользователя. Вы можете сделать это либо в GetProperties, например когда инициализируется свойство окна, или позже в функциях SetPropValue или SetPropCheck. mvRemoveProps(LPMV mV, LPVOID edPtr, PropData* pProperties)
Удаляет список свойств из отображения. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: используйте эту функцию для удаления набора свойств за один вызов, чтобы сделать список свойств подстраиваемым под ввод пользователя. mvSetAppPropCheck(LPMV mV, LPVOID edPtr, UINT nPropID, UINT nCheck) Меняет статус (TRUE или FALSE) свойства галочки текущего приложения. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: идентификаторы свойств приложения перечислены в Props.h. Например если хотите установить значение галочки опции "Hidden at start" в свойствах приложения, выполните следующее: mvSetAppPropCheck(mV, edPtr, PROPID_APP_HIDDENATSTART, TRUE); Внимание: изменение свойств приложения не рекомендуется. Вы должны предупредить пользователя, перед тем, как сделать это. mvSetAppPropValue(LPMV mV, LPVOID edPtr, UINT nPropID, CPropValue* pValue)
Меняет значение одного их свойств приложения. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: идентификаторы свойств приложения перечислены в Props.h. Например, если хотите поменять частоту смены фреймов (frame rate), то выполните следующее: CPropDWordValue* pv = new CPropDWordValue(dwNewFrameRate); mvSetAppPropValue(mV, edPtr, PROPID_APP_FRAMERATE, pv); pv->Delete(); Примечание: изменение свойств приложения не рекомендуется. Вы должны предупредить пользователя, перед тем, как сделать это. mvSetFramePropCheck(LPMV mV, LPVOID edPtr, UINT nPropID, UINT nCheck) Меняет статус (TRUE или FALSE) свойства галочки текущего фрейма. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: идентификаторы свойств фрейма перечислены в Props.h. Например, если Вы хотите установить опцию "Resize to screen size at start" в свойствах фрейма, выполните следующее: mvSetFramePropCheck(mV, edPtr, PROPID_FRAME_RESIZETOSCREENSIZE, TRUE); Примечание: изменение свойств фрейма не рекомендуется. Вы должны предупредить пользователя, перед тем как сделать это. mvSetFramePropValue(LPMV mV, LPVOID edPtr, UINT nPropID, CPropValue* pValue)
Изменение значения одно из свойств текущего фрейма. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: идентификаторы свойств фрейма перечислены в Props.h. Например, если хотите поменять цвет фона фрейма, выполните следующее: CPropDWordValue* pv = new CPropDWordValue(BLUE); mvSetFramePropValue(mV, edPtr, PROPID_FRAME_BACKGROUNDCOLOR, pv); pv->Delete(); Примечание: изменение свойств фрейма не рекомендуется. Вы должны предупредить пользователя, перед тем как сделать это. mvSetPropCheck(LPMV mV, LPVOID edPtr, UINT nPropID, UINT nCheck) Меняет статус (TRUE или FALSE) свойства галочки объекта. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: идентификаторы свойств перечислены в Props.h. Например, если хотите установить опцию "Create before fade-in transition" в свойствах объекта, выполните следующее: mvSetPropCheck(mV, edPtr, PROPID_DYNITEM_CREATEBEFOREFADEIN, TRUE); После этого Вы должны принудительно обновить отображение свойств: mvRefreshProp(mV, edPtr, PROPID_DYNITEM_CREATEBEFOREFADEIN); mvSetPropValue(LPMV mV, LPVOID edPtr, UINT nPropID, CPropValue* pValue)
Меняет значение одного из свойств объекта. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечания: идентификаторы свойств перечислены в Props.h. Например, если хотите удалить эффект чернил (ink effect) в свойствах объекта, выполните следующее: CPropDWordValue* pv = new CPropDWordValue(0); mvSetPropValue(mV, edPtr, PROPID_FITEM_INKFX, pv); pv->Delete(); После этого Вы должны обновить отображение свойства: mvRefreshProp(mV, edPtr, PROPID_FITEM_INKFX); mvRefreshProp(mV, edPtr, PROPID_FITEM_INKFXPARAM); Обзор Callback-функций в коде runtime. CF предлагает набор функций, которые можно вызывать из объекта во время выполнения приложения (runtime). Эти удобные подпрограммы могут понадобиться для того, чтобы Ваш объект перерисовал сам себя, получил параметры действия или условия, поставил на паузу приложение, и т. д. Callback-функции в коде runtime могут быть вызваны тремя разными способами: • Через структуру mv. Как и во время редактирования приложения (edit time), структура mv также доступна и в коде runtime. В этой структуре определены callback-функции. Подпрограммы с префиксом mv: void (CALLBACK * mvAddBackdrop) (cSurface* pSf, int x, int y, DWORD dwInkEffect, DWORD dwInkEffectParam, int nObstacleType, int nLayer) Создает новый объект backdrop из поверхности (surface). Параметры: cSurface* pSf поверхность, которая содержит картинку для добавления как задний фон (backdrop). Параметр nObstacleType может быть одним из значений: OBSTACLE_NONE, // добавит "дырку" в маску коллизий слоя 1 (Layer 1). // Идентично OBSTACLE_TRANSPARENT для слоев > 1 OBSTACLE_SOLID, // препятствие OBSTACLE_PLATFORM, // платформа OBSTACLE_LADDER, // лестница OBSTACLE_TRANSPARENT // нет эффекта при коллизиях Возвращаемое значение: отсутствует. void (CALLBACK * mvCloseHFile)(HANDLE hf) Закрывает файл, открытый вызовом OpenHFile. Параметры: HANDLE hf хендл файла, возвращенный вызовом OpenHFile. Возвращаемое значение: отсутствует. LPVOID (CALLBACK * mvGetExtUserData) (CRunApp* pApp, HINSTANCE hInst) Возвращает глобальные данные расширения, подсоединенные к приложению. Параметры: CRunApp* pApp приложение. Возвращаемое значение: то, что Вы сохранили с mvSetExtUserData. NULL, если mvSetExtUserData никогда не была вызвана этим расширением для этого приложения. Замечания: функции mvGetExtUserData и mvSetExtUserData позволяют Вам сохранить глобальные данные в приложение. Например, Вы можете сохранить данные с mvSetExtUserData в функции DestroyRunObject (вместо удаления их), и получить их вызовом mvGetExtUserData в функции CreateRunObject. Вы должны освободить в функции EndApp любые данные, сохраненные вызовом mvSetExtUserData (и также в функции StartApp для переинициализации данных, когда приложение перезапускается). BOOL (CALLBACK * mvGetFile)(LPCTSTR pPath, LPTSTR pFilePath, DWORD dwFlags)
Эта функция распаковывает файл из файлов, встроенных в файл EXE/CCN, во временную директорию и возвращает путь до этого временного файла. Параметры: LPCTSTR pPath путь до файла для открытия. Возвращаемое значение: TRUE если все в порядке, иначе FALSE в случае возникновения ошибки (например, если временный файл не был создан). Замечания: если файл встроен в файл EXE или CCN, то mvGetFile распаковывает файл во временную директорию, и копирует путь до этого временного файла в буфер pFilePath. Если файл уже был распакован предыдущим вызовом этой функции, то mvGetFile не будет его распаковывать повторно, она увеличит счетчик и вернет путь до уже распакованного временного файла. Если файл не встроен в файл EXE/CCN, если у нас отдельное приложение, то копирует pPath в pFilePath, и вернет TRUE. Вы должны использовать эту функцию, если Ваше расширение поддерживает встроенные библиотечные файлы, но может получить доступ к ним только если это независимый файл. Вы должны вызвать mvReleaseFile для каждого вызова mvGetFile. mvReleaseFile удаляет временный файл с диска. Примечание: временные файлы будут удалены по завершению работы приложения, если по какой-то причине Вы не хотели удалять их, когда Ваш объект больше не нуждается в этих файлах. Пример: short WINAPI CreateRunObject(LPRDATA rdPtr, LPEDATA edPtr, LPCOB cobPtr) { LPRH rhPtr = rdPtr->rHo.hoAdRunHeader; rhPtr->rh4.rh4Mv->mvGetFile(rdPtr->szFileName, rdPtr->szTempFileName, 0); return 0; } short WINAPI DestroyRunObject(LPRDATA rdPtr, long fast) { LPRH rhPtr = rdPtr->rHo.hoAdRunHeader; rhPtr->rh4.rh4Mv->mvReleaseFile(rdPtr->szFileName); return 0; } DWORD (CALLBACK * mvGetVersion) ()
Эта функция возвращает текущую версию CF. Возвращаемое значение: DWORD, содержащее номер версии CF. Пример: DWORD dwVersion = mV->mvGetVersion(); if ( (dwVersion & MMFVERSION_MASK) == MMFVERSION_25 ) ; // CF 2.5 if ( (dwVersion & MMFVERSION_PRO) != 0 ) ; // CF 2.5 Developer
int nBuildNumber = (dwVersion & MMFBUILD_MASK); HANDLE (CALLBACK * mvOpenHFile)(LPCTSTR pPath, LPDWORD pDwSize, DWORD dwFlags)
Вернет хендл файла, встроенного в файл EXE, или обычного файла, если он не встроенный. Файл открывается на доступ только для чтения. Параметры: LPCTSTR pPath путь до файла для открытия. Возвращаемое значение: хендл файла (который был возвращен Windows-функцией CreateFile). Замечания: если файл встроен в файл EXE или CCN, то mvOpenHFile откроет файл EXE/CCN, установит его позицию на начало встроенного файла, поместит его размер в pDwSize, и вернет хендл файла (file handle). Если файл не встроен в файл EXE/CCN, если код работает в отдельном приложении, то mvOpenHFile пытается открыть файл вызовом Windows-функции CreateFile, поместит его размер в pDwSize, и вернет хендл файла (это может быть значение INVALID_HANDLE_VALUE, если такой файл не существует). Хендл файла должен быть закрыт вызовом mvCloseHFile. Пример: см. действие LoadText в старой ANSI версии объекта Edit. short WINAPI LoadText(LPRDATA rdPtr, long param1, long param2) { DWORD dwSize; LPRH rhPtr = rdPtr->rHo.hoAdRunHeader; HANDLE hFile = rhPtr->rh4.rh4Mv->mvOpenHFile((LPCSTR)param1, &dwSize, 0); if (hFile != INVALID_HANDLE_VALUE) { if ( dwSize != 0 ) { LPSTR pBuf = (LPSTR)calloc(dwSize+1, 1); if ( pBuf != NULL ) { DWORD dwRead; ReadFile(hFile, pBuf, dwSize, &dwRead, NULL); if ( dwRead == dwSize ) { pBuf[dwSize] = 0; SetWindowText(rdPtr->hWnd, pBuf); } free(pBuf); } } rhPtr->rh4.rh4Mv->mvCloseHFile(hFile); } return 0; } void (CALLBACK * mvRegisterDialogBox)(HWND hDlg) Регистрирует немодальное окно диалога, так что система CF вызывает IsDialogMessage для этого диалогового окна. Параметры: HWND hDlg хендл окна диалога для регистрации. Возвращаемое значение: отсутствует. Замечания: если Ваше расширение открывает немодальное окно диалога во время работы приложения (runtime), оно должно регистрировать его вызовом этой функции, иначе горячие клавиши (TAB, и т. д.) не будут работать. Окно диалога, зарегистрированное вызовом mvRegisterDialogBox, должно быть дерегистрировано вызовом mvUnregisterDialogBox перед тем, как это окно уничтожается. void (CALLBACK * mvReleaseFile)(LPCTSTR pPath) Освобождает файл, запрошенный вызовом mvGetFile. Параметры: LPCTSTR pPath путь до освобождаемого файла (обратите внимание, что это тот же самый путь, который Вы передали в качестве первого параметра в функцию GetFile). Возвращаемое значение: отсутствует. Замечания: если этот файл находится как встроенный в двоичные файлы приложения, то эта функция декрементирует счетчик использования файла (file usage count), и удаляет связанный временный файл, если этот счетчик стал равным 0. Если файл не встроен в двоичные файлы приложения, то эта функция ничего не делает. Для дополнительной информации см. описание функции mvGetFile. Пример: short WINAPI CreateRunObject(LPRDATA rdPtr, LPEDATA edPtr, LPCOB cobPtr) { LPRH rhPtr = rdPtr->rHo.hoAdRunHeader; rhPtr->rh4.rh4Mv->mvGetFile(rdPtr->szFileName, rdPtr->szTempFileName, 0); return 0; } short WINAPI DestroyRunObject(LPRDATA rdPtr, long fast) { LPRH rhPtr = rdPtr->rHo.hoAdRunHeader; rhPtr->rh4.rh4Mv->mvReleaseFile(rdPtr->szFileName); return 0; } LPVOID (CALLBACK * mvSetExtUserData) (CRunApp* pApp, HINSTANCE hInst, LPVOID pData) Сохраняет глобальные данные для этого расширения в приложение. Параметры: CRunApp* pApp приложение. Возвращаемое значение: предыдущее значение. Замечания: функции mvGetExtUserData и mvSetExtUserData позволяют Вам сохранять данные, глобальные для приложения. Например, Вы можете сохранить данные вызовом mvSetExtUserData в функции DestroyRunObject (вместо удаления их) и получить их значение вызовом mvGetExtUserData в функции CreateRunObject. Вы должны освободить в функции EndApp любые данные, сохраненные вызовом mvSetExtUserData (и также в функции StartApp, для повторной инициализации данных, когда приложение перезапускается). void (CALLBACK * mvUnregisterDialogBox)(HWND hDlg) Отменяется регистрация немодального окна диалога, которая была ранее зарегистрирована вызовом mvRegisterDialogBox. Параметры: HWND hDlg хендл окна диалогового окна для дерегистрации. Возвращаемое значение: отсутствует. LRESULT (CALLBACK * mvCallFunction) (LPVOID edPtr, int nFnc, LPARAM lParam1=0, LPARAM lParam2=0, LPARAM lParam3=0) Эта функция фактически представляет набор подпрограмм. Вы можете вызвать эти подпрограммы передачей в функцию mvCallFunction индекса подпрограммы (nFnc) и параметров для неё (lParam1, и т. д.). Чтобы упростить Вам задачу и сделать исходный код легко читаемым, разработчики CF определили по макросу на функцию. Параметры: LPVOID edPtr указатель на структуру EDITDATA объекта. Индексы функций: // Только редактор EF_INSERTPROPS, // Вставка свойств в окно Property EF_REMOVEPROP, // Удаление свойства EF_REMOVEPROPS, // Удаление свойств EF_REFRESHPROP, // Обновление свойства EF_REALLOCEDITDATA, // Переразмещение edPtr EF_GETPROPVALUE, // Получение значения свойства объекта EF_GETAPPPROPVALUE, // Получение значения свойства приложения EF_GETFRAMEPROPVALUE, // Получение значения свойства фрейма EF_SETPROPVALUE, // Установка значения свойства объекта EF_SETAPPPROPVALUE, // Установка значения свойства приложения EF_SETFRAMEPROPVALUE, // Установка значения свойства фрейма EF_GETPROPCHECK, // Получение состояния галочки свойства объекта EF_GETAPPPROPCHECK, // Получение состояния галочки свойства приложения EF_GETFRAMEPROPCHECK, // Получение состояния галочки свойства фрейма EF_SETPROPCHECK, // Установка значения свойства галочки объекта EF_SETAPPPROPCHECK, // Установка значения свойства галочки приложения EF_SETFRAMEPROPCHECK, // Установка значения свойства галочки фрейма EF_INVALIDATEOBJECT, // Обновление объекта в редакторе фрейма EF_RECALCLAYOUT, // Перерасчет размещения окон во время работы программы // (recalc runtime layout, докинг) // Редактор и runtime EF_MALLOC, // Выделение памяти EF_CALLOC, // Выделение памяти и установка её в 0 EF_REALLOC, // Перераспределение памяти EF_FREE, // Освобождение памяти Макросы: // Только редактор mvInsertProps mvRemoveProp mvRemoveProps mvRefreshProp mvReAllocEditData mvGetPropValue mvGetAppPropValue mvGetFramePropValue mvSetPropValue mvSetAppPropValue mvSetFramePropValue mvGetPropCheck mvGetAppPropCheck mvGetFramePropCheck mvSetPropCheck mvSetAppPropCheck mvSetFramePropCheck mvInvalidateObject Пример, Вы можете использовать либо вызов: mV->mvCallFunction(edPtr, EF_REFRESHPROP, PROPID_MYPROP, FALSE, 0); или (mV это указатель на структуру mv): mvRefreshProp(mV, edPtr, PROPID_MYPROP, FALSE); LPVOID mvCalloc(LPMV mV, int nSize)
Выделяет буфер памяти и устанавливает его содержимое в 0. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на выделенный буфер, или NULL, если произошла ошибка. Замечание: используйте эту подпрограмму, если Вам нужно выделить буфер в памяти, который будет освобожден кодом CF runtime, например, если Вы должны переразместить буфер, выделенный системой CF, и сохраненный в одной из runtime структур CF. Используйте обычную calloc для Ваших других выделений памяти. void mvFree(LPMV mV, LPVOID ptr)
Освобождает буфер памяти, выделенный mvMalloc, mvCalloc или mvReAlloc. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Замечание: используйте эту подпрограмму, если нужно освободить буфер памяти, выделенный кодом CF runtime или вызовами mvMalloc, mvCalloc или mvReAlloc. Используйте обычную функцию free для для своих других выделений памяти. LPVOID mvMalloc(LPMV mV, int nSize)
Выделяет буфер памяти. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на выделенный буфер, или NULL, если произошла ошибка. Замечание: используйте эту подпрограмму, если Вам нужно выделить в памяти буфер, который будет освобожден кодом CF runtime, например если Вы должны перераспределить буфер, выделенный системой CF, и сохраненный в одну из структур CF. Используйте обычную функцию malloc для своих других выделений памяти. LPVOID mvReAlloc(LPMV mV, LPVOID ptr, int nNewSize)
Меняет размер буфера памяти, ранее выделенный вызовами mvMalloc, mvCalloc или mvReAlloc. Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: указатель на новый буфер. Если произошла ошибка, то функция должна вернуть NULL, и оригинальный буфер не будет изменен. Эта функция работает наподобие функции realloc языка C. Замечание: используйте эту подпрограмму, если нужно выделить буфер памяти, который будет освобожден кодом CF runtime, например если должны перераспределить буфер, выделенный системой CF, и сохраненный в runtime-структуры CF. Используйте обычную функцию realloc для своих собственных перераспределений памяти. mvRecalcLayout(LPMV mV) Эта функция повторно выравнивает прикрепляемые окна подчиненных приложений (re-arranges docked sub-applications). Параметры: LPMV mV указатель на информационную структуру mv. Возвращаемое значение: отсутствует. Обзор RFUNCTIONS. В системе CF определено несколько runtime callback-функций, чтобы выполнять разные задачи, относящиеся к объекту, когда приложение выполняется (runtime). Эти функции вызываются через макрос, определенный в cncf.h: long callRunTimeFunction(LPRDATA rdPtr, short funcNum, short wParam, long lParam) Параметры: LPRDATA rdPtr указатель на подпрограмму RUNDATA объекта. Возвращаемое значение: зависит от вызываемой функции. Пример, как можно принудительно перерисовать объект: callRunTimeFunction(rdPtr, RFUNCTION_REDRAW, 0, 0); callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_CALLMOVEMENT, WPARAM wParam, LPARAM lParam) Вызывает функцию перемещения (movement) расширения "ActionEntry". Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта для вызова. Возвращаемое значение: отсутствует. Замечание: эта функция позволяет Вам добавить новые действия к Вашему расширению перемещения. Для получения дополнительной информации прочитайте документацию по Movement developement kit. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_CONTINUE, WPARAM wParam, LPARAM lParam) Завершает режим паузы. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: для использования, когда Вы завершили длинную задачу. Комплементарная часть к RFUNCTION_PAUSE. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_DESTROY, WPARAM wParam, LPARAM lParam) Удаляет объект. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: после вызова этой функции объект уничтожается по окончанию текущего цикла. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_EDITINT, WPARAM wParam, LPARAM lParam) Открывает диалоговое окно для редактирования целочисленной величины. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: для диалогового окна может быть IDOK, если пользователь нажал OK, или IDCANCEL, если пользователь нажал cancel (отменить). Редактируемое значение будет находиться в поле "value" структуры EditDebugInfo. Эта функция предоставлен как быстрый способ редактирования значения, отображаемого в списке отладчика. Обратите внимание, что эта функция не доступна, если только приложение не работает в режиме свободного запуска (run only mode). Замечание: структура EditDebugInfo содержит 2 поля, которые Вы должны обслужить для работы функции: LPSTR pTitle указатель на строку, которая будет использована как заголовок окна диалога. NULL используется для стандартного заголовка. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_EDITINT, WPARAM wParam, LPARAM lParam) Открывает окно диалога для редактирования строки. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: для окна это может быть IDOK, если пользователь нажал OK, или IDCANCEL если пользователь нажал cancel (отмена). Отредактированное значение можно найти в поле "value" структуры EditDebugInfo. Эта функция предоставлена как быстрый способ редактирования строки, отображаемой в списке отладчика. Обратите внимание, что эта функция недоступна, если только приложение не работает в режиме свободного запуска (run only mode). Замечание: структура редактирования EditDebugInfo содержит три поля, которые Вы должны обслуживать, чтобы функция работала: LPCTSTR pTitle указатель на строку, которая будет использоваться в качестве заголовка диалогового окна. NULL используется для стандартного заголовка. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_EXECPROGRAM, WPARAM wParam, LPARAM lParam) Запускает внешнюю программу. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: структура prgParam содержит 3 поля, которые Вы должны заполнить: short prgFlags флаги для запуска программы. PRGFLAGS_WAIT ставит CF на паузу, пока приложение на завершит работу. PRGFLAGS_HIDE скрывает окно CF, пока работает программа. callRunTimeFunction(LPRUNDATA rdPtr, RFUNCTION_GENERATEEVENT, WPARAM wParam, LPARAM lParam) Генерирует действительное событие расширения (extension true event). Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: в системе CF имеется большое отличие между реальными условиями (TRUE conditions) и вычисленным условиями (evaluated conditions). Обратитесь к секции условий (conditions) и действий (actions) для дополнительной информации. RFUNCTION_GENERATEEVENT посылает события в очередь обработки событий (event-processing queue). Код события (event code) должен быть кодом, определяемым в Вашем расширении. Вы также должны определить подпрограмму обработки для этого условия. Если пользователь вставил условие как первую строку события, то будет вызвана Ваша подпрограмма. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_GETFILEINFOS, WPARAM wParam, LPARAM lParam) Возвращает информацию по текущему приложению: диск (drive), путь до исполняемого файла (pathname), имя (name) и т. д. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует (оно находится в буфере). Замечание: с этой подпрограммой Ваш объект может узнать полное имя текущего приложения, и получить доступ к файлам в подкаталогах папки, где находится программа. wParam может принимать следующие значения: FILEINFO_DRIVE: будет возвращен диск приложения (application drive). callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_GETPARAM1, WPARAM wParam, LPARAM lParam) Эта подпрограмма только для подпрограмм расширения. Она возвращает значение первого параметра и устанавливает указатель на начало следующего. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: значение типа long (или указатель на строку) в качестве результата вычисления параметра. Замечание: используется только если Ваше расширение требует параметр! Пожалуйста обратитесь к главе "Условия, действия и расширения". callRunTimeFunction(LPRUNDATA rdPtr, RFUNCTION_GETPARAM2, WPARAM wParam, LPARAM lParam); Эта подпрограмма используется только для подпрограмм выражения. Она возвращает значение второго и следующего параметров. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: значение типа long (или указатель на строку) в качестве результата вычисления выражения. Замечание: используется только если Ваше выражение имеет больше одного параметра! Должна быть вызвана после того, как Вы вызвали RFUNCTION_GETPARAM1. Пожалуйста обратитесь к главе "Условия, действия и расширения". callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_GETSTRINGSPACE, WPARAM wParam, LPARAM lParam) Запрашивает место для сохранения строки в основных буферах CF. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: указатель на выделенную область. Замечание: это только временная область строки, эта память может быть перезаписана на следующем цикле. Вы должны просто использовать эту подпрограмму для возврата результата строкового выражения. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_GETSTRINGSPACE_EX, WPARAM wParam, LPARAM lParam) Запрашивает место для сохранения строки в основных буферах CF. Работает для пространства свыше 65 килобайт. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: указатель на выделенную область. Предупреждение: это только временное пространство строки, память может быть перезаписана на следующем цикле. Вы должны просто использовать эту подпрограмму для возврата результата строкового выражения. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_PAUSE, WPARAM wParam, LPARAM lParam) Вход в режим паузы. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: Ваше расширение может открыть селектор файла или остановить выполнение приложения для отображения другого диалога. Разработчики CF настаивают, чтобы Вы поставили на паузу приложение перед тем, как это сделать. Если Вы так не сделаете, то все внутренние таймеры и процессы синхронизации будут повреждены. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_PUSHEVENT, WPARAM wParam, LPARAM lParam) Проталкивает действительное событие расширения (extension true event). Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: эта функция работает как RFUNCTION_GENERATEEVENT, но событие будет вызвано только по окончании текущего цикла, что позволит Вам выполнить задачи между моментом, когда генерируется событие, и временем, когда вызывается подпрограмма условия (condition routine). callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_REDISPLAY, WPARAM wParam, LPARAM lParam) Принуждает завершить повторное отображение фрейма. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Предупреждение: полная перерисовка фрейма занимает некоторое время. Используйте эту функцию с осторожностью. Вы должны использовать её только если Ваш объект является объектом заднего фона (backdrop object, такой как объект картинки, picture object). callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_REDRAW, WPARAM wParam, LPARAM lParam) Принуждает вызвать подпрограмму DisplayRunObject во время процесса обновления отображения. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: если Вы не используете эту подпрограмму, и если HandleRunObject не возвращает флаг REFLAG_REDRAW, то подпрограмма DisplayRunObject никогда не будет вызвана. callRunTimeFunction(LPRUNDATA rdPtr, RFUNCTION_REHANDLE, WPARAM wParam, LPARAM lParam) Принуждает вызвать подпрограмму на следующем цикле. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: если Ваша подпрограмма HandleRunObject возвращает значение REFLAG_ONESHOT, то это отключается от списка подпрограмм для вызова на каждом цикле. Эта функция повторно подключает вызов в список. Будьте осторожны с использованием этой возможности, Вы можете снизить влияние Вашего объекта на скорость выполнения приложения. Представим, что Ваш HandleRunObject должен работать только когда что-то было изменено в run-time структуре объекта, вот что Вы делаете: • Сначала будет вызвана автоматически HandleRunObject после создания объекта, она выполнит свою работу, и возвратит REFLAG_ONESHOT, и иногда REFLAG_REDRAW, если это необходимо. Разработчики CF используют эту технику для многих объектов, таких как объекты текста. callRunTimeFunction(LPRUNDATA rdPtr, RFUNCTION_SETPOSITION, WPARAM wParam, LPARAM lParam) Меняет позицию объекта. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: вместе с CF movement developement kit стало обязательным иметь callBack для изменения позиции объекта. Изменение hoX и hoY может быть недостаточно для многих перемещений, которые сохраняют внутренние переменные для вычислений перемещения. Поэтому разработчики CF реализовали этот callBack. Просто вызовите его с новыми координатами. Если Вы просто хотите поменять координату X или Y, вызовите этот callback с новой координатой в качестве параметра, и старой, полученной от hoX или hoY. callRunTimeFunction(LPRDATA rdPtr, RFUNCTION_SUBCLASSWINDOW, WPARAM wParam, LPARAM lParam) Разбивает на классы окна, открытые объектом, для вставки важных данных, таких как указатель на структуру RUNDATA. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: отсутствует. Замечание: для получения дополнительной информации пожалуйста прочитайте главу "Как управлять окном из расширения". Другие функции: long param = CNC_GetFirstExpressionParameter(LPRDATA rdPtr, long lParam, short wParam) Возвращает первый параметр расширения. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: параметр в формате long. Замечания: wParam может принять следующие значения: TYPE_INT возвращается целое число. float myFloat=*(float *)¶m; Пример можно найти в проекте Template. long param = CNC_GetNextExpressionParameter(LPRDATA rdPtr, long lParam, short wParam) Возвращает следующий параметр расширения. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: параметр в формате long. Замечания: wParam может принимать следующие значения: TYPE_INT возвращается целое число. float myFloat=*(float *)¶m; Вы должны вызвать CNC_GetFirstExpressionParameter перед вызовом этого макроса. Пример можно найти в проекте Template. long param = CNC_GetFloatParameter( LPRDATA rdPtr ) Возвращает следующий параметр действия (action) или условия (condition), в формате с плавающей точкой. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: значение параметра в формате long. Замечания: Вам нужно получить значение float путем небольшой подстройки указателей, примерно так: float fValue=*(float *)¶m; Эта функция обычно используется для действий и условий, у которых больше 2 параметров, как в случае 1 или 2 параметров, они передаются непосредственно в функцию. long param = CNC_GetIntParameter( LPRDATA rdPtr ) Возвращает следующий целочисленный параметр действия или условия. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: значение параметра. Если вычисление возвратит число с плавающей запятой, то значение приводится к типу long, Вы несомненно получите целое число. Замечания: эта функция обычно используется для действий и условий, у которых больше 2 параметров, как в случае 1 или 2 параметров, они передаются непосредственно в функцию. long param = CNC_GetParameter( LPRDATA rdPtr ) Возвращает следующий параметр действия или условия. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: значение параметра в формате long. Замечания: если возвращаемое значение имеет тип float, то Вам может понадобиться получить его путем небольшой подстройки указателей наподобие следующей: float fValue=*(float *)¶m; Эта функция обычно используется для действий и условий с количеством параметров больше 2, как в случае 1 или 2 параметров они передаются напрямую в функцию. long param = CNC_GetStringParameter( LPRDATA rdPtr ) Возвращает следующий строковый параметр действия или условия. Параметры: LPRDATA rdPtr указатель на структуру RUNDATA объекта. Возвращаемое значение: значение параметра. Вы должны преобразовать тип значения long в тип LPCTSTR: LPCTSTR pString=(LPCTSTR)param;
Эта функция обычно используется для действий и условий с количеством параметров больше 2, как в случае 1 или 2 параметров они передаются напрямую в функцию. [Библиотека MMFS2] MMFS2.DLL это runtime-библиотека для Clickteam Fusion 2.5. Она содержит все основные графические, спрайтовые, звуковые подпрограммы, которые используются для отображения и анимации приложений. Если Вы хотите выводить данные на экран, то Вам нужен доступ к функциям MMFS2.DLL. Некоторые из этих функций являются приватными для runtime, они не будут здесь описаны. Описание коснется только тех функций, которые Вы можете использовать безопасно. Если по какой-то любой причине Вам понадобится больше информации по поводу других функций, обращайтесь к разработчикам CF. Поверхности. В системе CF Вы можете получить доступ к продвинутым графическим функциям через объект C++, cSurface. Этот объект является высокоуровневым, который представляет графическую поверхность. Вы можете копировать (blit, побитно) прямоугольники с одной поверхности на другую, рисовать линии, треугольники, полигоны, пиксели, и т. д. Например, если Вы хотите нарисовать в окне эллипс, то получаете поверхность, подсоединенную к окну фрейма Вашего приложения (дочернее к основному окну), используйте функцию cSurface::Ellipse для рисования на этой поверхности, и говорите CF, что этот прямоугольник поверхности должен быть обновлен на экране. Ниже показано, как получить указатель на объект cSurface, подсоединенный к окну CF. Из структуры RUNDATA: LPRH rhPtr = rdPtr->rHo.hoAdRunHeader; LPSURFACE ps = WinGetSurface((int)rhPtr->rhIdEditWin); Из структуры mv: LPSURFACE ps = WinGetSurface((int)mV->mvIdEditWin); Возвращаемая поверхность это не физический экран, а скрытый экран. Когда Вы выполняете графическую операцию на этой поверхности, то это будет выведено на экран не немедленно, а на следующем цикле фрейма. Также Вы должны сказать CF, какая область была изменена, чтобы она смогла копировать её на экран. Чтобы сделать так, вызовите следующую функцию: RECT rc; // прямоугольник, ограничивающий измененную область rc.left = xxx; // и так далее... WinAddZone(rhPtr->rhIdEditWin, &rc); Примечание: Вам нужно вызвать WinAddZone только в runtime, не нужно вызывать её в функции EditorDisplay. Дальше показано, как получить объект cSurface из изображения объекта. Если Ваше расширение использует внутренние изображения (редактируемые через Picture Editor), Вам может понадобиться подсоединить объект cSurface к этой картинке. Обратите внимание: этот объект cSurface только для чтения, Вы не можете записать во внутренние изображения CF через объект cSurface. См. псевдокод: cSurface imageSurface; ::LockImageSurface (idApp, nImage, imageSurface, mode); idApp = либо rhPtr->rhIdAppli, либо mV->mvIdAppli nImage = номер Вашей картинки (номер Вы передаете в EnumElts) imageSurface = Ваша поверхность mode = LOCKIMAGE_READBLITONLY = разрешено только копирование и растягивание от поверхности изображения LOCKIMAGE_ALLREADACCESS = Вы можете получить доступ ко всем функциям (GetPixel, и т. д.) Вы должны вызвать UnlockImageSurface, когда Вам больше не нужна поверхность: ::UnlockImageSurface (imagesurface);
Пример, как отобразить простой красный прямоугольник: // Runtimeshort WINAPI DLLExport DisplayRunObject(LPRDATA rdPtr) { LPRH rhPtr = rdPtr->rHo.hoAdRunHeader; LPSURFACE ps = WinGetSurface((int)rhPtr->rhIdEditWin); if ( ps != NULL ) { RECT rc; int x = rc.left = rdPtr->rHo.hoX - rhPtr->rhWindowX; int y = rc.top = rdPtr->rHo.hoY - rhPtr->rhWindowY; int w = rdPtr->rHo.hoImgWidth; int h = rdPtr->rHo.hoImgHeight; rc.right = x + w; rc.bottom = y + h; COLORREF color = RGB(255,0,0); ps->Fill(x, y, w, h, color); WinAddZone(rhPtr->rhIdEditWin, &rc); } // OK return 0; } // Редактор
void WINAPI DLLExport EditorDisplay(mv _far *knpV, fpObjInfo oiPtr, fpLevObj loPtr, LPEDATA edPtr, RECT FAR *rc) { LPSURFACE ps = WinGetSurface((int)knpV->mvIdEditWin); if ( ps != NULL ) { int x = rc->left; int y = rc->top; int w = rc->right-rc->left; int h = rc->bottom-rc->top; COLORREF color = RGB(255,0,0); ps->Fill(x, y, w, h, color); } } Функции, описанные в этой врезке, позволяют работать непосредственно с битами растра поверхности. LPBYTE LockBuffer();
Эта функция блокирует растровую поверхность и возвращает указатель на биты растра первой строки. Замечания: как только bitmap Вам больше не нужен, Вы должны освободить его вызовом UnlockBuffer. Формат bitmap зависит от цветовой глубины поверхности. 8 бит (256 цветов). 1 байт на точку, каждый байт является индексом в цветовой палитре. Вы можете использовать макросы в BlitMac.h, чтобы преобразовать цветовые значения между разными режимами. Ширина каждой строки точек в байтах берут с помощью функции GetPitch. void UnlockBuffer(LPBYTE pBuffer); Разблокирует буфер, заблокированный вызовом LockBuffer. Параметр: LPBYTE pBuffer буфер, возвращенный вызовом LockBuffer.
Замечания: не используйте pBuffer после разблокировки поверхности. int GetPitch(); Возвращает ширину в байтах строки точек. Замечания: Вы должны использовать это после каждого вызова LockBuffer. Предупреждение: ширина (pitch) может быть отрицательной. Позволяет Вам копировать блок растра с одной поверхности на другую, с опциональными эффектами чернил (ink effects). BOOL Blit ( cSurface FAR & dest ); Копирует всю поверхность на другую. Параметры: cSurface& dest поверхность назначения. Замечания: если поверхность имеет канал альфа, то он копируется в поверхность назначения (и если у поверхности назначения нет альфа-канала, то он будет создан). BOOL Blit ( cSurface FAR & dest, int destX, int destY, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0, DWORD dwBlitFlags = 0 ); Копирует всю поверхность в позицию другой поверхности. Могут использоваться опциональные эффекты чернил (ink effects). Параметры: cSurface& dest поверхность назначения. Параметр bo может принимать значения: BOP_COPY = нет эффекта чернил Флаги dwBlitFlags могут принимать значения: BLTF_ANTIA = антиалиасинг Замечания: если указан флаг BLTF_COPYALPHA, и поверхность имеет альфа-канал, то он копируется в указанную позицию координат на поверхности назначения (и если у поверхности назначения нет альфа-канала, то он будет создан). Если BLTF_COPYALPHA не указан, и режим копирования (blit mode) установлен как BMODE_TRANSP, то исходная поверхность "микшируется" с поверхностью назначения. С альфа-каналом, если он есть. Если у поверхности нет альфа-канала, и режим копирования BMODE_TRANSP, то используется цвет прозрачности поверхности. В текущей версии эффекты чернил не поддерживаются для поверхностей с альфа-каналами. Поверхности источника и назначения могут иметь разную глубину цвета (конечно, в этом случае обработка будет медленней, чем когда обе поверхности имеют одинаковую глубину). BOOL Blit ( cSurface FAR & dest, int destX, int destY, int srcX, int srcY, int srcWidth, int srcHeight, BlitMode bm, BlitOp bo = BOP_COPY, LPARAM param = 0, DWORD dwBlitFlags = 0 ); Эта функция копирует прямоугольник их поверхности в указанную позицию другой поверхности. Параметры: cSurface& dest поверхность назначения. BOOL Scroll ( int xDest, int yDest, int xSrc, int ySrc, int width, int height ); Перемещает прямоугольную область в другую позицию. Параметры: int xDest, yDest координаты назначения прямоугольной области. Замечания: прямоугольники источника и назначения должны быть включены в поверхность. Эта функция не делает обрезку. BOOL FilterBlit ( cSurface FAR & dest, FILTERBLITPROC fbProc, LPARAM lUserParam, BlitMode bm = BMODE_OPAQUE ); Эта функция позволяет Вам копировать поверхность одну на другую через подпрограмму фильтра, которая преобразует каждую точку. Параметры: cSurface& dest поверхность назначения. Пример: // Функция фильтра, которая маскирует исходный цвет с параметром. COLORREF CALLBACK myFilter(COLORREF dest, COLORREF src, LPARAM lParam) { return (src & lParam); } // Копирование только зеленого компонента пикселов: mySurface.FilterBlit (mySurface2, &myFilter, 0x00FF00, BMODE_OPAQUE); BOOL FilterBlit (cSurface FAR & dest, int destX, int destY, int srcX, int srcY, int srcWidth, int srcHeight, BlitMode bm, FILTERBLITPROC fbProc, LPARAM lUserParam ); Эта функция позволяет Вам копировать прямоугольник с одной поверхности на другую через подпрограмму фильтра, которая преобразует каждую точку. Параметры: cSurface& dest поверхность назначения. Функции ниже позволяют Вам ограничить область рисования на поверхности заданным прямоугольником. void GetClipRect(int FAR & x, int FAR & y, int FAR & w, int FAR & h); Возвращает координаты текущего обрезающего прямоугольника. Параметры: int& x ссылка на координату X верхнего левого угла обрезающего прямоугольника. void SetClipRect(int x, int y, int w, int h); Меняет обрезающий прямоугольник. Параметры: int x новая координата X верхнего левого угла обрезающего прямоугольника. void ClearClipRect(void); Очищает обрезающий прямоугольник (становится доступной вся поверхность). DWORD CreateMask(LPSMASK pMask, UINT dwFlags);
Эта функция позволяет Вам создать монохромную маску из непрозрачных точек поверхности. Эта маска может использоваться в функциях детектирования столкновений (коллизий), во время работы приложения (runtime). Параметры: LPSMASK pMask указатель на маску коллизий назначения, может быть NULL. Возвращаемое значение: размер маски коллизий. Замечания: если pMask == NULL, то эта функция вернет размер маски. Тогда Вы можете выделить память и снова вызвать CreateMask с правильным указателем. Маска коллизий начинается со структуры sMask, за которой сразу идет растр (1 бит на точку). Ширина линии в байтах сохраняется в поле sMask.mkWidthBytes. Используйте функции ниже для обработки палитры в режиме 256 цветов. BOOL Indexed(void); Возвратит TRUE, если поверхность имеет цветовую палитру (глубина цвета = 8). BOOL SetPalette ( LPLOGPALETTE palette, SetPaletteAction action=SPA_NONE ); Меняет палитру поверхности с 256 цветами. Параметры: LPLOGPALETTE palette указатель на структуру LOGPALETTE, которая содержит палитру. SPA_NONE = ничего особенного, текущая палитра заменяется на новую. BOOL SetPalette (LPCSPALETTE pCsPal, SetPaletteAction action=SPA_NONE); Меняет палитру поверхности с 256 цветами. Параметры: LPCSPALETTE pCsPal указатель на структуру csPalette, где содержится палитра (внутренняя структура, используемая системой CF, начинающаяся на структуру LOGPALETTE). BOOL SetPalette (cSurface FAR& src, SetPaletteAction action=SPA_NONE); Копирует палитру из 256-цветной поверхности на текущую поверхность. Параметры: cSurface& stc исходная поверхность (должна быть 256-цветная). BOOL SetPalette(HPALETTE palette, SetPaletteAction action=SPA_NONE); Меняет палитру 256-цветовой поверхности. Параметры: HPALETTE palette хендл палитры Windows. void Remap ( cSurface FAR& src ); Заново привязывает растр 256-цветной поверхности с использованием палитры исходной 256-цветной поверхности (примечание: палитра не копируется). void Remap ( LPBYTE remapTable ); Заново привязывает растр 256-цветной поверхности с использованием 256-байтной таблицы привязки (remap table). LPCSPALETTE GetPalette();
Возвратит указатель на палитру поверхности (структуру csPalette). UINT GetPaletteEntries ( LPPALETTEENTRY paletteEntry, int index, int nbColors ); Получает цвета из палитры поверхности. int GetNearestColorIndex(COLORREF rgb); Получает индекс ближайшего цвета в цветовой палитре. COLORREF GetRGB(int index); Возвратит значение RGB цвета в цветовой палитре. int GetOpaqueBlackIndex(); Вернет ненулевой цвет, который является самым близким к RGB(0,0,0). Функции, которые позволяют Вам создавать поверхность. void Create (int width, int height, LPSURFACE prototype); Создает поверхность из другой поверхности. Параметры: int width ширина поверхности. Возвращаемое значение: эта функция не возвращает какой-либо код ошибки. Если Вам нужно проверить, была ли успешно создана поверхность, используйте функцию IsValid (см. врезку "Информационные функции" page). Замечания: если у Вас нет поверхности, чтобы создать из неё новую, то Вы можете получить такую поверхность глобальной функцией GetSurfacePrototype: BOOL WINAPI GetSurfacePrototype (LPSURFACE *proto, int depth, int st, int drv); Функция возвращает прототип поверхности. Параметры: LPSURFACE* proto переменная, которая примет указатель на прототип поверхности. Параметр типа st может быть одним из значений: ST_MEMORY = простой буфер памяти. Параметр drv может быть одним из значений: SD_DIB = стандартный драйвер, использует внутренние подпрограммы рисования и/или подпрограммы Windows GDI. Возвращаемое значение: если произошла ошибка, то эта функция вернет FALSE. Иначе она вернет TRUE, и поместит указатель на поверхность в переменную prototype. Примечание: Вам не нужно удалять прототипы поверхности, которые были возвращены вызовом GetSurfacePrototype. Пример: cSurface mySurface2; mySurface.Create(320, 200, mySurface1); LPSURFACE pProto = NULL;if ( GetSurfacePrototype(&pProto, 24, ST_MEMORYWITHDC, SD_DIB) ) { // OK cSurface mySurface; mySurface.Create(100, 100, pProto); // и т. д. }
void Clone (const cSurface FAR & pSrcSurface, int newW = -1, int newH = -1); Создает поверхность из другой, и копирует её растр. Параметры: LPSURFACE* pSrcSurface исходная поверхность. Примечание: если newW или newH отличаются от размеров исходной поверхности, то растр исходной поверхности будет растягиваться или сжиматься. void Create (HDC hDC); Создает чистую поверхность DC, т. е. поверхность без растра, подсоединенного к DC. С поверхностью такого типа работают только DC-операции, такие как побитные копирования (Blits) с других поверхностей (кроме простых поверхностей памяти). Эта разновидность поверхности используется для копирования поверхности на экран. Пример см. далее. void Delete(); Эта функция удаляет растр, подсоединенный к поверхности, и освобождает всю память, используемую поверхностью. Примечание: эта функция не удаляет сам объект поверхности. Пример ниже взят из объекта расширения CF, он отображает картинку на статическом элементе управления (static control) окна диалога (в сообщении WM_PAINT диалогового окна). Для дополнительной информации см. раздел документации MMFS2 с описанием функций LockImageSurface и UnlockImage. case WM_PAINT: { spa = (setupParams far *)GetWindowLong(hDlg, DWL_USER); edPtr = spa->edpt; PAINTSTRUCT ps; HDC hdc = BeginPaint(hDlg, &ps); if (hdc != NULL) { HWND hPreview = GetDlgItem(hDlg, IDC_IMAGES_VIEW); if ( hPreview != NULL ) { RECT rc; GetWindowRect(hPreview, &rc); ScreenToClient(hDlg, (LPPOINT)&rc.left); ScreenToClient(hDlg, (LPPOINT)&rc.right); // Создание временной поверхности (память + DC) int w = rc.right-rc.left; int h = rc.bottom-rc.top; int depth = GetDeviceCaps (hdc, BITSPIXEL) * GetDeviceCaps (hdc, PLANES); LPSURFACE proto = NULL; GetSurfacePrototype(&proto, depth, ST_MEMORYWITHDC, SD_DIB); if ( proto != NULL ) { cSurface sf; sf.Create(w, h, proto); // Получение палитры приложения и установка палитры поверхности LPBYTE bufpal = NULL; if ( depth == 8 ) { bufpal = new BYTE[sizeof(LOGPALETTE) + 256*sizeof(PALETTEENTRY)]; if ( bufpal != NULL ) { ((LPLOGPALETTE)bufpal)->palVersion = 0x300; ((LPLOGPALETTE)bufpal)->palNumEntries = 256; GetPaletteAppli((LPLOGPALETTE)bufpal, SM_8, spa->kv->mvIdAppli); sf.SetPalette((LPLOGPALETTE)bufpal); sf.GetPaletteEntries(&((LPLOGPALETTE)bufpal)->palPalEntry[0], 0, 256); } } // Фон диалога
sf.Fill(GetSysColor(COLOR_BTNFACE));
// Копирование картинки на временную поверхность cSurface imageSurface; ::LockImageSurface (spa->kv->mvIdAppli, spa->wImage, imageSurface, LOCKIMAGE_READBLITONLY); int iw = imageSurface.GetWidth(); int ih = imageSurface.GetHeight(); imageSurface.Blit (sf, (w - iw)/2, (h - ih)/2, 0, 0, iw, ih, BMODE_TRANSP); ::UnlockImageSurface (imageSurface); // Создание DC-поверхности
cSurface sdc;
sdc.Create(hdc);
// Выбор палитры HPALETTE hPal = NULL; HPALETTE hOldPal = NULL; if ( bufpal != NULL ) { hPal = CreatePalette((LPLOGPALETTE)bufpal); if ( hPal != NULL ) { hOldPal = SelectPalette(hdc, hPal, TRUE); // верхняя палитра RealizePalette(hdc); } delete [] bufpal; bufpal = NULL; } // Копирование временной поверхности на экран
sf.Blit(sdc, rc.left, rc.top);
// Восстановление палитры DC if ( hOldPal != NULL ) SelectPalette(hdc, hOldPal, TRUE); } } } EndPaint(hDlg, &ps); } break;
Эти функции позволяют Вам минимизировать (или "обрезать") поверхность, например уменьшить минимальный непрозрачный прямоугольник. BOOL GetMinimizeRect(RECT FAR* pRc); Возвратит минимум непрозрачного прямоугольника, т. е. удаляет прозрачные рамки. Параметры: RECT FAR* pRc прямоугольник, который получает координаты непрозрачного прямоугольника. Возвращаемое значение: TRUE если функция выполнилась успешно, FALSE если произошла ошибка (например если поверхность была полностью прозрачной). Замечания: если поверхность имеет альфа-канал, то только 100% прозрачные точки (со значением alpha = 0) считаются прозрачными. Если у поверхности нет альфа-канала, то используется цвет прозрачности. Координаты в pRc указаны относительно левого верхнего угла поверхности. BOOL Minimize();
Уменьшит поверхность до минимального непрозрачного прямоугольника (см. описание выше). Возвращаемое значение: TRUE если функция выполнилась успешно, FALSE если произошла ошибка (например если поверхность была полностью прозрачной). BOOL Minimize(RECT FAR* r); Уменьшает поверхность до минимального непрозрачного прямоугольника и вернет координаты этого прямоугольника относительно оригинальной поверхности. Параметры: RECT FAR* pRc прямоугольник, который получает координаты непрозрачного прямоугольника. Возвращаемое значение: TRUE если функция выполнилась успешно, FALSE если произошла ошибка (например если поверхность была полностью прозрачной). Если поверхность была создана с типом ST_MEMORYWITHDC или ST_MEMORYWITHPERMANENTDC, то Вы можете получить DC этой поверхности, и выполнить любую графическую операцию Windows. HDC GetDC(void); Вернет хендл device context (DC). Вы должны освободить хендл функцией ReleaseDC, когда он Вам больше не нужен. Примечание: Вы НЕ ДОЛЖНЫ использовать LockBuffer между GetDC и ReleaseDC. Вы НЕ ДОЛЖНЫ вызывать GetDC между LockBuffer и UnlockBuffer. void ReleaseDC(HDC dc); Освобождает DC, возвращенную GetDC. Эти функции позволяют Вам загрузить или сохранить поверхность из файла / в файл растра BMP (Windows bitmap). Примечание: если Вам нужно загрузить / сохранить Вашу картинку из/в другие форматы файла, см. раздел документации "MMFS2 / фильтры изображений". Важное замечание: если картинка имеет формат 15, 16 или 32 бита, то функции SaveImage сохраняют Windows bitmap в форматах 15, 16 или 32 бита. Некоторые программы (или даже старые версии Windows) не поддерживают DIB в этих форматах, так что в некоторых случаях Вы можете захотеть сохранять растр только в 8 или 24 битах. Чтобы сделать так, просто создайте временную поверхность в желаемом формате, выполните копию исходной поверхности на эту созданную поверхность, и затем сохраните её. BOOL LoadImage ( HFILE hf, DWORD lsize, LIFlags loadFlags = LI_NONE ); Загружает поверхность из хендла файла. Параметры: HFILE hf хендл файла (например открытого функцией CreateFile из API Windows). LI_NONE = ничего специального. Возвращаемое значение: TRUE если растр bitmap был успешно загружен, FALSE если произошла ошибка (файл не найден, не поддерживаемый формат, и т. п.). BOOL LoadImage ( LPCTSTR fileName, LIFlags loadFlags = LI_NONE ); Загружает поверхность из файла по его имени. Параметры: LPCTSTR fileName путь до файла. Возвращаемое значение: TRUE если растр bitmap был успешно загружен, FALSE если произошла ошибка (файл не найден, не поддерживаемый формат, и т. п.). BOOL LoadImage ( HINSTANCE hInst, int bmpID, LIFlags loadFlags = LI_NONE ); Загружает поверхность из растровой картинки, находящейся в ресурсах. Параметры: HINSTANCE hInst хендл модуля, который содержит bitmap. Возвращаемое значение: TRUE если растр bitmap был успешно загружен, FALSE если произошла ошибка (файл не найден, не поддерживаемый формат, и т. п.). BOOL LoadImage ( LPBITMAPINFO pBmi, LPBYTE pBits = NULL, LIFlags loadFlags = LI_NONE ); Загружает картинку из DIB в памяти. Параметры: LPBITMAPINFO pBmi указатель на структуру BITMAPINFO. Возвращаемое значение: TRUE если растр bitmap был успешно загружен, FALSE если произошла ошибка (файл не найден, не поддерживаемый формат, и т. п.). BOOL SaveImage ( HFILE hf, SIFlags saveFlags = SI_NONE ); Сохраняет поверхность в хендл файла. Параметры: HFILE hf хендл файла (например открытого функцией CreateFile из API Windows). SI_NONE = ничего специального. Возвращаемое значение: TRUE если растр bitmap был успешно сохранен, FALSE если произошла ошибка. BOOL SaveImage ( LPCTSTR fileName, SIFlags saveFlags = SI_NONE ); Сохраняет поверхность в файл. Параметры: LPCTSTR fileName путь до файла. Возвращаемое значение: TRUE если растр bitmap был успешно сохранен, FALSE если произошла ошибка. BOOL SaveImage ( LPBITMAPINFO pBmi, LPBYTE pBits, SIFlags saveFlags = SI_NONE ); Сохраняет поверхность в DIB памяти. Параметры: LPBITMAPINFO pBmi указатель на структуру BITMAPINFO. Возвращаемое значение: TRUE если растр bitmap был успешно сохранен, FALSE если произошла ошибка. Замечание: Вы можете использовать функцию GetDIBSize, чтобы определить размер DIB перед его сохранением. DWORD GetDIBSize ();
Возвратит размер DIB, сохраненный функцией, показанной выше. Это простые функции, которые позволяют Вам заполнять прямоугольник цветом, градиентом или шаблоном, чтобы "залить" область или заменить один цвет на другой. BOOL Fill (COLORREF c); BOOL Fill (CFillData FAR * fd); BOOL Fill (int index); BOOL Fill (int R, int G, int B); Заполняет всю поверхность. Параметры: COLORREF c цвет для заполнения поверхности. CFillData это базовый класс для следующих классов: CFillFlat заполнение сплошным цветом. Пример: CFillFlat fd(RED); mySurface.Fill(&fd); CFillDir заполнение градиентом. Пример: CFillDir fd(RED, BLUE, FALSE); // используйте TRUE для вертикального градиента mySurface.Fill(&fd); CFillMosaic заполнение неким шаблоном. Пример: CFillMosaic fd(pPatternSurface); mySurface.Fill(&fd);
BOOL Fill (int x, int y, int w, int h, COLORREF c); BOOL Fill (int x, int y, int w, int h, CFillData FAR * fd); BOOL Fill (int x, int y, int w, int h, int index); BOOL Fill (int x, int y, int w, int h, int R, int G, int B); Заполняет прямоугольник поверхности. Параметры: int x, y координаты X и Y прямоугольника для заполнения. BOOL FloodFill ( int x, int y, COLORREF crFill, BOOL AntiA = FALSE, int tol = 0, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0 ); Заполнение области. Параметры: int x, y координаты на области для заполнения. Замечания: если допуск 0, эта функция получает цвет по указанным координатам, и заменяет все соседние точки, которые имеют такой же цвет. Если допуск больше 0, то эта функция заменяет все соседние точки, которые имеют следующий диапазон цвета: red - Tolerance -> red + допуск BOOL FloodFill ( int x, int y, int FAR & left, int FAR & top, int FAR & right, int FAR & bottom, COLORREF crFill, BOOL AntiA = FALSE, int tol = 0, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0 ); Заполняет область и возвращает ограниченный прямоугольник измененной области. Параметры: int& left, top, right, bottom координаты ограниченного прямоугольника измененной области (значения устанавливаются функцией). Описание других параметров см. в предыдущей функции. BOOL ReplaceColor (COLORREF newColor, COLORREF oldColor);
Заменяет на поверхности один цвет другим. Параметры: COLORREF newColor новый цвет. Позволяет Вам выполнять простые геометрические операции: линия, прямоугольник, эллипс, полигон. Примечание: некоторые параметры необязательны, но Вы все равно должны их указать, так как компилятор C++ иногда входит в ступор и в некоторых случаях вызывает не ту функцию. BOOL Line ( int x1, int y1, int x2, int y2, int thickness = 1, COLORREF crOutl = BLACK ); BOOL Line ( int x1, int y1, int x2, int y2, int thickness, CFillData FAR * fdOutl, BOOL AntiA, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0); Рисует линию. Параметры: int x1, y1 координаты начальной точки. Параметр bo может принимать значение: BOP_COPY = нет эффекта чернил BOOL Rectangle ( int left, int top, int right, int bottom, int thickness = 1, COLORREF crOutl = BLACK ); BOOL Rectangle ( int left, int top, int right, int bottom, COLORREF crFill, int thickness, COLORREF crOutl, BOOL Fill = TRUE ); BOOL Rectangle ( int left, int top, int right, int bottom, int thickness, CFillData FAR * fdOutl, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0 ); BOOL Rectangle ( int left, int top, int right, int bottom, CFillData FAR * fdFill, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0 ); BOOL Rectangle ( int left, int top, int right, int bottom, CFillData FAR * fdFill, int thickness, CFillData FAR * fdOutl, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0, BOOL Fill = TRUE ); Рисует прямоугольник. Параметры: int left, top координата верхнего левого угла прямоугольника. BOOL Ellipse ( int left, int top, int right, int bottom, int thickness = 1, COLORREF crOutl = BLACK ); BOOL Ellipse ( int left, int top, int right, int bottom, COLORREF crFill, int thickness, COLORREF crOutl, BOOL Fill = TRUE); BOOL Ellipse ( int left, int top, int right, int bottom, int thickness, CFillData FAR * fdOutl, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0); BOOL Ellipse ( int left, int top, int right, int bottom, CFillData FAR * fdFill, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0); BOOL Ellipse ( int left, int top, int right, int bottom, CFillData FAR * fdFill, int thickness, CFillData FAR * fdOutl, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0, BOOL Fill = TRUE); Рисует эллипс. Параметры: int left, top координаты верхнего левого угла прямоугольника. BOOL Polygon ( LPPOINT pts, int nPts, int thickness = 1, COLORREF crOutl = BLACK ); BOOL Polygon ( LPPOINT pts, int nPts, COLORREF crFill, int thickness = 0, COLORREF crOutl = BLACK, BOOL Fill = TRUE ); BOOL Polygon ( LPPOINT pts, int nPts, int thickness, CFillData FAR * fdOutl, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0 ); BOOL Polygon ( LPPOINT pts, int nPts, CFillData FAR * fdFill, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0 ); BOOL Polygon ( LPPOINT pts, int nPts, CFillData FAR * fdFill, int thickness, CFillData FAR * fdOutl, BOOL AntiA = FALSE, BlitMode bm = BMODE_OPAQUE, BlitOp bo = BOP_COPY, LPARAM param = 0, BOOL Fill = TRUE ); Рисует полигон. Параметры: LPPOINT pts адрес списка точек. Иконки это объекты Windows, которые содержат прозрачный растр (transparent bitmaps). HICON CreateIcon (int iconWidth, int iconHeight, COLORREF transpColor, POINT *pHotSpot); Эта функция позволяет создавать иконки Windows из поверхности. Параметры: int iconWidth ширина иконки в пикселах. Возвращаемое значение: возвращает хендл иконки (HICON). Замечания: если необходимо, поверхность пропорционально меняет свой размер. Цвет прозрачности поверхности игнорируется, учитывается только transpColor. Эти функции возвращают разную информацию о поверхности. BOOL IsValid ();
Возвращает TRUE, если содержимое поверхности допустимое, например, если поверхность создана. int GetType(); Возвращает тип поверхности: ST_MEMORY, ST_MEMORYWITHDC, ST_MEMORYWITHPERMANENTDC. int GetDriver(); Возвращает поверхность драйвера: SD_DIB или SD_DDRAW. DWORD GetDriverInfo(LPVOID pInfo);
Возвращает информацию, относящуюся к драйверу. int GetWidth(void); Возвращает ширину поверхности в точках. int GetHeight(void); Возвращает высоту поверхности в точках. int GetDepth(void); Возвращает глубину цвета поверхности: 8, 15, 16, 24 или 32. BOOL GetInfo(int FAR & width, int FAR & height, int FAR & depth); Возвращает ширину, высоту поверхности и глубину её цвета. Функции ниже позволяют Вам установить точку в указанный цвет, или узнать цвет нужной точки. void SetPixel(int x, int y, COLORREF c); Устанавливает точку по указанным координатам указанным цветом. Параметры: int x координата X. void SetPixel(int x, int y, BYTE R, BYTE G, BYTE B); То же самое, что и функция выше, но цвет указан по компонентам цвета. void SetPixel(int x, int y, int index); То же самое, что и выше, но цвет указан по индексу в цветовой палитре. Поверхность должна быть 256-цветная. void SetPixelFast(int x, int y, COLORREF c); То же самое, что и SetPixel, но работает быстрее. Эта подпрограмма подразумевает, что координаты внутри поверхности относительно 0,0, и поверхность заблокирована (вызовом LockBuffer). void SetPixelFast8(int x, int y, int index); То же самое, что и SetPixel для 256-цветной поверхности, но работает быстрее. Эта подпрограмма подразумевает, что координаты находятся внутри поверхности, точка отсчета поверхности 0,0, и поверхность заблокирована (вызовом LockBuffer). Если оказывается, что координаты не внутри поверхности, то эта функция приводит к сбою. BOOL GetPixel(int x, int y, COLORREF FAR & c); Возвращает цвет точки по указанным координатам. Параметры: int x координата X. Возвращаемое значение: TRUE если все хорошо, FALSE если ошибка (например если точка находится вне ограничивающего прямоугольника поверхности). BOOL GetPixel(int x, int y, BYTE FAR & R, BYTE FAR & G, BYTE FAR & B); То же самое, что и выше, но цвет возвращается по отдельным цветовым компонентам. BOOL GetPixel(int x, int y, int FAR & index); То же самое, что и выше, но цвет это индекс в цветовой палитре. Поверхность должна быть 256-цветной. COLORREF GetPixelFast(int x, int y); Возвращает цвет точки по указанным координатам. Эта подпрограмма подразумевает, что координаты находятся внутри поверхности, точка отсчета поверхности 0,0, и поверхность заблокирована (вызовом LockBuffer). Если оказывается, что координаты не внутри поверхности, то эта функция приводит к сбою. int GetPixelFast8(int x, int y); То же самое, что и выше, но для 256-цветной поверхности. Возвращаемое значение это индекс цвета цветовой палитре. Простые функции, которые позволяют Вам быстро отразить изображение горизонтально или вертикально - поверхность целиком или прямоугольник поверхности. BOOL ReverseX();
Зеркалирует всю поверхность горизонтально. Возвратит FALSE, если произошла ошибка (например, если поверхность недопустимая). BOOL ReverseX(int x, int y, int width, int height); Зеркалирует всю поверхность горизонтально. Возвратит FALSE, если произошла ошибка (например, если поверхность недопустимая, или если прямоугольник находится вне поверхности). Параметры: int x координата X прямоугольника. BOOL ReverseY();
Зеркалирует всю поверхность вертикально. Возвратит FALSE, если произошла ошибка (например, если поверхность недопустимая). BOOL ReverseY(int x, int y, int width, int height); Зеркалирует всю поверхность вертикально. Возвратит FALSE, если произошла ошибка (например, если поверхность недопустимая, или если прямоугольник находится вне поверхности). Параметры: int x координата X прямоугольника. Позволяют повернуть поверхность. BOOL Rotate90 ( cSurface FAR& dest, BOOL b270 ); Копирует поверхность, повернутую на 90 или 270 градусов, на другую поверхность. Параметры: cSurface& dest поверхность назначения. Замечания: ширина поверхности назначения должна быть равна высоте исходной поверхности, и высота поверхности назначения должна быть равна ширине исходной поверхности. BOOL Rotate(cSurface FAR& dest, int a, BOOL bAA, COLORREF clrFill = 0L, BOOL bTransp=TRUE); Копирует поверхность, повернутую на указанный угол, в поверхность назначения. Параметры: cSurface& dest поверхность назначения. Замечания: если Вам нужно вычислить размер прямоугольника назначения перед поворотом поверхности, используйте функцию GetSizeOfRotatedRect. Или Вы можете использовать функцию CreateRotatedSurface, которая автоматически меняет размер поверхности назначения. BOOL Rotate ( cSurface FAR& dest, double a, BOOL bAA, COLORREF clrFill = 0L, BOOL bTransp=TRUE ); То же самое, что и функция выше, но угол указывается в радианах. BOOL CreateRotatedSurface ( cSurface FAR& ps, double a, BOOL bAA, COLORREF clrFill = 0L, BOOL bTransp=TRUE ); BOOL CreateRotatedSurface ( cSurface FAR& ps, int a, BOOL bAA, COLORREF clrFill = 0L, BOOL bTransp=TRUE ); Те же самые функции, что и Rotate но меняет размер поверхности назначения для поворачиваемого прямоугольника. static void GetSizeOfRotatedRect (int FAR *pWidth, int FAR *pHeight, int angle); Статическая функция. Возвращает размер прямоугольника после поворота. Параметры: int* pWidth указатель на ширину прямоугольника, обновляется функцией. Позволяет Вам копировать или менять размер блока растра от одной поверхности в другую, с необязательными эффектами чернил (ink effects). BOOL Stretch ( cSurface FAR & dest, DWORD dwFlags = 0 ); Натягивает всю поверхность на другую. Параметры: cSurface& dest поверхность назначения. STRF_RESAMPLE = повторная оцифровка поверхности (качество лучше). Замечания: если указывается STRF_COPYALPHA, и поверхность имеет альфа-канал, то осуществляется натяжка на поверхность назначения (если поверхность назначения имеет альфа-канал. Если его нет, то он будет создан). Поверхность источника и назначения может иметь разную глубину цвета (конечно в этом случае все будет работать медленнее, чем когда поверхности имеют одинаковую глубину цвета). BOOL Stretch ( cSurface FAR & dest, int destX, int destY, int destWidth, int destHeight, BlitMode bm, BlitOp bo = BOP_COPY, LPARAM param = 0, DWORD dwFlags = 0 ); Натягивает всю поверхность в прямоугольник внутри другой поверхности с применением необязательных эффектов чернил (ink effects). Параметры: cSurface& dest поверхность назначения. STRF_RESAMPLE = делает повторную оцифровку поверхности (лучше качество). Замечания: если указано STRF_COPYALPHA, и поверхность имеет альфа-канал, то он натягивается на поверхность назначения (и если поверхность назначения не имеет альфа-канала, то он создается). Если STRF_COPYALPHA не указан, и blit-режим указан BMODE_TRANSP, то исходная поверхность "микшируется" с поверхностью назначения вместе с альфа-каналом, если он есть. Если у поверхности нет альфа-канала, и blit-режим задан BMODE_TRANSP, то используется цвет прозрачности поверхности. В текущей версии эффекты чернил не поддерживаются для поверхностей с альфа-каналами. Поверхность источника и назначения может иметь разную глубину цвета (конечно в этом случае все будет работать медленнее, чем когда поверхности имеют одинаковую глубину цвета). BOOL Stretch ( cSurface FAR & dest, int destX, int destY, int destWidth, int destHeight, int srcX, int srcY, int srcWidth, int srcHeight, BlitMode bm, BlitOp bo = BOP_COPY, LPARAM param = 0, DWORD dwFlags = 0 ); Натягивает прямоугольник внутри одной поверхности на прямоугольник внутри другой поверхности, с применением необязательных эффектов чернил (ink effects). Параметры те же самые, что и у предыдущей функции, плюс: int srcX, srcY координаты левого верхнего угла прямоугольника исходной поверхности. Эти функции позволяют Вам рисовать текст на поверхности. int DrawText ( LPCTSTR text, DWORD dwCharCount, LPRECT pRc, DWORD dtflags, COLORREF color=0, HFONT hFnt=NULL, BlitMode bm=BMODE_TRANSP, BlitOp bo=BOP_COPY, LPARAM param=0, int AntiA=0, DWORD dwLeftMargin=0, DWORD dwRightMargin=0,DWORD dwTabSize=8); Эта функция работает наподобие Windows-функций DrawText / DrawTextEx. Параметры: LPCTSTR text текст для печати. Возвращаемое значение: высота текста, или 0 если произошла ошибка. int TextOut ( LPCTSTR text, DWORD dwCharCount, int x, int y, DWORD alignMode, LPRECT pClipRc, COLORREF color=0, HFONT hFnt=NULL, BlitMode bm=BMODE_TRANSP, BlitOp=BOP_COPY, LPARAM param=0, int AntiA=0); Эта функция работает наподобие Windows-функции ExtTextOut. Параметры: LPCTSTR text текст для печати. Возвращаемое значение: не нулевое значение, если текст был нарисован на поверхности, 0 если произошла ошибка. Есть 2 способа поменять прозрачность поверхности. Либо установите её цвет прозрачности, либо её альфа-канал. BOOL IsTransparent();
Возвращает TRUE, если вся поверхность прозрачная. Если у поверхности есть альфа-канал, то функция вернет TRUE, если альфа-канал пуст. Если у поверхности нет альфа-канала, то функция вернет TRUE, если вся поверхность заполнена своим цветом прозрачности. void SetTransparentColor(COLORREF rgb); Меняет цвет прозрачности поверхности указанного цвета. Цвет прозрачности используется, например, в операциях Blit (побитное копирование) / Stretch (растяжение, сжатие). Если у поверхности есть альфа-канал, то цвет прозрачности игнорируется. Предупреждение: реальный цвет прозрачности зависит от глубины цвета поверхности (surface depth). Например, если поверхность глубиной 15 бит, то установка цвета 0xFFFFFF в качестве цвета прозрачности фактически установит цвет прозрачности в 0xF8F8F8, поскольку в 15-битном режиме используется только 5 бит на составляющий цвет. Если поверхность в 256-цветном режиме, то цвет прозрачности будет одним из ближайших к указанному цвету в 256-цветной палитре. COLORREF GetTransparentColor();
Возвратит текущий цвет прозрачности. int GetTransparentColorIndex(); Возвратит индекс цвета прозрачности в 256-цветном режиме. BOOL HasAlpha();
Вернет TRUE, если у поверхности есть альфа-канал. LPBYTE LockAlpha();
Вернет указатель на растр (bitmap) альфа-канала. Растр альфа-канала это 8-битная плоскость, каждая точка которой является полупрозрачной с коэффициентом от 0 до 255. 0 соответствует прозрачности, 255 отсутствию прозрачности. Используйте GetAlphaPitch после LockAlpha, чтобы получить ширину в байтах строки точек (внимание: эта ширина может быть отрицательной). Вы должны вызвать UnlockAlpha, когда Вам больше не нужен доступ к растру альфа-канала. void UnlockAlpha(); Разблокирует растр альфа-канала, заблокированный вызовом LockAlpha. int GetAlphaPitch(); Возвратит ширину в байтах строки точек растра альфа-канала, заблокированного LockAlpha. Предупреждение: эта ширина может быть отрицательной. void CreateAlpha(); Создает альфа-канал для поверхности. Маска инициализируется в 0. void SetAlpha(LPBYTE pAlpha, int nPitch); Устанавливает альфа-канал поверхности. Растр (bitmap) копируется в растр альфа-канала поверхности. Если у поверхности нет альфа-канала, то он создается перед тем, как туда будет скопирован растр. Параметры: LPBYTE pAlpha указатель на растр альфа-канала. void AttachAlpha(LPBYTE pAlpha, int nPitch); Подсоединяет растр альфа-канала к поверхности. Параметры: LPBYTE pAlpha указатель на растр альфа-канала. Замечания: в отличие от функции SetAlpha здесь растр, переданный в эту функцию, становится альфа-каналом поверхности. Любой предыдущий альфа-канал освобождается. Поверхность не удаляет растр альфа-канала, переданные в эту функцию, Вы должны удалить их самостоятельно вызовом функции DetachAlpha. Используйте эту функцию только для поверхностей памяти. LPBYTE DetachAlpha(LPLONG pPitch);
Отсоединяет альфа-канал, подсоединенный к поверхности. Используйте эту функцию, если у Вас подключен альфа-канал с помощью функции AttachAlpha. Параметры: LPLONG pPitch эта переменная принимает высоту (pitch) альфа-канала. Графические фильтры. Это новая возможность в CF. Она позволяет Вам загружать графические файлы. В системе CF графические фильтры обрабатываются менеджером фильтров изображений (Image Filter Manager), представленным объектом CImageFilterManager. Этот объект сохранен в структуре mv: CImageFilterMgr* pImgMgr = rhPtr->rh4.rh4Mv->mvImgFilterMgr; Объект CImageFilterMgr содержит список объектов CImageFilter, каждый такой объект поддерживает определенный формат файла картинки. Класс CImageFilterMgr содержит функции для обзора (enumerate) фильтров, открытия фильтра, соответствующего файлу картинки, и т. д. Класс CImageFilter содержит функции для загрузки, сохранения или получения информации из открытого файла картинки. Предоставлены также некоторые высокоуровневые функции, позволяющие Вам загрузить или сохранить картинку из / в файл картинки. Обычно Вы можете использовать эти функции вместо прямого использования фильтров. Импорт файла картинки с помощью графических фильтров CF осуществляется очень просто. Для этого есть 3 способа: 1. Вы можете вызвать функцию cSurface::LoadImage, но эта функция позволяет Вам загрузить только файлы BMP или DIB из ресурсов. 2. Рекомендуемый способ. Вы можете вызывать функции ImportImage, находящиеся в DLL (для этого подключите к своему исходному коду заголовок ImgFlt.h). BOOL WINAPI ImportImage(CImageFilterMgr* pImgMgr, LPCTSTR fileName, cSurface* psf, LPDWORD pDWFilterID, DWORD dwFlags) Параметры: CImageFilterMgr* pImgMgr образ менеджера фильтров. IMPORT_IMAGE_USESURFACEDEPTH: адаптация изображения к глубине поверхности назначения. 3. Вы можете самостоятельно просмотреть (enumerate) фильтры изображений с функциями классов CImageFilterMgr и CImageFilter, и загрузить свою картинку. Чтобы разобраться, как это делается, просмотрите исходный код функции ImportImageFromInputFile. [Другие функции] Функция ImportImage, описанная выше, это только одна из функций, которую Вы можете использовать для загрузки картинки. Есть и другие: BOOL WINAPI CanImportImage(CImageFilterMgr* pImgMgr, LPCTSTR fileName)
Вернет TRUE, если как минимум один графический фильтр поддерживает формат указанного файла картинки. BOOL WINAPI ChoosePicture (LPOPENFILENAME pOFN, BOOL bOpen,
CImageFilterMgr* pImgMgr, LPDWORD pDWFilterID,
DWORD dwFlags)
Открывает селектор файлов, который показывает уменьшенный образ картинки и её информацию. Параметры: LPOPENFILENAME pOFN указатель на структуру OPENFILENAME (для дополнительной информации см. описание Windows-функции GetOpenFilename). PICSEL_IMAGES: показывает форматы файлов картинок. BOOL WINAPI ImportImageFromInputFile(CImageFilterMgr* pImgMgr, CInputFile* pf, cSurface* psf, LPDWORD pDWFilterID, DWORD dwFlags) То же самое, что и ImportImage, но загружает картинку из объекта CInputFile вместо именованного файла. Класс CInputFile является базовым классом для классов CInputBufFile (буферизованный файл) и CInputMemFile (буфер в памяти), это позволяет Вам загрузить данные либо из памяти, либо в буфере памяти. Вы также можете создать свой собственный класс, унаследованный от CInputFile. BOOL WINAPI CanImportAnimation (CImageFilterMgr* pImgMgr, LPCTSTR fileName, BOOL* bNeedConversion) Возвращает TRUE, если как минимум один из графических фильтров поддерживает формат указанного файла изображения. bNeedConversion == FALSE, если файл изображения имеется анимацией, TRUE если это простой файл картинки. BOOL WINAPI BeginAnimationImport (CImageFilterMgr* pImgMgr, LPCTSTR pFileName, cSurface* psf, CImageFilter* pFilter, DWORD dwFlags) Открывает файл анимации и загружает первую картинку. CImageFilterMgr* pImgMgr образ менеджера фильтров. IMPORT_IMAGE_USESURFACEDEPTH: адаптация изображения к глубине поверхности назначения. Пример: CImageFilter filter(pImgMgr); cSurface sf; sf.Create(4, 4, pProtoSurf); if ( BeginAnimationImport(pImgMgr, fname, &sf, &filter, IMPORT_IMAGE_USESURFACEDEPTH | IMPORT_IMAGE_USESURFACEPALETTE) ) { // и т. д. }
BOOL WINAPI GetNextAnimationFrame (CImageFilterMgr* pImgMgr, cSurface* psf, CImageFilter* pFilter) Загружает следующий фрейм из анимации. Использует те же параметры, что и BeginAnimationImport. void WINAPI EndAnimationImport (CImageFilterMgr* pImgMgr, CImageFilter* pFilter) Закрывает файл анимации. Экспорт картинки с помощью графических фильтров CF осуществляется просто. Есть 3 способа: 1. Вы можете вызвать функцию cSurface::SaveImage, но эта функция позволяет только сохранить файлы BMP. 2. Рекомендованный способ. Вы можете вызвать функции ExportImage, находящиеся в DLL (подключите заголовок ImgFlt.h в исходном коде). BOOL WINAPI ExportImage (CImageFilterMgr* pImgMgr, LPCTSTR fileName, cSurface* psf, DWORD pDWFilterID) CImageFilterMgr* pImgMgr образ менеджера фильтров. 3. Вы можете сами просмотреть (enumerate) фильтры изображений функциями классов CImageFilterMgr и CImageFilter, и сохранить Вашу картинку. Чтобы разобраться в этом, просмотрите исходный код функции ExportImage. [Другие функции] Вы можете экспортировать анимации следующими функциями: BOOL WINAPI BeginAnimationExport (CImageFilterMgr* pImgMgr, LPCTSTR fileName, cSurface* psf, CImageFilter* pFilter, int nFrames, int msFrameDuration, int nLoopCount, int nLoopFrame) Создает файл анимации и экспортирует первую картинку. Вам нужно сначала инициализировать объект CImageFilter и проинструктировать для использования определенного фильтра. BOOL WINAPI ExportNextFrame (CImageFilterMgr* pImgMgr, cSurface* psf, CImageFilter* pFilter, int msFrameDuration) Экспортирует следующий фрейм. BOOL WINAPI EndAnimationExport (CImageFilterMgr* pImgMgr, CImageFilter* pFilter) Сбрасывает файл и закрывает его. Классы: Класс CImageFilterMgr позволяет Вам получить информацию из графических фильтров CF, которые установлены на машине пользователя и доступны для приложения. Вы можете получить указатель на объект CImageFilterMgr системы CF из структуры mV: CImageFilterMgr* pImgMgr = rhPtr->rh4.rh4Mv->mvImgFilterMgr; Функции CImageFilterMgr: int GetFilterCount (): возвращает количество графических фильтров. LPCTSTR GetFilterName (int nIndex): возвращает имя графического фильтра. LPCTSTR GetFilterFileName (int nIndex): возвращает имя файла графического фильтра. DWORD GetFilterID (int nIndex): возвращает идентификатор графического фильтра. int GetFilterIndex (DWORD dwID): возвращает индекс графического фильтра по его идентификатору. LPCTSTR* GetFilterExts (int nIndex): возвращает указатель на массив строк, содержащий поддерживаемые расширения файла для указанного графического фильтра. LPCTSTR* GetFilterDependencies (int nIndex): возвращает указатель на массив строк, который содержит имена файлов требуемых DLL для указанного графического фильтра. Примечание: эти DLL должны быть подключены в папку Data\Runtime, и туда не должны быть подключены стандартные, системные DLL. BOOL CanReadFile (int nIndex, CInputFile* pif): возвращает TRUE, если указанный фильтр может прочитать имеющийся файл. void RemoveFilter (int nIndex): удаляет указанный фильтр из списка. BOOL DoesFilterSupportAnimations(int nIndex): возвращает TRUE, если указана поддержка файлов анимации. Класс CImageFilter позволяет Вам загрузить или сохранить графические файлы через графические фильтры CF. Графические функции, описанные в разделах "Импортирование / Экспортирование графических файлов", проще по использованию, чем функции класса CImageFilter, так что разработчики CF рекомендуют использовать их вместо функций класса CImageFilter, если это возможно. Также некоторые из описанных ниже функций не описаны подробно, поскольку у разработчиков есть платны обновить их в будущих версиях SDK. Функции CImageFilter: CImageFilter(CImageFilterMgr* pMgr): инициализирует объекты CImageFilter. pMgr это объект CImageFilterMgr системы CF. int Open(LPCTSTR fileName): находит графические фильтры, которые могут открыть указанный файл, и открывает найденный фильтр. int Open(CInputFile* pf): находит графический фильтр, который может открыть указанный файл, и открывает этот фильтр. Возвращает IF_OK, если все хорошо, или другой код ошибки IF_xxx. void Close(): закрывает фильтр. С ним не будет выполняться никаких операций, пока фильтр не будет открыт повторно. BOOL UseSpecificFilterIndex(int index): принуждает объект использовать указанный графический фильтр. Параметр index является индексом графического фильтра в объекте CImageFilterMgr. Возвращает TRUE, если фильтр не найден. BOOL UseSpecificFilterID(DWORD dwID): принуждает объект использовать указанный графический фильтр. Параметр dwID это идентификатор графического фильтра. Возвратит TRUE, если фильтр найден. DWORD GetFilterID(): возвращает идентификатор графического фильтра, который в настоящее время открыт объектом CImageFilter. LPCTSTR GetFilterName(): возвращает имя графического фильтра, который в настоящее время открыт объектом CImageFilter. int GetFilterIndex(): возвращает индекс графического фильтра, который в настоящее время открыт объектом CImageFilter. DWORD GetFilterColorCaps(): возвращает цветовые возможности графического фильтра, который в настоящее время открыт объектом CImageFilter. Результатом будет один или несколько следующих флагов: FLTCOLORCAPS_1: поддерживает монохромные картинки. int GetWidth(): возвращает ширину текущего изображения. int GetHeight(): возвращает высоту текущего изображения. int GetPitch(): возвращает высоту (ширину в байтах) текущего изображения. int GetDepth(): возвращает глубину текущего текущей картинки. DWORD GetDataSize(): возвращает размер буфера растра. LPLOGPALETTE GetPalette(): возвращает указатель на палитру картинки (NULL, если у картинки нет цветовой палитры). BOOL GetTransparentColor(COLORREF* pTranspColor): возвращает цвет прозрачности картинки, если он есть. BOOL ContainsAlphaChannel(): возвращает TRUE, если картинка содержит альфа-канал. int PrepareLoading(int width, int height, int depth, LPLOGPALETTE pPal): Вы не должны использовать эту функцию, она вызывается фунцией Load. int Load(LPBYTE pData, int width, int height, int pitch, int depth=0, LPLOGPALETTE pPal=NULL, LPBYTE pAlpha=NULL, int nAlphaPitch=0): загружает картинку (или следующую картинку для файлов анимации) в буфер. Параметр pData это адрес буфера, width / height / pitch / depth это характеристики буфера, pPal это указатель на палитру, используемую буфером, pAlpha указатель на буфер, который примет альфа-канал (если он есть), и nAlphaPitch это ширина в байтах строки в этом буфере. BOOL CanSave(): возвращает TRUE, если графический фильтр может сохранить файлы картинки. BOOL CanSaveAnim(): возвращает TRUE, если графический фильтр может сохранить файлы анимации. void SetCompressionLevel(int nLevel=-1); int Save(LPCTSTR fileName, LPBYTE pData, int nWidth, int nHeight, int nDepth, int nPitch, LPLOGPALETTE pPal, LPBYTE pAlpha=NULL, int nAlphaPitch=0); BOOL IsAnimation(): возвратит TRUE, если файл содержит анимацию. int GetNumberOfFrames(): возвращает количество фреймов в анимации. int GetCurrentFrame(): возвращает индекс текущего фрейма. int GetFrameDelay(int frameIndex=-1): возвращает длительность фрейма в миллисекундах. Параметр frameIndex это индекс фрейма. DWORD GetAnimDuration(): возвращает общую длительность анимации. LPBYTE GetUserInfo(): возвращает указатель на информацию пользователя, сохраненную в файле (если формат файла это поддерживает). DWORD GetUserInfoSize(): возвращает размер пользовательской информации, сохраненной в файле (если формат файла это поддерживает). void Restart(): перезапускает анимацию. int GoToImage(LPBYTE pData, int pitch, int n): переходит к определенному фрейму анимации (указан по параметру n) и загружает его в указанный буфер. void GetUpdateRect(LPRECT pRc): возвращает прямоугольник, который был модифицирован предыдущей функцией Load. int GetLoopCount(): возвращает счетчик циклов. int GetLoopFrame(): возвращает индекс фрейма для зацикливания. int CreateAnimation(LPCTSTR fname, int width, int height, int depth, int nFrames, int msFrameDuration, int nLoopCount = 1, int nLoopFrame = 0, LPBYTE pUserInfo = NULL, DWORD dwUserInfoSize = 0): создает файл анимации с указанными характеристиками. int CreateAnimation(COutputFile* pfout, int width, int height, int depth, int nFrames, int msFrameDuration, int nLoopCount = 1, int nLoopFrame = 0, LPBYTE pUserInfo = NULL, DWORD dwUserInfoSize = 0): создает файл анимации с указанными характеристиками. int SaveAnimationFrame(LPBYTE pData, int width, int height, int pitch, int depth, LPLOGPALETTE pPal, LPBYTE pAlpha, int nAlphaPitch, int msFrameDuration, DWORD dwFlags): сохраняет первый фрейм анимации. Параметр pData это буфер, содержащий данные растра, другие параметры содержат другие характеристики этого буфера. pAlpha содержит альфа-канал, если он есть. int SaveAnimationFrame(LPBYTE pData, LPBYTE pPrevData, int width, int height, int pitch, int depth, LPLOGPALETTE pPal, LPBYTE pAlpha, LPBYTE pPrevAlpha, int nAlphaPitch, int msFrameDuration, DWORD dwFlags): сохраняет следующий фрейм анимации. Параметр pData это буфер, содержащий данные растра, другие параметры содержат другие характеристики этого буфера. pPrevData это буфер, который содержит данные растра предыдущего фрейма. pAlpha содержит альфа-канал, если он есть. void AddPreviousFrameDuration(int msFrameDuration): инкрементирует длительность предыдущего фрейма (не используется в текущих фильтрах). DWORD GetCurrentSaveAnimSize(): возвращает текущую длину файла анимации, в байтах. Файловые функции. MMFS2 содержит некоторые функции и объекты C++, которые помогают обрабатывать файлы, особенно если Вы собираете или используете графические или звуковые файлы. Функции File_xxx работают с хендлами файлов Windows, и просто напрямую используют Windows-функции CreateFile / ReadFile / WriteFile / и т. д. Эти функции могут выглядеть бесполезными, поскольку Вы можете использовать вместо этого Windows-функции. Но Вы должны использовать их при возможности, потому что таким способом достигается независимость от определенной платформы, и не должны поменяться, когда код CF runtime будет портирован на другие платформы. Классы CInputFile и COutputFile это простые объекты C++, наподобие MFC-класса CFile. Они позволяют Вам читать (и записывать) файлы из разных источников, например дисковые файлы или буферы памяти. Вы можете создать свой собственный класс и унаследовать его от CInputFile или COutputFile. Класс CInputFile используется в фильтрах, это позволяет Вам передать либо буферы памяти, либо дисковые файлы для графических и звуковых файлов. HFILE WINAPI File_Create(LPCTSTR fname) Создает файл и открывает его для чтения или записи. Параметры: LPCTSTR fname имя файла. Возвращаемое значение: хендл файла (это HANDLE, возвращенный Windows-функцией CreateFile). Возвратит HFILE_ERROR (==INVALID_HANDLE_VALUE), если произошла ошибка. HFILE WINAPI File_Open (LPCTSTR fname, int mode)
Открывает файл для чтения из него и/или для записи в него. Параметры: LPCTSTR fname имя файла. OF_READ: открывает файл только для чтения. Возвращаемое значение: хендл файла (это HANDLE, возвращенный Windows-функцией CreateFile). Возвратит HFILE_ERROR (==INVALID_HANDLE_VALUE), если произошла ошибка. void WINAPI File_Close(HFILE hf)
Закрывает файл, открытый функциями File_Open или File_Create. Параметры: HFILE hf хендл файла. int WINAPI File_Read (HFILE hf, LPVOID buf, DWORD len)
int WINAPI File_ReadAndCount (HFILE hf, LPVOID buf, DWORD len)
Читает данные из указанного файла. Параметры: HFILE hf хендл файла. Возвращаемое значение: File_ReadAndCount возвратит количество прочитанных байт. File_Read вернет один из следующих кодов: CFCERROR_NOERROR = нет ошибки. BOOL WINAPI File_Write (HFILE hf, LPVOID buf, DWORD len) Запись данных в указанный файл. Параметры: HFILE hf хендл файла. Возвращаемое значение: один из следующих кодов: CFCERROR_NOERROR = нет ошибки. long WINAPI File_GetLength(HFILE hf)
Возвращает длину файла в байтах. Параметры: HFILE hf хендл файла. Возвращаемое значение: длина файла в байтах. long WINAPI File_GetPosition(HFILE hf)
Возвращает текущую позицию в файле. Параметры: HFILE hf хендл файла. Возвращаемое значение: позиция в байтах. long WINAPI File_SeekBegin (HFILE hf, long pos) long WINAPI File_SeekCurrent (HFILE hf, long pos) long WINAPI File_SeekEnd (HFILE hf, long pos) Перемещает указатель по файлу относительно начала файла (File_SeekBegin), от конца файла (File_SeekEnd) или от текущей позиции (File_SeekCurrent). Параметры: HFILE hf хендл файла. Возвращаемое значение: предыдущая позиция указателя по файле. BOOL WINAPI File_Exists(LPCTSTR pName) Эта функция проверяет, существует ли файл в указанном месте. Параметры: LPCTSTR pName имя файла. Возвращаемое значение: TRUE если файл существует, иначе FALSE. Классы: Класс CInputFile это базовый класс для чтения из файлов или буферов памяти. [Функции базового класса] virtual void Delete (): удаляет объект. Для использования ТОЛЬКО если объект был создан с помощью MMFS2.DLL, так как эта функция удаляет объект с выделениями памяти подпрограмм этой DLL. Обычно Вы не должны использовать эту функцию. virtual int Read (LPBYTE dest, DWORD lsize): читает lsize байт в буфер dest, возвратит код ошибки (CFCERROR_NOERROR если ошибки не было, CFCERROR_ENDOFFILE если был достигнут конец файла, или другой код в случае ошибки). virtual int Read (LPBYTE dest, DWORD lsize, LPDWORD pRead): читает lsize байт в буфер dest, и сохраняет количество прочитанных байт в ячейку *pRead, возвращает код ошибки. virtual int ReadByte (LPBYTE dest): читает 1 байт. virtual int ReadIntelWord (LPWORD dest): читает 1 слово в формате Intel (переставьте байты на платформах Mac). virtual int ReadIntelDWord (LPDWORD dest): читает одно двойное слово в формате Intel (переставьте байты на платформах Mac). virtual int ReadMacWord (LPWORD dest): читает 1 слово в формате Mac (переставьте байты на платформах Intel). virtual int ReadMacDWord (LPDWORD dest): читает одно двойное слово в формате Mac (переставьте байты на платформах Intel). virtual int ReadIntelFloat (PFLOAT dest): читает одно число float в формате Intel (переставьте байты на платформах Mac). virtual int ReadMacFloat (PFLOAT dest): читает одно число float в формате Mac (переставьте байты на платформах Intel). virtual int ReadIntelWordArray (LPWORD dest, int count): читает массив слов в формате Intel (переставьте байты на платформах Mac). virtual int ReadIntelDWordArray (LPDWORD dest, int count): читает массив двойных слов в формате Intel (переставьте байты на платформах Mac). virtual int ReadIntelFloatArray (PFLOAT dest, int count): читает массив чисел float в формате Intel (переставьте байты на платформах Mac). virtual int ReadMacWordArray (LPWORD dest, int count): читает массив слов в формате Mac (переставьте байты на платформах Intel). virtual int ReadMacDWordArray (LPDWORD dest, int count): читает массив двойных слов в формате Mac (переставьте байты на платформах Intel). virtual int ReadMacFloatArray (PFLOAT dest, int count): читает массив чисел float в формате Mac (переставьте байты на платформах Intel). virtual long GetPosition (): возвращает текущую позицию в файле. virtual long GetLength (): возвращает размер файла в байтах. virtual long Seek (long pos, int method): перемещает указатель в другую позицию, либо относительно начала (method=SEEK_SET), либо относительно конца (method=SEEK_END), либо относительно текущей позиции (method=SEEK_CUR) файла. virtual int Attach (HANDLE hnd): используется только классом CInputBufFile. Позволяет подсоединить хендл файла к объекту. virtual HANDLE Detach (): используется только классом CInputBufFile. Позволяет отсоединить хендл файла от объекта. virtual LPBYTE GetBuffer (UINT nSize): возвращает указатель на буфер, который содержит nSize байт, прочитанных из файла. Примечание: Вы не должны записывать в этот буфер. virtual void FreeBuffer (LPBYTE buf): освобождает любой буфер, выделенный вызовом GetBuffer. virtual LPCTSTR GetFileName (): возвращает указатель на имя файла, NULL если с этим объектом дисковый файл не ассоциирован. Примечание: если Вы создаете свой собственный класс, унаследованный от этого, то должны реализовать как минимум функции Read, ReadByte, GetPosition, GetLength, Seek, Attach, Detach и GetFilename. [Унаследованные классы] CInputBufFile. Этот класс позволяет Вам читать данные из дискового файла. Класс содержи функции класса CInputFile плюс следующее: static CInputBufFile* NewInstance(): создает новый объект CInputBufFile. Используется, если объект может быть удален из DLL. Если Вы хотите удалить объект, созданный этой функцией, то должны использовать его метод Delete. int Create(HFILE hf): создает новый объект CInputBufFile, подключенный к указанному хендлу файла. int Create(HFILE hf, DWORD dwOffset, DWORD dwSize): создает новый объект CInputBufFile для указанного хендла файла, но ограниченный указанной частью файла, начинающейся с указанного смещения и имеющей указанный размер. int Create(LPCTSTR filename): создает новый объект CInputBufFile для указанного файла. int Create(LPCTSTR filename, DWORD dwOffset, DWORD dwSize): создает новый объект CInputBufFile, подсоединенный к указанному файлу, но ограниченный указанной частью файла, начинающейся с указанного смещения и имеющей указанный размер. CInputMemFile. Этот класс позволяет Вам читать данные из буфера памяти. Он содержит функции класса CInputFile плюс следующее: static CInputMemFile* NewInstance (): создает новый объект CInputMemFile. Используется, если этот объект может быть удален из DLL. Если Вы хотите удалить объект, созданный этой функцией, то должны использовать его метод Delete. int Create (LPBYTE buffer, DWORD lsize): создает новый объект CInputMemFile, подключенный к имеющемуся буферу памяти. int Create (DWORD lsize): создает новый объект CInputMemFile, и выделяет новый буфер памяти. Используйте GetMemBuffer, чтобы получить указатель на буфер, который Вы можете заполнить. int GetMemBuffer (): возвращает указатель на буфер памяти. Класс COutputFile является базовым для записи файлов или буферов памяти. [Функции базового класса] virtual int Write (LPBYTE pb, UINT sz): записывает sz байт из буфера pb, возвращает код ошибки (CFCERROR_NOERROR если ошибки нет, CFCERROR_ENDOFFILE, если достигнут конец файла, или другое если произошла ошибка). virtual int WriteIntelWord (LPWORD dest): записывает одно слово в формате Intel (переставьте байты на платформах Mac). virtual int WriteIntelDWord (LPDWORD dest): записывает одно двойное слово в формате Intel (переставьте байты на платформах Mac). virtual int WriteMacWord (LPWORD dest): записывает одно слово в формате Mac (переставьте байты на платформах Intel). virtual int WriteMacDWord (LPDWORD dest): записывает одно двойное слово в формате Mac (переставьте байты на платформах Intel). virtual int WriteIntelFloat (PFLOAT dest): записывает одно число float в формате Intel (переставьте байты на платформах Mac). virtual long Flush (): принудительно заставляет сбросить в файл все внутренние буферы. virtual long GetPosition (): возвращает текущую позицию в файле. virtual long GetLength (): возвращает размер файла в байтах. virtual long Seek (long pos, int method): перемещает позицию в файле в другую позицию, либо с отсчетом относительно начала (method=SEEK_SET), либо от конца (method=SEEK_END), либо от текущей позиции (method=SEEK_CUR) файла. virtual LPCTSTR GetFileName (): возвращает указатель на имя файла, NULL если с объектом не связан дисковый файл. Примечание: если Вы создаете свой собственный класс, унаследованный от этого, то должны реализовать как минимум функции Write, Flush, GetPosition, GetLength, Seek и GetFilename. [Производные классы] COutputBufFile. Этот класс позволяет Вам записывать данные в дисковый файл. Он содержит функции родительского класса COutputFile плюс следующие: int Create(HFILE hf, UINT nBufferSize = 4096): создает новый объект COutputBufFile, подсоединенный к имеющемуся хендлу файла. Параметр nBufferSize задает размер внутреннего буфера. int Create(LPCTSTR fname, UINT nBufferSize = 4096): создает новый объект COutputBufFile, подсоединенный к указанному файлу. Параметр nBufferSize задает размер внутреннего буфера. COutputMemFile. Этот класс позволяет Вам записать данные в буфер памяти. Он содержит функции класса COutputFile плюс следующие: int Create (UINT nBlockSize = 512): создает новый объект COutputMemFile. Размер буфера будет кратным параметру nBlockSize. int Create (LPBYTE buffer, DWORD nBufferSize): создает новый объект COutputMemFile, подсоединенный к имеющемуся буферу памяти. Этот буфер не освобождается, когда объект будет удален. int GetBuffer (): возвращает указатель на буфер памяти. int DetachBuffer (): возвращает указатель на буфер памяти, и отсоединяет буфер памяти от объекта. int FreeBuffer (LPBYTE pBuffer): освобождает указатель, возвращенный вызовом DetachBuffer (если он был выделен сначала функцией Create). [Ссылки] 1. Download: Fusion 2.5 Windows SDK site:community.clickteam.com. |