Как сделать свой браузер на c

Добавил пользователь Дмитрий К.
Обновлено: 04.10.2024

Поставим задачу расширения дизайна этих компонентов. Мы не будем менять их код. Мы создадим на форме три кнопки, DriveComboBox, FileListBox сделаем невидимыми, в заменим их
ComboBox и ListBox компонентами соответсвенно.

Стандартные папки:
AnsiString SystemDir, WindowsDir, TempDir;
AnsiString MyDocumentsFolder ,Desktop;

char specfolder[MAX_PATH];
GetSystemDirectory(specfolder,100);
SystemDir = specfolder;
GetWindowsDirectory(specfolder,100);
WindowsDir=specfolder;
TempDir = WindowsDir+"\\Temp";
SHGetSpecialFolderPath(Handle, specfolder, 0x0005, false);
MyDocumentsFolder = specfolder;
SHGetSpecialFolderPath(Handle, specfolder, 0x0000, false);
Desktop = specfolder;

Теперь мы знаем местоположение и буквы дисков компьютера. Осталось заполнить полученными данными ComboBox.

Напишем специальную структуру, и создадим массив на её базе:
enum TPathType ptMyDocuments, ptWinSystem, ptWindows, ptWinTemp,
ptUserDefined >;

struct TPath TPathType PathType; //Тип пути
AnsiString DefDir; //Каталог пути
AnsiString Name; //Имя пути
>StdPath[40];

Для определения типа пути по его каталогу и размещения полученных данных в массиве напишем функцию:
void AddUserPath(AnsiString DefDir, AnsiString Name, int PathID) StdPath[PathID].Name = Name;
StdPath[PathID].DefDir = DefDir;
Form1->ComboBox1->Items->Add(DefDir+" "+Name+"");
if(DefDir.Length()==2) switch(GetDriveType(DefDir.c_str())) case DRIVE_CDROM:
StdPath[PathID].PathType = ptCdrom;
return;
case DRIVE_REMOTE:
StdPath[PathID].PathType = ptNetworkDrive;
return;
case DRIVE_FIXED:
StdPath[PathID].PathType = ptHardDisk;
return;
case DRIVE_REMOVABLE:
StdPath[PathID].PathType = ptFloppy;
return;
default:
StdPath[PathID].PathType = ptDisk;
return;
>
>
if(DefDir==MyDocumentsFolder) StdPath[PathID].PathType = ptMyDocuments;
return;
>
if(DefDir==SystemDir) StdPath[PathID].PathType = ptWinSystem;
return;
>
if(DefDir==WindowsDir) StdPath[PathID].PathType = ptWindows;
return;
>
if(DefDir==TempDir) StdPath[PathID].PathType = ptWinTemp;
return;
>
if(DefDir==Desktop) StdPath[PathID].PathType = ptDestkop;
return;
>
StdPath[PathID].PathType = ptUserDefined;
>

Благодаря функции GetDriveType мы узнаём тип данного диска.

Теперь мы можем проинициализировать ComboBox:
for(int i=0; i Items->Count; i++) AddUserPath(DriveComboBox1->Items->Strings[i].SubString(1,2),DriveComboBox1->Items->Strings[i].c_str()+3,i);
>
AddUserPath(SystemDir, "Системная папка", USER_PATH);
AddUserPath(WindowsDir, "Папка Windows", USER_PATH+1);
AddUserPath(TempDir, "Временные файлы", USER_PATH+2);
AddUserPath(MyDocumentsFolder, "Мои документы", USER_PATH+3);
AddUserPath(Desktop, "Рабочий стол", USER_PATH+4);

Для каждого типа пути нужна своя картинка. Проинициализируем её.
Мы разместим все картинки в папочке Interface. Каждому типу пути поставим в соответствие свою картинку:

AnsiString PathIconNames[] = "Destkop.bmp",
"NetDisk.bmp",
"HardDisk.bmp",
"CDDisk.bmp",
"Floppy.bmp",
"Disk.bmp",
"Mydocs.bmp",
"Winsys.bmp",
"Windows.bmp",
"WinTemp.bmp",
"User.bmp"
>;

Проинициализируем их:
for(int i=0; i

PathIcons[i] = new Graphics::TBitmap();
PathIcons[i]->LoadFromFile("interface\\" + PathIconNames[i]);
PathIcons[i]->Transparent = true;
>

void __fastcall TForm1::FormDestroy(TObject *Sender)
for(int i=0; i

Теперь самое интересное - отрисовка элементов ComboBox. Для этого свойство Style надо установить в csOwnerDrawFixed (только отрисовка), выбрать ItemHeight по размерам картинок (у меня было значение 24 для картинок 16 на 16), а событие OnDrawItem заполнить следующим кодом:
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control, int Index,
TRect &Rect, TOwnerDrawState State)
ComboBox1->Canvas->FillRect(Rect);
ComboBox1->Canvas->Draw(Rect.Left+4,Rect.Top+4, PathIcons[StdPath[Index].PathType]);
if(StdPath[Index].PathType>=ptNetworkDrive && StdPath[Index].PathType Canvas->TextOut(Rect.Left+48, Rect.Top+6, StdPath[Index].Name);
ComboBox1->Canvas->TextOut(Rect.Left+28, Rect.Top+6, StdPath[Index].DefDir);
>
else ComboBox1->Canvas->TextOut(Rect.Left+28, Rect.Top+6, StdPath[Index].Name);
>
>

Половина дела сделанa. Теперь на очереди FileListBox.
Так как картинки из этого компонента нам не подходят, а TIcon не может менять размеры значка, мы опять всё пишем руками :)
Сначала напишем функцию SetPath. Онабудет вызываться при изменении текущей папки.

void SetPath(AnsiString NewPath) if(DirectoryExists(NewPath)) Path = NewPath;
Form1->FileListBox1->Directory=Path;
if(Form1->DirectoryListBox1->Directory!=Path) Form1->DirectoryListBox1->Directory=Path;
Form1->ListBox1->Clear();
Form1->ListBox1->Items->AddStrings(Form1->FileListBox1->Items);
>
>

В конструктор добавится следующая строка: SetPath(MyDocumentsFolder); Теперь при стрте приложения текущей папкой будет "мои документы".
Наполнится кодом OnChange ComboBox'а:
void __fastcall TForm1::ComboBox1Change(TObject *Sender)
SetPath(StdPath[ComboBox1->ItemIndex].DefDir);
>

Теперь осталось написать отрисовку элемента в ListBox. Установим Для этого свойство Style надо установить в lbOwnerDrawVariable (отрисовка и подготовка к отрисовке). Выполним подготовительные действия для значков: установим папку со значками и их размер:

int IconSize=16;
AnsiString IconsDir;

void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index,
TRect &Rect, TOwnerDrawState State)
HICON hTypeIcon;
ListBox1->Canvas->Brush->Style = bsSolid;
ListBox1->Canvas->Rectangle(Rect);
ListBox1->Canvas->Brush->Style = bsClear;
ListBox1->Canvas->TextOut(Rect.Left+IconSize+4,Rect.Top+Rect.Height()/2-10,ListBox1->Items->Strings[Index]);
if(FileExists(IconsDir+AnsiLowerCase(ExtractFileExt(ListBox1->Items->Strings[Index]).SubString(2,3))+".ico")) < //Если есть значок для этого типа файлов грузим его, если нет то грузим default.ico.
hTypeIcon = LoadImage(NULL, (IconsDir+AnsiLowerCase(ExtractFileExt(ListBox1->Items->Strings[Index]).SubString(2,3))+".ico").c_str(), IMAGE_ICON, IconSize, IconSize, LR_LOADFROMFILE);
>
else hTypeIcon = LoadImage(NULL, "interface\\files16\\default.ico", IMAGE_ICON, IconSize, IconSize, LR_LOADFROMFILE);
>
DrawIconEx(ListBox1->Canvas->Handle, Rect.Left+2, Rect.Top+2, hTypeIcon, IconSize,IconSize, 0, NULL, DI_NORMAL);
DestroyIcon(hTypeIcon);
>
//---------------------------------------------------------------------------
void __fastcall TForm1::ListBox1MeasureItem(TWinControl *Control,
int Index, int &Height)
//Подготока к отрисовке
ListBox1->Canvas->Pen->Color = 0xFAFAFA;
if(ListBox1->ItemIndex == Index) < //Если этот элемент текущий
ListBox1->Canvas->Brush->Color=clNavy;
>
else ListBox1->Canvas->Brush->Color=clWhite;
>

