Blog. Just Blog

Встроенный браузер в приложении на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Встроенный браузер в приложении на Ассемблере
Встроенный браузер в приложении на Ассемблере

Сегодня будем рисовать свой браузер, а точнее внедрять фрейм web-браузера в интерфейс нашего приложения. Нечто подобное мы уже делали, но там были отдельные страницы, а сейчас полноценный браузер, встроенный в приложение. Языком исполнения, естественно, будет Ассемблер.

Браузер, встраиваемый в приложение, работает на движке Internet Explorer, а точнее на его системном компоненте IECore. Доступ к этому объекту осуществляется через COM-интерфейсы IWebBrowser2. Начинаем с описания структур и интерфейсов, которые понадобятся нам для дальнейшей работы.
  1. struct DECIMAL
  2.     wReserved dw ?
  3.     union
  4.         struct
  5.             scale db ?
  6.             sign db ?
  7.         ends
  8.         signscale dw ?
  9.     ends
  10.     Hi32 dd ?
  11.     union
  12.         struct
  13.             Lo32 dd ?
  14.             Mid32 dd ?
  15.         ends
  16.         Lo64 dq ?
  17.     ends
  18. ends
  19.  
  20. struct VARIANT
  21.     union
  22.         struct
  23.             vt dw ?
  24.             wReserved rw 3
  25.             union
  26.                 llVal dq ?
  27.                 lVal  dd ?
  28.                 iVal  dw ?
  29.                 bVal  db ?
  30.             ends
  31.         ends
  32.         decVal DECIMAL
  33.     ends
  34. ends
  35.  
  36. ; GUID {8856F961-340A-11D0-A96B-00C04FD705A2}
  37. CLSID_WebBrowser dd 08856F961h
  38.                  dw 0340Ah
  39.                  dw 011D0h
  40.                  db 0A9h, 06Bh, 000h, 0C0h, 04Fh, 0D7h, 005h, 0A2h
  41.  
  42. ; GUID {D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}
  43. IID_IWebBrowser2 dd 0D30C1661h
  44.                  dw 0CDAFh
  45.                  dw 011D0h
  46.                  db 08Ah, 03Eh, 000h, 0C0h, 04Fh, 0C9h, 0E2h, 06Eh
  47.  
  48. ; IID_IWebBrowser2 Interface
  49. struct IWebBrowser2
  50.     ; IUnknown
  51.     QueryInterface           dd ?   ; 000h
  52.     AddRef                   dd ?   ; 004h
  53.     Release                  dd ?   ; 008h
  54.     ; IWebBrowser2
  55.     GetTypeInfoCount         dd ?   ; 00Ch
  56.     GetTypeInfo              dd ?   ; 010h
  57.     GetIDsOfNames            dd ?   ; 014h
  58.     _Invoke                  dd ?   ; 018h
  59.     GoBack                   dd ?   ; 01Ch
  60.     GoForward                dd ?   ; 020h
  61.     GoHome                   dd ?   ; 024h
  62.     GoSearch                 dd ?   ; 028h
  63.     Navigate                 dd ?   ; 02Ch
  64.     Refresh                  dd ?   ; 030h
  65.     Refresh2                 dd ?   ; 034h
  66.     Stop                     dd ?   ; 038h
  67.     get_Application          dd ?   ; 03Ch
  68.     get_Parent               dd ?   ; 040h
  69.     get_Container            dd ?   ; 044h
  70.     get_Document             dd ?   ; 048h
  71.     get_TopLevelContainer    dd ?   ; 04Ch
  72.     get_Type                 dd ?   ; 050h
  73.     get_Left                 dd ?   ; 054h
  74.     put_Left                 dd ?   ; 058h
  75.     get_Top                  dd ?   ; 05Ch
  76.     put_Top                  dd ?   ; 060h
  77.     get_Width                dd ?   ; 064h
  78.     put_Width                dd ?   ; 068h
  79.     get_Height               dd ?   ; 06Ch
  80.     put_Height               dd ?   ; 070h
  81.     get_LocationName         dd ?   ; 074h
  82.     get_LocationURL          dd ?   ; 078h
  83.     get_Busy                 dd ?   ; 07Ch
  84.     Quit                     dd ?   ; 080h
  85.     ClientToWindow           dd ?   ; 084h
  86.     PutProperty              dd ?   ; 088h
  87.     GetProperty              dd ?   ; 08Ch
  88.     get_Name                 dd ?   ; 090h
  89.     get_HWND                 dd ?   ; 094h
  90.     get_FullName             dd ?   ; 098h
  91.     get_Path                 dd ?   ; 09Ch
  92.     get_Visible              dd ?   ; 0A0h
  93.     put_Visible              dd ?   ; 0A4h
  94.     get_StatusBar            dd ?   ; 0A8h
  95.     put_StatusBar            dd ?   ; 0ACh
  96.     get_StatusText           dd ?   ; 0B0h
  97.     put_StatusText           dd ?   ; 0B4h
  98.     get_ToolBar              dd ?   ; 0B8h
  99.     put_ToolBar              dd ?   ; 0BCh
  100.     get_MenuBar              dd ?   ; 0C0h
  101.     put_MenuBar              dd ?   ; 0C4h
  102.     get_FullScreen           dd ?   ; 0C8h
  103.     put_FullScreen           dd ?   ; 0CCh
  104.     Navigate2                dd ?   ; 0D0h
  105.     QueryStatusWB            dd ?   ; 0D4h
  106.     ExecWB                   dd ?   ; 0D8h
  107.     ShowBrowserBar           dd ?   ; 0DCh
  108.     get_ReadyState           dd ?   ; 0E0h
  109.     get_Offline              dd ?   ; 0E4h
  110.     put_Offline              dd ?   ; 0E8h
  111.     get_Silent               dd ?   ; 0ECh
  112.     put_Silent               dd ?   ; 0F0h
  113.     get_RegisterAsBrowser    dd ?   ; 0F4h
  114.     put_RegisterAsBrowser    dd ?   ; 0F8h
  115.     get_RegisterAsDropTarget dd ?   ; 0FCh
  116.     put_RegisterAsDropTarget dd ?   ; 100h
  117.     get_TheaterMode          dd ?   ; 104h
  118.     put_TheaterMode          dd ?   ; 108h
  119.     get_AddressBar           dd ?   ; 10Ch
  120.     put_AddressBar           dd ?   ; 110h
  121.     get_Resizable            dd ?   ; 114h
  122.     put_Resizable            dd ?   ; 118h
  123. ends
