加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

获取对话框中的IHTMLDocument2接口和跨域取得框架中的IHTMLDocument2接口

(2016-05-23 22:22:38)
标签:

杂谈

  1. 用SPY++取得窗口类名或窗口标题,用FindWindow取得窗口句柄
  2. 用SPY++取得各级子窗口类名,用EnumChildWindow枚举各级窗口直到得到类名为Internet Explorer_Server的子窗口的句柄
  3. 利用消息WM_HTML_GETOBJECT得到HtmlDocument对象

 

Option Explicit

'Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

Private Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long

Private Declare Function SetActiveWindow Lib "user32" (ByVal hWnd As Long) As Long

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

 

 

Public Declare Function timeSetEvent Lib "winmm.dll" (ByVal uDelay As Long, ByVal uResolution As Long, ByVal lpFunction As Long, ByVal dwUser As Long, ByVal uFlags As Long) As Long

Public Declare Function timeKillEvent Lib "winmm.dll" (ByVal uID As Long) As Long

 

'

' 要求:使用本模块时需要在工程中引用 Microsoft HTML Object Library。

'

 

Private Type GUID

Data1 As Long

Data2 As Integer

Data3 As Integer

Data4(0 To 7) As Byte

End Type

Private Declare Function GetClassName Lib "user32" _

Alias "GetClassNameA" ( _

ByVal hWnd As Long, _

ByVal lpClassName As String, _

ByVal nMaxCount As Long) As Long

Private Declare Function EnumChildWindows Lib "user32" ( _

ByVal hWndParent As Long, _

ByVal lpEnumFunc As Long, _

lParam As Long) As Long

Private Declare Function RegisterWindowMessage Lib "user32" _

Alias "RegisterWindowMessageA" ( _

ByVal lpString As String) As Long

Private Declare Function SendMessageTimeout Lib "user32" _

Alias "SendMessageTimeoutA" ( _

ByVal hWnd As Long, _

ByVal msg As Long, _

ByVal wParam As Long, _

lParam As Any, _

ByVal fuFlags As Long, _

ByVal uTimeout As Long, _

lpdwResult As Long) As Long

Private Const SMTO_ABORTIFHUNG = &H2

Private Declare Function ObjectFromLresult Lib "oleacc" ( _

ByVal lResult As Long, _

riid As GUID, _

ByVal wParam As Long, _

ppvObject As Any) As Long

Private Declare Function FindWindow Lib "user32" _

Alias "FindWindowA" ( _

ByVal lpClassName As String, _

ByVal lpWindowName As String) As Long

 

 

Private IframeIE() As SHDocVw.WebBrowser

 

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'传入类名为Internet Explorer_Server的WebBrowser控件的句柄,取得其IHTMLDocument对象接口

Function getIHTMLDocFromIEShWND(ByVal hWnd As Long) As IHTMLDocument

Dim IID_IHTMLDocument As GUID

Dim lRes As Long

Dim lMsg As Long

Dim hr As Long

 

If hWnd <> 0 Then

' 注册消息。

lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT")

' 获取对象的指针。

Call SendMessageTimeout(hWnd, lMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes)

If lRes Then

' 初始化接口 ID。

With IID_IHTMLDocument

.Data1 = &H626FC520

.Data2 = &HA41E

.Data3 = &H11CF

.Data4(0) = &HA7

.Data4(1) = &H31

.Data4(2) = &H0

.Data4(3) = &HA0

.Data4(4) = &HC9

.Data4(5) = &H8

.Data4(6) = &H26

.Data4(7) = &H37

End With

' 利用指针 lRes 获取 IHTMLDocument 对象。

hr = ObjectFromLresult(lRes, IID_IHTMLDocument, 0, getIHTMLDocFromIEShWND)

End If

End If

 

End Function

 

''''''''''''''''''''''''''''''''''''''''''''''''''

'由父窗口句柄枚举得到类名为Internet Explorer_Server的控件的句柄

Function getIEShWND(ByVal hWnd As Long) As Long

getIEShWND = hWnd

If hWnd <> 0 Then

If Not IsIEServerWindow(hWnd) Then

' 查找一个 WebBrowser 控件。

EnumChildWindows hWnd, AddressOf EnumChildProc, getIEShWND

End If

End If

End Function

 

Private Function IsIEServerWindow(ByVal hWnd As Long) As Boolean

Dim lRes As Long

Dim sClassName As String

' 初始化缓冲区大小。

sClassName = String$(255, 0)

' 获取 hWnd 句柄拥有者的类名称。

lRes = GetClassName(hWnd, sClassName, Len(sClassName))

sClassName = Left$(sClassName, lRes)

IsIEServerWindow = StrComp(sClassName, "Internet Explorer_Server", vbTextCompare) = 0

End Function

 

Function EnumChildProc(ByVal hWnd As Long, lParam As Long) As Long

If IsIEServerWindow(hWnd) Then

lParam = hWnd

Else

EnumChildProc = 1

End If

End Function

 

'''''''''''''''''''''''''''''''''''''''''''''''

'根据类名获得顶层窗口的句柄

Function gethWNDbyClassname(Optional className As String = "Internet Explorer_TridentDlgFrame") As Long

gethWNDbyClassname = FindWindow(className, vbNullString)

End Function

 

 

 

'''''''''''''''''''''''''''''''''''''''''''''''''''''

'以下代码通过HWnd取得HTML文档,并保存于文件中

Sub test()

Dim iesDoc As IHTMLDocument3

Dim hWnd As Long

 

hWnd = gethWNDbyClassname()

hWnd = getIEShWND(hWnd)

Set iesDoc = getIHTMLDocFromIEShWND(hWnd)

Open "E:\Users\st\Desktop\A000000.txt" For Output As #1

Write #1, iesDoc.URL & vbCrLf & vbCrLf & iesDoc.DocumentElement.innerHTML & vbCrLf & vbCrLf

 

Call EnumFrames(iesDoc)

Set iesDoc = IframeIE(0).document

Write #1, iesDoc.DocumentElement.innerHTML

 

 

'iesDoc.getElementsByName("qyjcxx.dacfd")(0).Value = "jhksfljhgslhglshg"

 

 

 

Close #1

 

 

End Sub

 

 

 

'问题:

' 当 Document 对象中包含多个 frames 的时候,直接通过 IHTMLDocument2.frames 或者 IHTMLFrameBase 或者

'IHTMLWindow2 都不能访问不同不同域名下 frame 对象. 这个看起来是乎可以防止恶意的网站行为.但对我们测试也带来麻烦.

'

' 解决问题的方法其实很简单 , 如下:

'

' (这个方法来源于国外的一个开发者论坛,解答者只是给出了微软关于获得HTML文档框架的连接 (见附录),没有其他的说

'明,我找不到那个地址了,不好意思.)

'

' 我们知道通过 IHTMLDcoument2 对象可以得到 IContainer 对象, 而 IContainer 对象包含当前 HTMLDocument2 对

'象中所有子对象的 IWebBrowser2 对象,访问 IWebBrowser2 对象中 IHTMLDocument2 对象就是我们需要的 frame 对象包

'含的 IHTMLDocument2 对象. 那么对于每个子 IWebBrowser2 对象如何判断它属于哪个 frame 呢? 只需要比较 IHTMLFrameBase

'和子 IWebBrowser2 对象的 IUnknown 指针地址是否相等就可以了.

'

' 上面的叙述有些复杂,可用 C# 描述获得第一个子 IHTMLDocument2 对象,如下:

'

' 输入参数为当前 Document, 和 Document 中所有的 frame 的 IHTMLFrameBase2 对象.

 

 

 

 

 

'下面代码的核心是修改自MVP Edanmo的大作

'枚举框架,参数WB是一个webbrowser控件的名称,其中承载着我们要分析的页面

Sub EnumFrames(ByVal hd As IHTMLDocument2)

Dim j As Integer

Dim pContainer As olelib.IOleContainer

Dim pEnumerator As olelib.IEnumUnknown

Dim pUnk As olelib.IUnknown

'获得页面的Document接口,然后我们就可以对其为所欲为了