Height = IconSize+4; //Высота элемента

Мы использовали функцию LoadImage. Это универсальная функция загрузки иконок, курсоров, битмапов из ресурса. Если использовать флаг LR_LOADFROMFILE, загрузка происходит из файла. Первыц параметр - Имя ресурса или путь к файлу. Второй параметр - тип картинки. Третий и четвёртый - размеры.

И, наконец, последний штрих, выбор размера значков. Для этого нам нужны три кнопки с заговками 16, 32 и 48

Привет. Хочу написать свой браузер причем с нуля в инете везде советуется встроенная в visual studio тулза CppWebBrowser но мне это не устраивает. Опыт у меня достаточно. С чего начать какие функции, апи, книги статии и тгд посоветуйте. Спасибо.

Здравствуйте, graviton9, Вы писали:

G>Привет. Хочу написать свой браузер причем с нуля в инете везде советуется встроенная в visual studio тулза CppWebBrowser но мне это не устраивает.

До пенсии планируешь закончить? Или уже внукам отдашь эстафету?

G> Опыт у меня достаточно.
(1)
G> С чего начать какие функции, апи, книги статии и тгд посоветуйте.
(2)

эти два пункта, мягко говоря, противоречат друг другу.

Итак, что нужно
Расскажу что нужно для простого браузера который умеет открывать html и поддерживать css, без js.

Сначала для невизуальной части
Модель хранящую структуру документа:
текст, форматирование(свойства) текста, стили текста
параграфы, форматирование параграфов,
изображения,
нумерованные списки
таблицы, форматирование таблиц, строк, ячеек, бордюров
поддержка блоков

