修改window.external使JS可调用Delphi方法
原文地址: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方法的更多相关文章
- 前台JS(Jquery)调用后台方法 无刷新级联菜单示例
前台用AJAX直接调用后台方法,老有人发帖提问,没事做个示例 下面是做的一个前台用JQUERY,AJAX调用后台方法做的无刷新级联菜单 http://www.dtan.so CasMenu.aspx页 ...
- JS与OC交互,JS中调用OC方法(获取JSContext的方式)
最近用到JS和OC原生方法调用的问题,查了许多资料都语焉不详,自己记录一下吧,如果有误欢迎联系我指出. JS中调用OC方法有三种方式: 1.通过获取JSContext的方式直接调用OC方法 2.通过继 ...
- js 动态调用字符串方法并传入对应参数
在项目应用中,经常会需要根据业务数据需要动态去拼凑字符串,然后将字符串作为js代码进行执行. js提供eval()来支持.这里分享一个调用函数并传入需要参数的一个方法demo //动态调用自定义js方 ...
- JS前端调用后台方法
//JS前端代码function Exportqmdltb() { var areavalue= GetQmdltmValue(); $.ajax({ type: "post", ...
- window.external 是调用外部方法
ie中,window.external 是调用外部方法,比如,是在 winform 中的 webbrower 中使用 window.external.SendData(),那么,SendData() ...
- 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. 动态参 ...
- flex与js相互调用
1.flex调用js方法 调用方法例如:ExternalInterface.call("UploadComplete",oldName,uidName,_dir+"/&q ...
- JS调用Silverlight方法拾遗
在最近做的物联网项目中,需要利用封装过的Silverlight刻度控件显示温度,湿度,二氧化碳浓度等值.由于最新的数据是通过js ajax获取的,所以需要把这些数据传递给silverlight显示,这 ...
- Android与js互相调用
有话要说: 本篇主要总结了简单的Android与js互相调用的方法. 在开发过程中遇到了需要在安卓中调用js方法的需求,于是将具体的实现过程总结成这篇博客. 效果: 其中“调用安卓方法”按钮是html ...
随机推荐
- Django之富文本编辑器kindeditor 及上传
1.什么是富文本编辑器 百度百科(https://baike.baidu.com/item/%E5%AF%8C%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%99%A8 ...
- linux网络编程实现投票功能
投票系统 1.说明: 写了一个投票系统.过程是先配置好server.在写一个网上投票功能,要实现网上投票功能. 事实上功能实现还是非常easy的,麻烦一点的在于过程比較繁杂,要做的东西还是挺多的! 2 ...
- Cocos2d-x 3.2 Lua演示样例FontTest(字体測试)
Cocos2d-x 3.2 Lua演示样例FontTest(字体測试) 本篇博客介绍Cocos2d-x 3.2中Lua測试项目中的FontTest样例,主要使用了字体文件来创建我们想要的字体样式: 第 ...
- Redis的增删改查、持久化你会了吗
原文:Redis的增删改查.持久化你会了吗 Redis是用C语言实现的,一般来说C语言实现的程序"距离"操作系统更近,执行速度相对会更快. Redis使用了单线程架构,预防了多线程 ...
- 【iOS】怎样推断文本文件的字符编码格式
整体思路: 遍历全部的字符编码.能正确读取输出转换的就是文本文件的编码格式. 代码例如以下: // // main.m // 检測文本字符编码格式的小技巧 // // Created by 杜子兮 ( ...
- 【Qt程序】基于Qt词典开发系列<十二>呼叫讲述
我们知道,win7系统自带有讲述人,即能够机器读出当前内容,详细能够将电脑锁定.然后点击左下角的button就可以.之前在用Matlab写扫雷游戏的时候,也以前调用过讲述人来进行游戏的语音提示. 详细 ...
- 【codeforces 782D】 Innokenty and a Football League
[题目链接]:http://codeforces.com/contest/782 [题意] 每个队名有两种选择, 然后第一个选择队名相同的那些队只能选第二种; 让你安排队名 [题解] 首先全都选成第一 ...
- MIPS重返硅谷 放眼AI未来
MIPS最近以一家独立公司之姿重新回到了矽谷,在Tallwood的带领下积极投入原有的嵌入式业务,并放眼下一代人工智能(AI)领域. MIPS最近以一家独立公司之姿重新回到了矽谷——加州圣塔克拉拉 ...
- hibernate annotation 相关主键生成策略
Hibernate 默认的全面支持 13 物种生成策略 : 1. increment 2. identity 3. sequence 4. hilo 5. seqhilo 6. uuid 7. uu ...
- Project Euler:Problem 28 Number spiral diagonals
Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is forme ...