原文:C#中实现WebBrowser控件的HTML源代码读写

C#中实现WebBrowser控件的HTML源代码读写

http://www.blogcn.com/user8/flier_lu/index.html?id=1125200&run=.0D9CAA6

趁周末想折腾一下嵌入ASP.NET的WinForm程序
 需要用到WebBrowser控件的HTML源码读写
 就把以前的一些代码片断移值到C#下
 顺便发个帖子备忘,呵呵
  
 思路其实很简单,直接通过document.documentElement.outerHTML
 或者使用IPersistStreamInit接口直接对流进行处理
 前者我就不废话了,后者实现方法如下
  
 首先是写入HTML到已初始化的WebBrowser控件
 初始化可以通过Navigate("about:blank")完成
 必须确保WebBrowser.Document != null
 否则应该推迟到DocumentComplete事件再读写

UCOMIStream stream = null;
  
 CreateStreamOnHGlobal(Marshal.StringToHGlobalUni(value), true, out stream);
   



 if(stream != null)
  
 {
   IPersistStreamInit persistentStreamInit =
     (IPersistStreamInit)WebBrowser.Document;
  
   persistentStreamInit.InitNew();
   persistentStreamInit.Load(stream);
   persistentStreamInit = null;
 }

UCOMIStream是COM中IStream的CLR版本
 CreateStreamOnHGlobal函数从一个字符串的地址
 创建一个IStream供使用

 [DllImport("ole32.dll", PreserveSig=false)]
 static extern void CreateStreamOnHGlobal(IntPtr hGlobal,
   Boolean fDeleteOnRelease, [Out] out UCOMIStream pStream);

然后就是通过IPersistStreamInit接口初始化并载入HTML源码,
 IPersistStreamInit接口CLR缺省没有导入,定义如下

 [ComVisible(true), ComImport(), Guid("7FD52380-4E07-101B-AE2D-08002B2EC713"),
  InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
 public interface IPersistStreamInit
 {
   void GetClassID([In, Out] ref Guid pClassID);
  
   [return: MarshalAs(UnmanagedType.I4)] [PreserveSig]
   int IsDirty();
  
   void Load([In, MarshalAs(UnmanagedType.Interface)] UCOMIStream pstm);
   void Save([In, MarshalAs(UnmanagedType.Interface)] UCOMIStream pstm,
             [In, MarshalAs(UnmanagedType.I4)] int fClearDirty);
   void GetSizeMax([Out, MarshalAs(UnmanagedType.LPArray)] long pcbSize);
   void InitNew();
 }

读取HTML也是类似思路,将HTML源码写到一个IStream中
 然后转换成字符串供C#代码使用,不过实现方式比较麻烦
  
 比较简单的方法还是使用ole32.dll提供的函数
 重建流,但这需要预先设定流的长度,如

UCOMIStream stream = null;
  
 CreateStreamOnHGlobal(Marshal.AllocHGlobal(4096), true, out stream);
  
 IPersistStreamInit persistentStreamInit =
   (IPersistStreamInit)WebBrowser.Document;
  
 persistentStreamInit.Save(stream, 0);
 persistentStreamInit = null;
  
 IntPtr pStr;
  
 GetHGlobalFromStream(stream, out pStr);
  
 return Marshal.PtrToStringAnsi(pStr);

然后使用GetHGlobalFromStream函数和
 Marshal.PtrToStringAnsi将流转换为字符串
 另外一种方法是自行实现一个支持IStream接口的类
 通过流的方式灵活完成读取操作,我比较喜欢这种

 using(MemoryStream stream = new MemoryStream())


 {
   ComStreamAdapter adapter = new ComStreamAdapter(stream);
  
   IPersistStreamInit persistentStreamInit =
     (IPersistStreamInit)WebBrowser.Document;
  
   persistentStreamInit.Save(adapter, 0);
  
   stream.Seek(0, SeekOrigin.Begin);
  
   using(StreamReader reader = new StreamReader(stream))
   {
     return reader.ReadToEnd();
   }
 }

这里的ComStreamAdapter是一个使用了adapter模式的类
 将普通的System.IO.Stream转换为IStream支持的类

  public class ComStreamAdapter : UCOMIStream
     {
       private Stream _stream;


  
       public ComStreamAdapter(Stream stream)
       {
         _stream = stream;
       }
  
       UCOMIStream Members#region UCOMIStream Members
  
       public void Commit(int grfCommitFlags)
       {
       }
  
       public void Clone(out UCOMIStream ppstm)
       {
         ppstm = null;
       }
  
       public void CopyTo(UCOMIStream pstm, long cb, System.IntPtr pcbRead, Syste
 m.IntPtr pcbWritten)
       {
       }
  


       public void Revert()
       {
       }
  
       public void LockRegion(long libOffset, long cb, int dwLockType)
       {
       }
  
       public void UnlockRegion(long libOffset, long cb, int dwLockType)
       {
       }
  
       public void Seek(long dlibMove, int dwOrigin, System.IntPtr plibNewPositio
 n)
       {
         _stream.Seek(dlibMove, (SeekOrigin)dwOrigin);
  
         if(plibNewPosition != IntPtr.Zero)
         {
           Marshal.WriteInt32(plibNewPosition, (int)_stream.Position);
         }
       }


  
       public void Read(byte[] pv, int cb, System.IntPtr pcbRead)
       {
         int size = _stream.Read(pv, (int)_stream.Position, cb);
  
         if(pcbRead != IntPtr.Zero)
         {
           Marshal.WriteInt32(pcbRead, size);
         }
       }
  
       public void Write(byte[] pv, int cb, System.IntPtr pcbWritten)
       {
         _stream.Write(pv, 0, cb);
  
         if(pcbWritten != IntPtr.Zero)
         {
           Marshal.WriteInt32(pcbWritten, cb);
         }
       }
  
       public void SetSize(long libNewSize)


         _stream.SetLength(libNewSize);
       }
  
       public void Stat(out STATSTG pstatstg, int grfStatFlag)
       {
         pstatstg = new STATSTG ();
       }
  
       #endregion
     }



