65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ Silverlight 主机与 Silverlight 应用程序之间的通信

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (9投票s)

2010年5月20日

CPOL

2分钟阅读

viewsIcon

76630

downloadIcon

952

本文档解释了如何从 C++ Silverlight 主机调用在 Silverlight 中定义的方法。

引言

在继续阅读本文之前,请先阅读我的上一篇文章 Host_Silverlight_In_ATL。 在本文中,我们将讨论 C++ Silverlight 主机和 Silverlight 应用程序之间的通信,这意味着我们可以从 C++ Silverlight 主机调用 Silverlight 应用程序的方法。

C__ToSilverlightCommunication.PNG

在 Silverlight 应用程序中需要做的事情

 using System.Windows.Browser;

使用上述命名空间进行通信。 我们将使用 HTML 通信桥与 C++ 主机进行通信。

使用以下语句注册 Communicator 对象。 我们将通过 IDispath 在 C++ Silverlight 主机中获取此 communicator 对象。

HtmlPage.RegisterScriptableObject("Communicator", this);

在 Silverlight 应用程序中编写另一个函数,我们将从 C++ Silverlight 主机调用它。

[ScriptableMember]
public void SetDataInTextBox(string strData)
{
	txtData.Text = strData;
}

Silverlight 页面的完整代码如下

using System.Windows.Browser;
namespace SilverlightTestApp
{
	public partial class MainPage : UserControl
	{
		public MainPage()
		{
			HtmlPage.RegisterScriptableObject("Communicator", this);
			InitializeComponent();
		}
		private void ClickMe_Click(object sender, RoutedEventArgs e)
		{	
			MessageBox.Show("Button click handler is in Silverlight :)", 
			"SilverlightTestApp", MessageBoxButton.OK);
		}
		[ScriptableMember]
		public void SetDataInTextBox(string strData)
		{
			txtData.Text = strData;
		}
	}
}

我这里不打算解释 Silverlight 开发问题,但我想说的是,我们对 Silverlight 和 JavaScript 的交互所做的事情是一样的。 如果您不熟悉上面的代码,请在 Google 上搜索 Silverlight 和 JavaScript 交互。 几乎每本书籍都会涵盖这个主题。

C++ Silverlight 主机

在 ATL 应用程序的对话框中添加一个编辑框和一个按钮。 我们将在编辑框中输入一些测试内容,并在我们刚刚添加的按钮的单击处理程序中编写一些代码。

按钮单击处理函数。 在 strData 中获取用户输入...

LRESULT CCMainDlg::OnBnClickedBtnSendDataToSilverlight
	(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
 	CAtlStringW strData;
 	GetDlgItem(IDC_EDIT_DATA).GetWindowTextW(strData);

现在我们来谈谈关键点 - 获取我们在 Silverlight 应用程序中刚刚注册的 Communicator 对象的 DISPID

IDispatch *pContent;
HRESULT hr = CXcpControlHost::GetXcpControlPtr()->get_Content(&pContent);
CComBSTR bstrMember(L"Communicator");
DISPID dispIDCommunicator = NULL;
hr = pContent->GetIDsOfNames(IID_NULL, &bstrMember, 1, 
	LOCALE_SYSTEM_DEFAULT, &dispIDCommunicator); 
if(FAILED(hr))
{
	::MessageBox(NULL, L"Failed to get the DISPID for Communicator", 
		L"Error :(", 0);
	return 0;
}

一旦我们获得了 Communicator 对象的有效 dispID ,我们就可以准备获取 Communicator 对象的 IDispatch*。 这有点棘手,我们将使用 DISPATCH_PROPERTYGET 进行调用。

VARIANT pVarResult;
DISPPARAMS dispparams; 
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = 0;
dispparams.rgvarg = NULL;
dispparams.cNamedArgs = 0;
// Getting IDispatch from for Scriptable object exposed by Silverlight Application. 
// Passing dispid for "Communicator" to get its IDispatch* using DISPATCH_PROPERTYGET.
hr = pContent->Invoke(dispIDCommunicator,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYGET,
&dispparams, &pVarResult, NULL, NULL);
if(FAILED(hr))
{
	::MessageBox(NULL, L"Failed to get the IDsipatch* of Communicator", 
		L"Error :(", 0);
	return 0;
}

IDispatch* pCommunicatorDispatch = pVarResult.pdispVal;

我们将 CommunicatorIDispatch* 存储在 pCommunicatorDispatch 中。 现在我们必须使用这个 pCommunicatorDispatch。 这是我们现在的主要角色,使用 pCommunicatorDispatch,我们将从 Silverlight 应用程序获取我们暴露的方法(SetDataInEditBox)的 DISPID ,然后进行 Invoke() 调用,通过将该 string 传递到该函数来调用 SetDataInEditBox()

bstrMember = L"SetDataInTextBox";
DISPID dispIDSetDataInTextBox = NULL;
hr = pCommunicatorDispatch->GetIDsOfNames(IID_NULL,&bstrMember,1, 
	LOCALE_SYSTEM_DEFAULT,&dispIDSetDataInTextBox); 
EXCEPINFO pexcepinfo ;
if(SUCCEEDED(hr))
{
	dispparams.cArgs = 1;
	dispparams.cNamedArgs = 1;
	dispparams.rgvarg = new VARIANT[1];
	dispparams.rgvarg[0].vt = VT_BSTR;
	dispparams.rgvarg[0].bstrVal = SysAllocString(strData.GetString());
	hr = pCommunicatorDispatch->Invoke(dispIDSetDataInTextBox, 
		IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, 
		&dispparams, &pVarResult,&pexcepinfo,NULL);
	delete [] dispparams.rgvarg;

	if (hr != S_OK)
	{
		::MessageBox(NULL, L"Failed to Invoke Silverlight function", 
			L"Error :(", 0);
		return 0;
	}
}
else
{
	::MessageBox(NULL, L"Failed to get the DISPID for SetDataInTextBox 
		function defined in Silverlight.", L"Error :(", 0);
}

结论

在本文中,我向您展示了如何从 C++ Silverlight 主机调用在 Silverlight 应用程序中定义的一个函数。

希望本文能对您在 Silverlight 和 C++ 交互方面有所帮助。

如有任何问题、意见和建议,请使用本文底部的评论区。

历史

  • 2010 年 5 月 20 日:初始发布
© . All rights reserved.