using System; using System.Security; using System.ComponentModel; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Windows.Forms; using System.Security.Permissions; using IfacesEnumsStructsClasses; using System.IO; namespace ExtendedWebBrowser2 { /// /// An extended version of the control. /// public class ExtendedWebBrowser : System.Windows.Forms.WebBrowser { private UnsafeNativeMethods.IWebBrowser2 axIWebBrowser2; /// /// /// /// /// public delegate void DocHostShowUIShowMessageEventHandler(object sender, ExtendedBrowserMessageEventArgs e); /// /// 在页面弹出消息对话框时激发 /// [Description("在页面弹出消息对话框时激发")] public event DocHostShowUIShowMessageEventHandler OnShowMessage = null; /// /// /// /// /// public delegate void DocHostShowUIExtendedCloseEventArgs(object sender, ExtendedCloseEventArgs e); /// /// /// public event DocHostShowUIExtendedCloseEventArgs Ex_WindowClosing = null; /// /// /// public Command Cmd; /// /// 打开页面并等待页面加载完毕 /// /// 要打开的页面地址 /// 小于等于0,则表示一直等待,否则表示等待指定秒后,如果依然没有加载完毕,就直接返回 public void NavigateWait(string url, int seconds) { this.Navigate(url); WaitComplete(seconds); } /// /// 等待页面加载完毕 /// /// 小于等于0,则表示一直等待,否则表示等待指定秒后,如果依然没有加载完毕,就直接返回 public bool WaitComplete(int seconds) { DateTime startTime = DateTime.Now; while (this.ReadyState != WebBrowserReadyState.Complete) { if (DateTime.Now >= startTime.AddSeconds(seconds) && seconds > 0) { return false; } System.Windows.Forms.Application.DoEvents(); } return true; } /// /// 等待指定毫秒 /// /// 等待指定毫秒 public void Wait(int Milliseconds) { if (Milliseconds <= 0) { return; } DateTime startTime = DateTime.Now; while (true) { if (DateTime.Now >= startTime.AddMilliseconds(Milliseconds) && Milliseconds > 0) { break; } System.Windows.Forms.Application.DoEvents(); } } /// /// 获取网页源代码,可以自动去除乱码 /// /// public new string DocumentText { get { Encoding encoding = Encoding.GetEncoding(this.Document.Encoding); System.IO.StreamReader strm = new System.IO.StreamReader(this.DocumentStream, encoding); string docment = strm.ReadToEnd(); return docment; } set { base.DocumentText = value; } } /// /// 加载html文本到浏览器中 /// /// /// public void LoadStrings(string s,Encoding encoding) { NavigateWait("about:blank", 10); //内存流,用于转换string MemoryStream ms = new MemoryStream(); try { byte[] htmlcode = encoding.GetBytes(s); ms.Write(htmlcode, 0, htmlcode.Length); Stream dataStream = ms; //恢复指针位置 dataStream.Seek(0, 0); if (this.Document != null) { //转换接口,并转换为IStream (this.Document.DomDocument as UnsafeNativeMethods.IPersistStreamInit).Load(new UnsafeNativeMethods.ComStreamFromDataStream(dataStream)); this.Document.Encoding = encoding.WebName; ; } } finally { ms.Close(); } } /// /// 加载html文本到浏览器中 /// /// public void LoadStrings(string s) { LoadStrings(s, System.Text.Encoding.Default); } bool _ForceOpenThisWindow = false; /// /// 强制用本窗体打开新链接 /// [Description("强制用本窗体打开新链接")] public bool ForceOpenThisWindow { get { return _ForceOpenThisWindow; } set { _ForceOpenThisWindow = value; } } #region ExtendedWebBrowserSite class ExtendedWebBrowserSite : WebBrowser.WebBrowserSite, UnsafeNativeMethods.IDocHostShowUI { private ExtendedWebBrowser _Browser; public ExtendedWebBrowserSite(ExtendedWebBrowser host) : base(host) { _Browser = host; } //public event EventHandler OnShowMessage; #region IDocHostShowUI int UnsafeNativeMethods.IDocHostShowUI.ShowMessage(int hwnd, string lpstrText, string lpstrCaption, uint dwType, string lpstrHelpFile, uint dwHelpContext, ref int lpResult) { //Initially //lpResult is set 0 //S_OK //Host did not display its UI. MSHTML displays its message box. int iRet = Hresults.S_FALSE; //raise event? ExtendedBrowserMessageEventArgs args = new ExtendedBrowserMessageEventArgs(hwnd, lpstrText, lpstrCaption, dwType, lpstrHelpFile, dwHelpContext); _Browser.OnShowMessage(this, args); if (args.Cancel == true) { //Host displayed its user interface (UI). MSHTML does not display its message box. iRet = Hresults.S_OK; lpResult = args.PResult; } ////uncomment to use //else //{ // lpResult = (int)WinApis.MessageBox(hwnd, lpstrText, lpstrCaption, dwType); // iRet = Hresults.S_OK; //} return iRet; } int UnsafeNativeMethods.IDocHostShowUI.ShowHelp(int hwnd, string pszHelpFile, uint uCommand, uint dwData, UnsafeNativeMethods.tagPOINT ptMouse, object pDispatchObjectHit) { return Hresults.E_NOTIMPL; } #endregion } /// /// /// /// protected override WebBrowserSiteBase CreateWebBrowserSiteBase() { return new ExtendedWebBrowserSite(this); } #endregion /// /// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code. /// Called by the control when the underlying ActiveX control is created. /// /// [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")] protected override void AttachInterfaces(object nativeActiveXObject) { this.axIWebBrowser2 = (UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject; this.axIWebBrowser2.Silent = true; base.AttachInterfaces(nativeActiveXObject); Cmd = new Command(this); } /// /// This method supports the .NET Framework infrastructure and is not intended to be used directly from your code. /// Called by the control when the underlying ActiveX control is discarded. /// [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")] protected override void DetachInterfaces() { this.axIWebBrowser2 = null; base.DetachInterfaces(); } /// /// Returns the automation object for the web browser /// public object Application { get { return axIWebBrowser2.Application; } } System.Windows.Forms.AxHost.ConnectionPointCookie cookie; WebBrowserExtendedEvents events; /// /// This method will be called to give you a chance to create your own event sink /// [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")] protected override void CreateSink() { // Make sure to call the base class or the normal events won't fire base.CreateSink(); events = new WebBrowserExtendedEvents(this); cookie = new AxHost.ConnectionPointCookie(this.ActiveXInstance, events, typeof(UnsafeNativeMethods.DWebBrowserEvents2)); } /// /// Detaches the event sink /// [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")] protected override void DetachSink() { if (null != cookie) { cookie.Disconnect(); cookie = null; } } /// /// 在文档下载开始时激发 /// [Description("在文档下载开始时激发")] public event EventHandler Downloading; /// /// Raises the event /// /// Empty /// /// You could start an animation or a notification that downloading is starting /// protected void OnDownloading(EventArgs e) { Downloading?.Invoke(this, e); } /// /// 下载完成后触发 /// /// /// Here you could start monitoring for script errors. /// [Description("在文档下载完毕后激发")] public event EventHandler DownloadComplete; /// /// Raises the event /// /// Empty public virtual void OnDownloadComplete(EventArgs e) { DownloadComplete?.Invoke(this, e); } /// /// 在开始浏览新网页时激发. /// [Description("在开始浏览新网页时激发")] public event EventHandler StartNavigate; /// ///在打开新的网页窗口时激发 /// [Description("在打开新的网页窗口时激发")] public event EventHandler StartNewWindow; /// /// Raises the event /// /// Thrown when BrowserExtendedNavigatingEventArgs is null public void OnStartNewWindow(BrowserExtendedNavigatingEventArgs e) { if (e == null) throw new ArgumentNullException("e"); if (_ForceOpenThisWindow) { e.Cancel = true; this.Navigate(e.Url.ToString()); } else { StartNewWindow?.Invoke(this, e); } } /// /// Raises the event /// /// Thrown when BrowserExtendedNavigatingEventArgs is null public void OnStartNavigate(BrowserExtendedNavigatingEventArgs e) { if (e == null) throw new ArgumentNullException("e"); StartNavigate?.Invoke(this, e); } #region The Implementation of DWebBrowserEvents2 for firing extra events /// /// /// public class WebBrowserExtendedEvents : UnsafeNativeMethods.DWebBrowserEvents2 { /// /// /// public WebBrowserExtendedEvents() { } ExtendedWebBrowser _Browser; /// /// /// /// public WebBrowserExtendedEvents(ExtendedWebBrowser browser) { _Browser = browser; } #region DWebBrowserEvents2 Members //Implement whichever events you wish /// /// /// /// /// /// /// /// /// /// public void BeforeNavigate2(object pDisp, ref object URL, ref object flags, ref object targetFrameName, ref object postData, ref object headers, ref bool cancel) { Uri urlUri = new Uri(URL.ToString()); string tFrame = null; if (targetFrameName != null) tFrame = targetFrameName.ToString(); BrowserExtendedNavigatingEventArgs args = new BrowserExtendedNavigatingEventArgs(pDisp, urlUri, tFrame, UrlContext.None); _Browser.OnStartNavigate(args); cancel = args.Cancel; pDisp = args.AutomationObject; } /// /// /// /// /// public void NewWindow2(ref object pDisp, ref bool cancel) { BrowserExtendedNavigatingEventArgs args = new BrowserExtendedNavigatingEventArgs(pDisp, null, null, UrlContext.None); _Browser.OnStartNewWindow(args); cancel = args.Cancel; pDisp = args.AutomationObject; } /// /// 新窗口事件,只限Window XP SP2或以上系统支持 /// /// /// /// /// /// public void NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl) { BrowserExtendedNavigatingEventArgs args = new BrowserExtendedNavigatingEventArgs(ppDisp, new Uri(bstrUrl), null, (UrlContext)dwFlags); _Browser.OnStartNewWindow(args); Cancel = args.Cancel; ppDisp = args.AutomationObject; } /// /// /// public void DownloadBegin() { _Browser.OnDownloading(EventArgs.Empty); } /// /// /// public void DownloadComplete() { _Browser.OnDownloadComplete(EventArgs.Empty); } #region Unused events /// /// /// /// /// [DispId(0x00000107)] public void WindowClosing(bool isChildWindow, ref bool cancel) { ExtendedCloseEventArgs args = new ExtendedCloseEventArgs(); _Browser.Ex_WindowClosing(this, args); if (args.Cancel == true) { //Host displayed its user interface (UI). MSHTML does not display its message box. cancel = true; } } /// /// /// public void OnQuit() { } /// /// /// /// public void StatusTextChange(string text) { } /// /// /// /// /// public void ProgressChange(int progress, int progressMax) { } /// /// /// /// public void TitleChange(string text) { } /// /// /// /// public void PropertyChange(string szProperty) { } /// /// /// /// /// public void NavigateComplete2(object pDisp, ref object URL) { } /// /// /// /// /// public void DocumentComplete(object pDisp, ref object URL) { } /// /// /// /// public void OnVisible(bool visible) { } /// /// /// /// public void OnToolBar(bool toolBar) { } /// /// /// /// public void OnMenuBar(bool menuBar) { } /// /// /// /// public void OnStatusBar(bool statusBar) { } /// /// /// /// public void OnFullScreen(bool fullScreen) { } /// /// /// /// public void OnTheaterMode(bool theaterMode) { } /// /// /// /// public void WindowSetResizable(bool resizable) { } /// /// /// /// public void WindowSetLeft(int left) { } /// /// /// /// public void WindowSetTop(int top) { } /// /// /// /// public void WindowSetWidth(int width) { } /// /// /// /// public void WindowSetHeight(int height) { } /// /// /// /// public void SetSecureLockIcon(int secureLockIcon) { } /// /// /// /// public void FileDownload(ref bool cancel) { //MessageBox.Show("1122"); } /// /// / /// /// /// /// /// /// public void NavigateError(object pDisp, ref object URL, ref object frame, ref object statusCode, ref bool cancel) { } /// /// /// /// public void PrintTemplateInstantiation(object pDisp) { } /// /// /// /// public void PrintTemplateTeardown(object pDisp) { } /// /// /// /// /// /// public void UpdatePageStatus(object pDisp, ref object nPage, ref object fDone) { } /// /// /// /// public void PrivacyImpactedStateChange(bool bImpacted) { } /// /// /// /// /// public void CommandStateChange(int Command, bool Enable) { } /// /// /// /// /// public void ClientToHostWindow(ref int CX, ref int CY) { } #endregion #endregion } #endregion #region Raises the Quit event when the browser window is about to be destroyed /// /// Overridden /// /// The send to this procedure [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")] protected override void WndProc(ref Message m) { if (m.Msg == (int)WindowsMessages.WM_PARENTNOTIFY) { //int lp = m.LParam.ToInt32(); int wp = m.WParam.ToInt32(); int X = wp & 0xFFFF; //int Y = (wp >> 16) & 0xFFFF; if (X == (int)WindowsMessages.WM_DESTROY) this.OnQuit(); } base.WndProc(ref m); } /// /// A list of all the available window messages /// enum WindowsMessages { WM_ACTIVATE = 0x6, WM_ACTIVATEAPP = 0x1C, WM_AFXFIRST = 0x360, WM_AFXLAST = 0x37F, WM_APP = 0x8000, WM_ASKCBFORMATNAME = 0x30C, WM_CANCELJOURNAL = 0x4B, WM_CANCELMODE = 0x1F, WM_CAPTURECHANGED = 0x215, WM_CHANGECBCHAIN = 0x30D, WM_CHAR = 0x102, WM_CHARTOITEM = 0x2F, WM_CHILDACTIVATE = 0x22, WM_CLEAR = 0x303, WM_CLOSE = 0x10, WM_COMMAND = 0x111, WM_COMPACTING = 0x41, WM_COMPAREITEM = 0x39, WM_CONTEXTMENU = 0x7B, WM_COPY = 0x301, WM_COPYDATA = 0x4A, WM_CREATE = 0x1, WM_CTLCOLORBTN = 0x135, WM_CTLCOLORDLG = 0x136, WM_CTLCOLOREDIT = 0x133, WM_CTLCOLORLISTBOX = 0x134, WM_CTLCOLORMSGBOX = 0x132, WM_CTLCOLORSCROLLBAR = 0x137, WM_CTLCOLORSTATIC = 0x138, WM_CUT = 0x300, WM_DEADCHAR = 0x103, WM_DELETEITEM = 0x2D, WM_DESTROY = 0x2, WM_DESTROYCLIPBOARD = 0x307, WM_DEVICECHANGE = 0x219, WM_DEVMODECHANGE = 0x1B, WM_DISPLAYCHANGE = 0x7E, WM_DRAWCLIPBOARD = 0x308, WM_DRAWITEM = 0x2B, WM_DROPFILES = 0x233, WM_ENABLE = 0xA, WM_ENDSESSION = 0x16, WM_ENTERIDLE = 0x121, WM_ENTERMENULOOP = 0x211, WM_ENTERSIZEMOVE = 0x231, WM_ERASEBKGND = 0x14, WM_EXITMENULOOP = 0x212, WM_EXITSIZEMOVE = 0x232, WM_FONTCHANGE = 0x1D, WM_GETDLGCODE = 0x87, WM_GETFONT = 0x31, WM_GETHOTKEY = 0x33, WM_GETICON = 0x7F, WM_GETMINMAXINFO = 0x24, WM_GETOBJECT = 0x3D, WM_GETTEXT = 0xD, WM_GETTEXTLENGTH = 0xE, WM_HANDHELDFIRST = 0x358, WM_HANDHELDLAST = 0x35F, WM_HELP = 0x53, WM_HOTKEY = 0x312, WM_HSCROLL = 0x114, WM_HSCROLLCLIPBOARD = 0x30E, WM_ICONERASEBKGND = 0x27, WM_IME_CHAR = 0x286, WM_IME_COMPOSITION = 0x10F, WM_IME_COMPOSITIONFULL = 0x284, WM_IME_CONTROL = 0x283, WM_IME_ENDCOMPOSITION = 0x10E, WM_IME_KEYDOWN = 0x290, WM_IME_KEYLAST = 0x10F, WM_IME_KEYUP = 0x291, WM_IME_NOTIFY = 0x282, WM_IME_REQUEST = 0x288, WM_IME_SELECT = 0x285, WM_IME_SETCONTEXT = 0x281, WM_IME_STARTCOMPOSITION = 0x10D, WM_INITDIALOG = 0x110, WM_INITMENU = 0x116, WM_INITMENUPOPUP = 0x117, WM_INPUTLANGCHANGE = 0x51, WM_INPUTLANGCHANGEREQUEST = 0x50, WM_KEYDOWN = 0x100, WM_KEYFIRST = 0x100, WM_KEYLAST = 0x108, WM_KEYUP = 0x101, WM_KILLFOCUS = 0x8, WM_LBUTTONDBLCLK = 0x203, WM_LBUTTONDOWN = 0x201, WM_LBUTTONUP = 0x202, WM_MBUTTONDBLCLK = 0x209, WM_MBUTTONDOWN = 0x207, WM_MBUTTONUP = 0x208, WM_MDIACTIVATE = 0x222, WM_MDICASCADE = 0x227, WM_MDICREATE = 0x220, WM_MDIDESTROY = 0x221, WM_MDIGETACTIVE = 0x229, WM_MDIICONARRANGE = 0x228, WM_MDIMAXIMIZE = 0x225, WM_MDINEXT = 0x224, WM_MDIREFRESHMENU = 0x234, WM_MDIRESTORE = 0x223, WM_MDISETMENU = 0x230, WM_MDITILE = 0x226, WM_MEASUREITEM = 0x2C, WM_MENUCHAR = 0x120, WM_MENUCOMMAND = 0x126, WM_MENUDRAG = 0x123, WM_MENUGETOBJECT = 0x124, WM_MENURBUTTONUP = 0x122, WM_MENUSELECT = 0x11F, WM_MOUSEACTIVATE = 0x21, WM_MOUSEFIRST = 0x200, WM_MOUSEHOVER = 0x2A1, WM_MOUSELAST = 0x20A, WM_MOUSELEAVE = 0x2A3, WM_MOUSEMOVE = 0x200, WM_MOUSEWHEEL = 0x20A, WM_MOVE = 0x3, WM_MOVING = 0x216, WM_NCACTIVATE = 0x86, WM_NCCALCSIZE = 0x83, WM_NCCREATE = 0x81, WM_NCDESTROY = 0x82, WM_NCHITTEST = 0x84, WM_NCLBUTTONDBLCLK = 0xA3, WM_NCLBUTTONDOWN = 0xA1, WM_NCLBUTTONUP = 0xA2, WM_NCMBUTTONDBLCLK = 0xA9, WM_NCMBUTTONDOWN = 0xA7, WM_NCMBUTTONUP = 0xA8, WM_NCMOUSEHOVER = 0x2A0, WM_NCMOUSELEAVE = 0x2A2, WM_NCMOUSEMOVE = 0xA0, WM_NCPAINT = 0x85, WM_NCRBUTTONDBLCLK = 0xA6, WM_NCRBUTTONDOWN = 0xA4, WM_NCRBUTTONUP = 0xA5, WM_NEXTDLGCTL = 0x28, WM_NEXTMENU = 0x213, WM_NOTIFY = 0x4E, WM_NOTIFYFORMAT = 0x55, WM_NULL = 0x0, WM_PAINT = 0xF, WM_PAINTCLIPBOARD = 0x309, WM_PAINTICON = 0x26, WM_PALETTECHANGED = 0x311, WM_PALETTEISCHANGING = 0x310, WM_PARENTNOTIFY = 0x210, WM_PASTE = 0x302, WM_PENWINFIRST = 0x380, WM_PENWINLAST = 0x38F, WM_POWER = 0x48, WM_PRINT = 0x317, WM_PRINTCLIENT = 0x318, WM_QUERYDRAGICON = 0x37, WM_QUERYENDSESSION = 0x11, WM_QUERYNEWPALETTE = 0x30F, WM_QUERYOPEN = 0x13, WM_QUEUESYNC = 0x23, WM_QUIT = 0x12, WM_RBUTTONDBLCLK = 0x206, WM_RBUTTONDOWN = 0x204, WM_RBUTTONUP = 0x205, WM_RENDERALLFORMATS = 0x306, WM_RENDERFORMAT = 0x305, WM_SETCURSOR = 0x20, WM_SETFOCUS = 0x7, WM_SETFONT = 0x30, WM_SETHOTKEY = 0x32, WM_SETICON = 0x80, WM_SETREDRAW = 0xB, WM_SETTEXT = 0xC, WM_SETTINGCHANGE = 0x1A, WM_SHOWWINDOW = 0x18, WM_SIZE = 0x5, WM_SIZECLIPBOARD = 0x30B, WM_SIZING = 0x214, WM_SPOOLERSTATUS = 0x2A, WM_STYLECHANGED = 0x7D, WM_STYLECHANGING = 0x7C, WM_SYNCPAINT = 0x88, WM_SYSCHAR = 0x106, WM_SYSCOLORCHANGE = 0x15, WM_SYSCOMMAND = 0x112, WM_SYSDEADCHAR = 0x107, WM_SYSKEYDOWN = 0x104, WM_SYSKEYUP = 0x105, WM_TCARD = 0x52, WM_TIMECHANGE = 0x1E, WM_TIMER = 0x113, WM_UNDO = 0x304, WM_UNINITMENUPOPUP = 0x125, WM_USER = 0x400, WM_USERCHANGED = 0x54, WM_VKEYTOITEM = 0x2E, WM_VSCROLL = 0x115, WM_VSCROLLCLIPBOARD = 0x30A, WM_WINDOWPOSCHANGED = 0x47, WM_WINDOWPOSCHANGING = 0x46, WM_WININICHANGE = 0x1A } /// /// Raises the event /// protected void OnQuit() { EventHandler h = Quit; h?.Invoke(this, EventArgs.Empty); } /// /// 在网页窗口关闭时激发 /// /// /// Do not confuse this with DWebBrowserEvents2.Quit... That's something else. /// [Description("在网页窗口关闭时激发")] public event EventHandler Quit; #endregion } }