Парсер html я (вручную написанный), который умеет применять стили и форматирование к добавленным в модель объектам, должен переваривать любые плохие html и, c незакрытыми тегами, обрабатывать ошибки (обобый гемор тут с таблицами, потому большинство страниц используют табличную верстку, и если в процессе импорта у вас ошибка в расчете табличного грида(span пропустили) — все разъедится или упадет.
Также нужен парсер секции со стилями и алгоритм применения стилей (не так просто, как звучит).

Чтобы эту радость показать нужно создать лайаут страницы. Тут нужно вам написать форматировщик, умещающий текст на строке , разбивающий на параграфы, учитывающий все отступы, + расчет таблиц, и расположение текста внутри( fit или нефит), потом блоки, обтекание текста..и прочий гемор.
Когда лайаут получен отрисовать его на форме дело техники, там и хиттест, селекшн (а селекшн хитрый, не просто по словам, там еще куча логики при выделении таблиц, ) .
Так, забыл, еще нужно поддержать копирование (алгоритм копирования не так прост) тут нужно еще rtf v1.9 поддержать, прийдется писать экспортёр для него ,и txt все это кладется вместе в клиборд при копировании. (+ экспортёр в html тоже).
Асинхронно грузить картинки.
еще 100500 всего, что я не слёту не вспомню.
Все это нужно чуть взболтать заоптимизить чтобы не лагало. примерно 6 человеколет упорного 8h/d труда. Удачи вам, надеюсь передумали. А если сможите 0.01 ую часть реализовать и не забъёте вы молодец.

Здравствуйте, graviton9, Вы писали:

G>С чего начать

Первым делом надо придумать красивое название новому браузеру.

Здравствуйте, graviton9, Вы писали:

G>Здравствуйте, DorfDepp, Вы писали:

DD>>Здравствуйте, graviton9, Вы писали:

G>>>Речь не идет о написании браузера типо chrome, mozzila, opera. имею ввиду простенкий браузер для отображения страниц

DD>>Для "отображения страниц" нужно освоить, как минимум, HTML и CSS, спецификации которых весьма путанны и неоднозначны, к тому же существуют разные версии. Потом еще нужно сделать восстановление после возникших ошибок парсинга. И еще тысяча вещей.

DD>>Одному человеку это не под силу.
G>Спасибо за ответы. Просто на одном форуме посоветовали (видимо пошутили). Просто после процессного менеджера и файл менеджера (закончил на 40 % примерно) хотелось что то посерезнее, кстати что посоветуйте напистаь ?

Тут главное, не размениваться на мелочи. Лучше сразу начинать писать свою ось. Тем более что есть масса положительных примеров: Таненбаум, Торвальдс.

Здравствуйте, graviton9, Вы писали:

G>Привет. Хочу написать свой браузер причем с нуля в инете везде советуется встроенная в visual studio тулза CppWebBrowser но мне это не устраивает. Опыт у меня достаточно. С чего начать какие функции, апи, книги статии и тгд посоветуйте. Спасибо.
Начать можно покурив травы отсюда

Здравствуйте, graviton9, Вы писали:

G>Привет. Хочу написать свой браузер причем с нуля в инете везде советуется встроенная в visual studio тулза CppWebBrowser но мне это не устраивает. Опыт у меня достаточно. С чего начать какие функции, апи, книги статии и тгд посоветуйте. Спасибо.

Здравствуйте, Xronosd, Вы писали:

X>Итак, что нужно
X>Расскажу что нужно для простого браузера который умеет открывать html и поддерживать css, без js.

X>Сначала для невизуальной части
X>Модель хранящую структуру документа:
X>текст, форматирование(свойства) текста, стили текста
X>параграфы, форматирование параграфов,
X>изображения,
X>нумерованные списки
X>таблицы, форматирование таблиц, строк, ячеек, бордюров
X>поддержка блоков
Я бы сюда добавил обработку стилей CSS, как то каскадирование, наследование, assigning.

X>Парсер html я (вручную написанный), который умеет применять стили и форматирование к добавленным в модель объектам, должен переваривать любые плохие html и, c незакрытыми тегами, обрабатывать ошибки (обобый гемор тут с таблицами, потому большинство страниц используют табличную верстку, и если в процессе импорта у вас ошибка в расчете табличного грида(span пропустили) — все разъедится или упадет.
Именно парсер html можно, полагаю, выбрать из уже написанных. Хотя, тут я немного не в теме, т.к. у нас xhtml.
X>Также нужен парсер секции со стилями и алгоритм применения стилей (не так просто, как звучит).
Совсем непросто. Но кроме секции со стилями, нужен еще и разбор внешних CSS, инлайн CSS.

X>Чтобы эту радость показать нужно создать лайаут страницы. Тут нужно вам написать форматировщик, умещающий текст на строке , разбивающий на параграфы, учитывающий все отступы, + расчет таблиц, и расположение текста внутри( fit или нефит), потом блоки, обтекание текста..и прочий гемор.
X>Когда лайаут получен отрисовать его на форме дело техники, там и хиттест, селекшн (а селекшн хитрый, не просто по словам, там еще куча логики при выделении таблиц, ) .
X>Так, забыл, еще нужно поддержать копирование (алгоритм копирования не так прост) тут нужно еще rtf v1.9 поддержать, прийдется писать экспортёр для него ,и txt все это кладется вместе в клиборд при копировании. (+ экспортёр в html тоже).
Выделение и копирование к самой собственно разметке не относятся. Имхо, это уже дополнительные фенечки, которые нужны не для всех задач, где нужна разметка.

X>Асинхронно грузить картинки.
Фенечка
X>еще 100500 всего, что я не слёту не вспомню.
+1
Например, загрузка шрифтов, чтение метрик, Font matching, не вспоминая уж о разметке под кернинг и т.п.

X>Все это нужно чуть взболтать заоптимизить чтобы не лагало. примерно 6 человеколет упорного 8h/d труда.
Это мало взболтать и запотимизить, т.к. кроме того, что бы собственно написать какой-то вариант какой-нибудь фичи, нужно долго болеть головой о том, какой же из существующих движков делает это более правильно, с чего лизать свою реализацию.
X>Удачи вам, надеюсь передумали. А если сможите 0.01 ую часть реализовать и не забъёте вы молодец.
Очень здорово, когда задача разметки ограничена и не нужно поддерживать всевозможные html. Например, отсутствие js — значительное облегчение. ограничение только xhtml — тоже.

Здравствуйте, graviton9, Вы писали:

G>Спасибо всем за советы. Просто есть желания написать серьезный проект до этого написал норм процессный менеджер и на 40% написал файл менеджер (после того как понял как все остальное реализовать пропал интерес).

Игрушку напиши.

G>И вот как -то на форуме посоветовали написать еще и браузер (видимо пошутили) и я подумал включить браузер в функциональность своего файл-менеджера.

Обычно свой браузер пишут, чтобы произвести автоматизацию или программное управление над некоторыми процессами. И как ни странно практически никто не хочет использовать встроенный компонент браузера той среды разработки, в которой создается проект. И здесь нет ничего удивительного. Поэтому разработчики вынуждены искать сторонние продукты для решения своих задач.

Дело в том, что в некоторых SDK, есть баги. Я сам недавно столкнулся, когда потребовалось написать новый проект. Часть исходного кода взял со старого проекта, а вот какой версии xulrunner в нем использовался, я забыл. Получив баг при работе проекта и прочитав пару статей (сначала подозрение падало на Visual Studio 2010) я узнал, что в некоторых версиях есть существенные недоработки. Поэтому демонстрация подключения браузера, будет происходить на проверенной версии платформы xulrunner и проверенной версии библиотеки-обертки.

Если вы скачали все необходимое, то можно переходить к созданию демонстрационного проекта. Но для начала необходимо разобраться с подключением xulrunner. Из полученного архива с xulrunner нас интересует каталог bin. Создадим на диске “С” к примеру, каталог “XPCOM” и в него скопируем все содержимое каталога bin из архива с нашим SDK. Затем, необходимо распаковать архив с библиотекой Skybound.GeckoFX.bin. Далее открываем Visual Studio и создаем стандартный проект под windows. На следующем шаге, необходимо открыть панель элементов. После чего кликаем по ее области, правой клавишей мыши. Перед вами должна появиться форма с выбором элементов панели управления.

Установка компонента Skybound.Gecko в Visual Studio 2010

Теперь необходимо произвести инициализацию компонента. Для начала необходимо добавить пространство имен Skybound.Gecko. Для этого в начале кода, вставим строку:

Затем в модуле формы, в конструкторе формы, добавим следующий код:

И еще одну строку кода необходимо добавить в обработчик события активации формы:

Все можно запустить проект. Если все заработало, то вы должны увидеть следующее:

Демонстрация проекта с подключенным браузером от Mozilla

В самом движке, есть все те возможности, которые присутствовали в Mozilla, а это около трех лет тому назад. Чего нельзя сказать о библиотеке-обертке. В этой версии, на основе которой построен демонстрационный проект, перечень возможностей очень и очень мал. Может быть и обратное: в xulrunner могут отсутствовать некоторые интерфейсы, реализация которых есть в установленной библиотеке-обертке. Посмотреть перечень доступных интерфейсов в xulrunner можно, если в каталоге с SDK открыть каталог bin\components. Там должны присутствовать файлы с расширением *.xpt. Это и есть библиотеки, которые получились в результате компиляции файлов с описанием интерфейсов. На данный момент движок Mozilla фундаментально изменен и существуют библиотеки-обертки, гораздо более новых версий (возможно там функциональных особенностей будет намного больше). Что я понимаю под ограничением функциональных возможностей?

Вот, к примеру, какие возможности отсутствуют в Skybound.Gecko v1.9.0.0:

  • удаление cookie;
  • возможность генерации событий от мыши;
  • и еще много всего;

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


На любом рабочем компьютере установлен браузер. И это понятно, ведь эту программу используют для выхода в сеть Интернет. Но задумывались ли вы, как создаются браузеры, что нужно знать и, вообще, сложно ли это? На сегодняшний день на рынке существует лишь несколько популярных браузеров, которыми часто пользуются. Например: "Яндекс. Браузер", Chrome, Opera, Firefox. Если создавать с нуля, то, конечно, конструирование браузера покажется вам очень долгим и сложным процессом. Но можно использовать уже готовые инструменты, при этом создать новый "Яндекс. Браузер" можно буквально за пару минут! Не верите? В этой статье расскажем о том, как создать свой браузер с помощью программы Construct 2 на основе Chrominium.

О Construct 2

Construct 2 - это программа для разработки приложений, в частности игр, под различные платформы. Продукты, созданные в этой программе, можно запускать как на мобильных платформах, так и на Windows. Хочется отметить, что для разработки не требуются знания программирования, все строится на событиях. Благодаря этому абсолютно любой человек сможет научиться создавать игры или программы за пару недель! Но мы будем использовать Construct 2 для быстрой разработки своего браузера. Есть платная и бесплатная версии программы. В бесплатной версии нет возможности создавать софт под мобильные платформы, но для создания браузера он сгодится. Приступаем к рассмотрению вопроса о том, как создать свой браузер!

Подготовка

Интерфейс программы Construct 2

Но перед тем, как начать разработку, нужно скачать плагин IFrame. Найти его можно на официальном сайте программы. Устанавливается он достаточно просто. Сначала выходим из Construct 2. Скачиваем плагин, содержимое архива нужно перекинуть в папку Construct2/exporters/html5/plugins. Плагин установлен!

Создаем проект

Все готово, можем приступать к созданию браузера. Для этого сначала запускаем Construct 2. В левом верхнем углу нажимаем на кнопку File - New. После чего перед нами появится следующее:

Проекты в Construct 2

Выбор огромный, различные форматы и прочее. Но все это нужно при создании игр под мобильные платформы. Нам необходимо выбрать самую первую и нажать на Open. Создается проект, но он выглядит безобразно:

Созданный проект в C2

Нужно определить размеры. Слева, во вкладке Properties, можно заметить поле Layout size. Там указываются размеры проекта, изначально это 1708x960. Поменяем эти значения на более удобные: 640x480. Дальше в этой же вкладке нажимаем на кнопку View и в поле Windows Size так же меняем значение на 640x480. Привели проект в нормальный вид, осталось только создать свой браузер. Как легко было все настраивать, так же легко будет создавать!

Создание браузера

Все подготовлено, можно начинать. Кликаем ПКМ по нашему полю и нажимаем Insert New Object. Видим следующее:

Список плагинов

Это список плагинов. Помните, мы устанавливали плагин IFrame, вот его-то в этом списке и нужно найти. Если вы все правильно установили, то он здесь будет. Выглядит он так:

Добавляем плагин IFrame

Кликаем по нему 2 раза и растягиваем появившийся объект по всему полю. Вот так:

Растягиваем плагин IFrame

После чего нам нужно добавить события, чтобы браузер начал работать. Для этого переходим во вкладку Event Sheet. Найти его можно сверху по центру. Переходим туда и нажимаем ПКМ - Add Event - System. В появившемся списке ищем On start of layout, что обозначает "При запуске уровня".

Добавляем событие в проект

Добавляем параметр: открыть url

Нажимаем Done. Все готово! Для теста необходимо запустить наш проект нажатием на F5. Запускается наш браузер, и выглядит он следующим образом:

Запуск созданного браузера

Не забывайте, что Construct 2 дает возможность скомпилировать свой проект под различные платформы: Android, iOS, Windows, Linux и прочие!

В этой статье мы рассмотрели вопрос о том, как создать свой браузер. Как можно заметить, это сделать достаточно легко, а сам процесс занимает всего несколько минут. Конечно, это браузер не с нуля, а на основе готового, но все же это начало!


Задача создания приложений, насыщенных медиаконтентом, связана с двумя важными критериями -- с богатством возможностей отображения информации и скоростью разработки.

Чтобы загрузить веб-страницу, нужно написать:

Следовательно, для QWebView требуется предоставить адрес в формате класса QUrl. Именно этот класс (а не какой-либо строковый тип) используется для работы с интернет-адресами.

ui->webView->back(); //Прошлая страница
ui->webView->forward(); //Следующая страница
ui->webView->reload(); //Обновление страницы
ui->webView->stop(); //Останов загрузки страницы

Собственно, это уже не просто описание методов, а фрагменты кода, и если вы еще не создавали проектов в QtCreator, то сделать это просто:

File -> New File or Project -> Qt C++Project->Qt Gui Application

По умолчанию в таком проекте уже будут существовать объекты menuBar, mainToolBar и statusBar.



В новый проект добавлен объект класса QWebView

Такой посредник дает программисту более гибкий механизм создания интерактивного графического интерфейса, где, благодаря древнему принципу повторяемости кода, одновременно сохраняются и эффективность, и эстетика. Разработчик описывает заголовок (который потом может стать пунктом меню) и другие атрибуты действия. К примеру, мы можем один раз описать действие обновления страницы. Для этого нужно добавить это действие в Action Editor, привязать к нему кнопку быстрого запуска (Shortcut), задать его имя (Object name) и значок, а потом включить в mainToolBar и в menuBar. Причем дело даже не успевает дойти до фактического описания программного события.



. Редактирование информации о действиях в Action Editor

Осталось создать необходимый код, соответствующий нажатию кнопки, т.е. описать внутреннюю кухню этого нового действия.
Следует вернуться в Action Editor и для созданного действия actionReload через всплывающее меню в пункте Go to slot. найти подходящий сигнал. После чего нужно привязать к нему необходимый код (Qt Creator любезно подскажет, куда именно его вписать) и вставить одну строку программы:



Выбор нужного сигнала

Аналогично можно поступить с методами back(), forward() и stop().

Адресная строка
А вот чтобы создать в том же ToolBar адресную строку с помощью компонента QLineEdit, визуальное программирование уже не поможет. Нужно открыть файл mainwindows.h и добавить в описание класса MainWindow эту самую адресную строку следующим образом:

Чтобы компилятор понял, что такое QLineEdit, вверху файла необходимо добавить:

Теперь в конструкторе в файле mainwindow.h требуется создать адресную строку и привязать ее к mainToolBar:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)

UrlPath = new QLineEdit(this);
ui->toolBar->addWidget(UrlPath);

>

Пора подумать, как привязать к созданной адресной строке нужный код. Для начала в файле mainwindow.h следует найти секцию private slots и декларировать там обработчик события нажатия клавиши в адресной строке:


а в файле mainwindow.cpp нужно описать соответствующую реализацию:

void MainWindow::slotGoEnterPressed() <
//Этот вариант самый простой, но не самый надежный
ui->webView->load(QUrl(UrlPath->text()));
>

Если же осталось ощущение, что slotGoEnterPressed() и UrlPath на самом деле ничего не связывает, то оно верное, потому что нужно записать магическую строку в конструкторе главного окна в файле mainwindow.h. В этой строке будет описано, что к чему привязывается и на каких условиях:

Раскроем ее для непосвященных.
Функция connect предназначена для связи сигнала с обработчиком приемника, указанным в макросе SLOT. Адресная строка UrlPath посылает стандартный сигнал нажатия клавиши . А то, что обрабатывается именно этот сигнал, указано в макросе SIGNAL.

Ура! В самом первом приближении адресная строка готова.

Отображение степени загрузки страницы
Для отображения степени загрузки нужно выделить в визуальном редакторе объект WebView и через пункт Go to slot… выбрать в открывшемся списке сигналов сигнал loadProgress(int). Оказавшись в редакторе кода, следует заполнить автоматически сгенерированную заготовку обработчика:


void MainWindow::on_webView_loadProgress(int progress)
ui->statusBar->showMessage("Загрузка "+ui->webView->url().toString()+". ",500);
>

Но этой строчкой просто отображается сам факт загрузки очередной страницы, а с процентами можно поступить хитрее. В файле mainwindow.h следует описать внутри класса MainWindow графический индикатор:


private:
QProgressBar *PageProgress;
А в конструкторе нужно описать
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) …
PageProgress = new QProgressBar(this);
PageProgress->setVisible(false);
ui->statusBar->addPermanentWidget(PageProgress);

