原文: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. ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇

    原文:ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇 第三章 为控件添加事件 后篇 前一篇文章只是简单的说了下事件,但是大家应该方法,在ASP.NET自定义控件中只是简单那么定义事件是 ...

  2. MVC 使用IBatis.net

    IBatis.net在asp.net MVC下的使用 IBatis.net 是2001年发起的开源项目,它是一个轻量级的ORM框架,现在IBatisNET已经是属于Apache下的一个子项目了,最新版 ...

  3. java这些东西发展(1)-------大约ORA00604和ORA12705

    ******************************有关myEclipse和oracle在连接发生的一个问题********************************* 用户界面显示的评 ...

  4. poj3281-Dining ,最大流量,内置图

    id=3281">点击打开链接 分析: 求最大流 建图: 拆点 牛拆成左边与食物相连的左牛 和 右边与饮料相连的右牛 1.s->食物 连边 2.食物->左牛 3.左牛-&g ...

  5. 解决github访问问题

    github这是个好地方.但是,上不去就蛋疼. 今天github上不去,果断f12下,看下network.发现里面好多请求都是指向 github.global.ssl.fastly.net这个域名的, ...

  6. 找呀志_ContentResolver操作ContentProvider数据

    当需要外部的应用ContentProvider该数据被添加.删.修改和查询操作.可以使用ContentResolver 类完成 要得到ContentResolver 物,可以使用Activity提供g ...

  7. windows 10 install oracle 12c error:[ INS-30131 ]

    "[ INS-30131 ] the Initial Setup That Is Required to Run the Installation Program Validation Wa ...

  8. Bob大叔观OO原则

    Bob大叔观OO原则 上篇总结了经典的23种 设计模式,详细的解读后期会陆续的详细揭开.使用设计模式的根本原因就是为了增强代码的复用性和可维护性.而面向对象是实现代码复用的有效途径,所以这里有必要了解 ...

  9. NSIS:使用FileFunc.nsh头文件判断文件版本

    原文 NSIS:使用FileFunc.nsh头文件判断文件版本 这里,轻狂拿WMP10做一个例子.关于WMP10的原始安装文件,可以下载后通过/C /T:D:\Windows Media Player ...

  10. JAVA web四个属性的范围汇总

    首先,你需要知道client跳跃和server差别: client跳转: response.sendRedict(String path),地址栏发生改变. 不能传递request属性. server ...