我遵循How to call Delphi code from scripts running in a TWebBrowser DelphiDabbler教程(Peter Johnson),允许Delphi听取TWebBrowser
JavaScript事件。
这可以达到我看到我的Delphi程序被调用的程度。但是,从那里我需要更新一些表单标签,我看不到从这些程序访问我的表单
DelphiDabbler示例代码很好地避免了直接表单访问的问题。由creating THintAction.Create(nil);
执行此操作:
这让我们可以很好地将我们的外部对象实现与程序的形式分离
但我想访问我的表格!要传递的数据是整数和字符串 我可以使用PostMessage()和WM_COPYDATA消息,但这些仍然需要表单句柄。并且没有直接的'路线到表格?
相关代码:
type
TWebBrowserExternal = class(TAutoIntfObject, IWebBrowserExternal, IDispatch)
protected
procedure SetVanLabel(const ACaption: WideString); safecall; // My 3 procedures that are called...
procedure SetNaarLabel(const AValue: WideString); safecall; // ... declared in the type library.
procedure SetDistanceLabel(AValue: Integer); safecall;
public
constructor Create;
destructor Destroy; override;
end;
type
TExternalContainer = 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 HostedBrowser: TWebBrowser);
end;
constructor TExternalContainer.Create(const HostedBrowser: TWebBrowser);
begin
inherited Create(HostedBrowser);
fExternalObj := TWebBrowserExternal.Create;
end;
表单中有一个property FContainer: TExternalContainer;
,在FormCreate中我做fContainer := TExternalContainer.Create(WebBrowser);
(参数是设计时TWebBrowser
),所以
TExternalContainer.fExternalObj
已分配给该帐户。
问题:
procedure TWebBrowserExternal.SetDistanceLabel(AValue: Integer);
begin
// **From here, how do I send AValue to a label caption on my form?**
end;
我必须承认界面不是我的强项; - )
[已添加:]注意:我的表单都是动态创建的,当前单元中没有TForm实例。
答案 0 :(得分:1)
你说你想要访问你的表格,但你真的没有 - 至少不是直接的。你确实希望“很好地将我们的外部对象实现与程序的形式分离”。您需要做的就是编写一个函数或过程来在程序中执行您想要的操作,然后从Web浏览器调用该函数或过程。这就是解耦和接口的全部内容。您从不直接从另一个应用程序处理属于一个应用程序的数据。而是使用函数和过程作为接口。顺便说一下,这就是为什么接口只包含函数和过程原型(和属性 - 但它们只是作为函数和过程在内部翻译) - 从不包含数据。
现在回答您的具体问题。当然,您可以访问您的表单 - 它是一个全局变量。假设您的主窗体是一个名为Main.pas的单元中的TMainForm类型,将会有一个名为MainForm的全局变量
var
MainForm : TMainForm;
所以在您的webbrowser单元中,在实现部分中,您将放置
implementation
uses Main;
...
procedure TWebBrowserExternal.SetDistanceLabel(AValue: Integer);
begin
// **From here, how do I send AValue to a label caption on my form?**
FormMain.MyLabel.Caption := StrToInt( AValue );
end;
在我所说的上下文中,SetDistanceLabel是接口函数,只能从Delphi应用程序中直接访问Form。
答案 1 :(得分:1)
接受建议你说你想要访问你的表格,但你真的不是 - 至少不是直接来自his/her answer的Dsm,我决定使用{ {1}} / PostMessage
(正如我在提问中暗示的那样)。
首先,我在SendMessage
和TWebBrowserExternal
的构造函数中传递窗口句柄,并将其存储为私有属性:
TExternalContainer
在FormCreate中,type
TWebBrowserExternal = class(TAutoIntfObject, IWebBrowserExternal, IDispatch)
private
fHandle: HWND;
procedure SendLocationUpdate(AWhere: Integer; ALocation: String); // Helper for SetVanLabel/SetNaarLabel
protected
procedure SetVanLabel(const AValue: WideString); safecall;
procedure SetNaarLabel(const AValue: WideString); safecall;
procedure SetDistanceLabel(AValue: Integer); safecall;
public
constructor Create(AHandle: HWND);
destructor Destroy; override;
end;
type
TExternalContainer = 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 HostedBrowser: TWebBrowser; AHandle: HWND);
end;
现在创建为
TExternalContainer
fContainer := TExternalContainer.Create(WebBrowser, Self.Handle);
方法实现为:
Set...
带辅助功能:
procedure TWebBrowserExternal.SetDistanceLabel(AValue: Integer);
begin
PostMessage(fHandle,UM_UPDATEDIST,AValue,0); // const UM_UPDATEDIST = WM_USER + 101;
end;
procedure TWebBrowserExternal.SetNaarLabel(const AValue: WideString);
begin
SendLocationUpdate(1,AValue);
end;
procedure TWebBrowserExternal.SetVanLabel(const AValue: WideString);
begin
SendLocationUpdate(0,AValue);
end;
我的表单包含两个实际更新标签的消息处理程序:
procedure TWebBrowserExternal.SendLocationUpdate(AWhere: Integer; ALocation: String);
var lCopyDataStruct: TCopyDataStruct;
begin
lCopyDataStruct.dwData := AWhere;
lCopyDataStruct.cbData := 2 * 2 * Length(ALocation);
lCopyDataStruct.lpData := PChar(ALocation);
SendMessage(fHandle, WM_COPYDATA, wParam(fHandle), lParam(@lCopyDataStruct));
end;