C#中实现WebBrowser控件的HTML源代码读写的更多相关文章

  1. Winform中修改WebBrowser控件User-Agent的方法(已经测试成功)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...

  2. vs2005中的WebBrowser控件的简单应用

    原文:vs2005中的WebBrowser控件的简单应用 这个控件被封装了一下,和以前的调用方式稍有不同.事件还是那几个,变化不大.方法变了不少.从网上能查到的资料不多,贴出一些代码来作参考.看看这段 ...

  3. WPF中嵌入WinForm中的webbrowser控件

    原文:WPF中嵌入WinForm中的webbrowser控件 使用VS2008创建WPF应用程序,需使用webbrowser.从工具箱中添加WPF组件中的webbrowser发现其中有很多属性事件不能 ...

  4. 在VC中使用WebBrowser控件的两方法

    ClassWizard方式: 1.创建包装类:View->ClassWizard->Add Class->Form a Type Library->C:/winnt/syste ...

  5. C#中的WebBrowser控件的使用

    0.常用方法   Navigate(string urlString):浏览urlString表示的网址 Navigate(System.Uri url):浏览url表示的网址 Navigate(st ...

  6. 009. C#中的WebBrowser控件的属性、方法及操作演示代码(转)

    本文转自 http://www.open-open.com/code/view/1430559996802 0.常用方法 Navigate(string urlString):浏览urlString表 ...

  7. WPF中禁止WebBrowser控件打开新窗口

    一.针对纯WPF的WebBrowser控件: <summary> Suppress Script Errors In WPF WebBrowser </summary> pub ...

  8. C#中的WebBrowser控件加载ActiveX插件

    C#中WebBrowser控件,将项目输入更改为x86输出,在页面打开时即可自动加载ActiveX控件

  9. C#中利用WebBrowser控件,获得HTML源码

    最近获得网页的几个老程序都不能用了. 我原来用 如下代码获得网页html 源码: <pre name="code" class="csharp"> ...

随机推荐

  1. RH033读书笔记(14)-Lab 15 Switching Users and Setting a Umask

    Lab 15 Switching Users and Setting a Umask Goal: Become familiar with the use of several essential c ...

  2. JavaWeb-11 (JSP&amp;EL表达)

    JavaWeb-11 JSP&EL表达式 JSP 四.JSP语法(学好的关键:相应的Servlet) JavaWeb-10 总结:session技术也是cookie的一种.server给浏览器 ...

  3. JAVA中的I/O流以及文件操作

    一 JAVA语言中主要通过流来完成IO操作. 流:计算机的输入输出之间流动的数据序列,也是类的对象.java中的流方式就像是建立在数据交换源和目的之间的一条通信路径. 数据源:计算机中的数据源是指可以 ...

  4. Swift继承

    //声明一个基类 class vehicle { var maxPassenger : Int = 0 var manufacturer : String! func description() -& ...

  5. jxl创Excel档java示例代码说明

    记得下载 并 导入jxl.jar 包,免积分下载地址:http://download.csdn.net/detail/u010011052/7561041 package Test; import j ...

  6. 它们的定义PropertyPlaceHolder无法完成更换任务

    Spring默认PropertyPlaceholderConfigurer只能加载properties格风格简介,现在,我们需要能够从类的完整支持允许似hadoop格风格xml配置文件读取配置信息,并 ...

  7. 了解大数据的技术生态系统 Hadoop,hive,spark(转载)

    首先给出原文链接: 原文链接 大数据本身是一个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你能够把它比作一个厨房所以须要的各种工具. 锅碗瓢盆,各 ...

  8. ashx一般处理程序和HttpHandler

    asp.net项目中,使用.ashx的文件(一般处理程序)可以用于处理客户端发送来的请求,并将服务器端的处理结果返回给客户端.它能返回的类型可以是文本.或者图片.有时候,我们可以在项目中使用.cs的文 ...

  9. 全栈JavaScript路(八)得知 CDATASection 种类 节点

    CDATASection 只船舶类型节点 基于XML 文件.演出CDATA 数据. 构造函数: CDATASection function(){[native code]} CDATASection ...

  10. 策略模式设计模式(Strategy)摘录

    23种子GOF设计模式一般分为三类:创建模式.结构模型.行为模式. 创建模式抽象的实例.一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将 ...