Инициализируем COM и создаем объект браузера. Тут ничего нового, работа с COM-объектами обсуждалась уже не раз. Все необходимые GUID'ы описаны выше.
  1.         invoke  CoInitialize,0
  2.  
  3.         ; Создать объект браузера
  4.         invoke  CoCreateInstance,CLSID_WebBrowser,NULL,\
  5.                 CLSCTX_ALL,IID_IWebBrowser2,pBrowser
  6.         cmp     eax,S_OK
  7.         jne     loc_error
Теперь нам надо связать свежесозданный объект браузера и элемент диалогового окна нашего приложения. Лучше всего подходит элемент STATIC. Для связки используются функции так называемого составного элемента управления. Сперва надо активировать этот механизм для нашего кода при помощи функции AtlAxWinInit, а затем выполнить связку при помощи функции AtlAxAttachControl.
  1.         ; Инициализировать составные элементы управления
  2.         invoke  AtlAxWinInit
  3.  
  4.         ; Подключить встроенный браузер к элементу STATIC
  5.         invoke  GetDlgItem,[hwnddlg],ID_BROWSER
  6.         invoke  AtlAxAttachControl,[pBrowser],eax,0
Границы и размеры фрейма браузера будут в точности соответствовать границам элемента диалогового окна. Если в процессе работы меняется размер родительского элемента, то аналогично меняется и размер браузера.

Осталось включить видимость фрейма браузера и передать ему команду на переход по указанной ссылке. Ссылка может быть как на удаленный сервер, так и на локальный файл или на ресурс в локальной сети. Короче, все, что может открыть "большой" браузер, может быть открыто и во встроенном браузере. Синтаксис ссылок тот же самый. Для продвинутых запросов можно сформировать дополнительные заголовки, передать куки или набор данных для POST-формы. Формат открываемых файлов также соответствует возможностям полноценного браузера. Например, используя эту технологию, я нарисовал для своих нужд очень шустрый и компактный просмотрщик SVG-файлов.
  1. VT_BSTR = 8
  2. VARIANT_TRUE = -1
  3.  
  4. szURL du 'https://yandex.ru',0
  5. vtURL VARIANT
  6.         ...
  7.         ...
  8.         ; Включить видимость
  9.         mov     eax,[pBrowser]
  10.         mov     eax,[eax]
  11.         stdcall dword [eax+IWebBrowser2.put_Visible],[pBrowser],VARIANT_TRUE
  12.  
  13.         ; Открыть указанную страницу
  14.         mov     [vtURL.vt],VT_BSTR
  15.         mov     [vtURL.lVal],szURL
  16.  
  17.         mov     eax,[pBrowser]
  18.         mov     eax,[eax]
  19.         stdcall dword [eax+IWebBrowser2.Navigate2],[pBrowser],vtURL,0,0,0,0
