为什么web浏览器COM对象火的页之前DocumentComplete事件被加载?我想这事件只发射时,页面被完全浏览器的窗口中呈现。
这是我的BHO实现:
[标记有ComVisible特性(真),
GUID(5a954357-44bd-4660-9570-17bb1b71eeaa),
ClassInterface(ClassInterfaceType.None)
公共类BHO:接口IObjectWithSite
{
私人web浏览器的浏览器;
私营的DateTime startTime时;
私人日期时间endTime的;
私有对象_pUnkSite;
公共无效OnDocumentComplete(对象pDisp,参考目标URL)
{
如果(!的ReferenceEquals(pDisp,_pUnkSite))
{
返回;
}
使用(StreamWriter的SW = File.AppendText(log_path))
{
endTime的= DateTime.Now;
时间跨度TS = endTime.Subtract(startTime时);
sw.WriteLine(完成了{0} {1},ts.Seconds,ts.Milliseconds);
}
}
公共无效OnBeforeNavigate2(对象pDisp,参考目标URL,引用对象旗帜,裁判的对象TargetFrameName,引用对象的PostData,引用对象接头,REF布尔取消)
{
如果(!的ReferenceEquals(pDisp,_pUnkSite))
{
返回;
}
的startTime = DateTime.Now;
}
公众诠释SetSite(对象的网站)
{
如果(网站!= NULL)
{
_pUnkSite =网站;
浏览器=(web浏览器)的网站;
browser.DocumentComplete + =新DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
browser.BeforeNavigate2 + =新DWebBrowserEvents2_BeforeNavigate2EventHandler(this.OnBeforeNavigate2);
}
其他
{
browser.DocumentComplete - =新DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
browser.BeforeNavigate2 - =新DWebBrowserEvents2_BeforeNavigate2EventHandler(this.OnBeforeNavigate2);
浏览器= NULL;
}
返回0;
}
公众诠释GetSite(REF的Guid GUID,出来的IntPtr ppvSite)
{
IntPtr的朋克= Marshal.GetIUnknownForObject(浏览器);
INT HR = Marshal.QueryInterface(朋克,裁判GUID,出ppvSite);
Marshal.Release(朋克);
返回小时;
}
}
解决方案
由于有一个页面上的其他文件。一个IFRAME,或图像,例如,将触发的DocumentComplete
事件。你需要做的是确保所提出的目标的DocumentComplete
是实际的页面。例如:
私人无效_webBrowser2Events_DocumentComplete(对象pdisp,参考目标URL)
{
如果(!的ReferenceEquals(pdisp,_pUnkSite))
{
//退出,因为一个DocumentComplete不是文档完整的页面。
返回;
}
//这里做你的正常的东西
}
其中, _pUnkSite
是从的 SetSite
。
Why does DocumentComplete event of WebBrowser COM object fire before page is loaded? I thought that this event is only fired when page is fully rendered in browser's window.
this is my BHO implementation:
[ComVisible(true),
Guid("5a954357-44bd-4660-9570-17bb1b71eeaa"),
ClassInterface(ClassInterfaceType.None)]
public class BHO : IObjectWithSite
{
private WebBrowser browser;
private DateTime startTime;
private DateTime endTime;
private object _pUnkSite;
public void OnDocumentComplete(object pDisp, ref object URL)
{
if (!ReferenceEquals(pDisp, _pUnkSite))
{
return;
}
using (StreamWriter sw = File.AppendText("log_path"))
{
endTime = DateTime.Now;
TimeSpan ts = endTime.Subtract(startTime);
sw.WriteLine("completed in {0}.{1}", ts.Seconds, ts.Milliseconds);
}
}
public void OnBeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)
{
if (!ReferenceEquals(pDisp, _pUnkSite))
{
return;
}
startTime = DateTime.Now;
}
public int SetSite(object site)
{
if (site != null)
{
_pUnkSite = site;
browser = (WebBrowser)site;
browser.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
browser.BeforeNavigate2 += new DWebBrowserEvents2_BeforeNavigate2EventHandler(this.OnBeforeNavigate2);
}
else
{
browser.DocumentComplete -= new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
browser.BeforeNavigate2 -= new DWebBrowserEvents2_BeforeNavigate2EventHandler(this.OnBeforeNavigate2);
browser = null;
}
return 0;
}
public int GetSite(ref Guid guid, out IntPtr ppvSite)
{
IntPtr punk = Marshal.GetIUnknownForObject(browser);
int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
Marshal.Release(punk);
return hr;
}
}
解决方案
Because there are other documents on a page. An iframe, or an image, for example, will fire the DocumentComplete
event. What you need to do is ensure that the object that raised DocumentComplete
is the actual page. For example:
private void _webBrowser2Events_DocumentComplete(object pdisp, ref object url)
{
if (!ReferenceEquals(pdisp, _pUnkSite))
{
//Exit, because the DocumentComplete is not the document complete for the page.
return;
}
//Do your normal stuff here
}
Where _pUnkSite
is the site that was passed in from SetSite
.