以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 Dot NET,C#,ASP,VB 』  (http://bbs.xml.org.cn/list.asp?boardid=43)
----  C#中实现WebBrowser控件的HTML源代码读写  (http://bbs.xml.org.cn/dispbbs.asp?boardid=43&rootid=&id=11794)


--  作者:admin
--  发布时间:11/9/2004 2:25:00 AM

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


发信人: flier (小海 [寻找风车中]), 信区: DotNET
标  题: C#中实现WebBrowser控件的HTML源代码读写
发信站: BBS 水木清华站 (Sat Feb  7 13:28:49 2004), 转信

趁周末想折腾一下嵌入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;
      }

      #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, System.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 plibNewPosition)
      {
        _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
    }     

--
.    生命的意义在于   /\   ____\ /\_ \   /\_\                                .  
.        希望         \ \  \___/_\/\ \   \/_/__     __    _ _★              .  
.        工作          \ \   ____\\ \ \    /\  \  /'__`\ /\`'_\              .  
.      爱你的人         \ \  \___/ \ \ \___\ \  \/\ __// \ \ \/              .  
.     和你爱的人         \ \___\    \ \_____\ \__\ \____\ \ \_\              .  
.        ……             \/___/     \/_____/\/__/\/____/  \/_/ @nsfocus.com.  


※ 来源:·BBS 水木清华站 smth.org·[FROM: 211.167.254.*]
上一篇
返回上一页
回到目录
回到页首
下一篇



W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
62.500ms