VC++編寫ActiveX控制項
作者:一點一滴的Beer http://beer.cnblogs.com/
前言:
暑假在做一個項目的時候,本來是用C#.NET來寫的一個港口進出閘的流程式控制製程序,裡面涉及一個響應用PLC的採集資訊的問題(PLC用串口和工控機相串連),然後思考如何用C#寫串口通訊程式,結果師兄在一旁直接用VC++寫了一個“*.ocx控制項”,並在自己的電腦上進行了測試,完工後就把產生的“*.ocx”控制項註冊檔案複製到了我們的電腦上。我們就在C#.NET程式裡面將此控制項拖入到主視窗中,然後就能直接利用此控制項的事件來捕捉PLC的命令了,感覺好神奇。然後,我對C++的態度有了極大的轉變,以前只知道C++寫視窗程序是多麼麻煩啊(遠不如C#.NET來得快和直接),而它的所謂“比較底層,和底層作業系統的關係比C#這些進階語言要密切很多”的好處一直都沒有體會到,現在才知道,正是因為C++比較底層,比較基礎,所以它可以開發出很多和語言無關的公用程式塊,如dll動態連結程式庫和COM組件,原則上,只要你的Windows的系統,用VC++開發出來的這些公用程式塊就能被任何語言調用(如果不用MFC架構,而用ATL架構來編寫,甚至還可以脫離Windwos系統,不僅僅實現跨語言,甚至跨平台叫用,這個筆者就沒有仔細研究了)。
本人大學本科所學本來是電子技術的工業自動化,結果中途做的幾次項目都是“純軟體”,這次暑假的經曆,終於讓我在“硬體”和“軟體”之前找到一個串連交匯點了。
以前做電子產品只是為了實現功能,現在發現這遠遠不夠,按照目前的時代潮流,一個系統除了要功能完備化,還要資訊化 ,資訊化就涉及到資料擷取、儲存、分析和顯示。當然如果你不是做系統的,那麼你也不必去用全域的眼光去看待這個問題,但你做了電子產品後,卻不能讓它的功能僅僅局限於在現場完成一些自動控制,而應該開發出和裝置相關的上層API,供廣大的非電子專業的上層程式員進行二次開發,在PC上層平台上對資料資訊進行更好的組織和處理。而提供的API最好是具有較好的移植性,以適應不同企業的不同語言的程式員。而COM組件技術很好地解決了這個問題。
說到跨語言的模組化程式設計,在本文之前發表的一篇《VC++的DLL應用(含Demo示範)》中講了dll的建立方法,使用者可以將一些公用函數放在dll源檔案中,然後編譯產生一個dll檔案,供程式動態載入串連並調用裡面的函數,這個也可以跨語言地進行調用。但dll有自己的局限性,就是沒有事件,而這個時候ActiveX控制項就隆重登場了,同樣能夠跨語言使用,ActiveX可以提供方法,屬性甚至是事件(當然對比dll也有缺點,它不是單獨的檔案,無法動態載入和卸載)。
因為筆者現在只是學習這個技術並作為一個技術積累,而沒有對這個技術進行原理上的深入研究,所以很多術語可能完全是錯誤的,希望高手看到後,不吝踢教和指正,也能防止本文誤認“子弟”了。本文中,作者是把ActiveX,COM,OCX當作相同的概念來對待的,可能不妥,請見識,如果想細究其具體的區別,請參考文章:
《Activex、OLE、COM、OCX、DLL之間有什麼區別?》 http://fykyx521.javaeye.com/blog/446275 |
其實不管你是否瞭解它們之前的區別,都無所謂,因為本文只是講解如何從零開始學習並應用這門技術來解決實際問題,大家只需要知道實現步驟就OK了。
好,多的話不說了,下面開始介紹ActiveX這門技術的實現方式。
本文:
ActiveX這門技術是通過產生“*.ocx”檔案來實現的。先來瞭解下OCX檔案,在百度百科上面對OCX是這樣解釋的:
“.ocx是ocx控制項的副檔名,OCX 是物件類別擴充組件。如果你用過Visual Basic或者Delphi一類的可視化編程工具,那麼對控制項這個概念一定不會陌生,就是那些工具條上的小按鈕,如EditBox,Grid,ImageBox,Timer等等。每個控制項都有自己的事件、方法和屬性。使用了控制項的編程非常容易。首先,在程式的設計階段可以設定一些屬性,如大小,位置,標題(caption)等等;在程式運行階段,可以更改這些屬性,還可以針對不同的事件,調用不同的方法來實現對該控制項的控制。控制項就好像一塊塊的積木,程式要做的事只是將這些積木搭起來。控制項的最大好處是可以重複使用,甚至可以在不同的程式設計語言之間使用,例如你可以在VB中嵌入用VC開發的控制項。”
裡面最後一句話比較重要,就是用VC開發的OCX控制項,你可以在其它語言裡面都能調用,這樣很好的實現了功能化組件的良好迴圈使用,而且還可以實現跨語言地調用(例如,你完全可以用C#調用C++開發的OCX控制項)。
下面開始介紹,如何用VC++一步步產生你想要的“*.ocx”檔案。
1. 建立最簡單的ocx檔案並進行調試
1.1 建立最簡單的ocx檔案
VC->建立項目->MFC ActiveX WinZard
一路點擊“確定”,直到點擊“完成”。最後VC++會自動產生一些檔案,這些檔案就構成了ActiveX的基本模板,檔案的主要結構如下:
直接編譯一下,然後在Debug目錄下面就會產生一個名為“ocxDemo.ocx”的控制項註冊檔案,然後利用“regsvr32”命令就可以實現本機對此控制項的註冊,然後就可以使用本語言或者跨語言編寫程式時引用此控制項來實現相應的功能(後面將會講到)。
1.2 ocx調試方法:
VC++內建有一個調試控制項的工具“ActiveX控制項測試容器”,通過三種方式可以開啟:
1.點擊“調試”按鈕,會出現如下對話方塊:
然後瀏覽"C:\Program Files\Microsoft Visual Studio\Common\Tools\TSTCON32.EXE“
2. 系統的“開始“-》“程式”-》“Microsoft Visual C++ 6.0”-》“Microsoft Visual C++ 6.0 Tools”-》“Active Control Test Container”
3. VC++開發環境中的“工具”-》“ActiveX Control Test Container”
通過上面的任意一種方法,都可以調出下面的程式:
右擊空白地區,插入控制項,然後會彈出下面的對話方塊:
選中指定控制項,然後點擊確定,控制項就被載入到此工具中了,然後可以通過這個工具來看此控制項的相關事件響應等等。
2.自VC++產生的模板基礎上自訂功能
所有的自訂功能基本上都來自於“MFC ClassWizard”類嚮導對話方塊。
(“快速鍵Ctrl+W”或者“查看”->“建立類嚮導…”)
在“Automation”選項卡中為控制項添加方法和屬性。
在“ActiveX Events”選項卡中為控制項添加事件。
2.1 添加控制項屬性
切換到“Automation”選項卡中,點擊右邊的“Add Property…”會彈出對話方塊:
External name:外部名稱。指此控制項被使用時,外部程式看到的屬性名稱,僅在外部參考時被使用。
Type:屬性類型。除了基本的整形等資料類型外,還有很多複雜的進階資料類型。
Variable name:變數名稱。此屬性在控制項源檔案中的變數名稱,在編寫控制項源碼時使用。
Notification function:提醒函數。當此屬性被改變時,會觸發此提醒函數。
Implementation:實現方式。指屬性的三種類型:固有型,成員變數型,Get/Set方法型。固有型是指系統賦予的固有屬性,如背景色,標題;成員變數型是使用者自訂的屬性;Get/Set方法型,可能是指只能通過Get/Set方法才能擷取和改變的變數吧(這個沒研究)。
2.2 添加控制項方法
在“Automation”選項卡中,點擊右邊的“Add Method…”會彈出對話方塊:
External name:方法外部名稱。
Internal name:方法內部名稱。
Return type:傳回值類型。除了基本的整形等資料類型外,還有很多複雜的進階資料類型。
Implementation:實現方式。兩種:固有方法,自訂方法。
Parameter list:參數列表。參數名稱和參數類型:參數類型包含很多進階資料類型。
2.3 添加控制項事件
切換到“ActiveX Events”選項卡中,點擊右邊的“Add Event…”會彈出對話方塊:
External name:事件外部名稱。
Internal name:事件內部名稱。比外部名稱多了個首碼“Fire”。
Implementation:實現方式。兩種:固有事件,自訂事件。固有事件一般是滑鼠移動,雙擊等等事件,這些事件都由系統訊息觸發;自訂事件則是完全由使用者定義的一個函數,但這個函數需要使用者在源檔案中調用(在內部調用,對於控制項的使用方來說,就相當於在調用的地方此事件被觸發,而內部傳入的參數,則是此事件產生的訊息附帶資訊)。
Parameter list:參數列表。參數名稱和參數類型:參數類型包含很多進階資料類型。
總述:通過“類嚮導”工具,為控制項添加屬性、方法和事件後,VC++會自動在相應的檔案裡面產生代碼,比如內部方法屬性和外部方法屬性之間的映射,訊息的建立,訊息的聲明,等等。如果使用者要對引進行深入研究,還需要對程式的結構比較熟悉,知道各部分代碼的作用,知道哪些地方的代碼是系統自動產生的,哪些代碼需要使用者手動加入的。Visual C++開發環境雖然有很多優點,但有個缺點也很明顯,就是代碼結構比較亂,感覺沒有VS2005和後面的Visual Studio系列要好。但是由於VC6.0作為一個比較經典的開發環境,而且網上的有關C++的程式設計基本上都是基於VC6.0的,所以,有必要對其進行學習,便於自己讀懂網上的代碼並進行消化吸收。
2.4 產生ocx檔案並調試
直接編譯使用者加入了自訂代碼的項目,然後在項目的Debug目錄下面會產生一個ocx檔案,這個就是此控制項的註冊檔案了。
控制項的調試工具仍然是“ActiveX Control Test Container”。
假設我們在控制項中加入了一個事件:固有事件——“MouseMove”滑鼠移動事件;使用者自訂事件——ocxClick事件(此事件是通過“WM_MOUSEMOVE”訊息來觸發的,返回的是滑鼠當前位置的x座標)。
運行“ActiveX Control Test Container”並插入當前控制項,當滑鼠在上面移動的時候,可以看到MouseMove產生了事件了。
同時可以通過“Control”-》“Invoke Method”來對控制項的方法進行測試,測試的方法就是你輸入參數,它返回計算結果(下面以自訂的方法funHello為例)。
3.控制項的使用方法
3.1 註冊控制項
ocx控制項的安裝方式有很多種,這裡介紹最簡單的一種。
步驟:
1.將需要安裝的OCX控制項檔案複製到某個目錄,例如C盤根目錄下。
2.進入開始,點擊運行。
3.在出現的框中鍵入regsvr32 C:/xxxx.ocx 。(XXXX為控制項名, C:/為目錄)
4.點擊確認後等待出現提醒註冊成功即可。
3.2 ActiveX控制項的調用
ActiveX作為一種通用的COM組件,可以被不同語言調用的。
3.2.1 通過VC++調用
利用VC6.0建立一個MFC的基本對話方塊應用程式
在完成程式嚮導後。執行下面的步驟:
1. 執行“工程”-》“添加到工程”--》“Components and Controls…”。
2. 在彈出的檔案瀏覽對話方塊中,找到Registered ActiveX Controls檔案目錄下的你剛才註冊的控制項,比如“OcxDemo Control”,然後點擊“Insert”按鈕即可將此控制項添加到控制項工具條集合中。
3. 將控制項工具條上新增加的OCX控制項拖入到應用程式主視窗中。
完成上面的步驟後,就可以像使用普通控制項一樣在VC中使用此控制項了(右擊此控制項,可以查看此控制項的“事件”和“屬性”,就是你在編寫控制項源碼時的那些“外部名稱External name”)。
3.2.2 通過C#調用
其實這個才是重點,因為跨語言調用ActiveX技術最被筆者看好的地方。
用Visual Studio 2005建立一個C#.NET的Windows視窗程序,然後在工具箱面板上,右擊“選擇項”,選擇COM組件,找到你註冊的ActiveX控制項:
確定後,那個OcxDemo Control控制項就載入到工具箱裡面了。可以直接拖動這個控制項到C#.NET應用程式的主視窗上去了,然後就像使用普通控制項那樣使用此控制項了。
比如,本文中的ActiveX控制項的自訂事件中,是通過滑鼠移動來觸發,那麼在應用程式中,只要滑鼠移動到控制項上,那麼就會觸發此自訂事件,並擷取當前滑鼠位置的橫座標。
4. 最後一些Tip
1) 在自訂控制項時,可在控制項源碼的OnDraw()函數中設定控制項的外觀(也就是控制項被拖入到應用程式中時呈現的樣子,一般預設是一個白色的方框內切橢圓的樣式)。
2) 用C#來使用ActiveX的事件時,事件所產生的資料都包含在Event變數中,只需要用個點運算子就可以取出來了。
5.展望
控制項函數的傳回值類型那麼多,那麼複雜,如果要用得好,還需要對那些OLE資料類型進行好好學習,這個等今後需要時再慢慢學習吧。
------------------------------------------------------------------
Author:一點一滴的Beer
Email /Gtalk:dreamzsm@gmail.com
From:http://www.cnblogs.com/beer
Notes:歡迎轉貼,但請在頁面中加個連結註明出處
Time:2010-8-21
作者:一點一滴的Beer
Email /Gtalk:dreamzsm@gmail.com
出處:http://www.cnblogs.com/beer/
本文著作權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,請尊重作者的勞動成果。