zoukankan      html  css  js  c++  java
  • [Delphi]如何挂上IDocHostUIHandler接口实现?

      为了更好地控制WebBrowser,我们可以在一个com对象中实现IDocHostUIHandler(和IDocHostUIHandler2)接口,并把这个接口实现挂到WebBrowser实例上去,成功挂接之后,我们就可以通过实现这些接口的com对象控制WebBrowser的行为方式及其外观了。
      为了演示如何挂接COM对象,我们假设我们在窗体上放置了一个TWebBrowser实例WB,并且实例化了一个实现IDocHostUIHandler接口的对象IEObject。我们将分别演示通过TWebBrowser的ICustomDoc接口和IOleObject实现挂接。
    1. 使用IOleObject接口
      TWebBrowser对象在初始化时会向宿主查询其是否实现了IDocHostUIHandler接口,假如宿主实现了该接口的话,就会调用该接口的方法控制自己的行为和外观。因此我们只要在TWebBrowser初始化之前将实现IDocHostUIHandler的com对象注册为TWebBrower对象的宿主的话,就可以让TWebBrowser控件自身来查询IDocHostUIHandler接口了。
    {code start}
    procedure TMainForm.FormCreate(Sender: TObject);
    var
      Rect: TRect;
    begin
      //设置浏览器站点,设置之后浏览器将自动查询IDocHostUIHandler、IDocHostUIHandler2、
      //IDocHostShowUI等接口
      (WB.Application as IOleObject).SetClientSite(IEObject as IOleClientSite);
      //本地激活浏览器控件
      Rect := Self.GetClientRect;
      (WB.Application as IOleObject).DoVerb(OLEIVERB_INPLACEACTIVATE, nil,
        Self, 0, Self.Handle, Rect);
      ManageConnection(True); //注册事件连接
      WB.GoHome;  //程序启动时导航到首页
    end;
    {code end}
    2. 使用ICustomDoc接口
      如果IEObject由于某种原因无法实现IOleClientSite的话,我们就不能简单地让TWebBrowser对象来查询其宿主的IDocHostUIHandler接口,我们必须显式地将实现该接口的对象赋给
    TWebBrowser的Document对象,ICustomDoc可以说就是为了这个目的而生的。
       使用该方法的一个至关重要的问题是必须在TWebBrowser的Document对象建立的时候才可以调用其ICustomDoc接口,否则就会挂接失败,由于Navigate方法是异步执行的,因此我们不能像这样挂接:
    {code start}
      WB.GoHome;    //or WB.Navigate('http://xxx");
      (WB.Document as ICustomDoc).SetUIHandler(IEObject);
    {code end}
    这种挂接方式可能会生效,但是SetUIHiandler完全可能在Document对象建立之前就被调用,因此这不是一个好的途径,我们可以在TWebBrowser的OnDocumentComplete处理函数中进行挂接,这时候我们可以确保TWebBrowser的Document对象确确实实已经建立起来了,因此调用理论上讲可以100%成功。
      除此之外,我们还可以这样做:
    {code start}
      WB.GoHome;
      while (WB.ReadState <> READYSTATE_COMPLETE )
        ;
     (WB.Document as ICustomDoc).SetUIHandler(IEObject);
    {code end}
    这样做同样可以达到我们的目的。缺点: 虽然这种方法可以达到挂接的目的,但是在实践中发现,由于WB是在装载文档完成之后才挂上IDocUIHandler接口实现的,因此第一次转载文档的时候是不会使用该接口来控制外观和行为的(没挂上当然就不知道怎么用了),因此必须在挂上之后再一次进行刷新才行。

    附:由于Delphi本身缺少IDocHostUIHandler等接口的声明,如果要编译上述代码,你可以去IE&Delphi下载IEConst.pas。其中ICustomDoc接口声明不存在于该文件中,特声明如下:
    {code start}
      ICustomDoc = interface(IUnknown)
        ['{3050F3F0-98B5-11CF-BB82-00AA00BDCE0B}']
        function SetUIHandler(const pUIHandler: IDocHostUIHandler): HRESULT; stdcall;
      end;
    {code end}

  • 相关阅读:
    c语言-关键字/标识符
    初识c语言
    MinGW-w64离线安装
    SpringBoot配置文件详解
    JS如何判断是不是为{},以下个人认为是比较好的方法
    IDEA下的SpringBoot工程的如何打包成war包
    cesium之城市行政划分
    cesium之平面裁切
    SSM框架的maven工程使用事务流程
    创建一个最简单的Cesium程序步骤
  • 原文地址:https://www.cnblogs.com/leafyoung/p/68637.html
Copyright © 2011-2022 走看看