Delphi7中WebBrowser控件HTML源码的读写

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/iteye_20565/article/details/82126309

写入:

procedure TForm1.LoadStream(WebBrowser:TWebBrowser; Stream:TStream);
var
  PersistStreamInit: IPersistStreamInit;
  StreamAdapter: IStream;
  MemoryStream: TMemoryStream;
begin
  WebBrowser.Navigate('about:blank');
  repeat
    Application.ProcessMessages;
    Sleep(0);
  until
    WebBrowser.ReadyState=READYSTATE_COMPLETE;
  if WebBrowser.Document.QueryInterface(IPersistStreamInit,PersistStreamInit)=S_OK then
  begin
    if PersistStreamInit.InitNew=S_OK then
    begin
      MemoryStream:=TMemoryStream.Create;
      try
        MemoryStream.CopyFrom(Stream,0);
        MemoryStream.Position:=0;
      except
        MemoryStream.Free;
        raise;
      end;
      StreamAdapter:=TStreamAdapter.Create(MemoryStream,soOwned);
      PersistStreamInit.Load(StreamAdapter);
    end;
  end
end;

 

测试:

procedure TForm1.btn_1Click(Sender: TObject);
var
  S: TStringStream;
begin
  S := TStringStream.Create(mm1.Text);
  try
    LoadStream(wb1,S);
  finally
    s.Free;
  end;
end;

 

读取就很简单了,这里不再阐述。

展开阅读全文

请教:直接访问WebBrowser控件中的HTML源码问题??

10-18

