Использование html-файлов для создания диалоговых окон применяется чаще всего в качестве сплэш-скринов разных триальных защит (первое, что приходит на память - протектор Armadillo и wrapper'ы от различных игровых дистрибьюторов) или в некоторых "демонстрашках", использующих графические эффекты. Плюсов тут много: вместо кропотливой низкоуровневой обработки шрифтов и цветных символов, визуальных эффектов и картинок, достаточно все это описать обычным CSS и HTML-тегами в HTML-странице, а с помощью скриптов JavaScript добавить нужную интерактивность. Кроме этого можно вынести из основного программного кода часть каких-нибудь зубодробильных вычислений на JavaScript, а потом передать результат основному приложению. У меня, например, по такому принципу написана новая версия
Eval JavaScript Unpacker.
Для создания окна сперва надо определить в сегменте данных некоторые значения. Главные из них - имя HTML-файла и параметры открываемого окна.
; Сегмент данных
section '.data' data readable writeable
szRes du 'res://',0
lenRes = $-szRes-2
szName du '/htmldialog.html',0 ; Имя html-файла в ресурсах
szParam du 'dialogWidth:350px;dialogHeight:200px;help:off;',0
hMoniker dd ? ; Хэндл моникера
szUrl rb 200h ; Путь к основному файлу
szParam - размер и дополнительные параметры создаваемого диалогового окна, их полный список и доступные значения есть в описании функции
showModalDialog. Обратите внимание, что строки пути к HTML-файлу записываются в юникоде, соответственно, все функции работы со строками в вашем приложении должны быть юникодные.
Для создания окна сперва надо определить полный путь до html-файла и создать из него системный моникер функцей
CreateURLMoniker. Моникер - это специальная метка, которая используется для подключения к COM-объектам. Здесь есть несколько особенностей. Если используется внешний файл, надо указывать полный путь до него. Если же HTML-файл хранится в ресурсах исполняемого файла, то к путь к нему формируется по схеме "res://" + полный путь до исполняемого файла + "/" + имя html-файла. Напомню, что все пути к HTML-файлу должны быть в юникоде. Поддерживаются упакованные и зашифрованные файлы, в которых ресурсы также упакованы. Идентификатор файла в ресурсах обязательно должен быть строковым, а не числовым. FASM не позволяет использовать строки в качестве идентификаторов в ресурсах, поэтому приходится подключать внешние файлы ресурсов, предварительно откомпилировав их. После того, как моникер создан, можно открывать диалоговое окно функцией
ShowHTMLDialog. Простейший код приведен ниже.
...
; Создать системный моникер
invoke CreateURLMoniker,NULL,szUrl,hMoniker
; Создать диалог из html-файла
invoke ShowHTMLDialog,NULL,[hMoniker],NULL,szParam,NULL
...
После его выполнения будет создано окно заданного размера и свойств, но с иконкой браузера Internet Exlporer. В Windows 7 вместо иконки IE будет иконка документа. Это один из основных недостатков описанного метода, и я пока не нашел простого способа, чтобы заменить иконку созданного окна на свою собственную. Другой недостаток в том, что даже из упакованных файлов можно извлечь содержимое HTML-файла для просмотра и изучения.
Теперь перейдем к самой интересной части - взаимодействию между основным приложением и окном из HTML-файла. По этой теме я не нашел никакой толковой документации, пришлось все изучать на живом коде под отладчиком. Поэтому все выкладки будут в основном теоретическими, и я не удивлюсь, если случайно изобрел велосипед. В параметрах функции ShowHTMLDialog передаются указатели на две структуры: данные, передаваемые HTML-окну и данные, передаваемые родительскому приложению после закрытия HTML-окна. Обе структуры имеют одинаковый формат:
; Структура для взаимодействия с html-окном
struct HTMLARGUMENT
wType dw ? ; Тип передаваемого или получаемого аргумента
wReserved dw ? ; 2 байта, зарезервировано
dReserved dd ? ; 4 байта, зарезервировано
lpArg dd ? ; Указатель на аргумент
ends
Первый элемент структуры - слово wType - тип передаваемых данных. Опытным путем удалось выяснить некоторые значения:
Code (Assembler) : Убрать нумерацию
VARTYPE_INTEGER = 3 ; Целое число
VARTYPE_STRING = 8 ; Строка
VARTYPE_ARRAY = 9 ; Массив
В зарезервированных полях могут быть случайные данные, их назначение пока непонятно, но на результат они никакого влияния не оказывают. В элементе lpArg записан указатель на сами передаваемые данные. Строка должна быть записана в юникоде и заканчиваться нулем, целое число хранится в ячейке размером в DWORD, а как хранится и передается массив, я так и не осилил. Обработка входных и выходных параметров в HTML-файле выполняется средствами JavaScript, например:
//-------------------------------------------------------------------
// Функция получения параметров от родительского приложения
//-------------------------------------------------------------------
function getArguments() {
// Получить переданные параметры
var tmp=window.dialogArguments;
if (tmp!='') {
alert('Переданы данные из основного приложения: '+tmp);
}
else {
alert('Ничего не передано');
}
}
//-------------------------------------------------------------------
// Функция передачи параметров родительскому приложению
//-------------------------------------------------------------------
function setArguments(tmp) {
// Установить параметры, передаваемые родительскому приложению
window.returnValue = tmp;
// Закрыть диалоговое окно
window.close();
}
В приложении пример программы, использующей HTML-файл из своих ресурсов для создания диалогового окна, которое взаимодействует с родительским приложением. А также я выложил отдельно Microsoft Resource Compiler из пакета MASM32 для компиляции ресурсов.