睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接
本文閱讀基礎:有一定的C++基礎知識(了解繼承、回調函數),對MFC的消息機制有一定了解,對COM的基礎知識有一定了解,對ActiveX控件有一定了解。
一. 前言
ActiveX控件和它的容器程序如何通訊是一個值得研究的問題,因為這涉及到ActiveX控件和它的容器程序如何交互的問題。VC知識庫的楊老師寫了一系列博客介紹了一些通訊方式。鏈接如下:
COM 組件設計與應用(十三)--事件和通知(VC6.0)
COM 組件設計與應用(十四)--事件和通知(vc.net)
COM 組件設計與應用(十五)--事件和通知(VC6.0)
COM 組件設計與應用(十六)--事件和通知(vc.net)
這些文章寫得真的很好,語言幽默風趣,深入淺出。我看后決心把它應用在ActiveX控件的回調實現上,經過實踐,覺得有些地方語焉不詳,自己做些摸索,寫就此文,算是對楊老師文章的一點補充。
二.通知的方法
ActiveX控件是一個窗口,它的容器程序自然也有一個父窗口;同時ActiveX控件是一個接口;ActiveX控件本質是一個COM組件,COM組件的客戶端和服務器端本身有自己的通訊方式。從這兩點我們可以想到二者之間的幾種通訊方式:

我和我的同事曾爭論ActiveX控件接口能否像一般C++的DLL那樣在導出函數參數列表里設置一個回調函數指針那樣實現回調,那時我認為是不行的。現在我看了ActiveX控件接口的參數類型,更加堅定了我的看法。其實從COM的初衷來看應該也是不行的,因為COM的初衷之一是提供一種跨語言的調用接口,而回調函數指針只對客戶端是C++程序是有意義,對于VB、C#則無回調函數指針一說的。
三.實踐檢驗
現在我們編一個這樣的小程序:在ActiveX控件上畫直線,在畫直線的同時把坐標傳給客戶端的視圖,在客戶端的視圖區上依據傳進來的坐標信息,繪制出相應的直線。
在動手之前我簡要介紹我的思路:所謂基于COM的回調虛接口實現ActiveX控件和客戶端程序的通訊,大致是這樣的,就是在ActiveX工程的內部的idl文件定義一個虛接口,在客戶端程序定義一個虛接口的派生類來實現回調函數,在客戶端程序傳遞派生類對象指針給ActiveX控件,在控件內部調用這個虛接口的函數來激發客戶端程序的派生類的對應的回調函數。這里其實有一個關鍵問題,就是定義在idl文件中回調虛接口如何被ActiveX工程和客戶端程序識別,而不至于成為未定義類型(說實話,這個問題折磨了我兩個晚上,之所以這么麻煩,大概因為這個接口是定義在idl文件,而不是C++源文件中),下面我將介紹如何解決這個問題。
首先我們創建一個MFC ActiveX Control的工程:DataX,具體如下圖:

接著在idl文件添加回調接口。這一步需要手動編輯idl文件。首先實現使用GUIDGEN.EXE(該工具在$/Microsoft Visual Studio 9.0/Common7/Tools路徑下,在VC6.0,VC 8.0都有這個工具)產生一個IID,生成時注意選擇是注冊表形式,具體如下圖:

然后在idl文件的開頭下加入以下內容:
[cpp] view plaincopy