Одной из возможностей, которые Microsoft предоставила в своих средствах разработки - использование функциональностей Internet Explorer в качестве интегрированной части любого приложения.
Цель лабораторной работы - познакомиться с вопросами:
ActiveX для Internet Explorer ( Internet Explorer ActiveX Object Model ) позволяет интегрировать все компоненты в приложениеCHtmlView библиотеки MFC инкапсулирует практически все функциональности Internet ExplorerMicrosoft ( COM -интерфейсам), доступным в объектной модели ActiveX для Internet ExplorerVisual C++ создать свои интерфейсные классы для COM -интерфейсов, т.е. как вызывать функции COM -интерфейсов из своего приложенияCHtmlView и Internet ExplorerКласс CHtmlView, будучи использован в качестве базового вместо класса CView, позволяет создавать однодокументные или многодокументные приложения с возможность просмотра HTML -документов и другими функциональностями Web -броузера. Класс содержит множество функций, в том числе и навигационных
Некоторые функции класса CHtmlView | |
|---|---|
| Функция | Назначение |
GoBack() |
Направляет пользователя на предыдущую Web - страницу |
GoForward() |
Направляет пользователя на последующую Web - страницу |
GoHome() |
Направляет пользователя на начальную страницу броузера Internet Explorer |
GoSearch() |
Направляет пользователя на страницу поиска по Internet |
Navigate(LPCTSTR URL) |
Направляет пользователя на страницу в Internet с указанным адресом URL |
Refresh() |
Заставляет браузер перезагрузить текущую Web - страницу |
Stop() |
Останавливает текущий процесс загрузки |
GetLocationURL() |
Возвращает URL текущей просматриваемой браузером Web - страницы |
GetBusy() |
Возвращает логическое значение, информирующее, занят ли в данный момент браузер загрузкой Web - страницы |
Создадим -приложение на базе класса CHtmlView. Добавим в него меню с функциями навигации назад и вперед. Добавим диалог для возможности вводить URL.
Чтобы приложение заработало, необходимо, чтобы на компьютере был установлен Web -браузер Internet Explorer. Обычно при установки IDE Visual C++ на компьютере устанавливается самая последняя версия Internet Explorer. Если разработанное приложение планируется запускать на других компьютерах, то там Internet Explorer также должен быть установлен для успешной работы нашего приложения.
Выберите папку для размещения проекта
Создайте новый проект с именем
Заполните вкладки мастера создания приложений так