Set pContainer = hd

'很奇怪,有时候上面这段对象赋值出错,用下面这句就没有问题了

'Set pContainer = WB.Document

If pContainer.EnumObjects(OLECONTF_EMBEDDINGS, pEnumerator) = 0 Then

Set pContainer = Nothing

Do While pEnumerator.Next(1, pUnk) = 0

On Error Resume Next

If Err.Number = 0 Then

'将框架页面依次赋值到IframeIE数组中

ReDim Preserve IframeIE(0 To j)

Set IframeIE(j) = pUnk

j = j + 1

End If

Loop

Set pEnumerator = Nothing

End If

End Sub

 

附:另一种方法是经过iserviceprovider接口的queryservice查询由Ihtmldocument2得到iwebbrowser2对象。

 

 

 

''''''''''''''''''"""""""""""""""""""""""""""""

消灭对话框的问题

  1. 据说在页面加载完成时,加载一段代码,可以消灭对话框于无形(未试用)
  2. 获得对话框窗口句柄和其上的控件按钮句柄,对其发送消息,

    缺点,要求窗口具有焦点,故电脑不能作他用;在IE自动化代码中难以准确定位查找对话框的地方,故代码难以产生效果,结果不得不动用计时器不断查找对话框才马虎解决

'根据窗口名取得对话框,打寻子窗口,发送消息

Function clickDialog(Optional Title As String = "来自网页的消息", Optional btnValue As String = "确定") As Boolean

Const WM_LBUTTONDOWN = &H201

Const WM_LBUTTONUP = &H202

Const BM_CLICK = &HF5

Dim msghWnd As Long, hWnd As Long

 

clickDialog = False

hWnd = FindWindow(vbNullString, Title) '以标题查找对话框

 

If hWnd > 0 Then

SetForegroundWindow hWnd

msghWnd = FindWindowEx(hWnd, 0, "button", btnValue) '找到确定按钮

'SetForegroundWindow msghWnd

SetActiveWindow hWnd

SetActiveWindow msghWnd

 

'实现鼠标点击操作

' PostMessage msghWnd, WM_LBUTTONDOWN, 0, ByVal (1 + 1 * 65536)

' PostMessage msghWnd, WM_LBUTTONUP, 0, ByVal (1 + 1 * 65536)

SendMessage msghWnd, BM_CLICK, 0, 0

 

clickDialog = True

End If

 

End Function

 

 

Sub testdia()

 

Call clickDialog

 

End Sub

 

 

Sub TimeProc1(ByVal uID As Long, ByVal uMsg As Long, ByVal dwUser As Long, ByVal dw1 As Long, ByVal dw2 As Long)

'回调函数的固定格式,不能自行更改,且只能是sub

 

Const BM_CLICK = &HF5

Dim msghWnd As Long, hWnd As Long

 

hWnd = FindWindow(vbNullString, "来自网页的消息") '以标题查找对话框

 

If hWnd > 0 Then

SetForegroundWindow hWnd

msghWnd = FindWindowEx(hWnd, 0, "button", "确定") '找到确定按钮

'SetForegroundWindow msghWnd

SetActiveWindow hWnd

SetActiveWindow msghWnd

 

'实现鼠标点击操作

' PostMessage msghWnd, WM_LBUTTONDOWN, 0, ByVal (1 + 1 * 65536)

' PostMessage msghWnd, WM_LBUTTONUP, 0, ByVal (1 + 1 * 65536)

SendMessage msghWnd, BM_CLICK, 0, 0

 

End If

 

End Sub

 

建立定显示器和消灭定时器的代码

TimerID1 = timeSetEvent(2000, 1, AddressOf TimeProc1, 1, 1) '注意定时器的时间要长于回调函数的执行时间

timeKillEvent (TimerID1)

 

 

http://s10/middle/002z94qRzy71UOIPbiF19&amp;690

 

凤凰树:取名于"叶如飞凰之羽,花若丹凤之冠",原产于马达加斯加,为其国树,属豆科植物,以其细腻繁茂的绿叶和火爆狂野的深红而成为初夏最引人注目的风景,全株有毒。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有