原文地址:http://hi.baidu.com/rarnu/blog/item/4ec80608022766d663d986ea.html

js中,有一个比较特殊的对象,即window.external,用它可以调用浏览器提供的外部方法
一个很简单的例子就是将当前页添加到收藏夹
window.external.addFavorite("http://blog.csdn.NET/youthon","弘石的博客');
这样写脚本就可以了。
那么如果我想自己定义external,以便在自己的软件内使用IE核心的浏览器作为UI容器,该如何做呢?
本文即是解决此问题。
一、制作TLB
在File | New | Other 菜单下,选择新建一个Type Library,这个向导在ActiveX页内。
然后按下图所示,新建一个接口,在接口下新建一个DoSearchData方法,这个方法即是将来需要添加到external中的。

完成添加后,点击保存为TLB按钮,将生成一个TLB文件,此处我将它命名为GetData.tlb
二、实现IDocHostUIHandler接口
这部分相对比较简单,从MSDN上找到相关的C++代码,把它转换成Delphi的即可。代码如下:
 unitDocHostUIHandler;

interface
 uses
 Windows, ActiveX;
 const
 DOCHOSTUIFLAG_DIALOG                     =$00000001;
 DOCHOSTUIFLAG_DISABLE_HELP_MENU          =$00000002;
 DOCHOSTUIFLAG_NO3DBORDER                 =$00000004;
 DOCHOSTUIFLAG_SCROLL_NO                  =$00000008;
 DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE    = $00000010;
 DOCHOSTUIFLAG_OPENNEWWIN                 =$00000020;
 DOCHOSTUIFLAG_DISABLE_OFFSCREEN          =$00000040;
 DOCHOSTUIFLAG_FLAT_SCROLLBAR             =$00000080;
 DOCHOSTUIFLAG_DIV_BLOCKDEFAULT           =$00000100;
 DOCHOSTUIFLAG_ACTIVATE_CLIENTHIT_ONLY    = $00000200;
 DOCHOSTUIFLAG_OVERRIDEBEHAVIORFACTORY    = $00000400;
 DOCHOSTUIFLAG_CODEPAGELINKEDFONTS        =$00000800;
 DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8  = $00001000;
 DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8   = $00002000;
 DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE  = $00004000;
 DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION  = $00010000;
 DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION    = $00020000;
 DOCHOSTUIFLAG_THEME                      =$00040000;
 DOCHOSTUIFLAG_NOTHEME                    =$00080000;
 DOCHOSTUIFLAG_NOPICS                     =$00100000;
 DOCHOSTUIFLAG_NO3DOUTERBORDER            =$00200000;
 DOCHOSTUIFLAG_DISABLE_EDIT_NS_FIXUP      = $1;
 DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK =$1;
 DOCHOSTUIFLAG_DISABLE_UNTRUSTEDPROTOCOL  = $1;
 DOCHOSTUIDBLCLK_DEFAULT        = 0;
 DOCHOSTUIDBLCLK_SHOWPROPERTIES = 1;
 DOCHOSTUIDBLCLK_SHOWCODE       = 2;
 DOCHOSTUITYPE_BROWSE = 0;
 DOCHOSTUITYPE_AUTHOR = 1;

type
 TDocHostUIInfo = record
    cbSize: ULONG;
    dwFlags: DWORD;
    dwDoubleClick: DWORD;
    pchHostCss: PWChar;
    pchHostNS: PWChar;
 end;
 PDocHostUIInfo = ^TDocHostUIInfo;
 IDocHostUIHandler = interface(IUnknown)
    ['{bd3f23c0-d43e-11cf-893b-00aa00bdce1a}']
    functionShowContextMenu(const dwID:DWORD;constppt: PPOINT;
      constpcmdtReserved:IUnknown;constpdispReserved: IDispatch): HResult;
      stdcall;
    functionGetHostInfo(var pInfo:TDocHostUIInfo): HResult;stdcall;
    functionShowUI(const dwID:DWORD;
      constpActiveObject: IOleInPlaceActiveObject;
      constpCommandTarget: IOleCommandTarget;const pFrame:IOleInPlaceFrame;
      constpDoc: IOleInPlaceUIWindow): HResult;stdcall;
    function HideUI:HResult;stdcall;
    function UpdateUI:HResult;stdcall;
    functionEnableModeless(const fEnable:BOOL):HResult;stdcall;
    functionOnDocWindowActivate(const fActivate:BOOL):HResult;stdcall;
    functionOnFrameWindowActivate(const fActivate:BOOL):HResult;stdcall;
    functionResizeBorder(const prcBorder:PRECT;
      constpUIWindow: IOleInPlaceUIWindow;const fFrameWindow:BOOL):HResult;
      stdcall;
    functionTranslateAccelerator(const lpMsg: PMSG;constpguidCmdGroup: PGUID;
      constnCmdID:DWORD): HResult;stdcall;
    functionGetOptionKeyPath(var pchKey:POLESTR;const dw:DWORD): HResult;
      stdcall;
    functionGetDropTarget(const pDropTarget:IDropTarget;
      out ppDropTarget: IDropTarget): HResult; stdcall;
    functionGetExternal(out ppDispatch: IDispatch): HResult;stdcall;
    functionTranslateUrl(const dwTranslate:DWORD;constpchURLIn: POLESTR;
      varppchURLOut: POLESTR): HResult;stdcall;
    functionFilterDataObject(const pDO:IDataObject;
      out ppDORet: IDataObject): HResult; stdcall;
    end;

implementation

end.
三、实现一个带有IE组件的容器
由于Delphi自带的WebBrowser控件不支持external的直接扩展,因此我们需要另外写一个容器,使它实现IDocHostUIHandler接口,并且通过ActiveX单元的IOleObject.SetClientSite方法,将我们自己的容器填充进去。
这部分的代码直接参考了EmbeddedWB组件的相关实现,具体代码如下:
unit NulContainer;

interface

uses
Windows, ActiveX, SHDocVw, DocHostUIHandler;

type
TNulWBContainer = class(TObject,
    IUnknown,IOleClientSite, IDocHostUIHandler)
private
   fHostedBrowser: TWebBrowser;
    procedureSetBrowserOleClientSite(const Site: IOleClientSite);
protected
    functionQueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function_AddRef: Integer; stdcall;
    function_Release: Integer; stdcall;
    functionSaveObject: HResult; stdcall;
    functionGetMoniker(dwAssign: Longint;
     dwWhichMoniker: Longint;
     out mk: IMoniker): HResult; stdcall;
    functionGetContainer(
     out Container: IOleContainer): HResult; stdcall;
    functionShowObject: HResult; stdcall;
    functionOnShowWindow(fShow: BOOL): HResult; stdcall;
    functionRequestNewObjectLayout: HResult; stdcall;
    functionShowContextMenu(const dwID: DWORD; const ppt: PPOINT;
     const pcmdtReserved: IUnknown; const pdispReserved: IDispatch):HResult;
     stdcall;
    functionGetHostInfo(var pInfo: TDocHostUIInfo): HResult; stdcall;
    functionShowUI(const dwID: DWORD;
     const pActiveObject: IOleInPlaceActiveObject;
     const pCommandTarget: IOleCommandTarget; const pFrame:IOleInPlaceFrame;
     const pDoc: IOleInPlaceUIWindow): HResult; stdcall;
    functionHideUI: HResult; stdcall;
    functionUpdateUI: HResult; stdcall;
    functionEnableModeless(const fEnable: BOOL): HResult; stdcall;
    functionOnDocWindowActivate(const fActivate: BOOL): HResult; stdcall;
    functionOnFrameWindowActivate(const fActivate: BOOL): HResult;stdcall;
    functionResizeBorder(const prcBorder: PRECT;
     const pUIWindow: IOleInPlaceUIWindow; const fFrameWindow: BOOL):HResult;
     stdcall;
    functionTranslateAccelerator(const lpMsg: PMSG; const pguidCmdGroup:PGUID;
     const nCmdID: DWORD): HResult; stdcall;
    functionGetOptionKeyPath(var pchKey: POLESTR; const dw: DWORD ):HResult;
     stdcall;
    functionGetDropTarget(const pDropTarget: IDropTarget;
     out ppDropTarget: IDropTarget): HResult; stdcall;
    functionGetExternal(out ppDispatch: IDispatch): HResult; stdcall;
    functionTranslateUrl(const dwTranslate: DWORD; const pchURLIn:POLESTR;
     var ppchURLOut: POLESTR): HResult; stdcall;
    functionFilterDataObject(const pDO: IDataObject;
     out ppDORet: IDataObject): HResult; stdcall;
public
    constructorCreate(const HostedBrowser: TWebBrowser);
    destructorDestroy; override;
    propertyHostedBrowser: TWebBrowser read fHostedBrowser;
end;

implementation

uses
SysUtils;

{ TNulWBContainer }

constructor TNulWBContainer.Create(const HostedBrowser:TWebBrowser);
begin
Assert(Assigned(HostedBrowser));
inherited Create;
fHostedBrowser := HostedBrowser;
SetBrowserOleClientSite(Self as IOleClientSite);
end;

destructor TNulWBContainer.Destroy;
begin
SetBrowserOleClientSite(nil);
inherited;
end;

function TNulWBContainer.EnableModeless(const fEnable: BOOL):HResult;
begin
Result := S_OK;
end;

function TNulWBContainer.FilterDataObject(const pDO:IDataObject;
out ppDORet: IDataObject): HResult;
begin
ppDORet := nil;
Result := S_FALSE;
end;

function TNulWBContainer.GetContainer(
out container: IOleContainer): HResult;
begin
container := nil;
Result := E_NOINTERFACE;
end;

function TNulWBContainer.GetDropTarget(const pDropTarget:IDropTarget;
out ppDropTarget: IDropTarget): HResult;
begin
ppDropTarget := nil;
Result := E_FAIL;
end;

function TNulWBContainer.GetExternal(out ppDispatch: IDispatch):HResult;
begin
ppDispatch := nil;
Result := E_FAIL;
end;

function TNulWBContainer.GetHostInfo(var pInfo: TDocHostUIInfo):HResult;
begin
Result := S_OK;
end;

function TNulWBContainer.GetMoniker(dwAssign, dwWhichMoniker:Integer;
out mk: IMoniker): HResult;
begin
mk := nil;
Result := E_NOTIMPL;
end;

function TNulWBContainer.GetOptionKeyPath(var pchKey:POLESTR;
const dw: DWORD): HResult;
begin
Result := E_FAIL;
end;

function TNulWBContainer.HideUI: HResult;
begin
Result := S_OK;
end;

function TNulWBContainer.OnDocWindowActivate(
const fActivate: BOOL): HResult;
begin
Result := S_OK;
end;

function TNulWBContainer.OnFrameWindowActivate(
const fActivate: BOOL): HResult;
begin
Result := S_OK;
end;

function TNulWBContainer.OnShowWindow(fShow: BOOL):HResult;
begin
Result := S_OK;
end;

function TNulWBContainer.QueryInterface(const IID: TGUID; outObj): HResult;
begin
if GetInterface(IID, Obj) then
    Result :=S_OK
else
    Result :=E_NOINTERFACE;
end;

function TNulWBContainer.RequestNewObjectLayout: HResult;
begin
Result := E_NOTIMPL;
end;

function TNulWBContainer.ResizeBorder(const prcBorder:PRECT;
const pUIWindow: IOleInPlaceUIWindow; const fFrameWindow: BOOL):HResult;
begin
Result := S_FALSE;
end;

function TNulWBContainer.SaveObject: HResult;
begin
Result := S_OK;
end;

procedure TNulWBContainer.SetBrowserOleClientSite(
const Site: IOleClientSite);
var
OleObj: IOleObject;
begin
Assert((Site = Self as IOleClientSite) or (Site = nil));
if not Supports(fHostedBrowser.DefaultInterface, IOleObject,OleObj) then
    raiseException.Create('Browser''s Default interface does not supportIOleObject');
OleObj.SetClientSite(Site);
end;

function TNulWBContainer.ShowContextMenu(const dwID:DWORD;
const ppt: PPOINT; const pcmdtReserved: IInterface;
const pdispReserved: IDispatch): HResult;
begin
Result := S_FALSE
end;

function TNulWBContainer.ShowObject: HResult;
begin
Result := S_OK;
end;

function TNulWBContainer.ShowUI(const dwID: DWORD;
const pActiveObject: IOleInPlaceActiveObject;
const pCommandTarget: IOleCommandTarget; const pFrame:IOleInPlaceFrame;
const pDoc: IOleInPlaceUIWindow): HResult;
begin
Result := S_OK;
end;

function TNulWBContainer.TranslateAccelerator(const lpMsg:PMSG;
const pguidCmdGroup: PGUID; const nCmdID: DWORD): HResult;
begin
Result := S_FALSE;
end;

function TNulWBContainer.TranslateUrl(const dwTranslate:DWORD;
const pchURLIn: POLESTR; var ppchURLOut: POLESTR): HResult;
begin
Result := E_FAIL;
end;

function TNulWBContainer.UpdateUI: HResult;
begin
Result := S_OK;
end;

function TNulWBContainer._AddRef: Integer;
begin
Result := -1;
end;

function TNulWBContainer._Release: Integer;
begin
Result := -1;
end;

end.

http://blog.csdn.net/youthon/article/details/8446135

修改window.external使JS可调用Delphi方法的更多相关文章

  1. 前台JS(Jquery)调用后台方法 无刷新级联菜单示例

    前台用AJAX直接调用后台方法,老有人发帖提问,没事做个示例 下面是做的一个前台用JQUERY,AJAX调用后台方法做的无刷新级联菜单 http://www.dtan.so CasMenu.aspx页 ...

  2. JS与OC交互,JS中调用OC方法(获取JSContext的方式)

    最近用到JS和OC原生方法调用的问题,查了许多资料都语焉不详,自己记录一下吧,如果有误欢迎联系我指出. JS中调用OC方法有三种方式: 1.通过获取JSContext的方式直接调用OC方法 2.通过继 ...

  3. js 动态调用字符串方法并传入对应参数

    在项目应用中,经常会需要根据业务数据需要动态去拼凑字符串,然后将字符串作为js代码进行执行. js提供eval()来支持.这里分享一个调用函数并传入需要参数的一个方法demo //动态调用自定义js方 ...

  4. JS前端调用后台方法

    //JS前端代码function Exportqmdltb() { var areavalue= GetQmdltmValue(); $.ajax({ type: "post", ...

  5. window.external 是调用外部方法

    ie中,window.external 是调用外部方法,比如,是在 winform 中的 webbrower 中使用 window.external.SendData(),那么,SendData()  ...

  6. atitit.js javascript 调用c# java php后台语言api html5交互的原理与总结p97

    atitit.js javascript 调用c# java php后台语言api html5交互的原理与总结p97 1. 实现html5化界面的要解决的策略1 1.1. Js交互1 1.2. 动态参 ...

  7. flex与js相互调用

    1.flex调用js方法 调用方法例如:ExternalInterface.call("UploadComplete",oldName,uidName,_dir+"/&q ...

  8. JS调用Silverlight方法拾遗

    在最近做的物联网项目中,需要利用封装过的Silverlight刻度控件显示温度,湿度,二氧化碳浓度等值.由于最新的数据是通过js ajax获取的,所以需要把这些数据传递给silverlight显示,这 ...

  9. Android与js互相调用

    有话要说: 本篇主要总结了简单的Android与js互相调用的方法. 在开发过程中遇到了需要在安卓中调用js方法的需求,于是将具体的实现过程总结成这篇博客. 效果: 其中“调用安卓方法”按钮是html ...

随机推荐

  1. 体验ArcGIS9.2的历史库功能

    转自原文 体验ArcGIS9.2的历史库功能 ESRI公司于2006年11月9日全球同步发布了历史上重要的软件版本ArcGIS9.2,在该版本中,主要新增了以下四大功能(ESRI田昌莲): 第一大新功 ...

  2. SQLite单表4亿订单,大数据测试

    [转载] SQLite单表4亿订单,大数据测试 http://www.cnblogs.com/nnhy/p/BigData.html

  3. C++ 指向类成员函数指针的用法(转自维基百科)

    类成员函数指针 类成员函数指针(member function pointer),是C++语言的一类指针数据类型,用于存储一个指定类具有给定的形参列表与返回值类型的成员函数的访问信息. 目录 1 语法 ...

  4. 学习鸟哥的Linux私房菜笔记(14)——硬件配置与管理

    一.设备文件 Linux沿袭了Unix的风格,将所有设备看成一个文件 设备文件分为两种: 块设备文件(b):比如硬盘.光驱 字符设备文件(c):比如串口.键盘 设备文件一般存放在/dev目录下 二.常 ...

  5. 与Boss大雷探讨JavaWeb开发、电商与网络安全

    最近几个月,与公司Boss大雷交流得比较多,也学习到了很多新的东西,了解到了一些没有接触和实践的业界做法. 简要介绍下Boss,姓雷,定居武汉好几年了,之前在一号店.UC.支付宝干过,有丰富的电商-支 ...

  6. 【BZOJ 1012】 [JSOI2008]最大数maxnumber(单调队列做法)

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1012 [题意] [题解] 后加入的元素,如果比之前的元素大, 那么之前的元素比它小的元 ...

  7. mongdb aggregate 聚合数据

    最近用到的一些mongodb的数据查询方法 及api用法 Aggregate() 数据聚合处理的方法 可以将聚合的一些方法放在其后面的括号中,也可继续以agg.的样式链式加入 aggregate.al ...

  8. 停止学习Wireshark

    下载和安装好Wireshark之后,启动Wireshark而且在接口列表中选择接口名,然后開始在此接口上抓包.比如.假设想要在无线网络上抓取流量,点击无线接口.点击Capture Options能够配 ...

  9. Android-apktool反汇编异常-Input file (XXX) was not found or was not readable.

    问题描述: 原因: 在apptool 2.0以后命令发生了变化,不能再使用 apktool d <apk_path> <outfile_path> 解决方法:解决方法: 使用命 ...

  10. 统计推断(statistical inference)

    样本是统计推断的依据: 统计推断的基本问题可以分为两大类: 估计问题 点估计, 区间估计 假设检验 1. 点估计 设总体 X 的分布函数 F(x;θ) 的形式已知,θ 是待估参数.X1,X2,-,Xn ...