原文: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. JTextAreaDemo

    问题:java swing 图形界面程序,拖了一个JTextArea出来,程序中有很多地方调用JTextArea中的append这个方法不断往文本域结尾处追加数据,但是程序每次运行,总是在程序运行完成 ...

  2. Binary Tree Inorder Traversal(转)

    Given a binary tree, return the inorder traversal of its nodes' values. For example: Given binary tr ...

  3. Cocos2d-x3.0游戏实例《不要救我》第十篇(结束)——使用Json配置数据类型的怪物

    如今我们有2种类型的怪物,并且创建的时候是写死在代码里的,这是要作死的节奏~ 所以.必须可配置.不然会累死人的. ; i < size; ++i) { int id = root[i][&quo ...

  4. SQLServer 2008 技术内幕——T-SQL 查询 笔记

    原文:SQLServer 2008 技术内幕--T-SQL 查询 笔记 1.SQL编程有许多独特之处,如:面向集合的思维方式.查询元素的逻辑处理顺序.三值逻辑.如果不掌握这些知识就开始用SQL编程,得 ...

  5. lua三底漆:lua转让c/c++库(动态链接模式)

    dll按功能luaL_openlib出口,然后lua使用package.loadlib导入库函数,基本就是这么个过程,以下上代码来说明一切. #include "stdafx.h" ...

  6. Canvas 生成base64的PNG图片快照,So Amazing!!!

    function canvasSupport(){     return Modernizr.canvas;}function callCanvasApps(){  var canvasOne=doc ...

  7. Cache基础知识OR1200在ICache一个简短的引论

    以下摘录<步骤吓得核心--软-core处理器的室内设计与分析>一本书 12.1 Cache基本知识 12.1.1 Cache的作用 处理器的设计者通常会声称其设计的处理器一秒钟能做多少次乘 ...

  8. java 它 引用(基本类型的包装,构造函数和析构函数c++不同)

      一个:java 和c++参考控制 他提到引用,我们会想到java它不喜欢c++里面的指针.当然java内引用和c++里面的引用是不同的. 比如: 比方C++中,我对某一个函数的声明.int a(i ...

  9. 百度地图 Android SDK - 个性化地图

    什么是百度个性化地图Android SDK? 百度个性化地图Android SDK是一套基于Android 2.2及以上版本号设备的应用程序接口,您能够通过该套接口实现主要的地图功能,而且能够定制地图 ...

  10. 2014 Multi-University Training Contest 1/HDU4861_Couple doubi(数论/法)

    解题报告 两人轮流取球,大的人赢,,, 贴官方题解,,,反正我看不懂.,,先留着理解 关于费马小定理 关于原根 找规律找到的,,,sad,,, 非常easy找到循环节为p-1,每个循环节中有一个非零的 ...