rn华中师范大学 rn卢小海 rn---- 为了实现在自己的程序中显示HTML文档,我们一般采用IE(Internet Explorer本文中简称为IE)发行时附带的一个ActiveX控件TWebBrowser。这个控件使用和IE相同的内核,功能强大,并从Delphi5开始,正式得到Inprise公司的支持,取代了原来的那个THTML控件,成为Delphi中显示HTML文档的首选控件。 rnrn---- 但是在实际编程过程中,我发现这个控件提供的功能有很多限制,比如对HTML文档的浏览,只能通过指定URL或文件名来实现,不能像以往使用THTML控件那样直接读写HTML源码。因此如果程序动态生成了一段HTML文本,就必须把文本内容先写到一个临时文件,然后再将此文件的文件名传递给WebBrowser控件,实现显示。走这一个弯路使程序响应速度受到很大影响,而且容易遗留下一些"垃圾"(临时文件)。 rnrn---- 在考察了一些使用了WebBrowser控件的程序后,我发现大部分程序,如著名国产软件FoxMail,都是使用的通过临时文件传递HTML文档的方法;但一些国外的软件,如MS自己的OutLook Express则不存在这个问题,而因为其无需产生临时文件,因此对HTML文档的显示速度明显超过Foxmail。 rnrn---- 为此,我查阅了一些相关资料,最后在网友的帮助下找到了实现直接访问WebBrowser控件中的HTML源码的方法。在此要特别感谢白云黄鹤BBS(bbs.whnet.edu.cn)上的网友AngleFalls提供线索。 rnrn---- 其实,WebBrowser控件中的Document对象,这个对象提供了一个IPersistStreamInit接口,通过此接口,我们可以方便地实现对HTML源码的读写。 rnrn---- 以下是IPersistStreamInit接口的相关定义及说明: rnrn IPersistStream interface //这些是在什么地方定义的??rnrn$EXTERNALSYM IPersistStreamrnIPersistStream = interface(IPersist)rn['00000109-0000-0000-C000-000000000046']rnfunction IsDirty: HResult; stdcall; rn// 最后一次存盘后是否被修改rnfunction Load(const stm: IStream): HResult; stdcall;rn// 从流中载入rnfunction Save(const stm: IStream; rnfClearDirty: BOOL): HResult; stdcall;rn// 保存到流rnfunction GetSizeMax(out cbSize: Largeint): rnHResult; stdcall; // 取得保存所需空间大小rnend;rnrn IPersistStreamInit interface rnrn$EXTERNALSYM IPersistStreamInitrnIPersistStreamInit = interface(IPersistStream)rn['7FD52380-4E07-101B-AE2D-08002B2EC713']rnfunction InitNew: HResult; stdcall; // 初始化rnend;rnrn首先来实现写,因为这是最迫切的要求:rnprocedure SetHtml(const WebBrowser: rnTWebBrowser; const Html: string);rnvarrnStream: IStream;rnhHTMLText: HGLOBAL;rnpsi: IPersistStreamInit;rnbeginrnif not Assigned(WebBrowser.Document) then Exit;rnrnhHTMLText := GlobalAlloc(GPTR, Length(Html) + 1);rnif 0 = hHTMLText then RaiseLastWin32Error;rnrnCopyMemory(Pointer(hHTMLText), rnPChar(Html), Length(Html));rnrnOleCheck(CreateStreamOnHGlobalrn(hHTMLText, True, Stream));rntryrnOleCheck(WebBrowser.Document.rnQueryInterface(IPersistStreamInit, psi));rntryrnOleCheck(psi.InitNew);rnOleCheck(psi.Load(Stream));rnfinallyrnpsi := nil;rnend;rnfinallyrnStream := nil;rnend;rnend;rnrn---- 首先,此过程需要的两个参数,WebBrowser是显示目的控件,Html是需要显示的HTML源码;然后,先检查WebBrowser.Document对象是否有效,无效则退出;接着在系统全局堆里分配一块内存,将需要显示的HTML源码复制进去。这是因为下一步需要建立一个WebBrowser控件可以读取的流。GlobalAlloc函数的参数GPTR表示需要分配一块固定的以0初始化过的内存区域,如果分配失败则返回0,则通过RaiseLastWin32Error函数引发一个异常,提示用户;然后用CreateStreamOnHGlobal函数建立一个基于全局堆内存块的流,第二个参数如果为True则流在释放时自动释放所占全局堆内存。如果建立成功则此流和刚刚建立的内存块共用同一块内存区域。接着用WebBrowser.Document.QueryInterface函数建立一个IPersistStreamInit接口。然后就可以直接使用此接口,psi.InitNew初始化状态;psi.Load(Stream)从流中载入HTML源码。 rn---- 至此,以Html参数指定的HTML源码就在WebBrowser参数指定的控件中显示出来。 rnrn---- 值得注意的是,每个关于COM接口的函数调用,也就是那些返回类型为HResult的函数,都必须以OleCheck包装,因为一个不检查返回状态的COM接口操作实在太危险了;此外接口的释放,虽然Delphi可以在后台自动完成,但作为一个好的编程习惯,还是应该显式地手工释放,释放只需将接口设为nil即可。 rnrn---- 接着来实现HTML源码的读: rnrnfunction GetHtml(const WebBrowser:rnTWebBrowser): string;rnconstrnBufSize = $10000;rnvarrnSize: Int64;rnStream: IStream;rnhHTMLText: HGLOBAL;rnpsi: IPersistStreamInit;rnbeginrnif not Assigned(WebBrowser.Document) then Exit;rnrnOleCheck(WebBrowser.Document.QueryInterfacern(IPersistStreamInit, psi));rntryrn//OleCheck(psi.GetSizeMax(Size));rnhHTMLText := GlobalAlloc(GPTR, BufSize);rnif 0 = hHTMLText then RaiseLastWin32Error;rnrnOleCheck(CreateStreamOnHGlobal(hHTMLText,rnTrue, Stream));rntryrnOleCheck(psi.Save(Stream, False));rnrnSize := StrLen(PChar(hHTMLText));rnSetLength(Result, Size);rnCopyMemory(PChar(Result), Pointer(hHTMLText), rnSize);rnfinallyrnStream := nil;rnend;rnfinallyrnpsi := nil;rnend;rnend;rnrn---- 此函数有一个参数WebBrowser指定从那个控件读取HTML源码,返回一个字符串为此控件中的HTML源码。首先还是要先检查WebBrowser.Document对象是否有效,无效则退出;然后取得IPersistStreamInit接口;接着取得HTML源码的大小:本来应该使用IPersistStreamInit接口的GetSizeMax函数,但在我的机器上测试,这个函数范围值衡为0,无效。因此只能先定义一个足够大的缓冲区,如BufSize = $10000字节(注意此缓冲区应该足够大);然后同样地分配全局堆内存块,建立流,然后将HTML文本写到流中。因为此HTML文本在流中是以#0结尾的字符串,因此可以用Size := StrLen(PChar(hHTMLText))取得实际长度,用SetLength(Result, Size);设置返回字符串长度为HTML源码实际长度,最后复制字符串到返回字符串中。 rn---- 至此,直接访问WebBrowser控件中的HTML源码所需的两个函数全部解析完毕。 rnrn---- 不过需要注意的时,在使用这两个函数前,最好对WebBrowser.Document对象进行初始化。下面提供一个函数,通过显示一个空白页面实现WebBrowser.Document对象初始化。 rnrnprocedure ShowBlankPage(WebBrowser: rnTWebBrowser);rnvarrnURL: OleVariant;rnbeginrnURL := 'about:blank';rnWebBrowser.Navigate2(URL);rnend;rnrn---- 建议在你有WebBrowser控件的Form的FormCreate事件里调用此函数,初始化WebBrowser.Document对象。 rn---- 本文程序在Win NT + Delphi 5 环境下调试通过 rnrn---- 参考资料:MSDN rn---- 特别感谢:白云黄鹤BBS(bbs.whnet.edu.cn)网友AngleFalls rn以上代码是怎么应用的?能帮写个例子吗?如果分不够,说一声可以再加!!!!!rnrn 论坛