Настройки остальных вкладок мастера создания приложений оставьте без изменения. Проследите, чтобы в последней вкладке Generated Classes (Генерируемые классы) для создаваемого мастером класса CWebBrowseView в качестве базового в поле был выбран класс CHtmlView.
После нажатия кнопки Finish мастер создаст заготовку приложения
Установите режим сборки проекта
Постройте проект и убедитесь, что мастер построил заготовку броузера, которую нам предстоит наделить функциональностью
URL ( - Internet. Обратите внимание, что мастер создал заготовку дополнительной панели управления со статической надписью " TODO: layout dialog bar ", указывающей на необходимость ее оформить.
Панель управления является гибридом панели инструментов и диалогового окна. Она представляет собой панель инструментов со средствами управления диалогом. Мастер MFC Application Wizard расположил ее не в разделе Toolbar, где и должны находиться панели инструментов, а в разделе Dialog, где располагаются ресурсы диалоговых окно.

Далее мы будем проектировать эту панель как обычный ресурс диалогового окна. На нее можно помещать поля редактирования, кнопки, поля со списком и переключатели - все, что используется в обычных диалоговых окнах.
Вызовите на редактирование ресурс диалогового окна IDR_MAINFRAME
Измените содержимое текстовой метки на Address и измените свойство Align Text метки на значение Right
Дополните ресурс полем редактирования Edit Control
Присвойте свойству ID поля редактирования значение IDC_EADDRESSНам не нужно для этого ресурса создавать класс поддержки функциональности, как это было бы необходимо сделать для обычного диалогового окна. Панель управления автоматически посылает свои сообщения классу главного фреймового окна приложения и их можно перенаправить через фрейм в классы представления или документа нашего -приложения.
Воспользуемся тем, что когда пользователь нажимает клавишу Enter после завершения ввода в поле редактирования, этот элемент управления Edit Control посылает фреймовому окну (класс CMainFrame ) идентификатор команды IDOK. Чтобы перехватить и обработать эту команду, нам только требуется добавить обработчик команды в карту сообщений класса CMainFrame (в файл ).
В реализации обработчика команды IDOK необходимо получить текст из поля редактирования на панели управления. Далее можно передать эту строку функции Navigate() класса представления, чтобы заставить броузер найти в сети или внутреннем кэше и отобразить указанную пользователем страницу.
В панели
Заполните мастер добавления функций так
Заполните код функции такФункция передачи URL броузеру в файле MainFrm.cpp
// Функция передачи адреса URL
void CMainFrame::OnNewAddress(void)
{
CString strAddress;
// Получить новый URL
m_wndDlgBar.GetDlgItem(IDC_EADDRESS)->GetWindowText(strAddress);
// Передать URL в броузер
((CWebBrowseView*)GetActiveView())->Navigate(strAddress);
}
Панель управления была зарегистрирована мастером создания приложений в функции OnCreate() файла MainFrm.cpp под именем m_wndDlgBar как экземпляр класса CDialogBar. Панель управления является родительской для элемента редактирования с идентификатором IDC_EADDRESS. Поэтому при получении содержимого URL мы адресуемся к полю редактирования через нее.
В последней строке кода тип возвращаемого функцией GetActiveView() указателя приводится к указателю на класс CWebBrowseView. Это позволяет вызвать функцию Navigate(), наследуемую представлением от базового класса CHtmlView.
Зарегистрируйте созданную функцию как обработчик команды IDOK нажатия клавиши. Для этого в карту сообщений класса CMainFrame вручную внесите следующий кодРегистрация функции как обработчика сообщения IDOK в карте сообщений класса CMainFrame в файле MainFrm.cpp // CMainFrame IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_COMMAND(IDOK, OnNewAddress) END_MESSAGE_MAP() ...................................
Добавьте в начало файла MainFrm.cpp директивы подключения описаний классов CWebBrowseView и CWebBrowseDocДирективы подключения заголовочных файлов с описаниями классов документа и Дирпредставления вначале файла MainFrm.cpp // MainFrm.cpp : implementation of the CMainFrame class // #include "stdafx.h" #include "WebBrowse.h" #include "MainFrm.h" #include ".\mainfrm.h" #include "WebBrowseDoc.h" #include "WebBrowseView.h" #ifdef _DEBUG #define new DEBUG_NEW #endif ..............................................
Если скомпилировать и запустить наше приложение, то можно ввести URL. После нажатия клавиши Enter, если в системе имеется соединение с Internet или настроена локальная PHP -машина (система HTML -страница как в настоящем броузере. Это может быть примерно такое...
Переходя от одной Web -странице к другой по ссылкам, настоящий броузер помещает текущее значение указателя URL в поле адреса. Тем самым дается возможность контролировать маршрут и, в случае необходимости, скопировать или изменить URL. Для получения текущего значения указателя URL нужно вызвать функцию GetLocationURL и передать полученное значение на панель управления.
Проблема в том, чтобы определить момент, когда можно получить текущий URL. Для этого в нашем классе представления CWebBrowseView, который является наследником базового класса CHtmlView, нужно переопределить некоторые функции. Данные функции вызываются, когда управляющий элемент броузера генерирует различные сообщения, в том числе:
Web -страницуWeb -страницыOnDocumentComplete.
Выберите класс CWebBrowseView на панели Class View
В панели
Создайте для OnDocumentComplete функцию замещения, которая будет вызываться после окончания загрузки Web -страницы и которую заполните так
Замещенная функция забора текущего URL в классе представления и вызова функции записи адреса
в поле редактирования из класса фрейма, где и находится панель управления с полем адреса
void CWebBrowseView::OnDocumentComplete(LPCTSTR lpszURL)
{
// TODO: Add your specialized code here and/or call the base class
// Передать текущий URL в класс фрейма для вывода в поле адреса
((CMainFrame*)GetParentFrame())->SetAddress(lpszURL);
CHtmlView::OnDocumentComplete(lpszURL);
}
Обратите внимание, что в итоге не пришлось вызывать функцию GetLocationURL(), тем более, нам неизвестно было, когда ее нужно вызывать. Искомый URL мы получили как аргумент lpszURL, который сразу передали во фреймовое окно. Теперь в классе фреймового окна нужно этот URL отобразить в поле адреса с идентификатором IDC_EADDRESS.
Чтобы в файле WebBrowseView.cpp компилятор видел описание класса CMainFrame, добавьте в начало этого файла директиву подключения файла MainFrm.hПодключение к файлу WebBrowseView.cpp директивы с описанием класса CMainFrame // WebBrowseView.cpp : implementation of the CWebBrowseView class // #include "stdafx.h" #include "WebBrowse.h" #include "WebBrowseDoc.h" #include "WebBrowseView.h" #include ".\webbrowseview.h" #include "MainFrm.h" #ifdef _DEBUG #define new DEBUG_NEW #endif ....................................
В панели
Заполните мастер добавления метода так
Незабудьте нажать кнопку Add перед щелчком по кнопке Finish
Заполните заготовку функции SetAddress() следующим кодом (мы помним, что панель управления с полем адреса ассоциирована с переменной m_wndDlgBar )Функция класса фреймового окна CMainFrame для заполнения поля адреса
текущим значением URL в файле MainFrm.cpp
// Заполнение поля адреса текущим значением URL
void CMainFrame::SetAddress(LPCTSTR lpszURL)
{
// Сменить значение URL после загрузки новой страницы
(m_wndDlgBar.GetDlgItem(IDC_EADDRESS))->SetWindowText(lpszURL);
}
Теперь можно построить приложение и убедиться, что при переходе по ссылкам в поле адреса отображается текущий URL страницы.
Добавим к нашему приложению возможности перехода на предыдущую и последующую Web -страницы. Для этого нужно воспользоваться функциями GoBack() и GoForward(), унаследованными нашим классом представления CWebBrowseView от базового MFC -класса CHtmlView. Вызовы этих функций можно связать с пунктами меню, клавишами быстрого вызова ("горячими клавишами"), или с кнопками панели инструментов.
В панели
В панели свойств
Вновь в панели
Удалите с панели меню категорию Edit все ее пункты и замените эту категорию на Navigate
Перетащите эту категорию на новое место перед категорией Help
Добавьте два новых пункта в категорию Navigate: один для функции GoBack, а второй - для функции GoForward
Установите значения свойств новых пунктов, как показано в таблице| Значения свойств пунктов меню | ||
|---|---|---|
| Пункт меню | Свойство | Значение |
| Первый | ID |
ID_NAVIGATE_BACK |
Caption |
Назад \tCtrl + B |
|
Prompt |
Назад на предыдущую Web -страницу \n Назад |
|
| Второй | ID |
ID_NAVIGATE_NEXT |
Caption |
Вперед \tCtrl + F |
|
Prompt |
Вперед на следующую Web -страницу\nВперед |
|
Внешний вид категории Navigate в редакторе меню должен выглядеть так

Для каждого пункта меню необходимо добавить обработчики сообщения о событии COMMAND. Эти сообщения должен принимать и обрабатывать класс представления CWebBrowseView. Обработчики будем создавать не двойным щелчком по соответствующему пункту, а через контекстное меню оболочки для соответствующего пункта нашего проектируемого меню в редакторе. Для меню способ создания обработчика двойным щелчком оболочкой не поддерживается, поскольку неизвестно, какой класс будет принимать и обрабатывать сообщения COMMAND, пришедшие от меню.
В редакторе меню щелкните правой кнопкой мыши на первом пункте категории
Выберите в списке
Нажмите кнопку Add and Edit и заполните созданный мастером обработчик следующим кодомОбработчик пункта меню "Назад"
void CWebBrowseView::OnNavigateBack()
{
// TODO: Add your command handler code here
// Идти к предыдущей странице
GoBack();
}
Подобным образом создайте обработчик для второго пункта меню и заполните его такОбработчик пункта меню "Вперед"
void CWebBrowseView::OnNavigateNext()
{
// TODO: Add your command handler code here
// Перейти на следующую страницу вперед
GoForward();
}
Запустите приложение и убедитесь, что пункты спроектированного меню работаютАкселераторы (горячие клавиши) применяются для быстрого доступа к командам меню при нажатии комбинации назначенных клавиш. Мы для наших пунктов меню "Назад" и "Вперед" зарезервировали комбинации клавиш " Ctrl + B " и " Ctrl + F ". Реализуем эти комбинации. Наша задача - закрепить за выбранными комбинациями те же самые идентификаторы ID_NAVIGATE_BACK и ID_NAVIGATE_NEXT, которые мы назначали для соответствующих пунктов меню Navigate.
Раскройте узел Accelerator в дереве ресурсов панели Resource View и щелкните дважды по ресурсу IDR_MAINFRAME

Откроется на редактирование таблица ID и закрепленной за ним комбинации клавиш.
Щелкните правой кнопкой мыши в любом месте таблицы New Accelerator

Выбрав этот пункт, мы тем самым добавили новую строку в конец таблицы, где можно ввести параметры акселератора. Но в конце таблицы итак имеется пустая строка, готовая для заполнения, поэтому контекстное меню добавления можно и не вызывать.
Введите значение ID_NAVIGATE_BACK в поле ID добавленной новой строки (или выберите из раскрывающегося в поле списка, поскольку раньше мы их вводили для пунктов меню), в качестве модификатора ( Modifier ) оставьте Ctrl, а в качестве клавиши ( Key ) введите латинскую B
В следующую пустую строку в поле ID введите значение ID_NAVIGATE_NEXT (или выберите из раскрывающегося в поле списка), в качестве модификатора ( Modifier ) оставьте Ctrl, а в качестве клавиши ( Key ) введите F
Теперь таблица

Вернитесь в редактор меню и проверьте, остались ли у идентификаторов пунктов те же значения ID_NAVIGATE_BACK и ID_NAVIGATE_NEXT. Если нет, то в раскрывающемся списке панели свойств Properties восстановите их вновь

Таким образом, мы назначили для пунктов меню "Назад" и "Вперед" горячие клавиши. Теперь глубокоуважаемый жирный Пользователь (у него много денежек, которые мы должны выманить!!!) нашего шедевра сможет осуществлять переходы на уже просмотренные Web-страницы или использованные ссылки, которые хранятся в кэше броузера, не только через пункты меню, но и по горячим клавишам.
Постройте приложение и убедитесь, что все работаетДобавим в панель управления правее строки ввода адреса две кнопки, дублирующие команды перехода категории Navigate главного меню приложения.
Во вкладке Resource View вызовите на редактирование диалоговый ресурс панели управления
Поместите на нее правее поля ввода адреса две кнопки Button из вкладки Toolbox
Сделайте ширину кнопок примерно равной высоте ( Width=16, Height=15 )
По поводу точных размеров кнопок сильно не напрягайтесь. Позже мы присоединим к ним изображения, которые размеры кнопок определят автоматически.

Настройте свойства кнопок в соответствии с таблицей| Значения свойств кнопок перехода | ||
|---|---|---|
| Кнопка | Свойство | Значение |
| Левая | ID |
ID_BUTTON_BACK |
Caption |
BACK |
|
Prompt |
Назад на предыдущую Web-страницу\nНазад | |
Owner Draw |
True |
|
| Правая | ID |
ID_BUTTON_NEXT |
Caption |
NEXT |
|
Prompt |
Вперед на следующую Web-страницу\nВперед | |
Owner Draw |
True |
|
Не беспокойтесь, что надписи кнопок не вмещаются в отведенные размеры. Надписи в окончательном варианте отображаться не будут и они нужны нам только для того, чтобы привязать будущие изображения к кнопкам.
Теперь нужно создать обработчики для кнопок. Кнопки находятся в классе CMainFrame и будут подавать сообщения BN_CLICKED при щелчках по ним. Принимать же и обрабатывать сообщения нужно в классе CWebBrowseView. Это точно такая же ситуация, как при создании пунктов меню, которые сами тоже находятся во фреймовом окне CMainFrame, а посылаемые ими команды перехватываются и обрабатываются в окне представления, поддерживаемого классом CWebBrowseView.
Выполните правый щелчок мышью на левой кнопке панели управления и в появившемся контекстном меню выполните команду
Настройте мастер добавления обработчиков, выделив в качестве целевого класс
Нажмите кнопку Add and Edit и мастер создаст заготовку обработчика, которую заполните такОбработчик щелчка на левой кнопке ID_BUTTON_BACK
void CWebBrowseView::OnBnClickedButtonBack()
{
// TODO: Add your control notification handler code here
// Идти к предыдущей странице
GoBack();
}
Повторите такие же шаги для создания заготовки обработчика щелчка на правой кнопке панели управления. Заготовку заполните следующим кодомОбработчик щелчка на правой кнопке ID_BUTTON_NEXT
void CWebBrowseView::OnBnClickedButtonNext()
{
// TODO: Add your control notification handler code here
// Перейти на следующую страницу вперед
GoForward();
}
Перед тем как построить приложение после введенных кнопок, привяжитесь покрепче к стулу, на котором сидите.
Постройте приложение и убедитесь, что наши кнопки исчезли с панели управления. Но вместе с тем, щелчки по тому месту, где они должны находиться, приводят к ожидаемым действиям.
Исчезновение кнопок с панели управления произошло потому, что мы установили для них свойство Owner Draw в значение True. Тем самым мы определили, что кнопки должен рисовать их владелец ( Owner ), а о самом коде рисования внутри владельца мы пока не позаботились. Владельцем (родителем) кнопок, в данном случае, является панель управления m_wndDlgBar как экземпляр класса CDialogBar, объявленная в файле MainFrm.h.
Измените свойство Owner Draw на значение False и снова постройте приложениеКнопки появились и ведут себя как и положено, обеспечивая переходы броузера, но невмещающиеся внутри них надписи портят всю картину

Заменим традиционные текстовые надписи внутри кнопок на содержательные рисунки. Для этого нужно подготовить нужные картинки в формате Bitmap, добавить в них немного соли, густо поперчить и подавать горячими. Студент Жук - разрешаю Вам передохнуть, а остальные и примкнувший к ним Панасюк - продолжайте. До Силиконовой долины или Редмонда осталось совсем немного (почти как до психушки).
Присоединяемые к кнопкам картинки будут состоять из стрелок и должны быть одинакового размера. Иначе в разных состояниях они начнут скакать по экрану. Одна картинка будет изображать стрелку влево, другая - стрелку вправо. Мы установили для левой кнопки свойство Caption в значение BACK, а для правой - NEXT. В дальнейшем мы воспользуемся этими именами для привязки изображений.
Каждая картинка будет состоять из двух экземпляров, представлющих изображение кнопки для двух состояний:
Down (экземпляры BACKD и NEXTD )Up (экземпляры BACKU и NEXTU )(Можно еще: кнопка получила фокус ввода - Focus (экземпляры BACKF и NEXTF кнопка не получила фокус ввода - экземпляры BACKX и NEXTX )
Картинки в файл ресурсов можно добавить готовыми ( Import ), а можно нарисовать средствами встроенного в оболочку графического редактора ( New ). В любом случае размер картинок должен примерно соответствовать размеру кнопок. Ранее мы определили размеры кнопок примерно такими ( Width=16, Height=15 ). Значит и картинки нужно выполнить такого же размера. Хотя при загрузке картинок в кнопки их размеры автоматически подстроятся под размеры картинок. Но нам важно, чтобы кнопки не вышли по размерам за пределы панели управления. Итак, создаем картинки для кнопок.
Щелкните правой кнопкой мыши в любом месте панели Resource View и выполните в появившемся контекстном меню команду Add Resource
Установите категорию ресурса
В открывшемся графическом редакторе щелкните правой кнопкой мыши рядом с полем рисования и через панель
Сохраните ресурс, щелкнув по вкладке правой кнопкой мыши
Нарисуйте стрелку влево, при этом для рисования активно используйте панель инструментов Панель Colors обеспечивает настройку инструментов рисования как цветовую пару с текущим значением для левой (передний цвет пары) и правой (задний цвет пары) кнопок мыши. Цветовая пара текущего цвета выбирается в панели Colors щелчками по образцам соответствующими кнопками мыши. Количество доступных цветовых образцов устанавливается в панели Properties. Дополнительные возможности графического редактора заложены в меню Image оболочки.
Сам графический редактор представлен двумя фреймами. В правом фрейме масштаб поля рисования можно менять через инструмент "Увеличительное стекло"

В левом фрейме рисунок представлен в натуральную величину.
Вновь сохраните готовый рисунок стрелки влево в файле ресурсов. Убедитесь, что в проект добавился соответствующий ресурс![]() |
![]() |
Сейчас создадим рисунок для стрелки вправо, используя уже созданное изображение стрелки влево.
Закройте окно графического редактора, войдите в панель
Выполните команду
Сохраните проект и убедитесь, что в панели


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

Должен получиться такой результат

В панели


Сохраните проект и убедитесь, что у нас теперь есть по две картинки для каждой кнопки
Вызовите на редактирование две последних картинки с идентификаторами
Теперь переназначьте каждой картинке значение свойства ID как показано в таблицеЧисловые идентификаторы мы назначали ранее для того, чтобы не запутаться. Не забудьте, что новые имена ресурсов растров нужно обязательно заключать в двойные кавычки.
Новые значения свойства ID для картинок кнопок | |||
|---|---|---|---|
Старый ID |
Bitmap | Новый ID |
Назначение |
IDB_BITMAP_BACK |
![]() |
" BACKU " |
Картинка для левой кнопки в отпущенном состоянии. Свойству Caption самой левой кнопки мы ранее присвоили значение BACK |
IDB_BITMAP_BACK_INV |
![]() |
" BACKD " |
Картинка для левой кнопки в нажатом состоянии. Свойству Caption самой левой кнопки мы ранее присвоили значение BACK |
IDB_BITMAP_NEXT |
![]() |
" NEXTU " |
Картинка для правой кнопки в отпущенном состоянии. Свойству Caption самой правой кнопки мы ранее присвоили значение NEXT |
IDB_BITMAP_NEXT_INV |
![]() |
" NEXTD " |
Картинка для правой кнопки в нажатом состоянии. Свойству Caption самой правой кнопки мы ранее присвоили значение NEXT |
Иными словами, если на кнопке текст BACK, то мы для нее создаем два растра с идентификаторами " BACKU " и " BACKD " - соответственно для отжатого и нажатого состояния. Для другой кнопки - то же самое. Этот прием обеспечит нормальную работу картинок на кнопках. Теперь панель ресурсов должна выглядеть так

Теперь осталось немного для завершения работы с кнопками: создать два экземпляра класса CBitmapButton и обеспечить с их помощью динамическую загрузку изображений в кнопки и управление ими.
Откройте через панель Solution Explorer файл MainFrm.h с описанием класса фреймового окна и внесите в конец класса следующий кодОбъявление поддерживающих объектов в файле MainFrm.h
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
public:
// Operations
public:
// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT cs);
// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext dc) const;
#endif
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
CReBar m_wndReBar;
CDialogBar m_wndDlgBar;
// Generated message map functions
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
public:
// Функция передачи адреса URL
void OnNewAddress(void);
// Заполнение поля адреса текущим значением URL
void SetAddress(LPCTSTR lpszURL);
private:
CBitmapButton m_Back, m_Next;
};
Откройте файл MainFrm.cpp, найдите в нем функцию OnCreate() и вставьте в конце код загрузки ресурсов в кнопкиКод загрузки картинок в кнопки
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
.....................................................
// TODO: Remove this if you don't want tool tips
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY);
m_Back.AutoLoad(ID_BUTTON_BACK, m_wndDlgBar);
m_Next.AutoLoad(ID_BUTTON_NEXT, m_wndDlgBar);
return 0;
}
Не забудьте установить свойство Owner Draw кнопок в значение True
Постройте проект и убедитесь, что изображения кнопок меняются, сами кнопки функционируют правильно и посылают сообщения классу CWebBrowseView, а обработчики для кнопок в файле WebBrowseView.cpp мы построили ранееТеперь наш уважаемый Пользователь имеет возможность перехода на посещенные страницы по командам меню, по горячим клавишам и кнопкам панели управления. Вот сколько много мы для него постарались.
Рассмотрим возможности прерывания загрузки, обновления страницы и перехода на начальную страницу браузера.
Если Web-страница большого объема или пропускная способность соединения слабая, то у пользователя может возникнуть необходимость прервать загрузку страницы броузером. Для этого в класса CHtmlView предусмотрена функция Stop().
Когда пользователь перемещается кнопками "Назад" и "Вперед" по уже посещенным Web-страницам, то он фактически использует информацию, которую броузер хранит в своем внутреннем кэше. Чтобы заставить броузер перегрузить страницу, а не просто отобразить версию из кэша, существует функция Refresh().
И последнее... Чтобы быстро переместиться на домашнюю страницу броузера, а это как правило стартовая страница с именем Home или Index, можно использовать встроенную в класс CHtmlView функцию GoHome(). При выполнении этой функции внутренний кэш броузера очищается.
Прежде всего нужно дополнить меню Navigate нашего приложения соответствующими пунктами.
Отредактируйте меню приложения, добавив сепаратор и три пункта в соответствии с рисунком
Откорректируйте свойства новых пунктов меню, используя информацию из таблицы| Свойства дополнительных пунктов меню | |
|---|---|
| Свойство | Значение |
ID |
ID_NAVIGATE_STOP |
Caption |
Stop |
Prompt |
Остановить загрузку\nСтоп |
ID |
ID_NAVIGATE_REFRESH |
Caption |
Refresh |
Prompt |
Обновить текущую страницу\nОбновить |
ID |
ID_NAVIGATE_GOHOME |
Caption |
GoHome |
Prompt |
Перейти на начальную страницу\nДомой |
Создайте обработчики для каждого нового пункта меню через контекстное меню пункта и команду
Заполните обработчики следующим кодомОбработчики для дополнительных возможностей броузера
void CWebBrowseView::OnNavigateStop()
{
// TODO: Add your command handler code here
// Остановить текущую загрузку
Stop();
}
void CWebBrowseView::OnNavigateRefresh()
{
// TODO: Add your command handler code here
// Перезагрузить текущую страницу
Refresh();
}
void CWebBrowseView::OnNavigateGohome()
{
// TODO: Add your command handler code here
// Идти на начальную страницу
GoHome();
}
Постройте приложение - все должно работать!Чтобы получить заголовок текущей Web -страницы и установить его в заголовке окна приложения воспользуемся свойством Title и функцией (средством доступа к свойству) get_title() интерфейса IHTMLDocument2. Для этого выполним несколько пошаговых инструкций.
Добавьте к приложению новый класс, выполнив команду