>

Таким образом PageProgress будет не только создан, но и размещен внутри statusBar. Предполагается, что PageProgress будет виден только в периоды загрузки страницы, в чем помогут сигналы loadStarted() и loadFinished(bool).
Теперь обработчик on_webView_loadProgress можно дополнить строкой:

Отображение истории
Процесс создания главного меню браузера представляет собой рутинную работу, так что описывать его полностью вряд ли уместно. К тому же нет пределов совершенства любой программы. Но все же для примера динамически отобразим историю работы с браузером, т.е. будем перестраивать соответствующий пункт главного меню по мере необходимости:

Таким образом, в динамическом режиме перестраивается список интернет-адресов, и к каждому пункту вновь привязывается обработчик следующего содержания:

//Декларация обработчика пункта меню истории браузера в файле mainwindow.h
.
private slots:
void slotLoadHistPage();

/* Файл mainwindow.h
Реализация приемника сигнала пункта меню истории браузера выглядит очень загадочно */
void MainWindow::slotLoadHistPage() //Извлекаем из источника сигнала информацию для загрузки страницы
QAction* a = qobject_cast ( sender() );

//Загружаем страницу из истории
ui->webView->load(QUrl(a->text()));
>


// Пробуем написать более универсальный метод для загрузки веб-страниц
void MainWindow::smartLoad(QString value) QString validLink = value;
//Заменяем палочки на правильные
if (validLink.toLower().startsWith("http:\") ||
validLink.toLower().startsWith("ftp:\")) validLink = validLink.replace(":\\","://");
>
//Добавляем информацию о протоколе, если она совсем отсутствует
if (!validLink.toLower().startsWith("http") &&
!validLink.toLower().startsWith("ftp")) validLink = "http://" + validLink;
>
//Загружаем страницу
ui->webView->load(validLink);
//Обновляем на всякий случай меню с историей адресов
buildHistory();
>

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

Загрузка файла или HTML-строки
А если нужно загрузить HTML-страницу с диска? Тогда следует просто указать соответствующий тип данных:

И конечно, допустимо загрузить строку гипертекста напрямую, так можно поступить при выводе информации о браузере:


Опять ничего? Действительно, мы просто попросили браузер не обрабатывать самостоятельно ссылки со страницы при щелчке, а вместо этого выдать сигнал, под который мы и сделаем обработчик. В списке сигналов для WebView найдем сигнал linkClicked(QUrl) и напишем для него обработчик:

Три волшебные строки
В проекте нужно обязательно упомянуть про три строки, которые, скорее всего, при создании браузера придется добавить в функцию main (main.cpp) :

/* Разрешение на автоматическую загрузку картинок в странице*/
QWebSettings::globalSettings()->setAttribute(QWebSettings::AutoLoadImages,true);
/* Разрешение на запуск java-скриптов*/
QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, true);
/* Разрешение на использование плагинов*/
QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true);

В руководстве написано, что первые две опции активны по умолчанию, но в Рунете много раз встречаются все три разрешения вместе, особенно когда речь идет об активизации Flash.



Новый браузер – почти за 5 минут

Браузер готов?
В заключение стоит отметить, что на форумах самыми проблемными темами, связанными с QWebView, являются вопросы взаимодействия с Flash и Java-скриптами. К примеру, если у вас наконец заработал в браузере Flash, то, возможно, радоваться еще рано, погоняйте браузер с разными сайтами -- велика вероятность новых сюрпризов… Однако в тех случаях, когда речь идет не об обычном публичном браузере, а о проекте с заранее известными характеристиками отображаемого контента (например, платежный терминал), все становится проще. Но такой вариант уже будет темой отдельной статьи.

Читайте также: