gpt4 book ai didi

javascript - TEmbeddedWB/TWebbrowser : window. external 是一个空对象但是可以调用函数,为什么一开始是 'empty'?

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:24:47 25 4
gpt4 key购买 nike

用例(先是一些信息):

我制作了一些 HTML/CSS3/Javascript 游戏,它们可以在特定于平台的可执行文件中的 WebView/嵌入式浏览器中的不同平台上运行。我自己设计了它,因为我厌倦了周围的所有“框架”,它们告诉我使用他们的框架是多么简单。我不需要这些框架及其令人印象深刻的类和东西的所有膨胀,它必须像 ABC 一样简单,对吧?此外,由于 webview 比 native 代码慢,因此它必须简单直接才能获得最佳性能。

所以我设计了一个在 javascript 中作为变量可用的接口(interface),无需加载额外的 javascript 类(如 cordova 或 phonegap 或其他)。因为我也使用 Windows(Windows 无法将对象变量的名称更改为“publish”),所以它可以通过 javascript 通过 window.external 访问。当 html 加载到 webview/browser 中时,此变量将是一个对象。

问题

这一切都工作得很好(在不同的平台上)但是 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 .

我的代码(简化版):

类型库:

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;

附言:

我也想知道如何在类型库中创建一个函数,因为它只允许创建过程或属性(但不支持像 Android 上的属性)。

编辑:

另请参阅我的回答,但由于上面的 PS,问题仍然悬而未决。

最佳答案

使用 ObjComAuto.TObjectDispatch 提供的后期绑定(bind)功能,可以使用更简单的方法在 Delphi 中实现 external 方法.

这样您就不需要定义任何接口(interface)或类型库。您所需要的只是一个实现所需事件的简单类,以及 $METHODINFO 提供的扩展 RTTI 信息。 .

您可以实现过程和函数,并接收 Delphi 类型或 javascript 对象作为参数。也可以从 Delphi 中使用 Javascript 对象(可以访问属性和方法)。

示例:(只需在表单中放置一个 TEmbeddedWB)

uses MSHTML_EWB, ObjComAuto;

type
{$METHODINFO ON} // activate detailed RTTI
TJavascriptReceiver = class
procedure MyMouseMove(event: variant);
procedure MyClick(event: variant);
function MyGet(msg: string): string;
end;
{$METHODINFO OFF}

{ TJavascriptReceiver }

procedure TJavascriptReceiver.MyMouseMove(event: variant);
begin
Form1.Caption := IntToStr(event.clientX) + ', ' + IntToStr(event.clientY);
end;

procedure TJavascriptReceiver.MyClick(event: variant);
var
w: variant;
begin
w := (Form1.EmbeddedWB1.Document as IHTMLDocument2).parentWindow;
w.testGet('Caption: ');
end;

function TJavascriptReceiver.MyGet(msg: string): string;
begin
Result := msg + Form1.Caption;
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
strs: TStringStream;
begin
strs := TStringStream.Create;
try
strs.WriteString(
'<!DOCTYPE html>'
+'<html>'
+'<head>'
+' <style>'
+' html, body { margin: 0; padding: 0; height: 100%; }'
+' </style>'

+' <script>'
+' function testGet(msg) {'
+' alert(external.MyGet(msg));'
+' }'
+' </script>'
+'</head>'

+'<body'
+' onmousemove="external.MyMouseMove(event)"'
+' onclick="external.MyClick(event)"'
+'>'
+'Click anywhere'
+'</body>'
+'</html>'
);
EmbeddedWB1.LoadFromStream(strs);
finally
strs.Free;
end;
end;

procedure TForm1.EmbeddedWB1GetExternal(Sender: TCustomEmbeddedWB;
var ppDispatch: IDispatch);
begin
ppDispatch := TObjectDispatch.Create(TJavascriptReceiver.Create);
end;

注意:

Javascript arrays are sparse ,因此您无法使用通常的 myArray[3] 语法从 Delphi 访问它们。相反,您需要像使用索引一样使用索引,即某种 myArray.3。这不是 Delphi 直接支持的,而是使用 ComObj.GetDispatchPropValue : GetDispatchPropValue(myArray, '3')。更多信息 here .

编辑:

有关如何通过 window.external 方法进行迭代的信息,请参阅我的其他答案。

关于javascript - TEmbeddedWB/TWebbrowser : window. external 是一个空对象但是可以调用函数,为什么一开始是 'empty'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22165895/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com