如何实现对Frame中HTML源码的直接读写

10-07

CMyView(派生于CHtmlView)的成员函数SetHtml的作用是在框架lpszTargetFrameName中显示lpszHtml所代表的Web内容(lpszHtml就是HTML源码),当lpszTargetFrameName为空时则直接显示在CMyView所在的页面中。程序运行时对非Frame可以正常工作,可对Frame却检取不到文档对象的IPersistStreamInit接口.rn要求:rn 实现对Frame中HTML源码的直接读写(不能借助于临时文件);rn 给出例程rn 对最早给出可行方案的至少给予200分,其他人酌情给分。rn 如分数不够可以再加。rnrn 下面是SetHtml程序的实现rnBOOL CMyView::SetHtml(LPCTSTR lpszHtml, LPCTSTR lpszTargetFrameName)rnrn LPSTREAM pStream=NULL;rn HGLOBAL hHTMLText=NULL;rn IPersistStreamInit *psi=NULL;rn LPDISPATCH pDisp=GetHtmlDocument( );rn if (pDisp==NULL) return FALSE;rn IHTMLDocument2 *pDoc=NULL;rn HRESULT hr=pDisp->QueryInterface(IID_IHTMLDocument2,(void**)&pDoc);rn pDisp->Release();rn if (hr!=S_OK) return FALSE; rn if (lpszTargetFrameName&&_tcslen(lpszTargetFrameName)>0)rn rn IHTMLFramesCollection2 *pFrames=NULL;rn hr=pDoc->get_frames(&pFrames);rn pDoc->Release();rn pDoc=NULL;rn if (hr==S_OK)rn rn COleVariant varIndex(lpszTargetFrameName),varResult;rn hr=pFrames->item(&varIndex, &varResult);rn pFrames->Release();rn pDisp=varResult.pdispVal;rn if (hr==S_OK&&pDisp!=NULL)rn rn IHTMLWindow2 *pWin = NULL;rn hr=pDisp->QueryInterface(IID_IHTMLWindow2,(void**)&pWin);rn pDisp->Release();rn if (hr==S_OK)rn rn hr=pWin->get_document(&pDoc);rn pWin->Release();rn if (hr!=S_OK) return FALSE;rn rn rn rn rn tryrn rn //一面这行对于Frame总是查询不到IPersistStreamInit接口rn if (pDoc->QueryInterface(IID_IPersistStreamInit, (void**)&psi)!=S_OK) throw 1;rn if (psi->InitNew()!=S_OK) throw 2;rn int len=_tcslen(lpszHtml)+1;rn hHTMLText=GlobalAlloc(GPTR,len*sizeof(TCHAR));rn if (hHTMLText==NULL) throw 3;rn _tcscpy((LPTSTR)hHTMLText,lpszHtml);rn if (CreateStreamOnHGlobal(hHTMLText, true, &pStream)!=S_OK) throw 4;rn if (psi->Load(pStream)!=S_OK) throw 5;rn return TRUE;rn rn catch(int e)rn rn switch(e)rn rn case 5:rn pStream->Release();rn case 4:rn GlobalFree(hHTMLText);rn case 3:rn case 2:rn psi->Release();rn case 1:rn pDoc->Release();rn break;rn rn return FALSE;rn rnrn 论坛

没有更多推荐了,返回首页