1. 程式人生 > >使用C#開發ActiveX控制元件

使用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;

// 有關程式集的常規資訊通過下列屬性集

// 控制。更改這些屬性值可修改

// 與程式集關聯的資訊。

[assemblyAssemblyTitle("ActivexDemo")]

[assemblyAssemblyDescription

("")]

[assemblyAssemblyConfiguration("")]

[assemblyAssemblyCompany("微軟中國")]

[assemblyAssemblyProduct("ActivexDemo")]

[assemblyAssemblyCopyright("Copyright © 微軟中國 2012")]

[assemblyAssemblyTrademark("")]

[assemblyAssemblyCulture("")]

// 將 ComVisible 設定為 false 使此程式集中的型別

// 對 COM 元件不可見。如果需要從 COM 訪問此程式集中的型別,

// 則將該型別上的 ComVisible 屬性設定為 true。

[assemblyComVisible(true)]

// 如果此專案向 COM 公開,則下列 GUID 用於型別庫的 ID

[assemblyGuid("f5438267-5c1e-4c24-b2e0-c2f172e753a4")]

// 程式集的版本資訊由下面四個值組成:

//

//     主版本

//      次版本

//      內部版本號

//      修訂號

//

// 可以指定所有這些值,也可以使用“內部版本號”和“修訂號”的預設值,

// 方法是按如下所示使用“*”:

// [assembly: AssemblyVersion("1.0.*")]

[assemblyAssemblyVersion("1.0.0.0")]

[assemblyAssemblyFileVersion("1.0.0.0")]

[assemblyAllowPartiallyTrustedCallers()]

 新增一個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的兩個簡單應用,更多的東西可以自行研究下..