在上一篇隨筆:ActiveX(一)第一個簡單的Demo 中,已經能夠實現 js 單向調用 ActiveX 中的方法,在不少狀況下ActiveX中的方法的執行時相對耗時、耗性能的。在這樣的狀況下、ActiveX的方法執行會使用異步策略,那麼方法異步時,js又如何獲取異步執行結果呢?方案無非兩種,一種是輪訓、一種是Notify。html
若是是Notify,Js如何監聽其事件呢? 這將是本篇隨筆接下來的重點: 異步
繼續上一個Demo,假設,技術需求以下:當按回車時、ActiveX將密碼框中的密碼主動推給Js (使用Notify機制)。函數
在常規開發中,ActiveX的代碼以下便可:post
[Guid("30A3C1B8-9A9A-417A-9E87-80D0EE827658")] public partial class PasswordControl : UserControl { public delegate void NotifyHandler(string pwd); /// <summary> /// 在js中監聽該事件 /// </summary> public event NotifyHandler OnNotify; public PasswordControl() { InitializeComponent(); } public string GetPwd() { return this.txtPwd.Text; } private void txtPwd_KeyPress(object sender, KeyPressEventArgs e) { if ((Keys)e.KeyChar == Keys.Enter) { // 回車 觸發事件 if (this.OnNotify != null) { this.OnNotify(this.txtPwd.Text); } } } }
咱們只須要在 Js 中監聽相應的事件、便可完成技術需求。性能
可是、通過嘗試,都沒法監聽到ActiveX中的事件,因而 Google了一下、 找到了解決方案。測試
1)添加一個新接口,ui
2)爲新接口添加一個新的GUID,(不能和 PasswordControl 的GUID 相同)this
3)添加屬性: [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]url
4)添加 和 須要監聽的事件 相同簽名的方法。spa
即,造成以下所示的代碼:
[Guid("FDA0A081-3D3B-4EAB-AE01-6A40FDDA9A60")] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface IComEvents { [DispId(0x00000001)] void OnNotify(string pwd); }
5) 爲PasswordControl 添加屬性: [ComSourceInterfaces(typeof(IComEvents))]
即、以下所示:
[ComSourceInterfaces(typeof(IComEvents))] [Guid("30A3C1B8-9A9A-417A-9E87-80D0EE827658")] public partial class PasswordControl : UserControl { //... 其餘代碼 }
6)Js端用以下的方式監聽事件:
<script language="Javascript" event="OnNotify(pwd)" for="activieX"> function activieX::OnNotify(pwd) { console.info("密碼:" + pwd); } </script>
event:指定監聽的事件
for:指定監聽對象
js函數名稱使用 :[監聽對象]::[監聽事件]的形式,注意、中間是兩個冒號。
這樣,Js就能夠在密碼框敲回車的時候、接收到ActiveX推送的密碼了。 是否是很簡單呢?
有兩點須要注意:
一、事件所對應的delegate需自定義、不要使用系統的Action<T>
二、js函數名稱使用 :[監聽對象]::[監聽事件]的形式,中間是兩個冒號。
測試項目源碼:TestActiveX.zip
(未完待續...)