• 熙熙WebBrowser判断登录成功WebBrowser404错误500错误屏蔽消息窗口Webbrowser判断是否加载成功


    在这里,我来讲讲怎么应付WebBrowser里面的那点破事:

    文档真的完成了吗?

    也许你和我一样,打开一个页面,听到了不少次的哒哒哒哒的声音,但是单个页面怎么会造成多次的触发DocumentCompleted函数?不信自己试试,判断文档是否真的完成,需要在这个处理函数内判断ReadyState如下:

    private void WebBrowserEx_DocumentCompleted(object sender
                , WebBrowserDocumentCompletedEventArgs e)
            {
                if (this.ReadyState == WebBrowserReadyState.Complete)
                {
                    if (null != this.Document && null != this.OnDocumentCompleted)
                    {
                        this.OnDocumentCompleted(sender, e);
                    }
                }
            }

    404错误怎么办?500错误怎么办?

    正如你所猜测的,即便是页面浏览错了,在页面中还是会显示内容,还是会无耻的触发DocumentCompleted事件,那么怎么判断到底是404页面还是500页面呢?看招:

    SHDocVw.WebBrowser sw = this.ActiveXInstance as SHDocVw.WebBrowser;
    sw.NavigateError += sw_NavigateError;
    //-----------------------------------------
     void sw_NavigateError(object pDisp, ref object URL, ref object Frame
        , ref object StatusCode, ref bool Cancel)
    {
        ErrorCodes errorcode = ErrorCodes.HTTP_STATUS_BAD_REQUEST;
        foreach (ErrorCodes ecode in Enum.GetValues(typeof(ErrorCodes)))
        {
            if (((long)ecode) == (Int32)StatusCode)
            {
                errorcode = ecode;
                break;
            }
        }
        System.Console.WriteLine("Error " + URL + ">>" + errorcode);
    }

    上面的代码中存在一个很丑陋的转换Enum的操作,我懒得修改了,这个枚举是俺自己定义的,定义的就是错误的名字信息,如下:

       1:  publicenumErrorCodes:long
       2:  {
       3:  HTTP_STATUS_BAD_REQUEST=400,
       4:  HTTP_STATUS_DENIED=401,
       5:  HTTP_STATUS_PAYMENT_REQ=402,
       6:  HTTP_STATUS_FORBIDDEN=403,
       7:  HTTP_STATUS_NOT_FOUND=404,
       8:  HTTP_STATUS_BAD_METHOD=405,
       9:  HTTP_STATUS_NONE_ACCEPTABLE=406,
      10:  HTTP_STATUS_PROXY_AUTH_REQ=407,
      11:  HTTP_STATUS_REQUEST_TIMEOUT=408,
      12:  HTTP_STATUS_CONFLICT=409,
      13:  HTTP_STATUS_GONE=410,
      14:  HTTP_STATUS_LENGTH_REQUIRED=411,
      15:  HTTP_STATUS_PRECOND_FAILED=412,
      16:  HTTP_STATUS_REQUEST_TOO_LARGE=413,
      17:  HTTP_STATUS_URI_TOO_LONG=414,
      18:  HTTP_STATUS_UNSUPPORTED_MEDIA=415,
      19:  HTTP_STATUS_RETRY_WITH=449,
      20:  HTTP_STATUS_SERVER_ERROR=500,
      21:  HTTP_STATUS_NOT_SUPPORTED=501,
      22:  HTTP_STATUS_BAD_GATEWAY=502,
      23:  HTTP_STATUS_SERVICE_UNAVAIL=503,
      24:  HTTP_STATUS_GATEWAY_TIMEOUT=504,
      25:  HTTP_STATUS_VERSION_NOT_SUP=505,
      26:   
      27:  INET_E_INVALID_URL=0x800C0002L,
      28:  INET_E_NO_SESSION=0x800C0003L,
      29:  INET_E_CANNOT_CONNECT=0x800C0004L,
      30:  INET_E_RESOURCE_NOT_FOUND=0x800C0005L,
      31:  INET_E_OBJECT_NOT_FOUND=0x800C0006L,
      32:  INET_E_DATA_NOT_AVAILABLE=0x800C0007L,
      33:  INET_E_DOWNLOAD_FAILURE=0x800C0008L,
      34:  INET_E_AUTHENTICATION_REQUIRED=0x800C0009L,
      35:  INET_E_NO_VALID_MEDIA=0x800C000AL,
      36:  INET_E_CONNECTION_TIMEOUT=0x800C000BL,
      37:  INET_E_INVALID_REQUEST=0x800C000CL,
      38:  INET_E_UNKNOWN_PROTOCOL=0x800C000DL,
      39:  INET_E_SECURITY_PROBLEM=0x800C000EL,
      40:  INET_E_CANNOT_LOAD_DATA=0x800C000FL,
      41:  INET_E_CANNOT_INSTANTIATE_OBJECT=0x800C0010L,
      42:  INET_E_REDIRECT_FAILED=0x800C0014L,
      43:  INET_E_REDIRECT_TO_DIR=0x800C0015L,
      44:  INET_E_CANNOT_LOCK_REQUEST=0x800C0016L,
      45:  INET_E_USE_EXTEND_BINDING=0x800C0017L,
      46:  INET_E_TERMINATED_BIND=0x800C0018L,
      47:  INET_E_INVALID_CERTIFICATE=0x800C0019L,
      48:  INET_E_CODE_DOWNLOAD_DECLINED=0x800C0100L,
      49:  INET_E_RESULT_DISPATCHED=0x800C0200L,
      50:  INET_E_CANNOT_REPLACE_SFP_FILE=0x800C0300L,
      51:  INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY=0x800C0500L,
      52:  INET_E_CODE_INSTALL_SUPPRESSED=0x800C0400L,
      53:  }

    Winform的WebBrowser居然不自己定义错误值,真是一个半成品啊。

    让内部的Html调用的JS可以使用外部提供的C#类的函数

    做起来简单。首先生成一个类(第一行不能少)

    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public class A
    {
        public String Fun()
        {
            return Guid.NewGuid().ToString();
        }
    }

    构造WebBrowser的时候设置属性 ObjectForScripting=new A();

    页面中使用类似如下的代码(注意函数名为window.external):

    <a href="javascript:{alert(window.external.Fun());}">测试按钮</a>

    赶紧试试吧

    事件调用转换成过程调用

    需求是这样的,我需要做一个模拟的操作界面,包括:登录,打开特定页面,填写内容,提交几步。在事件模型之下,我需要先调用Navigate函数, 然后在DocumentCompleted的处理函数中处理每个的返回内容,这样很麻烦,能不能使用一个函数将事件处理直接屏蔽掉 (SynchronizedNavigate),我的操作转换成:

    1. SynchronizedNavigate(登录页面)
    2. 填写登录信息
    3. 模拟点击登录按钮
    4. SynchronizedNavigate(数据填充页面)
    5. 填写页面内容
    6. 提交到服务器
    7. 取得返回页面校验实际输入的值

    是不是很玄妙,其实很简单(注意不能缺少函数Application.DoEvents())

       1:  public void SynchronizedNavigate(String strUrl)
       2:  {
       3:      this.Navigate(strUrl);
       4:      WaitNavigatingDone();
       5:  }
       6:   
       7:  public void WaitNavigatingDone()
       8:  {
       9:      while (m_isDocumentationCompleted == false)
      10:      {
      11:          Application.DoEvents();
      12:          Thread.Sleep(50);
      13:      }
      14:  }

    怎么屏蔽内部的消息窗口?

    直接看代码,很无耻滴注册了函数进去

    private void WebBrowserEx_Navigated(object sender, WebBrowserNavigatedEventArgs e)
            {
                if (this.Document == null || this.Document.DomDocument == null)
                {
                    return;
                }
                mshtml.IHTMLDocument2 doc2 = this.Document.DomDocument as mshtml.IHTMLDocument2;
                if (this.BlockClientMessage)
                {
                    if (null != doc2 && null != doc2.parentWindow)
                    {
                        //block alert and confirm
                        doc2.parentWindow.execScript(@"function alert(){} function confirm(){return true;}"
                            , "javaScript");
                    }
     
                }
            }

    怎么屏蔽网页内部弹出内容到新窗口?

    也许你可以使用Navigate的变种,里面有void Navigate(string urlString, bool newWindow)和Navigate(Uri url, bool newWindow)这两个函数,俺没有仔细试过,我使用的是COM接口:

    this.Navigate("about:blank");
    SHDocVw.WebBrowser sw = this.ActiveXInstance as SHDocVw.WebBrowser;
    if (null != sw)
    {
        sw.NewWindow3 += new SHDocVw.DWebBrowserEvents2_NewWindow3EventHandler(sw_NewWindow3);
    }
    ----------------------
     void sw_NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl)
     {
         if (null == OnNewWindow && this.BlockPopWindow)
         {
             Cancel = true;
             this.Navigate(bstrUrl);
         }
         else if (null != OnNewWindow)
         {
             OnNewWindow(this, bstrUrl, ref Cancel);
         }
     }

    自定义协议?

    你是不是想玩玩在<a href=”personal://username=1235”>用户信息</a>的点击的时候弹出一个内部的页面,而不是默认的 Http访问?实现类似的协议很简单,在_Navigating(object sender, WebBrowserNavigatingEventArgs e)这个事件处理中处理即可:当碰到您的协议的时候,e.Cancel=true;然后生成HTML,设置DocumentText就完成了。

    取得当前的选择的文本

     public string SelectedText
    {
        get
        {
            IHTMLDocument2 doc = (IHTMLDocument2)this.Document.DomDocument;
            IHTMLTxtRange txt = (IHTMLTxtRange)doc.selection.createRange();
            return txt.htmlText;
        }
    }

    高亮指定的文本

       1:   public void HilightText(string keyword, int nindexK)
       2:          {
       3:              if (null == keyword ||
       4:                  keyword.Trim().Length < 1 ||
       5:                  null == this.Document ||
       6:                  this.Document.DomDocument == null ||
       7:                  this.IsBusy ||
       8:                  this.IsDisposed
       9:                  )
      10:              {
      11:                  return;
      12:              }
      13:              HTMLDocument document = (HTMLDocument)this.Document.DomDocument;
      14:              IHTMLDOMNode bodyNode = (IHTMLDOMNode)this.Document.Body.DomElement;
      15:              HilightText(document, bodyNode, keyword.Trim(), nindexK);
      16:          }
      17:   
      18:          private void HilightText(HTMLDocument document, IHTMLDOMNode node, string keyword, int nindexK)
      19:          {
      20:              // nodeType = 3:text节点
      21:              if (node.nodeType == 3)
      22:              {
      23:                  string nodeText = node.nodeValue.ToString();
      24:                  // 如果找到了关键字
      25:                  if (nodeText.Contains(keyword))
      26:                  {
      27:                      IHTMLDOMNode parentNode = node.parentNode;
      28:                      // 将关键字作为分隔符,将文本分离,并逐个添加到原text节点的父节点
      29:                      string[] result = nodeText.Split(new string[] { keyword }, StringSplitOptions.None);
      30:                      for (int i = 0; i < result.Length - 1; i++)
      31:                      {
      32:                          if (result[i] != "")
      33:                          {
      34:                              IHTMLDOMNode txtNode = document.createTextNode(result[i]);
      35:                              parentNode.insertBefore(txtNode, node);
      36:                          }
      37:                          IHTMLDOMNode orgNode = document.createTextNode(keyword);
      38:                          IHTMLDOMNode hilightedNode = (IHTMLDOMNode)document.createElement("SPAN");
      39:                          IHTMLStyle style = ((IHTMLElement)hilightedNode).style;
      40:                          style.color = "black";
      41:                          style.backgroundColor = colorTables[nindexK % colorTables.Length];
      42:                          hilightedNode.appendChild(orgNode);
      43:   
      44:                          parentNode.insertBefore(hilightedNode, node);
      45:                      }
      46:                      if (result[result.Length - 1] != "")
      47:                      {
      48:                          IHTMLDOMNode postNode = document.createTextNode(result[result.Length - 1]);
      49:                          parentNode.insertBefore(postNode, node);
      50:                      }
      51:                      parentNode.removeChild(node);
      52:                  } // End of nodeText.Contains(keyword)
      53:              }
      54:              else
      55:              {
      56:                  // 如果不是text节点,则递归搜索其子节点
      57:                  IHTMLDOMChildrenCollection childNodes = node.childNodes as IHTMLDOMChildrenCollection;
      58:                  foreach (IHTMLDOMNode n in childNodes)
      59:                  {
      60:                      HilightText(document, n, keyword, nindexK);
      61:                  }
      62:              }
      63:          }
  • 相关阅读:
    闭包
    TCL
    [Go] gin框架渲染html字符串
    [Go] 使用packr包把静态文件打包进二进制内
    [javascript] 获取正则子表达式里的内容
    [redis] Zremrangebylex命令移除元素令人困惑不能理解
    [Go] 获取文件夹下面指定模式的文件列表 , 并且获取文件创建时间删除超过30分钟的文件
    [vuejs] 聊天框在overflow:auto中填数据时滚动到底部
    [vuejs] 在vuejs中使用websocket进行实时通讯
    Egret顶级开发者—李昌平
  • 原文地址:https://www.cnblogs.com/c51port/p/2089350.html
Copyright © 2020-2023  润新知