截获"浏览器的信息对话框"弹出消息:
基于某些特殊需求的需要,程序需要知道浏览器控件的信息对话框何时弹出了,消息的内容是什么,以及其它相关的信息.
思路一:
向浏览的页面中添加如下代码(为避免与页面中原有的元素相冲突,可以将下面代码内的方法名,元素名等替换成不同的guid)
<script language="JavaScrip\">
window.alert=myFunction; //替换alert
function myFunction(u1) //在自定义的方法中将alert内容赋值给自己添加的button,并click该button
{
document.myForm.myButton.value = u1;
document.myForm.myButton.click();
}
</script>
<form method="get" name="myForm">
<input type="button" name = "myButton" value=""/> <!--自己添加button-->
</form>
并在宿主程序中响应该button的click事件消息:
((ExtendedWebBrowser)sender).Document.All["myButton"].Click +=
new HtmlElementEventHandler(myAlertElement_Click);
这样一来,便可以一种迂回的方式巧妙获取到alert消息框弹出事件.
但是通过使用HtmlElement.AppendChild(..) / HtmlDocument.Write(..) 以及 HTMLWindow2.execScript(...) 等方法向载入的页面中添加上述代码,均未能得到理想的结果,遂暂时放弃(哪位知道该怎么弄的话,请不吝赐教!!!)
思路二:
额外开一监视线程,实时枚举所有子窗口.以达到获取该消息框弹出事件的目的.
可以预计,该方法会影响到整个系统的性能,会影响到程序的稳定性,同时其可靠性也不高(不能保证每次弹出消息框时刚好能够枚举到).
所以这只能作为备用方法,在没有找到其它更好方法的情况下,勉强用用.
思路三:
再一次扩展浏览器控件.
查询MSDN,可以找到对WebBrowser.CreateWebBrowserSiteBase 方法的描述:
『返回对非托管 WebBrowser ActiveX 控件站点的引用,扩展该站点可以对托管 WebBrowser 控件进行自定义。
若要使用此功能,请实现从 WebBrowser 和 WebBrowser.WebBrowserSite 类继承的类。非托管 WebBrowser ActiveX 控件使用受保护的 CreateWebBrowserSiteBase 方法检索由 WebBrowser.WebBrowserSite 类实现的扩展性接口。重写 CreateWebBrowserSiteBase 方法以返回自己的从 WebBrowser.WebBrowserSite 类继承的类的实例。WebBrowser.WebBrowserSite 类提供 OLE IDocHostUIHandler 的默认实现。您可以为此接口提供自己的实现,或者实现任何其他 WebBrowser ActiveX 控件接口,从而对控件行为进行自定义。』
可以看出,我们只需重写CreateWebBrowserSiteBase 方法,扩展WebBrowserSite ,便可实现对浏览器控件的扩展。
我们知道,IDocHostUIHandler ,IDocHostUIHandler2 和 IDocHostShowUI这三个接口是浏览器控件用户界面的自定义的核心。当一个容器提供对ActiveX 控件支持的时候 , 当浏览器控件被实例化时,如果可能的话,它尝试找来自宿主的 IDocHostUIHandler , IDocHostUIHandler2 和 IDocHostShowUI 实现。当我们修改浏览器控件的时候 , 这些是我们应该在程序中实现的接口。
在这里,我们需要的仅仅是截获"浏览器的信息对话框"弹出消息,所以我们也没有必要把所有这些接口全部实现一遍。
IDocHostShowUI 这个接口提供给我们对浏览器控件显示的信息对话框和帮助的控制。我们实现它,这样在浏览器控件显示它自己的任何的信息或帮助之前 ,能调用我们定义的IDocHostShowUI的方法。这样我们便有一个机会捕获该信息对话框弹出的消息。IDocHostShowUI有两个方法,IDocHostShowUI::ShowMessage和IDocHostShowUI::ShowHelp。
已经准备得很充分了。现在开工!!!
在文件UnsafeNativeMethods.cs的 public class UnsafeNativeMethods里面添加如下代码:
#region IDocHostShowUI
[StructLayout(LayoutKind.Explicit, Pack = 4)]
public struct __MIDL_IWinTypes_0009
{
// Fields
[FieldOffset(0)]
public int hInproc;
[FieldOffset(0)]
public int hRemote;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct _RemotableHandle
{
public int fContext;
public __MIDL_IWinTypes_0009 u;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct tagPOINT
{
public int x;
public int y;
}
[ComImport, Guid("C4D244B0-D43E-11CF-893B-00AA00BDCE1A"), InterfaceType((short)1)]
public interface IDocHostShowUI
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void ShowMessage([In, ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.wireHWND")] ref _RemotableHandle hwnd, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrText, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrCaption, [In] uint dwType, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrHelpFile, [In] uint dwHelpContext, [ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.LONG_PTR")] out int plResult);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void ShowHelp([In, ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.wireHWND")] ref _RemotableHandle hwnd, [In, MarshalAs(UnmanagedType.LPWStr)] string pszHelpFile, [In] uint uCommand, [In] uint dwData, [In] tagPOINT ptMouse, [Out, MarshalAs(UnmanagedType.IDispatch)] object pDispatchObjectHit);
}
#endregion
在文件ExtendedWebBrowser.cs的 public class ExtendedWebBrowser : System.Windows.Forms.WebBrowser里面添加如下代码:
#region ExtendedWebBrowserSite
class ExtendedWebBrowserSite : WebBrowser.WebBrowserSite, UnsafeNativeMethods.IDocHostShowUI
{
public ExtendedWebBrowserSite(WebBrowser host)
: base(host)
{
}
void UnsafeNativeMethods.IDocHostShowUI.ShowMessage(ref UnsafeNativeMethods._RemotableHandle hwnd, string lpstrText, string lpstrCaption, uint dwType, string lpstrHelpFile, uint dwHelpContext, out int plResult)
{
//TODO:自定义
}
void UnsafeNativeMethods.IDocHostShowUI.ShowHelp(ref UnsafeNativeMethods._RemotableHandle hwnd, string pszHelpFile, uint uCommand, uint dwData, UnsafeNativeMethods.tagPOINT ptMouse, object pDispatchObjectHit)
{
//TODO:自定义
}
}
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ExtendedWebBrowserSite(this);
}
#endregion
OK,现在便可以添加相应的自定义事件了,这个轻车熟路,不再赘述。