Все дальнейшие действия выполняются уже в контексте браузера, но в любой момент вы можете открыть нужную страницу при помощи метода Navigate2. Состояние запрошенной страницы отслеживается при помощи метода get_ReadyState, возможные значения статусов смотрите в документации:
  1.         mov     eax,[pBrowser]
  2.         mov     eax,[eax]
  3.         stdcall dword [eax+IWebBrowser2.get_ReadyState],[pBrowser],dState
  4.         ; Страница загружена?
  5.         cmp     [dState],READYSTATE_COMPLETE
  6.         je      page_loaded
Когда браузер становится ненужным, удаляем связанный с ним объект.
  1.         mov     eax,[pBrowser]
  2.         mov     eax,[eax]
  3.         stdcall dword [eax+IWebBrowser2.Release],[pBrowser]
  4.  
  5.         invoke  CoUninitialize
Если нужно получить исходный код страницы, загруженной во встроенный браузер, или же требуется извлечь какой-то отдельный ее элемент, то почитайте эту статью.

В приложении пример программы с исходным текстом, которая создает окно с двумя встроенными независимыми браузерами.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Embedded.Browser.Demo.zip (3,645 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 1389 | Комментариев: 9

Метки: Assembler, сеть, COM
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (11.07.2022 в 14:23):
Это ж демонстрашка браузеров, поэтому так и задумано. Для разворотов надо рисовать обработчики на WM_SIZE, динамически подгонять размеры элементов под новые размеры и все такое прочее. Тут тема совсем не про это, незачем загромождать исходники лишним кодом.
Kemper (11.07.2022 в 14:18):
А чего на фулскрин не разворачивает - или так и задумано?
ManHunter (07.07.2022 в 14:29):
А вообще очень удобная штука получилась. На сервере крутится скрипт, который делает свою работу и по итогам дает какой-то выхлоп. На десктопе висит маленькое окошко-виджет, в котором открыта web-морда этого скрипта и периодически обновляется.
кодер (07.07.2022 в 13:11):
Хромовский движок - это если обязательно нужна полноценная поддержка современного веба. Да, для узкоспециализированных задач, IE - вполне себе вариант.

Вот что майкрософт сейчас мутит с Win32 API:

Раньше разработчикам приходилось выбирать между классической архитектурой Win32, совместимой с прошлыми версиями Windows, и UWP, работающей на Windows 10. Платформа Project Reunion должна объединить программные интерфейсы Win32 и UWP и сохранить обратную совместимость.

В состав Project Reunion включен компонент WebView2 - с его помощью любое приложение Windows будет поддерживать веб-контент через встроенный Microsoft Edge и Chromium.

Там вроде бы как вызовы Win32 API хитро транслируются на новую платформу. Т.е. некоторые старые программы C++ теоретически можно просто перекомпилировать, ничего не изменяя. Не знаю, зайдёт ли эта новая "технология" в массы, или будет как всегда, посмотрим. :)

Да, сейчас Project Reunion называется Windows App SDK.
https://en.wikipedia.org/wiki/Windows_App_SDK
https://docs.microsoft.com/en-...ows-app-sdk/
ManHunter (07.07.2022 в 11:26):
Тогда не вижу причины для паники и необходимости перехода на хромовский движок. Вон, TheBat перешли, сразу дистрибутив x3 и до сих пор баги вычистить не могут. Периодически ставлю новые версии, плююсь, удаляю и откатываюсь на 9.1
кодер (07.07.2022 в 11:21):
Конечно работает. Более того, скорее всего IE никогда и не выпилят из Windows, потому что даже некоторые гос. учреждения до сих пор завязаны на ActiveX IE.
Однако IE скорее всего не будет открывать некоторые https сайты с новым TLS, и появятся сложности с поддержкой новых версий JS/CSS.
User (07.07.2022 в 10:02):
https://docs.microsoft.com/en-...crosoft-edge

не deprecated. Скорее obsolete
ManHunter (06.07.2022 в 21:10):
С чего бы вдруг? Под Win10 все прекрасно работает. И в MSDN ни слова про deprecated.
кодер (06.07.2022 в 19:01):
Это IE (который с 15 июня официально уже deprecated). А c Edge такое вроде уже и не сработает. Вообще майкрософт не поймёшь, клепают технологии-однодневки. То ли они забросили свой COM+/OLE, то ли будут его как-то реанимировать - ничего не понятно. В итоге смотрю в сторону Chromium Embedded Framework (сокр. CEF) - открытый фреймворк для встраивания в приложение браузерного движка из проекта Chromium.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0055 сек.) / Память: 4.5 Mb
Наверх