Обработка событий IWebBrowser на Ассемблере
Обработка событий IWebBrowser на Ассемблере
В предыдущей статье про работу со встроенным браузером я написал, что статус полной загрузки страницы можно отслеживать при помощи таймера и вызова метода get_ReadyState интерфейса IWebBrowser2. Способ имеет место быть, но также имеет немало недостатков. Правильное решение этой задачи - получения сигналов от объекта браузера и обработка событий IWebBrowser. Пришлось провести пару бессонных ночей в отладчике, но результат меня порадовал.
Как и при любой другой работе с COM-объектами, процесс начинается с описания нужных структур, констант и GUID'ов. Какие-то вам уже знакомы по предыдущим публикациям, какие-то новые.
Code (Assembler) : Убрать нумерацию
- ; GUID {00000000-0000-0000-C000-000000000046}
- IID_IUnknown \
- dd 000000000h
- dw 00000h
- dw 00000h
- db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
- ; GUID {D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}
- IID_IWebBrowser2 \
- dd 0D30C1661h
- dw 0CDAFh
- dw 011D0h
- db 08Ah, 03Eh, 000h, 0C0h, 04Fh, 0C9h, 0E2h, 06Eh
- ; GUID {8856F961-340A-11D0-A96B-00C04FD705A2}
- CLSID_WebBrowser \
- dd 08856F961h
- dw 0340Ah
- dw 011D0h
- db 0A9h, 06Bh, 000h, 0C0h, 04Fh, 0D7h, 005h, 0A2h
- ; GUID {B196B284-BAB4-101A-B69C-00AA00341D07}
- IID_IConnectionPointContainer \
- dd 0B196B284h
- dw 0BAB4h
- dw 0101Ah
- db 0B6h, 09Ch, 000h, 0AAh, 000h, 034h, 01Dh, 007h
- ; GUID {B196B286-BAB4-101A-B69C-00AA00341D07}
- IID_IConnectionPoint \
- dd 0B196B286h
- dw 0BAB4h
- dw 0101Ah
- db 0B6h, 09Ch, 000h, 0AAh, 000h, 034h, 01Dh, 007h
- ; GUID {34A715A0-6587-11D0-924A-0020AFC7AC4D}
- IID_DWebBrowserEvents2 \
- dd 034A715A0h
- dw 06587h
- dw 011D0h
- db 092h, 04Ah, 000h, 020h, 0AFh, 0C7h, 0ACh, 04Dh
- ; IID_IWebBrowser2 Interface
- struct IWebBrowser2
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IWebBrowser2
- GetTypeInfoCount dd ? ; 00Ch
- GetTypeInfo dd ? ; 010h
- GetIDsOfNames dd ? ; 014h
- _Invoke dd ? ; 018h
- GoBack dd ? ; 01Ch
- GoForward dd ? ; 020h
- GoHome dd ? ; 024h
- GoSearch dd ? ; 028h
- Navigate dd ? ; 02Ch
- Refresh dd ? ; 030h
- Refresh2 dd ? ; 034h
- Stop dd ? ; 038h
- get_Application dd ? ; 03Ch
- get_Parent dd ? ; 040h
- get_Container dd ? ; 044h
- get_Document dd ? ; 048h
- get_TopLevelContainer dd ? ; 04Ch
- get_Type dd ? ; 050h
- get_Left dd ? ; 054h
- put_Left dd ? ; 058h
- get_Top dd ? ; 05Ch
- put_Top dd ? ; 060h
- get_Width dd ? ; 064h
- put_Width dd ? ; 068h
- get_Height dd ? ; 06Ch
- put_Height dd ? ; 070h
- get_LocationName dd ? ; 074h
- get_LocationURL dd ? ; 078h
- get_Busy dd ? ; 07Ch
- Quit dd ? ; 080h
- ClientToWindow dd ? ; 084h
- PutProperty dd ? ; 088h
- GetProperty dd ? ; 08Ch
- get_Name dd ? ; 090h
- get_HWND dd ? ; 094h
- get_FullName dd ? ; 098h
- get_Path dd ? ; 09Ch
- get_Visible dd ? ; 0A0h
- put_Visible dd ? ; 0A4h
- get_StatusBar dd ? ; 0A8h
- put_StatusBar dd ? ; 0ACh
- get_StatusText dd ? ; 0B0h
- put_StatusText dd ? ; 0B4h
- get_ToolBar dd ? ; 0B8h
- put_ToolBar dd ? ; 0BCh
- get_MenuBar dd ? ; 0C0h
- put_MenuBar dd ? ; 0C4h
- get_FullScreen dd ? ; 0C8h
- put_FullScreen dd ? ; 0CCh
- Navigate2 dd ? ; 0D0h
- QueryStatusWB dd ? ; 0D4h
- ExecWB dd ? ; 0D8h
- ShowBrowserBar dd ? ; 0DCh
- get_ReadyState dd ? ; 0E0h
- get_Offline dd ? ; 0E4h
- put_Offline dd ? ; 0E8h
- get_Silent dd ? ; 0ECh
- put_Silent dd ? ; 0F0h
- get_RegisterAsBrowser dd ? ; 0F4h
- put_RegisterAsBrowser dd ? ; 0F8h
- get_RegisterAsDropTarget dd ? ; 0FCh
- put_RegisterAsDropTarget dd ? ; 100h
- get_TheaterMode dd ? ; 104h
- put_TheaterMode dd ? ; 108h
- get_AddressBar dd ? ; 10Ch
- put_AddressBar dd ? ; 110h
- get_Resizable dd ? ; 114h
- put_Resizable dd ? ; 118h
- ends
- ; IID_IConnectionPointContainer Interface
- struct IConnectionPointContainer
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IConnectionPointContainer
- EnumConnectionPoints dd ? ; 00Ch
- FindConnectionPoint dd ? ; 010h
- ends
- ; IID_IConnectionPoint Interface
- struct IConnectionPoint
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IConnectionPoint
- GetConnectionInterface dd ? ; 00Ch
- GetConnectionPointContainer dd ? ; 010h
- Advise dd ? ; 014h
- Unadvise dd ? ; 018h
- EnumConnections dd ? ; 01Ch
- ends
- ; DWebBrowserEvents2 Interface
- struct DWebBrowserEvents2
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; DWebBrowserEvents2
- GetTypeInfoCount dd ? ; 00Ch
- GetTypeInfo dd ? ; 010h
- GetIDsOfNames dd ? ; 014h
- _Invoke dd ? ; 018h
- refcount dd ?
- ends
- CLSCTX_INPROC_SERVER = 0x01
- CLSCTX_INPROC_HANDLER = 0x02
- CLSCTX_LOCAL_SERVER = 0x04
- CLSCTX_REMOTE_SERVER = 0x10
- CLSCTX_SERVER = CLSCTX_INPROC_SERVER + CLSCTX_LOCAL_SERVER\
- + CLSCTX_REMOTE_SERVER
- CLSCTX_ALL = CLSCTX_INPROC_HANDLER + CLSCTX_SERVER
- S_OK = 0
- VARIANT_TRUE = -1
- VARIANT_FALSE = 0
- VT_BSTR = 8
- DISPID_DOCUMENTCOMPLETE = 259
Code (Assembler) : Убрать нумерацию
- ;----------------------------------------------------------------------------
- ; Обработчик метода QueryInterface
- ;----------------------------------------------------------------------------
- proc IWebBrowserEvents_QueryInterface pthis:DWORD, iid:DWORD, ppvObject:DWORD
- pusha
- mov eax,[ppvObject]
- cmp eax,0
- jne @f
- ; E_POINTER
- mov eax,0x80004003
- jmp .loc_ret
- @@:
- ; Это интерфейс DWebBrowserEvents2?
- push 4
- pop ecx
- mov esi,[iid]
- mov edi,IID_DWebBrowserEvents2
- xor eax,eax
- repe cmpsd
- jz .loc_call
- ; Это интерфейс IUnknown?
- push 4
- pop ecx
- mov esi,[iid]
- mov edi,IID_IUnknown
- xor eax,eax
- repe cmpsd
- jz .loc_call
- ; E_NOINTERFACE
- mov eax,0x80004002
- jmp .loc_ret
- .loc_call:
- mov eax,[pthis]
- ; Установить интерфейс
- mov ecx,[ppvObject]
- mov [ecx],eax
- mov ecx,[eax]
- stdcall dword [ecx+DWebBrowserEvents2.AddRef],eax
- .loc_ok:
- ; S_OK
- xor eax,eax
- .loc_ret:
- mov [esp+28],eax
- popa
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода AddRef
- ;----------------------------------------------------------------------------
- proc IWebBrowserEvents_AddRef pthis:DWORD
- mov eax,[pthis]
- inc [eax+DWebBrowserEvents2.refcount]
- mov eax,[eax+DWebBrowserEvents2.refcount]
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Обработчик метода Release
- ;----------------------------------------------------------------------------
- proc IWebBrowserEvents_Release pthis:DWORD
- push ecx
- mov eax,[pthis]
- mov ecx,[eax+DWebBrowserEvents2.refcount]
- or ecx,ecx
- jz @f
- dec [eax+DWebBrowserEvents2.refcount]
- dec ecx
- @@:
- mov eax,ecx
- pop ecx
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Заглушка для метода GetTypeInfoCount
- ;----------------------------------------------------------------------------
- proc IWebBrowserEvents_GetTypeInfoCount pthis:DWORD, pctinfo:DWORD
- ; E_NOTIMPL
- mov eax,0x80000001
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Заглушка для метода GetTypeInfo
- ;----------------------------------------------------------------------------
- proc IWebBrowserEvents_GetTypeInfo pthis:DWORD, iTInfo:DWORD,\
- lcid:DWORD, ppTInfo:DWORD
- ; E_NOTIMPL
- mov eax,0x80000001
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Заглушка для метода GetIDsOfNames
- ;----------------------------------------------------------------------------
- proc IWebBrowserEvents_GetIDsOfNames pthis:DWORD, riid:DWORD,\
- rgszNames:DWORD, cNames:DWORD, lcid:DWORD, rgDispId:DWORD
- ; S_OK
- xor eax,eax
- ret
- endp
- ;----------------------------------------------------------------------------
- ; Основной обработчик событий
- ;----------------------------------------------------------------------------
- proc IWebBrowserEvents_Invoke pthis:DWORD, dispIdMember:DWORD,\
- riid:DWORD, lcid:DWORD, wFlags:DWORD, pDispParams:DWORD,\
- pVarResult:DWORD, pExcepInfo:DWORD, puArgErr:DWORD
- ; Пришло событие DISPID_DOCUMENTCOMPLETE?
- cmp [dispIdMember],DISPID_DOCUMENTCOMPLETE
- jne @f
- pusha
- invoke MessageBox,0,szText,szTitle,0
- popa
- @@:
- ; S_OK
- xor eax,eax
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ; Настроить структуру IWebBrowserEvents для браузера
- mov [WebBrowserEvents.QueryInterface],IWebBrowserEvents_QueryInterface
- mov [WebBrowserEvents.AddRef],IWebBrowserEvents_AddRef
- mov [WebBrowserEvents.Release],IWebBrowserEvents_Release
- mov [WebBrowserEvents.GetTypeInfoCount],IWebBrowserEvents_GetTypeInfoCount
- mov [WebBrowserEvents.GetTypeInfo],IWebBrowserEvents_GetTypeInfo
- mov [WebBrowserEvents.GetIDsOfNames],IWebBrowserEvents_GetIDsOfNames
- mov [WebBrowserEvents._Invoke],IWebBrowserEvents_Invoke
- ; Заполнить указатель на структуру
- mov [pWebBrowserEvents],WebBrowserEvents
Code (Assembler) : Убрать нумерацию
- ; Запросить интерфейс IConnectionPointContainer у объекта браузера
- mov eax,[pBrowser]
- mov eax,[eax]
- stdcall dword [eax+IWebBrowser2.QueryInterface],[pBrowser],\
- IID_IConnectionPointContainer,cPointContainer
- ; Найти точку соединения с DWebBrowserEvents2
- mov eax,[cPointContainer]
- mov eax,[eax]
- stdcall dword [eax+IConnectionPointContainer.FindConnectionPoint],\
- [cPointContainer],\
- IID_DWebBrowserEvents2,cPoint
- ; Подключить интерфейс к точке соединения
- mov [pCookie],Cookie
- mov eax,[cPoint]
- mov eax,[eax]
- stdcall dword [eax+IConnectionPoint.Advise],[cPoint],\
- pWebBrowserEvents,[pCookie]
Code (Assembler) : Убрать нумерацию
- ; Подключить интерфейс к точке соединения
- mov [pCookie],Cookie
- invoke AtlAdvise,[pBrowser],pWebBrowserEvents,\
- IID_DWebBrowserEvents2,[pCookie]
Code (Assembler) : Убрать нумерацию
- ; Отключиться от точки соединения
- mov eax,[cPoint]
- mov eax,[eax]
- stdcall dword [eax+IConnectionPoint.Unadvise],[cPoint],[Cookie]
Code (Assembler) : Убрать нумерацию
- ; Отключиться от точки соединения
- invoke AtlUnadvise,[pBrowser],IID_DWebBrowserEvents2,[Cookie]
Как видите, ничего страшного в обработке событий IWebBrowser нет. Кроме объекта браузера подобные функции наблюдателя можно прикрепить к отдельным элементам HTML-страницы и отслеживать, например, переход по ссылкам. Пока такой задачи не стоит, но искать нужные теги на странице мы уже умеем.
В приложении примеры программ с исходными текстами, которые реализуют обработку событий встроенного браузера описанными в статье способами.
Просмотров: 495 | Комментариев: 0
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария