使用案例(先一些信息):
我制作了一些 HTML/CSS3/Javascript 游戏,可以在特定于平台的可执行文件中的 WebView/嵌入式浏览器中的不同平台上运行。我自己设计了它,因为我厌倦了周围所有的“框架”,这些“框架”告诉我使用他们的框架是多么简单。我不需要这些框架及其令人印象深刻的类和东西,它一定很简单,对吧?另外,由于 Web 视图比本机代码慢,因此它必须简单直接才能获得最佳性能。
所以我设计了一个接口,它可以作为 JavaScript 中的变量使用,无需加载额外的 JavaScript 类(如 cordova 或phonegap 或其他)。因为我也使用 Windows(Windows 无法将对象变量的名称更改为“publish”),所以可以通过 javascript 通过 window.external 访问它。当 html 加载到 webview/浏览器中时,该变量将是一个对象。
Question
这一切都运行得很好(在不同的平台上),但是window.external
变量在Windows上似乎是一个空对象,但是当你尝试调用像这样的函数时window.external.vibrate(500)
它将被正确执行(该函数存在于该对象的所有平台版本中)。
然而,像typeof window.external.vibrate
结果是'undefined'
。遍历对象不执行任何操作,例如:
for( var p in window.external ) {
alert( p );
}
因此,测试外部对象是否是“真实的”外部对象并不容易,并且无法查看支持哪些功能(如果需要)。
对此我能做什么?我错过了什么内在的东西吗?
为了给您提供一些信息,我遵循了这个“指南”:http://www.delphidabbler.com/articles?article=22 http://www.delphidabbler.com/articles?article=22.
我的代码(简化):
类型库:
unit WebBrowserBridge_TLB;
// ************************************************************************ //
// WARNING
// -------
// The types declared in this file were generated from data read from a
// Type Library. If this type library is explicitly or indirectly (via
// another type library referring to this type library) re-imported, or the
// 'Refresh' command of the Type Library Editor activated while editing the
// Type Library, the contents of this file will be regenerated and all
// manual modifications will be lost.
// ************************************************************************ //
// PASTLWTR : $Revision: 1.88.1.0.1.0 $
// File generated on 4-3-2014 6:50:23 from Type Library described below.
// ************************************************************************ //
// Type Lib: ExternalInterface\WebBrowserBridge.tlb (1)
// IID\LCID: {517F7078-5E73-4E5A-A8A2-8F0FF14EF21B}\0
// Helpfile:
// DepndLst:
// (1) v2.0 stdole, (C:\Windows\SysWOW64\stdole2.tlb)
// ************************************************************************ //
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
interface
uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL;
// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:
// Type Libraries : LIBID_xxxx
// CoClasses : CLASS_xxxx
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
// *********************************************************************//
const
// TypeLibrary Major and minor versions
WebBrowserBridgeMajorVersion = 1;
WebBrowserBridgeMinorVersion = 0;
LIBID_WebBrowserBridge: TGUID = '{517F7078-5E73-XXXX-B8A2-8F0FF14EF21B}';
IID_IWebBrowserBridge: TGUID = '{4F995D09-XXXX-4042-993E-C71A8AED661E}';
type
// *********************************************************************//
// Forward declaration of types defined in TypeLibrary
// *********************************************************************//
IWebBrowserBridge = interface;
IWebBrowserBridgeDisp = dispinterface;
// *********************************************************************//
// Interface: IWebBrowserBridge
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {4F995D09-CF9E-XXX-993E-C71A8AED661E}
// *********************************************************************//
IWebBrowserBridge = interface(IDispatch)
['{4F995D09-CF9E-4042XXXX-C71A8AED661E}']
procedure isAvailable; safecall;
procedure vibrate(ms: Integer); safecall;
end;
// *********************************************************************//
// DispIntf: IWebBrowserBridgeDisp
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {4F995D09-CF9E-XXX-993E-C71A8AED661E}
// *********************************************************************//
IWebBrowserBridgeDisp = dispinterface
['{4F995D09-CF9E-404XXXE-C71A8AED661E}']
procedure isAvailable; dispid 200;
procedure vibrate(ms: Integer); dispid 201;
end;
implementation
uses ComObj;
end.
对象库(类):
unit WebBrowserBridge;
interface
uses
// Delphi
ActiveX, SHDocVw, Windows, Classes, ComObj, Dialogs,
// Project
IntfDocHostUIHandler, UNulContainer, WebBrowserBridge_TLB;
type
TWebBrowserBridge = class(TAutoIntfObject, IWebBrowserBridge, IDispatch)
public
{ IMyExternal methods }
procedure isAvailable(); safecall;
procedure vibrate(ms: Integer); safecall;
public
constructor Create;
destructor Destroy; override;
end;
{
TWebBrowserBridgeContainer:
UI handler that extends browser's external object.
}
TWebBrowserBridgeContainer = class(TNulWBContainer, IDocHostUIHandler, IOleClientSite)
private
fExternalObj: IDispatch; // external object implementation
protected
{ Re-implemented IDocHostUIHandler method }
function GetExternal(out ppDispatch: IDispatch): HResult; stdcall;
public
constructor Create(const WBDefaultInterface: IDispatch);
end;
implementation
uses
SysUtils, StdActns;
{ TWebBrowserBridgeContainer }
constructor TWebBrowserBridgeContainer.Create(const WBDefaultInterface: IDispatch);
begin
inherited;
fExternalObj := TWebBrowserBridge.Create;
end;
function TWebBrowserBridgeContainer.GetExternal(out ppDispatch: IDispatch): HResult;
begin
ppDispatch := fExternalObj;
Result := S_OK; // indicates we've provided script
end;
{ TWebBrowserBridge }
constructor TWebBrowserBridge.Create;
var
TypeLib: ITypeLib; // type library information
ExeName: WideString; // name of our program's exe file
begin
// Get name of application
ExeName := ParamStr(0);
// Load type library from application's resources
OleCheck(LoadTypeLib(PWideChar(ExeName), TypeLib));
// Call inherited constructor
inherited Create(TypeLib, IWebBrowserBridge);
end;
destructor TWebBrowserBridge.Destroy;
begin
inherited;
end;
procedure TWebBrowserBridge.isAvailable();
begin
//Result:=1;
end;
procedure TWebBrowserBridge.vibrate(ms: Integer);
begin
windows.beep( 100, ms );
//showMessage( IntToStr( ms ));
end;
PS:
我还想知道如何在类型库中创建函数,因为它只允许创建过程或属性(但不支持像 Android 上的属性)。
EDIT:
另请参阅我的回答,但问题仍然悬而未决,因为PS above.