В появившемся окне
После щелчка по кнопке
Для настройки мастера Add Class From TypeLib Wizard выполните следующее:Available type libraries выберите значение Microsoft HTML Object Library <4.0> Interfaces найдите строку IHTMLDocument2 и выделите ееGenerated classes имя создаваемого класса, соответствующее выбранному интерфейсу
Щелкните по кнопке Finish для создания классаВ результате мастер создаст исходный код интерфейсного класса для интерфейса IHTMLDocument2, который полностью разместится в заголовочном файле CHTMLDocument2.h приложения и нам остается только воспользоваться кодом этого класса для решения поставленной задачи загрузки заголовка текущей Web -страницы.
В файле WebBrowseView.cpp класса представления CWebBrowseView найдите уже использованную нами ранее функцию OnDocumentComplete() и дополните ее кодом, как показано нижеКод, добавленный в функцию OnDocumentComplete() файла WebBrowseView.cpp
void CWebBrowseView::OnDocumentComplete(LPCTSTR lpszURL)
{
// TODO: Add your specialized code here and/or call the base class
// Передать текущий URL в класс фрейма для вывода в поле адреса
((CMainFrame*)GetParentFrame())->SetAddress(lpszURL);
// Создать экземпляр интерфейса класса CHTMLDocument2
CHTMLDocument2* pHDoc = new CHTMLDocument2(GetHtmlDocument());
// Получить заголовок текущей страницы
CString strTitle = pHDoc->get_title();
// Получить указатель на класс документа
CWebBrowseDoc* pDoc = GetDocument();
// Установить заголовок окна приложения
pDoc->SetTitle(strTitle);
// Удалить экземпляр интерфейса на куче
delete pHDoc;
CHtmlView::OnDocumentComplete(lpszURL);
}
Добавьте директиву #include в начало файла WebBrowseView.cpp для подключения описания нового класса CHTMLDocument2Подключение класса интерфейса к файлу представления WebBrowseView.cpp // WebBrowseView.cpp : implementation of the CWebBrowseView class // #include "stdafx.h" #include "WebBrowse.h" #include "WebBrowseDoc.h" #include "WebBrowseView.h" #include ".\webbrowseview.h" #include "MainFrm.h" #include "CHTMLDocument2.h" #ifdef _DEBUG #define new DEBUG_NEW #endif .........................................
Постройте приложение и убедитесь, что заголовок текущей страницы отображается в заголовке окна приложения
Если при построении приложения Ваш компилятор выдает ошибки в коде добавленного нами файла интерфейса CHTMLDocument2.h (мой выдает!), то сделайте следующее

