- 浏览: 10682 次
最新评论
在JavaScript中,有一个比较特殊的对象,即window.external,用它可以调用浏览器提供的外部方法.
一个很简单的例子就是将当前页添加到收藏夹:
window.external.addFavorite("http://suton.iteye.com","suton的博客");
这样写脚本就可以了。
那么如果我想自己定义external,以便在自己的软件内使用IE核心的浏览器作为UI容器,该如何做呢?本文即是解决此问题。
一、制作TLB
在File | New | Other 菜单下,选择新建一个Type Library,这个向导在ActiveX页内。
然后按下图所示,新建一个接口,在接口下新建一个DoSearchData方法,这个方法即是将来需要添加到external中的。
完成添加后,点击保存为TLB按钮,将生成一个TLB文件,此处我将它命名为GetData.tlb
在JavaScript中,有一个比较特殊的对象,即window.external,用它可以调用浏览器提供的外部方法
一个很简单的例子就是将当前页添加到收藏夹
window.external.addFavorite("http://hi.baidu.com/rarnu","橙子的百度博客');
这样写脚本就可以了。
那么如果我想自己定义external,以便在自己的软件内使用IE核心的浏览器作为UI容器,该如何做呢?
本文即是解决此问题。
一、制作TLB
在File | New | Other 菜单下,选择新建一个Type Library,这个向导在ActiveX页内。
然后按下图所示,新建一个接口,在接口下新建一个DoSearchData方法,这个方法即是将来需要添加到external中的。
完成添加后,点击保存为TLB按钮,将生成一个TLB文件,此处我将它命名为GetData.tlb
二、实现IDocHostUIHandler接口
这部分相对比较简单,从MSDN上找到相关的C++代码,把它转换成Delphi的即可。代码如下:
三、实现一个带有IE组件的容器
由于Delphi自带的WebBrowser控件不支持external的直接扩展,因此我们需要另外写一个容器,使它实现IDocHostUIHandler接口,并且通过ActiveX单元的IOleObject.SetClientSite方法,将我们自己的容器填充进去。
这部分的代码直接参考了EmbeddedWB组件的相关实现,具体代码如下:
四、实现TLB内的接口
上面的两个单元都可以当作公共单元来处理,因为以后永远都不再需要修改它们了,下面要做的事情是重点。新建一个VCL Application,然后我们来实现TLB内的接口。
这样即是一个实现的了TLB。可以看到,其中有个DoSearchData()方法里是空的,下面我们为它填上代码。
五、编写业务逻辑代码
新建一个Data Module,然后放上ADOConnection与ADOQuery两个控件,相互关联后,连接到SQL Server 2000的一个默认数据库Northwind上。在Data Module内,写一个方法SearchDataHtml()。
很明显的,上面的代码即是查询一个表,并把它的内容拼装成一个Table。
然后我们在GetData_TLB_Impl中引用Data Module,并补完DoSearchData()方法中的代码:
六、实现一个External容器
接下来的事情就很简单了,我们用自己写的external去替换掉浏览器本身的。
七、将浏览器控件放进自定义的external容器
就一句代码,就能把把WebBrowser内的external替换了
八、引用TLB并编译
打开Dpr的源码,添加一句{$R GetData.tlb},然后编译程序,运行。
九、总结
到此为止,external的替换就结束了
一个很简单的例子就是将当前页添加到收藏夹:
window.external.addFavorite("http://suton.iteye.com","suton的博客");
这样写脚本就可以了。
那么如果我想自己定义external,以便在自己的软件内使用IE核心的浏览器作为UI容器,该如何做呢?本文即是解决此问题。
一、制作TLB
在File | New | Other 菜单下,选择新建一个Type Library,这个向导在ActiveX页内。
然后按下图所示,新建一个接口,在接口下新建一个DoSearchData方法,这个方法即是将来需要添加到external中的。
完成添加后,点击保存为TLB按钮,将生成一个TLB文件,此处我将它命名为GetData.tlb
在JavaScript中,有一个比较特殊的对象,即window.external,用它可以调用浏览器提供的外部方法
一个很简单的例子就是将当前页添加到收藏夹
window.external.addFavorite("http://hi.baidu.com/rarnu","橙子的百度博客');
这样写脚本就可以了。
那么如果我想自己定义external,以便在自己的软件内使用IE核心的浏览器作为UI容器,该如何做呢?
本文即是解决此问题。
一、制作TLB
在File | New | Other 菜单下,选择新建一个Type Library,这个向导在ActiveX页内。
然后按下图所示,新建一个接口,在接口下新建一个DoSearchData方法,这个方法即是将来需要添加到external中的。
完成添加后,点击保存为TLB按钮,将生成一个TLB文件,此处我将它命名为GetData.tlb
二、实现IDocHostUIHandler接口
这部分相对比较简单,从MSDN上找到相关的C++代码,把它转换成Delphi的即可。代码如下:
unit DocHostUIHandler; 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}'] function ShowContextMenu(const dwID: DWORD; const ppt: PPOINT; const pcmdtReserved: IUnknown; const pdispReserved: ispatch): HResult; stdcall; function GetHostInfo(var pInfo: TDocHostUIInfo): HResult; dcall; function ShowUI(const dwID: DWORD; const pActiveObject: IOleInPlaceActiveObject; const pCommandTarget: IOleCommandTarget; const pFrame: IOleInPlaceFrame; const pDoc: IOleInPlaceUIWindow): HResult; stdcall; function HideUI: HResult; stdcall; function UpdateUI: HResult; stdcall; function EnableModeless(const fEnable: BOOL): HResult; stdcall; function OnDocWindowActivate(const fActivate: BOOL): HResult; stdcall; function OnFrameWindowActivate(const fActivate: BOOL): HResult; stdcall; function ResizeBorder(const prcBorder: PRECT; const pUIWindow: IOleInPlaceUIWindow; const fFrameWindow: BOOL): HResult; stdcall; function TranslateAccelerator(const lpMsg: PMSG; const pguidCmdGroup: PGUID; const nCmdID: DWORD): HResult; stdcall; function GetOptionKeyPath(var pchKey: POLESTR; const dw: DWORD ): HResult; stdcall; function GetDropTarget(const pDropTarget: IDropTarget; out ppDropTarget: IDropTarget): HResult; stdcall; function GetExternal(out ppDispatch: IDispatch): HResult; stdcall; function TranslateUrl(const dwTranslate: DWORD; const pchURLIn: POLESTR; var ppchURLOut: POLESTR): HResult; stdcall; function FilterDataObject(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; procedure SetBrowserOleClientSite(const Site: IOleClientSite); protected function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; function SaveObject: HResult; stdcall; function GetMoniker(dwAssign: Longint; dwWhichMoniker: Longint; out mk: IMoniker): HResult; stdcall; function GetContainer( out container: IOleContainer): HResult; stdcall; function ShowObject: HResult; stdcall; function OnShowWindow(fShow: BOOL): HResult; stdcall; function RequestNewObjectLayout: HResult; stdcall; function ShowContextMenu(const dwID: DWORD; const ppt: PPOINT; const pcmdtReserved: IUnknown; const pdispReserved: IDispatch): HResult; stdcall; function GetHostInfo(var pInfo: TDocHostUIInfo): HResult; stdcall; function ShowUI(const dwID: DWORD; const pActiveObject: IOleInPlaceActiveObject; const pCommandTarget: IOleCommandTarget; const pFrame: IOleInPlaceFrame; const pDoc: IOleInPlaceUIWindow): HResult; stdcall; function HideUI: HResult; stdcall; function UpdateUI: HResult; stdcall; function EnableModeless(const fEnable: BOOL): HResult; stdcall; function OnDocWindowActivate(const fActivate: BOOL): HResult; stdcall; function OnFrameWindowActivate(const fActivate: BOOL): HResult; stdcall; function ResizeBorder(const prcBorder: PRECT; const pUIWindow: IOleInPlaceUIWindow; const fFrameWindow: BOOL): HResult; stdcall; function TranslateAccelerator(const lpMsg: PMSG; const pguidCmdGroup: PGUID; const nCmdID: DWORD): HResult; stdcall; function GetOptionKeyPath(var pchKey: POLESTR; const dw: DWORD ): HResult; stdcall; function GetDropTarget(const pDropTarget: IDropTarget; out ppDropTarget: IDropTarget): HResult; stdcall; function GetExternal(out ppDispatch: IDispatch): HResult; stdcall; function TranslateUrl(const dwTranslate: DWORD; const pchURLIn: POLESTR; var ppchURLOut: POLESTR): HResult; stdcall; function FilterDataObject(const pDO: IDataObject; out ppDORet: IDataObject): HResult; stdcall; public constructor Create(const HostedBrowser: TWebBrowser); destructor Destroy; override; property HostedBrowser: 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; out Obj): 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 raise Exception.Create('Browser''s Default interface does not support IOleObject'); 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.
四、实现TLB内的接口
上面的两个单元都可以当作公共单元来处理,因为以后永远都不再需要修改它们了,下面要做的事情是重点。新建一个VCL Application,然后我们来实现TLB内的接口。
unit GetData_TLB_Impl; interface uses Classes, ComObj, GetData_TLB; type TMyExternal = class(TAutoIntfObject, IGetData, IDispatch) private protected function DoSeaarchData(const ASQL: WideString): WideString; safecall; public constructor Create; destructor Destroy; override; end; implementation uses SysUtils, ActiveX, StdActns; { TMyExternal } constructor TMyExternal.Create; var TypeLib: ITypeLib; ExeName: WideString; begin ExeName := ParamStr(0); OleCheck(LoadTypeLib(PWideChar(ExeName), TypeLib)); inherited Create(TypeLib, IGetData); end; destructor TMyExternal.Destroy; begin inherited; end; function TMyExternal.DoSeaarchData(const ASQL: WideString): WideString; safecall; begin end; end.
这样即是一个实现的了TLB。可以看到,其中有个DoSearchData()方法里是空的,下面我们为它填上代码。
五、编写业务逻辑代码
新建一个Data Module,然后放上ADOConnection与ADOQuery两个控件,相互关联后,连接到SQL Server 2000的一个默认数据库Northwind上。在Data Module内,写一个方法SearchDataHtml()。
function TDM.SearchDataHtml(ASQL: string): string; var i: Integer; ret: string; begin ret := '<table border="1" cellspacing="0" cellpadding="0">'; with Qry do begin Close; SQL.Text := ASQL; try Open; except on E: Exception do begin Result := e.Message; Exit; end; end; ret := ret + '<tr>'; for i:=0 to FieldCount - 1 do ret := ret + Format('<td nowrap><b>%s</b></td>',[Fields[i].FieldName]); ret := ret + '</tr>'; First; while not Eof do begin ret := ret + '<tr>'; for i:=0 to FieldCount - 1 do begin if Fields[i].DataType in [ftString, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime, ftAutoInc, ftMemo, ftFmtMemo, ftWideString, ftFixedChar, ftLargeint, ftVariant, ftGuid, ftTimeStamp, ftFMTBcd] then ret := ret + Format('<td nowrap>%s</td>',[Fields[i].AsString]) else ret := ret + '<td nowrap>(Unsupported Data)</td>'; end; ret := ret + '</tr>'; Next; end; end; ret := ret+ '</table>'; Result := ret; end;
很明显的,上面的代码即是查询一个表,并把它的内容拼装成一个Table。
然后我们在GetData_TLB_Impl中引用Data Module,并补完DoSearchData()方法中的代码:
function TMyExternal.DoSeaarchData(const ASQL: WideString): WideString; safecall; begin Result := DM.SearchDataHtml(ASQL); end;
六、实现一个External容器
接下来的事情就很简单了,我们用自己写的external去替换掉浏览器本身的。
unit ExternalContainer; interface uses ActiveX, SHDocVw, DocHostUIHandler, NulContainer, GetData_TLB_Impl; type TExternalContainer = class(TNulWBContainer, IDocHostUIHandler, IOleClientSite) private fExternalObj: IDispatch; protected function GetExternal(out ppDispatch: IDispatch): HResult; stdcall; public constructor Create(const HostedBrowser: TWebBrowser); end; implementation { TExternalContainer } constructor TExternalContainer.Create(const HostedBrowser: TWebBrowser); begin inherited Create(HostedBrowser); fExternalObj := TMyExternal.Create; end; function TExternalContainer.GetExternal(out ppDispatch: IDispatch): HResult; begin ppDispatch := fExternalObj; Result := S_OK; end; end.
七、将浏览器控件放进自定义的external容器
就一句代码,就能把把WebBrowser内的external替换了
procedure TFormMain.FormCreate(Sender: TObject); begin f := TExternalContainer.Create(WB); WB.Navigate(ExtractFilePath(ParamStr(0))+'Data.html'); end;
八、引用TLB并编译
打开Dpr的源码,添加一句{$R GetData.tlb},然后编译程序,运行。
九、总结
到此为止,external的替换就结束了
相关推荐
DELPHI+chrome+替换WebBrowser让你的程序嵌入chrome浏览器,此控件非常方便的让你的程序内置chrome浏览器,解决老webbrowser的各种问题,非常方便。Chrome不挑食,基本上什么系统都可以跑,而且速度那是飞快,所以C/...
delphi twebbrowser小例子。
1.获得网页中变量值 2.执行网页中的函数 3.设置网页背景 4.调用网页中已知对象
delphi 中使用TWebBrowser控件.WEB版编程一定会用到的控件。
delphi的TWebBrowser控件,实际上是IE,版本比较低,经济打不开网页,可以通过修改注册表的方法进行修改成IE11
Delphi能用TWebBrowser制作网页编辑器吗demo宣贯.pdf
Delphi禁止WebBrowser弹出IE的对话框
禁止TWebBrowser的默认的右键菜单,改成自己的右键菜单
delphi 从TWebBrowser WebBrowser得到全部html源码 收藏 网上查询出很多方法,归结起来有两种
delphi动态 WebBrowser 释放问题.txt var web:TwebBrowser; procedure TForm1.Button1Click(Sender: TObject); begin web:=TWebBrowser.Create(Self); web.ParentWindow:=Self.Handle; web.SetBounds(100,100,...
使用TWebBrowser将Html文件批量转换成纯文本文件的delphi源代码
原理: 取鼠标下的HTML元素IHTMLElement,然后把焦点框(一个特殊的窗体)显示到元素所在的位置。未使用js。
直接向Delphi中的TWebBrowser组件中写入HTML代码,显示之。TWebBrowser通常是用ref方式链接到一个地址或打开文件的,本代码给出的方法更直接方便
delphi 下用Chorme 内核开发的浏览器示例程序,DELPHI 7 DELPHI XE , DELPHI 10.2亲测可以用
用TWebBrowser组件在DELPHI中POST数据和取得网页源文件 在 WebBrowser 中直接载入流,不通过文件 判断下载网页成功 WebBrowser 失去焦点问题的解决 添加到收藏夹和整理收藏夹 使WebBrowser获得焦点 提取网页中所有...
post数据 从Internet下载文件 从TServerSocket发送文件到TClientSocket 允许在TWebbrowser中复制、粘贴、拖拽 列举网络驱动器 ...调用默认email程序发送email 通过拖拽填充表单域 隐藏网页浏览器的滚动条
Delphi TEdgeBrowser插件及运行库,含 EdgeBrowser Dev和WebView2SDk_DLL。 适用于Delphi 10.4.x 及 Windows10. TWebBrowser使用Win10之前的操作系统提供的IE浏览器; 只要Windows上安装有IE,它就可以工作。 ...
解决了webbrowser下载文件的三个问题: 1、屏蔽了另存为的弹出 2、获得webbrowser所有的cookie值 3、让webclient支持cookie
在csdn http://download.csdn.net/detail/duet/3328143下载了一个直接将HTML写入TWebBrowser,发现只能写入一次内容,再写入就显示空白页面,百度了一下,发现少了一个语句,现补上,这是修改后的文件
懶惰鬼自動登入器 - (利用 Delphi 控制網頁的 Demo) 如何列出所有已開啟的網頁? 如何取得網頁的原始程式碼? 如何填資料後自動按下Submit? 如何執行網頁上的 Java S c r i p t ? 如何執行 S c r i p t 後,取回執行內...