上一节介绍了一个ActiveX的例子,后续的文章将针对这个例子进行扩充和说明。这篇文章将介绍C#如何在ActiveX控件中调用javascript的函数,这里参考网上的例子介绍两种方法,虽然代码不一样,但是殊途同归。而且都使用了mshtml。
1、方法一
(1)在VS项目中添加Com对象引用:Microsoft Html Object Library(mshtml.tlb)
(2)ActiveX中公开一个方法,传递window对象到ActiveX中
ActiveX中公开一个方法,接受传递进来的参数
/// <summary>
/// 将window对象传递进来
/// </summary>
/// <param name="obj">The obj.</param>
public void SetHtml(object obj)
{
html = (mshtml.HTMLWindow2Class)obj;
}
在页面中调用ActiveX的公开方法,传递当前window对象进去:
window.onload = function() {
document.HelloBossma.SetHtml(this);
};
(3)在ActiveX控件中添加一个按钮,当点击这个按钮时,触发页面中的javascript。
点击按钮的方法:
/// <summary>
/// 调用页面Javascript
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
html.execScript("CallByActiveX();", "javascript");
}
现在卸载掉原来的ActiveX控件,安装新的控件,打开页面,点击按钮,看到如下效果,说明成功。
调用javascript时还可以传递参数,这里不做演示了,自己可以试一下。
参考:http://www.cnblogs.com/liubiqu/articles/92632.html
2、方法二
(1)在VS项目中添加Com对象引用:Microsoft Html Object Library(mshtml.tlb)
和第一种方法相同。
(2)用c#实现两个COM类,IOleClientSite和IOleContainer
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace HelloBossma
{
[ComImport, Guid("00000118-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleClientSite
{
void SaveObject();
void GetMoniker(uint dwAssign, uint dwWhichMoniker, object ppmk);
void GetContainer(out IOleContainer ppContainer);
void ShowObject();
void OnShowWindow(bool fShow);
void RequestNewObjectLayout();
}
[ComImport, Guid("0000011B-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleContainer
{
void EnumObjects([In, MarshalAs(UnmanagedType.U4)] int grfFlags, [Out, MarshalAs(UnmanagedType.LPArray)] object[] ppenum);
void ParseDisplayName([In, MarshalAs(UnmanagedType.Interface)] object pbc, [MarshalAs(UnmanagedType.BStr)] string pszDisplayName, [Out, MarshalAs(UnmanagedType.LPArray)] int[] pchEaten,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] ppmkOut);
void LockContainer([In, MarshalAs(UnmanagedType.I4)] int fLock);
}
}
(3)在ActiveX中编写CallJavascript方法:
/// <summary>
/// 调用Javascript
/// </summary>
/// <param name="Filenames">The filenames.</param>
private void CallJavaScript(string param)
{
//反射获取当前的控件的ClientSite
Type typeIOleObject = this.GetType().GetInterface("IOleObject", true);
object oleClientSite = typeIOleObject.InvokeMember("GetClientSite",
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
this,
null);
//获取Container
IOleClientSite oleClientSite2 = oleClientSite as IOleClientSite;
IOleContainer pObj;
oleClientSite2.GetContainer(out pObj);
//参数数组
object[] args = new object[1];
args[0] = param;
//获取页面的Script集合
IHTMLDocument pDoc2 = (IHTMLDocument)pObj;
object script = pDoc2.Script;
try
{
//调用JavaScript方法OnScaned并传递参数,因为此方法可能并没有在页面中实现,所以要进行异常处理
script.GetType().InvokeMember("ShowNowTime", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
script,
args);
}
catch { }
}
点击按钮时的操作:
/// <summary>
/// 调用Javascript
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
CallJavaScript(this.label2.Text);
}
(4)网页中的javascript
function ShowNowTime(nowtime) {
alert("当前时间:" + nowtime);
}
卸载原来的ActiveX控件,重新安装,实际效果:
参考:http://blog.youkuaiyun.com/sabty/archive/2009/05/10/4165342.aspx
这篇文档到这里就结束了