Пишем электронную книгу или добавление других файлов в исполняемый файл



Сейчас мы поговорим о возможности добавления в скомпилированный исполняемый файл других файлов без использования секции ресурсов.
Файлы будут располагаться непосредственно в секции кода исполняемого файла.
Это значит что они будут загружаться в память при запуске программы.

В PureBasic, для размещения файлов в секции кода, существуют операторы DataSection, IncludeBinary и EndDataSection
Синтаксис такой:
Код:
DataSection
Metka_1:
IncludeBinary "Путь к файлу"
Metka_2:
EndDataSection
После оператора IncludeBinary в кавычках указывается абсолютный или относительный путь к требуемому файлу.
Метки с именами Metka_1 и Metka_2 расположеные перед и после оператора IncludeBinary позволяют получить содержимое файла. Для этого достаточно узнать адрес метки в памяти.


Для примера, создадим небольшую электронную книгу из этих html файлов. Для этого понадобится создать окно и разместить там два веб браузера, один для странички навигации, а второй для страничек учебника. Кроме того, нам понадобится перехватывать клики по ссылкам в первом браузере, чтобы во первых, предотвратить загрузку данных в браузер по этим ссылкам, а во вторых чтобы узнать имя загружаемой странички и самим ещё загрузить из кодовой секции исполняемого файла.

Код программы приведён ниже

Код:
; Пример электронного учебника.
; Компилятор PureBasic

Procedure NavigationCallback(Gadget, Url$) ; В этой процедуре перехватываем клики в браузере-навигаторе.
If Url$<>""
Url$=LCase(Url$)
pos=FindString(Url$, "about:blank",1)
If pos>0
Url$=Right(Url$,Len(Url$)-pos-10)
EndIf

Select Url$ ; Узнаём какую страничку загрузить из памяти в браузер
Case "ch1.html"
SetGadgetItemText(1,#PB_Web_HtmlCode,PeekS(?ch1, ?ch1End-?ch1))
Case "ch2.html"
SetGadgetItemText(1,#PB_Web_HtmlCode,PeekS(?ch2, ?ch2End-?ch2))
Case "ch3.html"
SetGadgetItemText(1,#PB_Web_HtmlCode,PeekS(?ch3, ?ch3End-?ch3))
Case "ch4.html"
SetGadgetItemText(1,#PB_Web_HtmlCode,PeekS(?ch4, ?ch4End-?ch4))
Case "ch5.html"
SetGadgetItemText(1,#PB_Web_HtmlCode,PeekS(?ch5, ?ch5End-?ch5))
Case "ch6.html"
SetGadgetItemText(1,#PB_Web_HtmlCode,PeekS(?ch6, ?ch6End-?ch6))
EndSelect

EndIf
ProcedureReturn 0 ; Запрет открытия ссылки браузером
EndProcedure

; Открываем окно
If OpenWindow(0, 0, 0, 800, 500, "WebGadget", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible)
WebGadget(0, 10, 10, 150, 480, "") ; Браузер-навигатор
SetGadgetItemText(0,#PB_Web_HtmlCode,PeekS(?h, ?hEnd-?h)) ; Загрузка из памяти странички навигации
SetGadgetAttribute(0,#PB_Web_NavigationCallback,@NavigationCallback()) ; Установка процедуры-перехватчика кликов по ссылкам
WebGadget(1, 180, 10, 780-180, 480, "") ; Браузер, отображающий выбираемые странички
SetGadgetItemText(1,#PB_Web_HtmlCode,PeekS(?ch1, ?ch1End-?ch1)) ; Загрузка из памяти начальной странички
HideWindow(0,0) ; Отображение окна

Repeat ; Это главный цикл прогаммы - обработчик событий. Мы отслеживаем только закрытие окна
Until WaitWindowEvent() = #PB_Event_CloseWindow

EndIf
End ; Типа всё, программа завершает работу


; Вот этот код при компиляции загружает файлы в исполняемый файл.
; Доступ к файлам как к памяти получаем с помощью меток
DataSection
h:
IncludeBinary "h.html"
hEnd:

ch1:
IncludeBinary "ch1.html"
ch1End:

ch2:
IncludeBinary "ch2.html"
ch2End:

ch3:
IncludeBinary "ch3.html"
ch3End:

ch4:
IncludeBinary "ch4.html"
ch4End:

ch5:
IncludeBinary "ch5.html"
ch5End:

ch6:
IncludeBinary "ch6.html"
ch6End:
EndDataSection
Теперь разберёмся как этот код работает.
Процедура NavigationCallback вызывается при клике по ссылке в браузере-навигаторе и ей передаётся адрес ссылки через переменную строковую Url$. В процедуре анализируется адрес ссылки и загружается из памяти соответствующий Html файл.
Например, файл ch1.html загружает в браузер такая строка
Код:
SetGadgetItemText(1, #PB_Web_HtmlCode, PeekS(?ch1, ?ch1End-?ch1) )
С помощью функции PeekS производится загрузка текста из памяти (html код это текст). Адрес памяти и длина памяти вычисляется с помощью меток перед и после оператора IncludeBinary, о чём писалось выше. Для получения адреса метки, перед её именем нужно поставить символ ?.
Подробнее об этом можно узнать здесь
Функция SetGadgetItemText загружает текст в браузер в формате html, что задаётся с помощью константы-флага #PB_Web_HtmlCode.

Фактически программа начинает выполнятся с функции OpenWindow, открывающей окно.
После открытия окна, создаётся браузер с идентификатором 0 и в него по умолчанию загружается код html странички ch1.html.
После этого, процедура NavigationCallback регистрируется как обработчик кликов этого браузера.

Далее создаётся ещё один браузер (ему присваивается идентификатор 1), в котором будут отображаться странички учебника.
Далее следует код
Код:
Repeat ; Это главный цикл программы - обработчик событий. Мы отслеживаем только закрытие окна
Until WaitWindowEvent() = #PB_Event_CloseWindow
являющийся главным циклом программы, в котором обрабаотывается только одно событие, закрытие окна.


В конце исходного текста, находятся операторы DataSection, IncludeBinary и EndDataSection загружающие html-файлы в исполняемый файл программы на этапе компиляции.



Скачать все требуемые файлы




Учебник                Главная
Сайт создан в системе uCoz