Откройте в оболочке на редактирование файл CHTMLDocument2.h, найдите в нем функции write() и writeln() и внесите в них следующие измененияКорректируем "Ошибки Билла"
......................................
void write(SAFEARRAY * psarray)
{
// static BYTE parms[] = VTS_NONE ;
static BYTE* parms = (BYTE*)VTS_NONE ;
InvokeHelper(0x41e, DISPATCH_METHOD, VT_EMPTY, NULL, parms, psarray);
}
void writeln(SAFEARRAY * psarray)
{
// static BYTE parms[] = VTS_NONE ;
static BYTE* parms = (BYTE*)VTS_NONE ;
InvokeHelper(0x41f, DISPATCH_METHOD, VT_EMPTY, NULL, parms, psarray);
}
......................................
Теперь опять постройте приложение (ошибок больше быть не должно) и убедитесь, что заголовок текущей страницы отображается в заголовке окна приложенияТот стандартный каркас приложения, который сгенерировал для нас мастер в самом начале, не рассчитан на открытие документов в формате HTML. Заложенные изначально базовые возможности открытия документа реализуются посылкой сообщения ON_FILE_OPEN в ответ на щелчок Пользователя по кнопке Open панели инструментов (значок ) или выполнения одноименной команды меню. Это сообщение перехватывается в классе CWebBrowseApp (карта сообщений файла WebBrowse.cpp ) и обрабатывается функцией базового класса CWinApp::OnFileOpen()
Карта сообщений для класса CWebBrowseApp в файле WebBrowse.cpp // CWebBrowseApp BEGIN_MESSAGE_MAP(CWebBrowseApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP()
Для того, чтобы реализовать задуманное, прежде всего нужно убрать выделенный код из карты сообщений класса CWebBrowseApp. Перехватывать это сообщение мы будем во фреймовом окне, в классе которого у нас есть доступ к полю редактирования адреса. В классе фреймового окна мы построим обработчик сообщения ON_FILE_OPEN, в котором создадим и настроим диалог FileOpen, из которого извлечем информацию об имени выбранного Пользователем открываемого файла. После этого имя файла можно передать в поле ввода адреса панели управления и сгенерировать сообщение IDOK, обработчик которого у нас уже создан. Итак, приступим.
Закомментируйте код маршрутизации сообщения ON_FILE_OPEN в карте сообщений класса CWebBrowseApp, как показано нижеКомментируем код базового сообщения ON_FILE_OPEN для класса CWebBrowseApp в файле WebBrowse.cpp // CWebBrowseApp BEGIN_MESSAGE_MAP(CWebBrowseApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) // ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP()
Постройте приложение и убедитесь, что кнопка и команда меню Open стали недоступными ( Disabled )
В панели Class View выделите класс CMainFrame и сразу после этого в панели Properties установите режим Events
Найдите сообщение
Постройте приложение и убедитесь, что команда и кнопка Open стали доступными, но естественно ничего не делают, так как обработчик пока пустой
Внесите в обработчик код, который и решит всю задачуКод нового обработчика сообщения ON_FILE_OPEN
void CMainFrame::OnFileOpen()
{
// TODO: Add your command handler code here
// Создать диалог File Open
static char szFilter[] =
"HTM Files (*.htm)|*.htm|HTML Files (*.html)|*.html|All Files (*.*)|*.*||";
CFileDialog openFile(TRUE, ".htm", "",
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
CString name;
if(openFile.DoModal() == IDOK)
name = openFile.GetPathName();// Полное имя с путем
else
return;
// Сменить значение поля адреса
(m_wndDlgBar.GetDlgItem(IDC_EADDRESS))->SetWindowText(name);
OnNewAddress();// Вызвать нашу функцию
}
Постройте приложение и убедитесь, что все работает как задумали. Отметьте также, что полнофункционально работает и контекстное меню, генерируемое базовым классом Теперь осталось совсем немного - убрать лишние интерфейсы, которые из добрых побуждений создал для нас мастер при генерации -приложения. Он же не мог предположить, что мы станем "извращаться" с его заготовкой и приспосабливать ее под самопальный броузер.
Вызовите на редактирование панель инструментов и удалите лишние кнопки
Кнопки удаляйте перетаскиванием мышью за пределы панели. Сепараторы между кнопками вводятся более широкими отступами по ширине панели.

Ресурс панели инструментов после редактирования должен выглядеть так

Вызовите на редактирование ресурс меню, и приведите категорию File в соответствие с действительной функциональностью приложения

Теперь, когда мы удалили инструменты New и Save, в классе документа CWebBrowseDoc стали ненужными переопределения функций OnNewDocument() и Serialize(). Теперь уже никто их не сможет вызвать. Все ниточки-веревочки для их вызова мы обрезали. Они конечно никому не мешают и код не портят, но место все-таки занимают, да и могут смутить бедного сопровождающего программиста. Поэтому удалим их объявления в файле WebBrowseDoc.h и реализацию в файле WebBrowseDoc.cpp.
Откройте файл WebBrowseDoc.h и удалите (или закомментируйте) в объявлении класса CWebBrowseDoc следующий кодУдаление объявлений функций в классе CWebBrowseDoc
class CWebBrowseDoc : public CDocument
{
........................................
// Overrides
public:
// virtual BOOL OnNewDocument();
// virtual void Serialize(CArchive ar);
........................................
};
Откройте файл WebBrowseDoc.cpp и удалите (или закомментируйте) в реализации класса CWebBrowseDoc код функций OnNewDocument() и Serialize(CArchive ar) Удаление лишнего кода в реализации класса CWebBrowseDoc
// WebBrowseDoc.cpp : implementation of the CWebBrowseDoc class
//
#include "stdafx.h"
#include "WebBrowse.h"
#include "WebBrowseDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CWebBrowseDoc
IMPLEMENT_DYNCREATE(CWebBrowseDoc, CDocument)
BEGIN_MESSAGE_MAP(CWebBrowseDoc, CDocument)
END_MESSAGE_MAP()
// CWebBrowseDoc construction/destruction
CWebBrowseDoc::CWebBrowseDoc()
{
// TODO: add one-time construction code here
}
CWebBrowseDoc::~CWebBrowseDoc()
{
}
/*
BOOL CWebBrowseDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
// CWebBrowseDoc serialization
void CWebBrowseDoc::Serialize(CArchive ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
*/
// CWebBrowseDoc diagnostics
#ifdef _DEBUG
void CWebBrowseDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CWebBrowseDoc::Dump(CDumpContext dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CWebBrowseDoc commands
Откройте файл WebBrowse.cpp и удалите в карте сообщений маршрутизатор сообщения ID_FILE_NEW. Все равно теперь никто в приложении это сообщение не пошлет - мы все стерилизовалиКорректировка карты приема сообщений класса CWebBrowseApp BEGIN_MESSAGE_MAP(CWebBrowseApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // Standard file based document commands // ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) // ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP()
Добавьте в категорию
Оформите About и смените иконку приложения
Запустите и испытайте приложение - работает как настоящий Броузер (почти)
Одной из возможностей, которые Microsoft предоставила в своих средствах разработки - использование функциональностей Internet Explorer в качестве интегрированной части любого приложения.
Цель лабораторной работы - познакомиться с вопросами:
ActiveX для Internet Explorer ( Internet Explorer ActiveX Object Model ) позволяет интегрировать все компоненты в приложениеCHtmlView библиотеки MFC инкапсулирует практически все функциональности Internet ExplorerMicrosoft ( COM -интерфейсам), доступным в объектной модели ActiveX для Internet ExplorerVisual C++ создать свои интерфейсные классы для COM -интерфейсов, т.е. как вызывать функции COM -интерфейсов из своего приложенияCHtmlView и Internet ExplorerКласс CHtmlView, будучи использован в качестве базового вместо класса CView, позволяет создавать однодокументные или многодокументные приложения с возможность просмотра HTML -документов и другими функциональностями Web -броузера. Класс содержит множество функций, в том числе и навигационных
Некоторые функции класса CHtmlView | |
|---|---|
| Функция | Назначение |
GoBack() |
Направляет пользователя на предыдущую Web - страницу |
GoForward() |
Направляет пользователя на последующую Web - страницу |
GoHome() |
Направляет пользователя на начальную страницу броузера Internet Explorer |
GoSearch() |
Направляет пользователя на страницу поиска по Internet |
Navigate(LPCTSTR URL) |
Направляет пользователя на страницу в Internet с указанным адресом URL |
Refresh() |
Заставляет браузер перезагрузить текущую Web - страницу |
Stop() |
Останавливает текущий процесс загрузки |
GetLocationURL() |
Возвращает URL текущей просматриваемой браузером Web - страницы |
GetBusy() |
Возвращает логическое значение, информирующее, занят ли в данный момент браузер загрузкой Web - страницы |
Создадим -приложение на базе класса CHtmlView. Добавим в него меню с функциями навигации назад и вперед. Добавим диалог для возможности вводить URL.
Чтобы приложение заработало, необходимо, чтобы на компьютере был установлен Web -браузер Internet Explorer. Обычно при установки IDE Visual C++ на компьютере устанавливается самая последняя версия Internet Explorer. Если разработанное приложение планируется запускать на других компьютерах, то там Internet Explorer также должен быть установлен для успешной работы нашего приложения.
Выберите папку для размещения проекта
Создайте новый проект с именем
Заполните вкладки мастера создания приложений так




Настройки остальных вкладок мастера создания приложений оставьте без изменения. Проследите, чтобы в последней вкладке Generated Classes (Генерируемые классы) для создаваемого мастером класса CWebBrowseView в качестве базового в поле был выбран класс CHtmlView.
После нажатия кнопки Finish мастер создаст заготовку приложения
Установите режим сборки проекта
Постройте проект и убедитесь, что мастер построил заготовку броузера, которую нам предстоит наделить функциональностью
URL ( - Internet. Обратите внимание, что мастер создал заготовку дополнительной панели управления со статической надписью " TODO: layout dialog bar ", указывающей на необходимость ее оформить.
Панель управления является гибридом панели инструментов и диалогового окна. Она представляет собой панель инструментов со средствами управления диалогом. Мастер MFC Application Wizard расположил ее не в разделе Toolbar, где и должны находиться панели инструментов, а в разделе Dialog, где располагаются ресурсы диалоговых окно.

Далее мы будем проектировать эту панель как обычный ресурс диалогового окна. На нее можно помещать поля редактирования, кнопки, поля со списком и переключатели - все, что используется в обычных диалоговых окнах.
Вызовите на редактирование ресурс диалогового окна IDR_MAINFRAME
Измените содержимое текстовой метки на Address и измените свойство Align Text метки на значение Right
Дополните ресурс полем редактирования Edit Control
Присвойте свойству ID поля редактирования значение IDC_EADDRESSНам не нужно для этого ресурса создавать класс поддержки функциональности, как это было бы необходимо сделать для обычного диалогового окна. Панель управления автоматически посылает свои сообщения классу главного фреймового окна приложения и их можно перенаправить через фрейм в классы представления или документа нашего -приложения.
Воспользуемся тем, что когда пользователь нажимает клавишу Enter после завершения ввода в поле редактирования, этот элемент управления Edit Control посылает фреймовому окну (класс CMainFrame ) идентификатор команды IDOK. Чтобы перехватить и обработать эту команду, нам только требуется добавить обработчик команды в карту сообщений класса CMainFrame (в файл ).
В реализации обработчика команды IDOK необходимо получить текст из поля редактирования на панели управления. Далее можно передать эту строку функции Navigate() класса представления, чтобы заставить броузер найти в сети или внутреннем кэше и отобразить указанную пользователем страницу.
В панели
Заполните мастер добавления функций так
Заполните код функции такФункция передачи URL броузеру в файле MainFrm.cpp
// Функция передачи адреса URL
void CMainFrame::OnNewAddress(void)
{
CString strAddress;
// Получить новый URL
m_wndDlgBar.GetDlgItem(IDC_EADDRESS)->GetWindowText(strAddress);
// Передать URL в броузер
((CWebBrowseView*)GetActiveView())->Navigate(strAddress);
}
Панель управления была зарегистрирована мастером создания приложений в функции OnCreate() файла MainFrm.cpp под именем m_wndDlgBar как экземпляр класса CDialogBar. Панель управления является родительской для элемента редактирования с идентификатором IDC_EADDRESS. Поэтому при получении содержимого URL мы адресуемся к полю редактирования через нее.
В последней строке кода тип возвращаемого функцией GetActiveView() указателя приводится к указателю на класс CWebBrowseView. Это позволяет вызвать функцию Navigate(), наследуемую представлением от базового класса CHtmlView.
Зарегистрируйте созданную функцию как обработчик команды IDOK нажатия клавиши. Для этого в карту сообщений класса CMainFrame вручную внесите следующий кодРегистрация функции как обработчика сообщения IDOK в карте сообщений класса CMainFrame в файле MainFrm.cpp // CMainFrame IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_COMMAND(IDOK, OnNewAddress) END_MESSAGE_MAP() ...................................
Добавьте в начало файла MainFrm.cpp директивы подключения описаний классов CWebBrowseView и CWebBrowseDocДирективы подключения заголовочных файлов с описаниями классов документа и Дирпредставления вначале файла MainFrm.cpp // MainFrm.cpp : implementation of the CMainFrame class // #include "stdafx.h" #include "WebBrowse.h" #include "MainFrm.h" #include ".\mainfrm.h" #include "WebBrowseDoc.h" #include "WebBrowseView.h" #ifdef _DEBUG #define new DEBUG_NEW #endif ..............................................
Если скомпилировать и запустить наше приложение, то можно ввести URL. После нажатия клавиши Enter, если в системе имеется соединение с Internet или настроена локальная PHP -машина (система HTML -страница как в настоящем броузере. Это может быть примерно такое...
Переходя от одной Web -странице к другой по ссылкам, настоящий броузер помещает текущее значение указателя URL в поле адреса. Тем самым дается возможность контролировать маршрут и, в случае необходимости, скопировать или изменить URL. Для получения текущего значения указателя URL нужно вызвать функцию GetLocationURL и передать полученное значение на панель управления.
Проблема в том, чтобы определить момент, когда можно получить текущий URL. Для этого в нашем классе представления CWebBrowseView, который является наследником базового класса CHtmlView, нужно переопределить некоторые функции. Данные функции вызываются, когда управляющий элемент броузера генерирует различные сообщения, в том числе:
Web -страницуWeb -страницыOnDocumentComplete.
Выберите класс CWebBrowseView на панели Class View
В панели
Создайте для OnDocumentComplete функцию замещения, которая будет вызываться после окончания загрузки Web -страницы и которую заполните так
Замещенная функция забора текущего URL в классе представления и вызова функции записи адреса
в поле редактирования из класса фрейма, где и находится панель управления с полем адреса
void CWebBrowseView::OnDocumentComplete(LPCTSTR lpszURL)
{
// TODO: Add your specialized code here and/or call the base class
// Передать текущий URL в класс фрейма для вывода в поле адреса
((CMainFrame*)GetParentFrame())->SetAddress(lpszURL);
CHtmlView::OnDocumentComplete(lpszURL);
}
Обратите внимание, что в итоге не пришлось вызывать функцию GetLocationURL(), тем более, нам неизвестно было, когда ее нужно вызывать. Искомый URL мы получили как аргумент lpszURL, который сразу передали во фреймовое окно. Теперь в классе фреймового окна нужно этот URL отобразить в поле адреса с идентификатором IDC_EADDRESS.
Чтобы в файле WebBrowseView.cpp компилятор видел описание класса CMainFrame, добавьте в начало этого файла директиву подключения файла MainFrm.hПодключение к файлу WebBrowseView.cpp директивы с описанием класса CMainFrame // WebBrowseView.cpp : implementation of the CWebBrowseView class // #include "stdafx.h" #include "WebBrowse.h" #include "WebBrowseDoc.h" #include "WebBrowseView.h" #include ".\webbrowseview.h" #include "MainFrm.h" #ifdef _DEBUG #define new DEBUG_NEW #endif ....................................
В панели
Заполните мастер добавления метода так
Незабудьте нажать кнопку Add перед щелчком по кнопке Finish
Заполните заготовку функции SetAddress() следующим кодом (мы помним, что панель управления с полем адреса ассоциирована с переменной m_wndDlgBar )Функция класса фреймового окна CMainFrame для заполнения поля адреса
текущим значением URL в файле MainFrm.cpp
// Заполнение поля адреса текущим значением URL
void CMainFrame::SetAddress(LPCTSTR lpszURL)
{
// Сменить значение URL после загрузки новой страницы
(m_wndDlgBar.GetDlgItem(IDC_EADDRESS))->SetWindowText(lpszURL);
}
Теперь можно построить приложение и убедиться, что при переходе по ссылкам в поле адреса отображается текущий URL страницы.
Добавим к нашему приложению возможности перехода на предыдущую и последующую Web -страницы. Для этого нужно воспользоваться функциями GoBack() и GoForward(), унаследованными нашим классом представления CWebBrowseView от базового MFC -класса CHtmlView. Вызовы этих функций можно связать с пунктами меню, клавишами быстрого вызова ("горячими клавишами"), или с кнопками панели инструментов.
В панели
В панели свойств
Вновь в панели
Удалите с панели меню категорию Edit все ее пункты и замените эту категорию на Navigate
Перетащите эту категорию на новое место перед категорией Help
Добавьте два новых пункта в категорию Navigate: один для функции GoBack, а второй - для функции GoForward
Установите значения свойств новых пунктов, как показано в таблице| Значения свойств пунктов меню | ||
|---|---|---|
| Пункт меню | Свойство | Значение |
| Первый | ID |
ID_NAVIGATE_BACK |
Caption |
Назад \tCtrl + B |
|
Prompt |
Назад на предыдущую Web -страницу \n Назад |
|
| Второй | ID |
ID_NAVIGATE_NEXT |
Caption |
Вперед \tCtrl + F |
|
Prompt |
Вперед на следующую Web -страницу\nВперед |
|
Внешний вид категории Navigate в редакторе меню должен выглядеть так

Для каждого пункта меню необходимо добавить обработчики сообщения о событии COMMAND. Эти сообщения должен принимать и обрабатывать класс представления CWebBrowseView. Обработчики будем создавать не двойным щелчком по соответствующему пункту, а через контекстное меню оболочки для соответствующего пункта нашего проектируемого меню в редакторе. Для меню способ создания обработчика двойным щелчком оболочкой не поддерживается, поскольку неизвестно, какой класс будет принимать и обрабатывать сообщения COMMAND, пришедшие от меню.
В редакторе меню щелкните правой кнопкой мыши на первом пункте категории
Выберите в списке
Нажмите кнопку Add and Edit и заполните созданный мастером обработчик следующим кодомОбработчик пункта меню "Назад"
void CWebBrowseView::OnNavigateBack()
{
// TODO: Add your command handler code here
// Идти к предыдущей странице
GoBack();
}
Подобным образом создайте обработчик для второго пункта меню и заполните его такОбработчик пункта меню "Вперед"
void CWebBrowseView::OnNavigateNext()
{
// TODO: Add your command handler code here
// Перейти на следующую страницу вперед
GoForward();
}
Запустите приложение и убедитесь, что пункты спроектированного меню работаютАкселераторы (горячие клавиши) применяются для быстрого доступа к командам меню при нажатии комбинации назначенных клавиш. Мы для наших пунктов меню "Назад" и "Вперед" зарезервировали комбинации клавиш " Ctrl + B " и " Ctrl + F ". Реализуем эти комбинации. Наша задача - закрепить за выбранными комбинациями те же самые идентификаторы ID_NAVIGATE_BACK и ID_NAVIGATE_NEXT, которые мы назначали для соответствующих пунктов меню Navigate.
Раскройте узел Accelerator в дереве ресурсов панели Resource View и щелкните дважды по ресурсу IDR_MAINFRAME

Откроется на редактирование таблица ID и закрепленной за ним комбинации клавиш.
Щелкните правой кнопкой мыши в любом месте таблицы New Accelerator

Выбрав этот пункт, мы тем самым добавили новую строку в конец таблицы, где можно ввести параметры акселератора. Но в конце таблицы итак имеется пустая строка, готовая для заполнения, поэтому контекстное меню добавления можно и не вызывать.
Введите значение ID_NAVIGATE_BACK в поле ID добавленной новой строки (или выберите из раскрывающегося в поле списка, поскольку раньше мы их вводили для пунктов меню), в качестве модификатора ( Modifier ) оставьте Ctrl, а в качестве клавиши ( Key ) введите латинскую B
В следующую пустую строку в поле ID введите значение ID_NAVIGATE_NEXT (или выберите из раскрывающегося в поле списка), в качестве модификатора ( Modifier ) оставьте Ctrl, а в качестве клавиши ( Key ) введите F
Теперь таблица

Вернитесь в редактор меню и проверьте, остались ли у идентификаторов пунктов те же значения ID_NAVIGATE_BACK и ID_NAVIGATE_NEXT. Если нет, то в раскрывающемся списке панели свойств Properties восстановите их вновь

Таким образом, мы назначили для пунктов меню "Назад" и "Вперед" горячие клавиши. Теперь глубокоуважаемый жирный Пользователь (у него много денежек, которые мы должны выманить!!!) нашего шедевра сможет осуществлять переходы на уже просмотренные Web-страницы или использованные ссылки, которые хранятся в кэше броузера, не только через пункты меню, но и по горячим клавишам.
Постройте приложение и убедитесь, что все работаетДобавим в панель управления правее строки ввода адреса две кнопки, дублирующие команды перехода категории Navigate главного меню приложения.
Во вкладке Resource View вызовите на редактирование диалоговый ресурс панели управления
Поместите на нее правее поля ввода адреса две кнопки Button из вкладки Toolbox
Сделайте ширину кнопок примерно равной высоте ( Width=16, Height=15 )
По поводу точных размеров кнопок сильно не напрягайтесь. Позже мы присоединим к ним изображения, которые размеры кнопок определят автоматически.

Настройте свойства кнопок в соответствии с таблицей| Значения свойств кнопок перехода | ||
|---|---|---|
| Кнопка | Свойство | Значение |
| Левая | ID |
ID_BUTTON_BACK |
Caption |
BACK |
|
Prompt |
Назад на предыдущую Web-страницу\nНазад | |
Owner Draw |
True |
|
| Правая | ID |
ID_BUTTON_NEXT |
Caption |
NEXT |
|
Prompt |
Вперед на следующую Web-страницу\nВперед | |
Owner Draw |
True |
|
Не беспокойтесь, что надписи кнопок не вмещаются в отведенные размеры. Надписи в окончательном варианте отображаться не будут и они нужны нам только для того, чтобы привязать будущие изображения к кнопкам.
Теперь нужно создать обработчики для кнопок. Кнопки находятся в классе CMainFrame и будут подавать сообщения BN_CLICKED при щелчках по ним. Принимать же и обрабатывать сообщения нужно в классе CWebBrowseView. Это точно такая же ситуация, как при создании пунктов меню, которые сами тоже находятся во фреймовом окне CMainFrame, а посылаемые ими команды перехватываются и обрабатываются в окне представления, поддерживаемого классом CWebBrowseView.
Выполните правый щелчок мышью на левой кнопке панели управления и в появившемся контекстном меню выполните команду
Настройте мастер добавления обработчиков, выделив в качестве целевого класс
Нажмите кнопку Add and Edit и мастер создаст заготовку обработчика, которую заполните такОбработчик щелчка на левой кнопке ID_BUTTON_BACK
void CWebBrowseView::OnBnClickedButtonBack()
{
// TODO: Add your control notification handler code here
// Идти к предыдущей странице
GoBack();
}
Повторите такие же шаги для создания заготовки обработчика щелчка на правой кнопке панели управления. Заготовку заполните следующим кодомОбработчик щелчка на правой кнопке ID_BUTTON_NEXT
void CWebBrowseView::OnBnClickedButtonNext()
{
// TODO: Add your control notification handler code here
// Перейти на следующую страницу вперед
GoForward();
}
Перед тем как построить приложение после введенных кнопок, привяжитесь покрепче к стулу, на котором сидите.
Постройте приложение и убедитесь, что наши кнопки исчезли с панели управления. Но вместе с тем, щелчки по тому месту, где они должны находиться, приводят к ожидаемым действиям.
Исчезновение кнопок с панели управления произошло потому, что мы установили для них свойство Owner Draw в значение True. Тем самым мы определили, что кнопки должен рисовать их владелец ( Owner ), а о самом коде рисования внутри владельца мы пока не позаботились. Владельцем (родителем) кнопок, в данном случае, является панель управления m_wndDlgBar как экземпляр класса CDialogBar, объявленная в файле MainFrm.h.
Измените свойство Owner Draw на значение False и снова постройте приложениеКнопки появились и ведут себя как и положено, обеспечивая переходы броузера, но невмещающиеся внутри них надписи портят всю картину

Заменим традиционные текстовые надписи внутри кнопок на содержательные рисунки. Для этого нужно подготовить нужные картинки в формате Bitmap, добавить в них немного соли, густо поперчить и подавать горячими. Студент Жук - разрешаю Вам передохнуть, а остальные и примкнувший к ним Панасюк - продолжайте. До Силиконовой долины или Редмонда осталось совсем немного (почти как до психушки).
Присоединяемые к кнопкам картинки будут состоять из стрелок и должны быть одинакового размера. Иначе в разных состояниях они начнут скакать по экрану. Одна картинка будет изображать стрелку влево, другая - стрелку вправо. Мы установили для левой кнопки свойство Caption в значение BACK, а для правой - NEXT. В дальнейшем мы воспользуемся этими именами для привязки изображений.
Каждая картинка будет состоять из двух экземпляров, представлющих изображение кнопки для двух состояний:
Down (экземпляры BACKD и NEXTD )Up (экземпляры BACKU и NEXTU )(Можно еще: кнопка получила фокус ввода - Focus (экземпляры BACKF и NEXTF кнопка не получила фокус ввода - экземпляры BACKX и NEXTX )
Картинки в файл ресурсов можно добавить готовыми ( Import ), а можно нарисовать средствами встроенного в оболочку графического редактора ( New ). В любом случае размер картинок должен примерно соответствовать размеру кнопок. Ранее мы определили размеры кнопок примерно такими ( Width=16, Height=15 ). Значит и картинки нужно выполнить такого же размера. Хотя при загрузке картинок в кнопки их размеры автоматически подстроятся под размеры картинок. Но нам важно, чтобы кнопки не вышли по размерам за пределы панели управления. Итак, создаем картинки для кнопок.
Щелкните правой кнопкой мыши в любом месте панели Resource View и выполните в появившемся контекстном меню команду Add Resource
Установите категорию ресурса
В открывшемся графическом редакторе щелкните правой кнопкой мыши рядом с полем рисования и через панель
Сохраните ресурс, щелкнув по вкладке правой кнопкой мыши
Нарисуйте стрелку влево, при этом для рисования активно используйте панель инструментов Панель Colors обеспечивает настройку инструментов рисования как цветовую пару с текущим значением для левой (передний цвет пары) и правой (задний цвет пары) кнопок мыши. Цветовая пара текущего цвета выбирается в панели Colors щелчками по образцам соответствующими кнопками мыши. Количество доступных цветовых образцов устанавливается в панели Properties. Дополнительные возможности графического редактора заложены в меню Image оболочки.
Сам графический редактор представлен двумя фреймами. В правом фрейме масштаб поля рисования можно менять через инструмент "Увеличительное стекло"

В левом фрейме рисунок представлен в натуральную величину.
Вновь сохраните готовый рисунок стрелки влево в файле ресурсов. Убедитесь, что в проект добавился соответствующий ресурс![]() |
![]() |
Сейчас создадим рисунок для стрелки вправо, используя уже созданное изображение стрелки влево.
Закройте окно графического редактора, войдите в панель
Выполните команду
Сохраните проект и убедитесь, что в панели


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

Должен получиться такой результат

В панели


Сохраните проект и убедитесь, что у нас теперь есть по две картинки для каждой кнопки
Вызовите на редактирование две последних картинки с идентификаторами
Теперь переназначьте каждой картинке значение свойства ID как показано в таблицеЧисловые идентификаторы мы назначали ранее для того, чтобы не запутаться. Не забудьте, что новые имена ресурсов растров нужно обязательно заключать в двойные кавычки.
Новые значения свойства ID для картинок кнопок | |||
|---|---|---|---|
Старый ID |
Bitmap | Новый ID |
Назначение |
IDB_BITMAP_BACK |
![]() |
" BACKU " |
Картинка для левой кнопки в отпущенном состоянии. Свойству Caption самой левой кнопки мы ранее присвоили значение BACK |
IDB_BITMAP_BACK_INV |
![]() |
" BACKD " |
Картинка для левой кнопки в нажатом состоянии. Свойству Caption самой левой кнопки мы ранее присвоили значение BACK |
IDB_BITMAP_NEXT |
![]() |
" NEXTU " |
Картинка для правой кнопки в отпущенном состоянии. Свойству Caption самой правой кнопки мы ранее присвоили значение NEXT |
IDB_BITMAP_NEXT_INV |
![]() |
" NEXTD " |
Картинка для правой кнопки в нажатом состоянии. Свойству Caption самой правой кнопки мы ранее присвоили значение NEXT |
Иными словами, если на кнопке текст BACK, то мы для нее создаем два растра с идентификаторами " BACKU " и " BACKD " - соответственно для отжатого и нажатого состояния. Для другой кнопки - то же самое. Этот прием обеспечит нормальную работу картинок на кнопках. Теперь панель ресурсов должна выглядеть так

Теперь осталось немного для завершения работы с кнопками: создать два экземпляра класса CBitmapButton и обеспечить с их помощью динамическую загрузку изображений в кнопки и управление ими.
Откройте через панель Solution Explorer файл MainFrm.h с описанием класса фреймового окна и внесите в конец класса следующий кодОбъявление поддерживающих объектов в файле MainFrm.h
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
public:
// Operations
public:
// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT cs);
// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext dc) const;
#endif
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
CReBar m_wndReBar;
CDialogBar m_wndDlgBar;
// Generated message map functions
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
public:
// Функция передачи адреса URL
void OnNewAddress(void);
// Заполнение поля адреса текущим значением URL
void SetAddress(LPCTSTR lpszURL);
private:
CBitmapButton m_Back, m_Next;
};
Откройте файл MainFrm.cpp, найдите в нем функцию OnCreate() и вставьте в конце код загрузки ресурсов в кнопкиКод загрузки картинок в кнопки
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
.....................................................
// TODO: Remove this if you don't want tool tips
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY);
m_Back.AutoLoad(ID_BUTTON_BACK, m_wndDlgBar);
m_Next.AutoLoad(ID_BUTTON_NEXT, m_wndDlgBar);
return 0;
}
Не забудьте установить свойство Owner Draw кнопок в значение True
Постройте проект и убедитесь, что изображения кнопок меняются, сами кнопки функционируют правильно и посылают сообщения классу CWebBrowseView, а обработчики для кнопок в файле WebBrowseView.cpp мы построили ранееТеперь наш уважаемый Пользователь имеет возможность перехода на посещенные страницы по командам меню, по горячим клавишам и кнопкам панели управления. Вот сколько много мы для него постарались.
Рассмотрим возможности прерывания загрузки, обновления страницы и перехода на начальную страницу браузера.
Если Web-страница большого объема или пропускная способность соединения слабая, то у пользователя может возникнуть необходимость прервать загрузку страницы броузером. Для этого в класса CHtmlView предусмотрена функция Stop().
Когда пользователь перемещается кнопками "Назад" и "Вперед" по уже посещенным Web-страницам, то он фактически использует информацию, которую броузер хранит в своем внутреннем кэше. Чтобы заставить броузер перегрузить страницу, а не просто отобразить версию из кэша, существует функция Refresh().
И последнее... Чтобы быстро переместиться на домашнюю страницу броузера, а это как правило стартовая страница с именем Home или Index, можно использовать встроенную в класс CHtmlView функцию GoHome(). При выполнении этой функции внутренний кэш броузера очищается.
Прежде всего нужно дополнить меню Navigate нашего приложения соответствующими пунктами.
Отредактируйте меню приложения, добавив сепаратор и три пункта в соответствии с рисунком
Откорректируйте свойства новых пунктов меню, используя информацию из таблицы| Свойства дополнительных пунктов меню | |
|---|---|
| Свойство | Значение |
ID |
ID_NAVIGATE_STOP |
Caption |
Stop |
Prompt |
Остановить загрузку\nСтоп |
ID |
ID_NAVIGATE_REFRESH |
Caption |
Refresh |
Prompt |
Обновить текущую страницу\nОбновить |
ID |
ID_NAVIGATE_GOHOME |
Caption |
GoHome |
Prompt |
Перейти на начальную страницу\nДомой |
Создайте обработчики для каждого нового пункта меню через контекстное меню пункта и команду
Заполните обработчики следующим кодомОбработчики для дополнительных возможностей броузера
void CWebBrowseView::OnNavigateStop()
{
// TODO: Add your command handler code here
// Остановить текущую загрузку
Stop();
}
void CWebBrowseView::OnNavigateRefresh()
{
// TODO: Add your command handler code here
// Перезагрузить текущую страницу
Refresh();
}
void CWebBrowseView::OnNavigateGohome()
{
// TODO: Add your command handler code here
// Идти на начальную страницу
GoHome();
}
Постройте приложение - все должно работать!Чтобы получить заголовок текущей Web -страницы и установить его в заголовке окна приложения воспользуемся свойством Title и функцией (средством доступа к свойству) get_title() интерфейса IHTMLDocument2. Для этого выполним несколько пошаговых инструкций.
Добавьте к приложению новый класс, выполнив команду



В появившемся окне
После щелчка по кнопке
Для настройки мастера Add Class From TypeLib Wizard выполните следующее:Available type libraries выберите значение Microsoft HTML Object Library <4.0> Interfaces найдите строку IHTMLDocument2 и выделите ееGenerated classes имя создаваемого класса, соответствующее выбранному интерфейсу
Щелкните по кнопке Finish для создания классаВ результате мастер создаст исходный код интерфейсного класса для интерфейса IHTMLDocument2, который полностью разместится в заголовочном файле CHTMLDocument2.h приложения и нам остается только воспользоваться кодом этого класса для решения поставленной задачи загрузки заголовка текущей Web -страницы.
В файле WebBrowseView.cpp класса представления CWebBrowseView найдите уже использованную нами ранее функцию OnDocumentComplete() и дополните ее кодом, как показано нижеКод, добавленный в функцию OnDocumentComplete() файла WebBrowseView.cpp
void CWebBrowseView::OnDocumentComplete(LPCTSTR lpszURL)
{
// TODO: Add your specialized code here and/or call the base class
// Передать текущий URL в класс фрейма для вывода в поле адреса
((CMainFrame*)GetParentFrame())->SetAddress(lpszURL);
// Создать экземпляр интерфейса класса CHTMLDocument2
CHTMLDocument2* pHDoc = new CHTMLDocument2(GetHtmlDocument());
// Получить заголовок текущей страницы
CString strTitle = pHDoc->get_title();
// Получить указатель на класс документа
CWebBrowseDoc* pDoc = GetDocument();
// Установить заголовок окна приложения
pDoc->SetTitle(strTitle);
// Удалить экземпляр интерфейса на куче
delete pHDoc;
CHtmlView::OnDocumentComplete(lpszURL);
}
Добавьте директиву #include в начало файла WebBrowseView.cpp для подключения описания нового класса CHTMLDocument2Подключение класса интерфейса к файлу представления WebBrowseView.cpp // WebBrowseView.cpp : implementation of the CWebBrowseView class // #include "stdafx.h" #include "WebBrowse.h" #include "WebBrowseDoc.h" #include "WebBrowseView.h" #include ".\webbrowseview.h" #include "MainFrm.h" #include "CHTMLDocument2.h" #ifdef _DEBUG #define new DEBUG_NEW #endif .........................................
Постройте приложение и убедитесь, что заголовок текущей страницы отображается в заголовке окна приложения
Если при построении приложения Ваш компилятор выдает ошибки в коде добавленного нами файла интерфейса CHTMLDocument2.h (мой выдает!), то сделайте следующее

Откройте в оболочке на редактирование файл CHTMLDocument2.h, найдите в нем функции write() и writeln() и внесите в них следующие измененияКорректируем "Ошибки Билла"
......................................
void write(SAFEARRAY * psarray)
{
// static BYTE parms[] = VTS_NONE ;
static BYTE* parms = (BYTE*)VTS_NONE ;
InvokeHelper(0x41e, DISPATCH_METHOD, VT_EMPTY, NULL, parms, psarray);
}
void writeln(SAFEARRAY * psarray)
{
// static BYTE parms[] = VTS_NONE ;
static BYTE* parms = (BYTE*)VTS_NONE ;
InvokeHelper(0x41f, DISPATCH_METHOD, VT_EMPTY, NULL, parms, psarray);
}
......................................
Теперь опять постройте приложение (ошибок больше быть не должно) и убедитесь, что заголовок текущей страницы отображается в заголовке окна приложенияТот стандартный каркас приложения, который сгенерировал для нас мастер в самом начале, не рассчитан на открытие документов в формате HTML. Заложенные изначально базовые возможности открытия документа реализуются посылкой сообщения ON_FILE_OPEN в ответ на щелчок Пользователя по кнопке Open панели инструментов (значок ) или выполнения одноименной команды меню. Это сообщение перехватывается в классе CWebBrowseApp (карта сообщений файла WebBrowse.cpp ) и обрабатывается функцией базового класса CWinApp::OnFileOpen()
Карта сообщений для класса CWebBrowseApp в файле WebBrowse.cpp // CWebBrowseApp BEGIN_MESSAGE_MAP(CWebBrowseApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP()
Для того, чтобы реализовать задуманное, прежде всего нужно убрать выделенный код из карты сообщений класса CWebBrowseApp. Перехватывать это сообщение мы будем во фреймовом окне, в классе которого у нас есть доступ к полю редактирования адреса. В классе фреймового окна мы построим обработчик сообщения ON_FILE_OPEN, в котором создадим и настроим диалог FileOpen, из которого извлечем информацию об имени выбранного Пользователем открываемого файла. После этого имя файла можно передать в поле ввода адреса панели управления и сгенерировать сообщение IDOK, обработчик которого у нас уже создан. Итак, приступим.
Закомментируйте код маршрутизации сообщения ON_FILE_OPEN в карте сообщений класса CWebBrowseApp, как показано нижеКомментируем код базового сообщения ON_FILE_OPEN для класса CWebBrowseApp в файле WebBrowse.cpp // CWebBrowseApp BEGIN_MESSAGE_MAP(CWebBrowseApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) // ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP()
Постройте приложение и убедитесь, что кнопка и команда меню Open стали недоступными ( Disabled )
В панели Class View выделите класс CMainFrame и сразу после этого в панели Properties установите режим Events
Найдите сообщение
Постройте приложение и убедитесь, что команда и кнопка Open стали доступными, но естественно ничего не делают, так как обработчик пока пустой
Внесите в обработчик код, который и решит всю задачуКод нового обработчика сообщения ON_FILE_OPEN
void CMainFrame::OnFileOpen()
{
// TODO: Add your command handler code here
// Создать диалог File Open
static char szFilter[] =
"HTM Files (*.htm)|*.htm|HTML Files (*.html)|*.html|All Files (*.*)|*.*||";
CFileDialog openFile(TRUE, ".htm", "",
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
CString name;
if(openFile.DoModal() == IDOK)
name = openFile.GetPathName();// Полное имя с путем
else
return;
// Сменить значение поля адреса
(m_wndDlgBar.GetDlgItem(IDC_EADDRESS))->SetWindowText(name);
OnNewAddress();// Вызвать нашу функцию
}
Постройте приложение и убедитесь, что все работает как задумали. Отметьте также, что полнофункционально работает и контекстное меню, генерируемое базовым классом Теперь осталось совсем немного - убрать лишние интерфейсы, которые из добрых побуждений создал для нас мастер при генерации -приложения. Он же не мог предположить, что мы станем "извращаться" с его заготовкой и приспосабливать ее под самопальный броузер.
Вызовите на редактирование панель инструментов и удалите лишние кнопки
Кнопки удаляйте перетаскиванием мышью за пределы панели. Сепараторы между кнопками вводятся более широкими отступами по ширине панели.

Ресурс панели инструментов после редактирования должен выглядеть так

Вызовите на редактирование ресурс меню, и приведите категорию File в соответствие с действительной функциональностью приложения

Теперь, когда мы удалили инструменты New и Save, в классе документа CWebBrowseDoc стали ненужными переопределения функций OnNewDocument() и Serialize(). Теперь уже никто их не сможет вызвать. Все ниточки-веревочки для их вызова мы обрезали. Они конечно никому не мешают и код не портят, но место все-таки занимают, да и могут смутить бедного сопровождающего программиста. Поэтому удалим их объявления в файле WebBrowseDoc.h и реализацию в файле WebBrowseDoc.cpp.
Откройте файл WebBrowseDoc.h и удалите (или закомментируйте) в объявлении класса CWebBrowseDoc следующий кодУдаление объявлений функций в классе CWebBrowseDoc
class CWebBrowseDoc : public CDocument
{
........................................
// Overrides
public:
// virtual BOOL OnNewDocument();
// virtual void Serialize(CArchive ar);
........................................
};
Откройте файл WebBrowseDoc.cpp и удалите (или закомментируйте) в реализации класса CWebBrowseDoc код функций OnNewDocument() и Serialize(CArchive ar) Удаление лишнего кода в реализации класса CWebBrowseDoc
// WebBrowseDoc.cpp : implementation of the CWebBrowseDoc class
//
#include "stdafx.h"
#include "WebBrowse.h"
#include "WebBrowseDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CWebBrowseDoc
IMPLEMENT_DYNCREATE(CWebBrowseDoc, CDocument)
BEGIN_MESSAGE_MAP(CWebBrowseDoc, CDocument)
END_MESSAGE_MAP()
// CWebBrowseDoc construction/destruction
CWebBrowseDoc::CWebBrowseDoc()
{
// TODO: add one-time construction code here
}
CWebBrowseDoc::~CWebBrowseDoc()
{
}
/*
BOOL CWebBrowseDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
// CWebBrowseDoc serialization
void CWebBrowseDoc::Serialize(CArchive ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
*/
// CWebBrowseDoc diagnostics
#ifdef _DEBUG
void CWebBrowseDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CWebBrowseDoc::Dump(CDumpContext dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CWebBrowseDoc commands
Откройте файл WebBrowse.cpp и удалите в карте сообщений маршрутизатор сообщения ID_FILE_NEW. Все равно теперь никто в приложении это сообщение не пошлет - мы все стерилизовалиКорректировка карты приема сообщений класса CWebBrowseApp BEGIN_MESSAGE_MAP(CWebBrowseApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // Standard file based document commands // ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) // ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP()
Добавьте в категорию
Оформите About и смените иконку приложения
Запустите и испытайте приложение - работает как настоящий Броузер (почти)
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.