使用C#開發ActiveX控制元件
ActiveX 是一個開放的整合平臺,為開發人員、使用者和 Web生產商提供了一個快速而簡便的在 Internet 和 Intranet 建立程式整合和內容的方法。 使用ActiveX, 可輕鬆方便的在 Web頁中插入 多媒體效果、 互動式物件、以及複雜程式,建立使用者體驗相當的高質量多媒體 CD-ROM 。
簡單的說,用activeX和js差不多,但是有些是js無法實現的,這個時候就可以考慮一下activeX,一般要求是在客戶端執行的程式,比如對本機的串列埠操作等,下面來簡單介紹下如何用C#自己開發一個activeX元件,並在web中應用
更改“專案屬性-應用程式-程式集資訊”設定,勾選“使程式集 COM 可見”:
更改“專案屬性-生成”設定,勾選“為 COM 互操作 註冊”
修改AssemblyInfo.cs檔案,新增[assembly: AllowPartiallyTrustedCallers()]項(需要引用System.Security名稱空間):
using System.Runtime.InteropServices;
using System.Security;
// 有關程式集的常規資訊通過下列屬性集
// 控制。更改這些屬性值可修改
// 與程式集關聯的資訊。
[assembly: AssemblyTitle("ActivexDemo")]
[assembly: AssemblyDescription
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("微軟中國")]
[assembly: AssemblyProduct("ActivexDemo")]
[assembly: AssemblyCopyright("Copyright © 微軟中國 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 將 ComVisible 設定為 false 使此程式集中的型別
// 對 COM 元件不可見。如果需要從 COM 訪問此程式集中的型別,
// 則將該型別上的 ComVisible 屬性設定為 true。
[assembly: ComVisible(true)]
// 如果此專案向 COM 公開,則下列 GUID 用於型別庫的 ID
[assembly: Guid("f5438267-5c1e-4c24-b2e0-c2f172e753a4")]
// 程式集的版本資訊由下面四個值組成:
//
// 主版本
// 次版本
// 內部版本號
// 修訂號
//
// 可以指定所有這些值,也可以使用“內部版本號”和“修訂號”的預設值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AllowPartiallyTrustedCallers()]
新增一個Windows使用者控制元件:
完成控制元件開發後,為了使該使用者控制元件作為一個ActiveX控制元件進行使用,還需要做以下修改:
首先,為控制元件類新增GUID,這個編號將用於B/S系統的客戶端呼叫時使用(可以使用 工具-建立GUID 選單建立一個GUID):
或者通過程式獲得
MessageBox.Show(Guid.NewGuid().ToString());
為了提高程式的安全性,以便在客戶端安裝的時候在瀏覽器提高信任度,我們需要實現介面IObjectSafety
using System;using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ActivexDemo
{
[ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
[PreserveSig()]
int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
}
然後在程式碼中實現介面即可
using System;using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;//Guid引用namespace ActivexDemo
{
[Guid("0b6ed426-9e67-4cf3-99da-8a346a98e5c6")]
public partial class Uc : UserControl,IObjectSafety
{
public Uc()
{
InitializeComponent();
}
#region IObjectSafety 成員
private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
private const int S_OK = 0;
private const int E_FAIL = unchecked((int)0x80004005);
private const int E_NOINTERFACE = unchecked((int)0x80004002);
private bool _fSafeForScripting = true;
private bool _fSafeForInitializing = true;
public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
{
int Rslt = E_FAIL;
string strGUID = riid.ToString("B");
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForInitializing == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
break;
default:
Rslt = E_NOINTERFACE;
break;
}
return Rslt;
}
public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
{
int Rslt = E_FAIL;
string strGUID = riid.ToString("B");
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
Rslt = S_OK;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
Rslt = S_OK;
break;
default:
Rslt = E_NOINTERFACE;
break;
}
return Rslt;
}
#endregion
}
}
這樣ActiveX的基本設定完成了,這個時候我們就可以利用ActiveX實現自己需要的功能了,我們兩個舉個例子
一、 在頁面中放置一個文字框和一個按鈕,當點選按鈕的時候,把ActiveX中的值傳到頁面的文字框中
二、 在ActiveX的控制元件中放置一個按鈕,當觸發按鈕事件後,把ActiveX的值傳到頁面的文字框中
上面這兩個例子其實就是想實現如何實現js呼叫ActiveX和ActiveX呼叫頁面的Js的,現在我們寫一下程式碼,先看看第一種情況,在ActiveX中我們寫了一個GetStr方法,用來返回一個值,然後把這個值傳到頁面中
public string GetStr()
{
return "這是從ActiveX傳過來的值";
}
好了,現在我們需要新建一個安裝檔案
1、 新建一個安裝專案
2、 在專案上點右鍵,【新增】->【專案輸出】,選擇上邊的專案
如果有多個專案,可以選擇需要安裝的專案就可以了
點選專案,按下“F4”,設定屬性
3、 生成專案
會生成兩個檔案,一個exe檔案和一個msi檔案
然後把這兩個檔案拷到專案的lib資料夾下面
1、 新建一個頁面,新增下面的程式碼
<object classid="clsid:0b6ed426-9e67-4cf3-99da-8a346a98e5c6" codebase="lib/setup.exe"
width="200" height="40" id="helloBossma">
</object>
然後在頁面中新增javascript程式碼,按鈕和文字框
<head runat="server"><title>無標題頁</title>
<script type="text/javascript">
function passValue()
{
document.getElementById("textValue").value=document.getElementById("helloBossma").GetStr();
}
</script>
</head>
<body>
<object classid="clsid:0b6ed426-9e67-4cf3-99da-8a346a98e5c6" codebase="lib/setup.exe"
width="200" height="40" id="helloBossma">
</object>
<form id="form1" runat="server">
<div>
<input id="textValue" type="text"/>
<input id="Button1" type="button" value="傳值" onclick="passValue()"/>
</div>
</form>
</body>
</html>
這個時候我們就可以開啟瀏覽器瀏覽頁面了
執行載入提示的載入項就可以了
這個時候我們點選按鈕傳值就可以把ActiveX中的值傳過來了
接著看看如何用ActiveX呼叫Javascript
首先在ActiveX中寫一個方法用來將頁面的js函式傳過來。
頁面的js函式
window.onload=function()
{
document.getElementById("helloBossma").regJs(window,"show");
}
function show(str)
{
document.getElementById("text1").value=str;
}
ActiveX中我們需要新增引用
using mshtml;private IHTMLWindow2 temphtml = null;
private string functionstr = "";
public void RegJs(object win, string fuc)
{
temphtml = (IHTMLWindow2)win;
if (temphtml != null && !string.IsNullOrEmpty(fuc))
{
functionstr = fuc;
}
else
{
temphtml = null;
functionstr = "";
MessageBox.Show("註冊指令碼失敗!");
}
}
在控制元件中放置一個按鈕,觸發按鈕的onclick事件,在事件中將值傳給頁面的js,從而完成賦值
private void button1_Click(object sender, EventArgs e)
{
temphtml.execScript(functionstr + "('從activeX中傳值到頁面')", "JScript");
}
上面是activeX的兩個簡單應用,更多的東西可以自行研究下..