问题的起源:设置自己喜欢的浏览器为系统绝对默认的浏览器。
(修改.http等关联不是重点)探索过程:
请看测试程序1:
Private Sub Form_Load()
WebBrowser1.Navigate "www.sina.com.cn"
End Sub
就这么一行代码,其他不做任何处理。当WebBrowser1打开网页后,随便点一个会打开新窗口的超链接,这个时候会发生什么事情?通常情况是IE打开了这个窗口。我们都知道新窗口是在WebBrowser1_NewWindow2事件中发生的,但为什么会打开IE呢?那一定是通过某种途径通知了IE。
继续研究,发现通知到这里:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{0002DF01-0000-0000-C000-000000000046}\LocalServer32
起值="C:\Program Files\Internet Explorer\iexplore.exe"
调用的方式大约是Shell C:\Program Files\Internet Explorer\iexplore.exe -Embedding为了证明我的猜测,请看测试程序2:
Private Sub Form_Load()
MsgBox Command
End Sub
用以监视调用参数,将其编译为c:\app2.exe,然后将上述注册表的值修改为c:\app2.exe,再在测试程序1中随便点一个会打开新窗口的超链接,这个时候又会发生什么事情?没有打开IE了,app2.exe执行了,并且MsgBox显示-Embedding,由此证明了调用的流程:没有处理WebBrowser1_NewWindow2的情况下,调用了HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{0002DF01-0000-0000-C000-000000000046}\LocalServer32所指向的程序,带参数-Embedding那问题就来了,当LocalServer32=IE或MT的时候,IE和MT等浏览器为什么能正确打开呢?请注意这里带的参数是-Embedding而并不是暴露的URL地址。似乎唯一的解释就是IE和MT等在发现带-Embedding这个参数调用的时候从某个接口等获得了WebBrowser1_NewWindow2的ppDisp或URL。而我们自己写的程序如何做到这一点呢?就象上面的测试程序2,当检测到-Embedding这个参数的时候如何正确打开呢?请各路英雄详加指点,不胜感激!
(修改.http等关联不是重点)探索过程:
请看测试程序1:
Private Sub Form_Load()
WebBrowser1.Navigate "www.sina.com.cn"
End Sub
就这么一行代码,其他不做任何处理。当WebBrowser1打开网页后,随便点一个会打开新窗口的超链接,这个时候会发生什么事情?通常情况是IE打开了这个窗口。我们都知道新窗口是在WebBrowser1_NewWindow2事件中发生的,但为什么会打开IE呢?那一定是通过某种途径通知了IE。
继续研究,发现通知到这里:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{0002DF01-0000-0000-C000-000000000046}\LocalServer32
起值="C:\Program Files\Internet Explorer\iexplore.exe"
调用的方式大约是Shell C:\Program Files\Internet Explorer\iexplore.exe -Embedding为了证明我的猜测,请看测试程序2:
Private Sub Form_Load()
MsgBox Command
End Sub
用以监视调用参数,将其编译为c:\app2.exe,然后将上述注册表的值修改为c:\app2.exe,再在测试程序1中随便点一个会打开新窗口的超链接,这个时候又会发生什么事情?没有打开IE了,app2.exe执行了,并且MsgBox显示-Embedding,由此证明了调用的流程:没有处理WebBrowser1_NewWindow2的情况下,调用了HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{0002DF01-0000-0000-C000-000000000046}\LocalServer32所指向的程序,带参数-Embedding那问题就来了,当LocalServer32=IE或MT的时候,IE和MT等浏览器为什么能正确打开呢?请注意这里带的参数是-Embedding而并不是暴露的URL地址。似乎唯一的解释就是IE和MT等在发现带-Embedding这个参数调用的时候从某个接口等获得了WebBrowser1_NewWindow2的ppDisp或URL。而我们自己写的程序如何做到这一点呢?就象上面的测试程序2,当检测到-Embedding这个参数的时候如何正确打开呢?请各路英雄详加指点,不胜感激!
比如象WEB迅雷,快车等的“下载”和“全部下载”等功能,就可以取到所有需要的信息。
FORM1,上面一个PICTURE控件picDDE
设:
With Me
.LinkMode = 1: .LinkTopic = "FormDDE": .Visible = False: .WindowState = 1
End With If App.PrevInstance Then ' 程序已经运行
Me.LinkTopic = ""
Me.LinkMode = 0 '
Me.Caption = "MYSTART"
LinkAndSendMessage command' 有命令行参数就传递过去
End
Else ' 程序未运行
msgbox "no run!"
end ifPrivate Sub LinkAndSendMessage(ByVal Msg As String)
Dim t&
picDDE.LinkMode = 0
picDDE.LinkTopic = App.EXEName & "|FormDDE"
picDDE.LinkMode = 2
picDDE.LinkExecute Msg
t = picDDE.LinkTimeout
picDDE.LinkTimeout = 1
picDDE.LinkMode = 0
picDDE.LinkTimeout = t
End Sub
然后我子类化我的测试窗口,检测WM_DDE_INITIATE, WM_DDE_ACK, WM_DDE_POKE, WM_DDE_TERMINATE
结果一个消息都没有!
启动以后直接操作对象。
程序之间的DDE本身就类似这个原理,只不过更多应用是同名程序本身.比如WMP,当我们播放着一首音乐,此时我们CLICK了硬盘或网络的一个WMA连接或文件就自动WMP播放新曲目了呢?就是DDE过去的命令,这个在注册表里可以看的一清2楚.
再有,楼主可以自己做个带命令行的VB小程序,再去挖掘WEBBROSER中的这些问题可能更有帮助些,呵呵.我乱说说,不怪罪吧?
请看我的描述,我已经测试命令行参数了,就是-Embedding而我没办法监视webbrowser到底发送了什么DDE……
我监视客户端,也就是上面描述的 测试程序1 的DDE消息,发现在点击连接的时候发送了WM_DDE_INITIATE消息。经过查询,说会向所有应用程序发送这个消息,我另外用 测试程序2 检测,发现的确如此。问题似乎可以解决了,但需要注意到,测试程序2 必须事先启动才能检测到这个消息。但是上是每次点击一个连接的时候才会启动 测试程序2 ,等这个程序启动后,已经无法接收到这个消息了……
感觉你对DDE还是没有完全搞清楚:你可以带程序1中写DDE
具体来说就是,当你CLICK了一个WEB控件连接时,记录下URL作为一个命令字符串;
然后将这个字符串作为COMMAND传送回程序1的启动函数,比如MODUAL1的 SUB MAIN(BY VAL strCmd$).这样就可以在程序1里按照我上面的简单例子做判断执行.
实际上,如果你是在程序的WEB控件上点了连接,那肯定是已经开了程序1的实例,呵呵
之所以要判断是因为,你可以在系统的[运行]窗口直接敲:程序1.exe -"http://xxx.com/yy.htm"
If App.PrevInstance Then ' 程序已经运行
Me.LinkTopic = ""
Me.LinkMode = 0 '
Me.Caption = "MYSTART"
LinkAndSendMessage command' 有命令行参数就传递过去
End
Else ' 程序未运行
运行程序1实例,且直接把网址传给WEB控件
end if
DDE是个好东西,去年我写的播放器就是用DDE检测音乐连接地址的
你想想QQ迷你网页的情况吧,要不然总是……
这个问题需要DDE和子类结合才能解决。估计如此
http://msdn2.microsoft.com/en-us/library/ms648996.aspx
WM_DDE_ACK应该向谁发送呢?
frmMain
------------------------------------------------------
Option Explicit
Dim WithEvents Web_V1 As SHDocVwCtl.WebBrowser_V1Private Sub Form_Load()
Set Web_V1 = WebBrowser1.Object
On Error Resume Next
WebBrowser1.Navigate "http://www.sohu.com"
End SubPrivate Sub Web_V1_NewWindow(ByVal URL As String, ByVal Flags As Long, ByVal TargetFrameName As String, PostData As Variant, ByVal Headers As String, Processed As Boolean)
Processed = True
Debug.Print URL, Flags, TargetFrameName, PostData, Headers
WebBrowser1.Navigate2 URL
End SubPrivate Sub WebBrowser1_BeforeNavigate2(ByVal pDisp As Object, URL As Variant, Flags As Variant, TargetFrameName As Variant, PostData As Variant, Headers As Variant, Cancel As Boolean)
Dim str$, pos%
'过滤广告页
pos = InStr(URL, "ima")
If pos > 0 Then Cancel = True
End Sub
所以只好用老旧的WebBrowser_V1来玩玩,呵呵
要是是我自己的程序里面的webbrowser,我爱怎样就怎样了.又何必如此麻烦……
就拿QQ迷你网页来说,我能获得他的webbrowser吗?(就算用枚举能获得,当IE和QQ迷你网页以及其他使用webbrowser的程序存在的时候,你又如何知道是哪个程序的webbrowser给你发请求?)何况是点击之后才调用我的程序,这个时候该发生的事件已经发生了,又怎么可能获得URL?
我研究出60-70%了,就是DDE配合子类。
仔细跟踪消息,发现webbrowser(也就是外部程序,比如QQ迷你网页)并没有发送什么消息,简直是悲哀。
当我的程序建立DDECallBack后,启动的时候会向向DDEMLAnsiClient这个类发送一个WM_DDE_INITIATE消息,但DDEMLAnsiClient这个类好象是一个系统自动创建的不可见窗口。用来测试的webbrowser所在的窗口只有在DDECallBack启动后才会收到一个每个消息都一模一样的消息。根本没有任何用处。因为外部程序对DDE的处理我们是无法控制的。
真是难啊……
Set ppDisp = W1.Object
ppDisp.Navigate url
End SubPrivate Sub WebBrowser1_StatusTextChange(ByVal Text As String)
url= Text
End Sub
Set ppDisp = WebBrowser1.Object
ppDisp.Navigate url
End SubPrivate Sub WebBrowser1_StatusTextChange(ByVal Text As String)
url= Text
End Sub不好意思,上帖 W1 是我的程式中的变量,没改过来。