ActiveX 控件是基於組件對象模型 (COM) 的可重用軟件組件,廣泛應用於桌面及Web應用中。在VC下ActiveX控件的開發可以分為三種,一種是直接用COM的API來開發,這樣做顯然非常的麻煩,對程序員要求也非常高,因此一般是不予考慮的;一種是基於傳統的MFC,采用面向對象的方式將COM的基本功能封裝在若干MFC的C++類中,開發者通過繼承這些類得到COM支持功能。MFC為廣大VC程序員所熟悉,易於上手學習,但缺點是MFC封裝的東西比較多,因此用MFC開發出來的控件相對會比較大,因此比較適於開發桌面ActivexX控件,尤其是有GUI界面的控件。第三種就是基於ATL的,ATL可以說是專門面向COM開發的一套框架,使用了C++的模板技術,在運行時不需要依賴於類似MFC程序所需要的龐大的代碼模塊,更適合於Web應用開發。
本文介紹的是采用第二種方式,即應用MFC進行桌面可視控件開發的方法步驟,開發環境則是基於VC2005。
1.創建控件項目
打開VC2005后,我們要先創建一個項目,在新建項目頁的左側選擇Visual C++-MFC,在右側選擇MFC ActiveX控件,填上解決方案和項目名稱,比如在這里我的項目名稱是activexdemo1,解決方案名稱是activexdemo。
然后進入控件向導頁,在向導的第二頁有個運行時許可證,選中這個的話會在生成控件的同時生成一個許可證文件,其他用戶在使用這個控件的時候必須同時附有這個許可證,在此我們保持默認狀態,不選。
下一頁是關於項目中各部分的命名問題,可以根據需要自定義,這里就按默認的情況不做修改了。
下一頁是選擇控件基於哪種控件的擴展以及控件的一些基本特性。如果新建的控件是基於某種特定控件的話,就在創建的控件基於下選擇所要繼承的控件名,否則就保持none。下方的附加功能根據實際需要進行選擇,並且可以將鼠標放置於選項上方,功能的說明會自動顯示在動態出現的小提示信息窗口中。選擇完畢點擊完成,向導就根據你的選擇生成新項目。
進入開發環境,我們可以先看一下類視圖。
其中的Cactivexdemo1App是我們這個控件的主程序模塊,定義了控件的注冊(DllRegisterServer)、刪除(DllUnregisterServer)等功能,一般不用動,如有需要我們可以在其中的InitInstance和ExitInstance中定義我們自己的初始化和終止操作代碼,一般也就是一些資源的初始化和銷毀工作。
Caxtivexdemo1Ctrl是控件類,我們要做的控件功能基本上就是要在這個類中實現。
需要提一下的是在這個類中重寫了父類的OnDraw函數,有如下兩句代碼:
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
也就是在控件上畫了一個橢圓,實際控件開發中可以根據功能需要修改重寫這個函數來繪制控件界面。
Caxtivexdemo1PropPage是屬性頁類,這個類實現了一個在開發時設定控件屬性的對話框。
activexdemo1Lib是為客戶程序提供本控件的屬性、方法以及可能響應的事件的接口的庫節點,在添加控件的這些功能的時候會用得到。
其中的Cactivexdemo1App是我們這個控件的主程序模塊,定義了控件的注冊(DllRegisterServer)、刪除(DllUnregisterServer)等功能,一般不用動,如有需要我們可以在其中的InitInstance和ExitInstance中定義我們自己的初始化和終止操作代碼,一般也就是一些資源的初始化和銷毀工作。
Caxtivexdemo1Ctrl是控件類,我們要做的控件功能基本上就是要在這個類中實現。
需要提一下的是在這個類中重寫了父類的OnDraw函數,有如下兩句代碼:
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
也就是在控件上畫了一個橢圓,實際控件開發中可以根據功能需要修改重寫這個函數來繪制控件界面。
Caxtivexdemo1PropPage是屬性頁類,這個類實現了一個在開發時設定控件屬性的對話框。
activexdemo1Lib是為客戶程序提供本控件的屬性、方法以及可能響應的事件的接口的庫節點,在添加控件的這些功能的時候會用得到。
設置項目屬性 將配置類型設置成靜態庫(.lib)
2.生成並測試控件
好,現在我們就可以先來生成一下這個項目,當然到目前我們只是用系統自動生成的一個控件項目,什么功能都沒有,只是一個空框架。
幾秒鍾后,項目應該是順利生成。控件也被自動注冊到系統中去。那怎么才能測試一下這個控件呢?當然你可以再建個新項目,比如一個對話框程序,在對話框資源編輯窗口中右邊的工具箱里鼠標右鍵菜單里點選擇項。
從彈出窗口中的COM組件下找到我們剛剛生成的這個控件,打勾選中。
然后在工具箱里就會出現這個控件。
然后用鼠標拖到對話框里就能用這個控件了。
除了這種方法,VS還提供了一種簡便的控件測試工具。在VisualStudio中菜單的工具下有個ActiveX控件測試容器。
在工具欄里點新控件按鈕。
在插入控件對話框中找到並選擇我們的這個控件。
然后就能在這個容器中測試控件的各種功能了。
3.事件
ActiveX 控件使用事件通知容器控件上發生了某些事情。事件的常見示例包括單擊控件、使用鍵盤輸入數據和控件狀態更改。當發生這些操作時,控件將引發事件以提醒容器。
MFC 支持兩種事件:常用和自定義。常用事件是 COleControl 類自動處理的事件。自定義事件使控件得以在該控件特定的操作發生時通知容器。控件內部狀態發生更改或收到某個窗口消息即屬於此類事件。
常用事件
常用事件由 COleControl 類自動引發。COleControl 包含預定義成員函數,它們引發常見操作所導致的事件。一些由 COleControl 實現的常見操作包括單擊和雙擊控件、鍵盤事件和鼠標按鈕狀態發生更改。
添加常用事件的操作是在類視圖中右擊ActiveX 控件類,比如在此例中就是Caxtivexdemo1Ctrl。在菜單中選擇添加事件,打開添加事件向導。
在添加事件向導中的事件名稱中選擇Click,也就是鼠標點擊事件,添加到控件中。然后再選中類視圖中庫節點下的第三個節點,也就是Dactivexdemo1Events。在下面就能看到我們剛剛添加的這個事件。
然后生成新的控件程序,我們來看看測試一下這個新事件。
打開上面提到的ActiveX控件測試容器,把這個控件添加進來,用鼠標點擊控件,就會在程序下方的消息欄中看到activexdemo1 Control: Click這樣的消息,這就是我們添加進去的鼠標相應事件。
那在開發環境中使用控件的時候是什么樣子的呢?好,像上面提到過的那樣新建一個對話框項目,把控件放到對話框上。選中這個控件,在屬性窗口中的控件事件中就有這個Click事件了,如果在使用控件中需要相應鼠標點擊事件,就點添加ClickActivexdemo1ctrl1,事件響應函數中添加你需要的功能了。
比如像這樣:
void CtestMFCDlg::ClickActivexdemo1ctrl1()
{
// TODO: 在此處添加消息處理程序代碼
MessageBox(_T(“Hi.”));
}
編譯運行這個測試程序,點擊控件位置就會彈出帶有Hi.字樣的MessageBox。
自定義事件
自定義事件與常用事件的區別在於,自定義事件不由 COleControl 類自動引發。自定義事件將控件開發人員確定的某一操作識別為事件。
添加常用事件的操作是在類視圖中右擊ActiveX 控件類,比如在此例中就是Caxtivexdemo1Ctrl。在菜單中選擇添加事件,打開添加事件向導。定義一個叫做MyEvent的事件,事件可以帶參數,比如我們加個BSTR的參數msg。
然后,回到類視圖,這次選中庫節點下的第三個節點,也就是_Dactivexdemo1Events,在下面就會看到新添加的這個事件。
再選中類視圖中的控件類,即Cactivexdemo1Ctrl,下面也會出現一個MyEvent函數。
雙擊這個MyEvent可以看到定義代碼如下:
void MyEvent(BSTR msg)
{
FireEvent(eventidMyEvent, EVENT_PARAM(VTS_PI1), msg);
}
這里的這個MyEvent(BSTR msg)函數就是用於觸發MyEvent事件用的,什么意思呢,就是說當在控件中需要出發自定義的這個MyEvent的時候調用這個MyEvent(BSTR msg)就可以了。下面結合例子看看是怎么回事。
比如說我們希望用戶鼠標雙擊左鍵的時候觸發這個事件,就這么來作。選中類視圖中的控件類,即Cactivexdemo1Ctrl,然后在消息窗口中找到WM_LBUTTONDBCLK,添加這個消息的處理函數。
在消息處理函數中如下修改:
void Cactivexdemo1Ctrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
MyEvent(_T(“HI, MyEvent.”));
COleControl::OnLButtonDblClk(nFlags, point);
}
這樣每次用戶在雙擊控件的時候就會觸發我們自定義的MyEvent事件了。
然后看一下測試效果。
打開ActiveX控件測試容器,添加這個控件,然后雙擊控件,看消息框里出現什么了?
由於雙擊自然也就是兩次單擊,所以會同時出現兩種事件。
activexdemo1 Control: MyEvent {msg=72}
activexdemo1 Control: Click
打開測試項目,控件的控件事件里就多了一個MyEvent事件。
添加一個針對此事件的處理函數MyEventActivexdemo1ctrl1 (LPCTSTR msg),msg就是我們定義事件時的那個msg參數,在上面的定義中我們是傳遞了一個”HI, MyEvent.”字符串消息。現在看看是不是這個樣子。在MyEventActivexdemo1ctrl1函數中我們顯示一個MessageBox,把msg參數打印出來。
void CtestMFCDlg::MyEventActivexdemo1ctrl1(LPCTSTR msg)
{
// TODO: 在此處添加消息處理程序代碼
MessageBox(msg);
}
同時注意要把上面常用事件中定義的Click事件的處理函數ClickActivexdemo1ctrl1注釋掉,然后編譯運行程序后雙擊控件就會彈出HI, MyEvent.對話框。也就是說,由於雙擊操作觸發了我們定義的MyEvent事件,進而調用MyEvent的處理函數。
4.方法
方法就是控件開放給用戶使用的一些功能函數,類似於C++的類函數。控件方法分兩類,一類是常用方法,其實現由父類COleControl 提供。自定義方法由開發人員定義,由此向用戶提供自定義的功能實現。
常用方法
COleControl 支持兩個常用方法:DoClick 和 Refresh。Refresh 由控件的用戶調用,用以立即更新控件的外觀;而調用 DoClick 是用於引發控件的 Click 事件。
添加常用方法的操作是在類視圖中打開庫節點,在本例中就是activexdemo1Lib節點。選中第二個節點,也就是本例中的_Dactivexdemo1,在右鍵菜單中選擇添加方法,打開添加方法向導。
在方法名中選擇需要添加的常用方法。比如DoClick。
然后在類視圖中選中_Dactivexdemo1,就會在下面看到我們剛才添加的那個常用方法。同時,你也可以在這里看到有一個AboutBox方法,這是系統自動給我們添加進去的,功能是顯示一個About窗口,這個窗口可以在項目的資源視圖中的Dialog下找到並編輯。
同樣也要驗證一下這個新添加的方法。還是打開ActiveX控件測試容器,添加此控件,然后點擊工具欄上的這個紅色方框,也就是調用方法。
在調用方法對窗口的方法名中選中我們剛添加的這個DoClick方法,然后點擊調用。還記得這個DoClick是干什么的來着嗎?,對了,它是要引發Click事件的,上面介紹事件的時候我們已經添加了Click這個常用事件了,那么現在調用DoClick也就是要引發我們在上面添加的這個 Click事件了,於是在測試容器主窗口的消息框中出現了activexdemo1 Control: Click。
那么在開發環境中是什么效果呢?
好,再回到剛才那個測試項目里。我們先在窗體上添加一個按鈕,就叫DoClick,等會用點擊它的方式來調用DoClick方法。
然后為了方便操作,我們先給剛才添加到對話框中的那個控件添加一個綁定的對象變量。鼠標右擊控件選擇添加變量。
在添加成員變量向導中添加與此控件綁定的控件變量,比如叫做m_activexdemo。
然后,雙擊剛才新加到窗體上的那個按鈕,即添加這個按鈕的鼠標點擊事件函數中,如下添加一行代碼,即調用控件的DoClick方法。
void CtestMFCDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知處理程序代碼
m_activexdemo.DoClick();
}
最后,編譯運行測試程序,點擊DoClick按鈕,結果彈出Hi.對話框。這就是說,我們通過執行控件對象的DoClick方法引發了控件的鼠標點擊事件,因此上文常用事件一節中我們添加的事件處理函數ClickActivexdemo1ctrl1被執行了。
自定義方法
自定義方法與常用方法的區別在於,自定義方法未由 COleControl 實現。必須為添加到控件的每個自定義方法提供實現。
添加自定義方法的操作是在類視圖中打開庫節點,在本例中就是activexdemo1Lib節點。選中第二個節點,也就是本例中的_Dactivexdemo1,在右鍵菜單中選擇添加方法,打開添加方法向導。
在添加方法向導里添加需要自定義的方法的名稱、返回值和參數。
注意這里有個內部名稱,默認情況是與上面的方法名一樣,但是也可以修改為其他名,這個內部名稱是方法在控件類內的函數名稱,比如這里我們的方法名為MyThod,則選中類視圖中的庫接口下的第二個節點,下面會出現剛定義的MyMethod方法。
而選中控件類Cactivexdemo1Ctrl,下面會看到在這個類中定義的方法名稱就是我們上面指定內部名稱MyMethodInner。
而方法的具體功能也就是在這個內部函數中實現。比如我們如下定義MyMethodInner:
void Cactivexdemo1Ctrl::MyMethodInner(LPCTSTR msg)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加調度處理程序代碼
MessageBox(msg);
}
也就是說要彈出一個消息對話框,消息內容就是參數中傳遞的字符串。
然后來測試一下效果,首先還是ActiveX控件測試容器,打開調用方法窗口,在方法名中會看到我們定一個MyMethod,選擇之,然悔會在參數區看到我們定義的msg參數,選中,然后在下面參數值中填入你想傳遞給參數的值,比如hello,然后點擊設置值,最后點擊調用,MyMethodInner就會被執行,也就是彈出hello消息窗口。
然后再看一下使用控件開發的時候的效果。
回到測試項目,還記得那個DoClick按鈕吧,還是用這個,不過有點小問題,因為上面我們為這個控件綁定控件變量的時候還沒有這個自定義方法,所以在綁定的時候生成的控件類定義中沒有這個方法,就無法測試了。為了省事,我們就干脆新建一個項目,像前文提到的那樣添加控件,綁定控件變量,在 DoClick的單擊事件中寫入如下代碼:
void Ct1Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知處理程序代碼
m_activexdemo.MyMethod(_T(“This is mymethod.”));
}
編譯執行,點擊DoClick按鈕,就會看到那個This is mymethod消息框了。
5.屬性
屬性是 ActiveX 控件中向所有容器公開的數據成員。與事件和方法類似,也分為常用屬性和自定義屬性。
常用屬性
常用屬性已由 COleControl 類實現。COleControl 類包含支持控件的通用屬性的預定義成員函數。某些通用屬性包括控件的標題以及前景色和背景色。
添加常用屬性的操作是在類視圖中打開庫節點,在本例中就是activexdemo1Lib節點。選中第二個節點,也就是本例中的 _Dactivexdemo1,在右鍵菜單中選擇添加屬性,打開添加屬性向導。選中實現類型下的常用,在屬性名下選擇要添加的屬性,比如在此我們選擇的是 Caption。
然后在類視圖中就能看到新添加的這個屬性。
這個Caption也就是我們在使用控件進行開發的時候,控件屬性窗口中的那個Caption屬性。
在開發環境中我們可以用控件變量的GetCaption和SetCaption來獲取和設定控件的這個屬性。
比如在測試項目中的DoClick按鈕的點擊事件函數中如下修改:
void Ct1Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知處理程序代碼
MessageBox(m_activexdemo.GetCaption());
m_activexdemo.SetCaption(_T(“change”));
MessageBox(m_activexdemo.GetCaption());
}
這樣在點擊DoClick按鈕的時候會顯示控件的Caption名稱對話框,然后修改名稱,再把修改后的名稱顯示在彈出的對話框中。
如果是在ActiveX控件測試容器中的話,我們還是打開調用方法窗口,在方法名中會看到Caption(ProPut)和 Caption(ProGet)的方法,也就是對應上面的SetCaption 和GetCaption,同樣在這里也可以試着給Caption修改內容並獲取修改后的值。
自定義屬性
自定義屬性與常用屬性的區別在於,自定義屬性未由 COleControl 類實現。自定義屬性用於將 ActiveX 控件的某個狀態或外觀向使用該控件的程序員公開。
添加自定義屬性的操作是在類視圖中打開庫節點,在本例中就是activexdemo1Lib節點。選中第二個節點,也就是本例中的_Dactivexdemo1,在右鍵菜單中選擇添加屬性,打開添加屬性向導。這里自定義屬性有成員變量和Get/Set方法兩種。
成員變量屬性
我們先看一下成員變量這種屬性。根據需要選擇屬性的類型,並填入屬性名,同時變量名和通知函數會被自動填入,如不滿意默認的名稱也可以手動修改這兩個名稱。
其中這個變量名是作為控件類的一個成員變量來存儲控件屬性的,比如選中類視圖中的的控件類,也就是Cactivexdemo1Ctrl,就會在下面看到這個m_MyProp1成員變量。
這種自定義屬性的使用與常用屬性類似,在ActiveX控件測試容器中也是有着MyProp1(ProPut)和MyProp1 (ProGet)這樣的方法以供測試時調用,在開發時也會有屬性出現在控件的屬性窗口中,在程序中也是可以通過GetMyProp1和 SetMyProp1來獲取和設置屬性值。
而通知函數是當這個屬性被修改是所觸發的一個函數。被定義為控件類中的一個成員函數。
舉個例子,假如我們在這個函數中寫入如下代碼:
void Cactivexdemo1Ctrl::OnMyProp1Changed(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加屬性處理程序代碼
MessageBox(_T(“MyProp1 Changed.”));
SetModifiedFlag();
}
然后在ActiveX控件測試容器中調用MyProp1(PropPut)來修改這個屬性值,則會彈出這個對話框。同樣的,在開發時如果在屬性窗口中修改此屬性值或在代碼里修改此屬性值都會觸發這個通知函數,進而彈出我們代碼中的對話框。
Get/Set方法型屬性
添加Get/Set方法型屬性則是在添加屬性向導窗口中的實現類型中選中Get/Set方法,指定屬性類型和屬性名,向導會自動填入Get和Set函數,同時可以指定自定義的參數。
然后在控件類的定義中就會出現GetMyProp2(void)和SetMyProp2(LPCTSTR newVal)兩個函數,分別用於獲取和設置屬性值。但要注意的是,如果看一下這兩個函數的代碼的話,這兩個自動生成的函數實際上並沒有真正起到獲取和設置屬性值的功能,這只是兩個框架,基本上什么也沒做,如果放在ActiveX控件測試容器中調用這兩個函數的話會看不到什么反應,於是就還需要我們來手動定義函數的具體功能。
比如說我們可以為控件類添加一個成員變量用來存儲我們的屬性值,由於我們這個屬性定義的是BSTR類型,我們可以把添加的這個成員變量聲明為 CString m_MyProp2,然后分別修改GetMyProp2(void)和SetMyProp2(LPCTSTR newVal)為如下:
BSTR Cactivexdemo1Ctrl::GetMyProp2(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString strResult(m_MyProp2);
// TODO: 在此添加調度處理程序代碼
return strResult.AllocSysString();
}
void Cactivexdemo1Ctrl::SetMyProp2(LPCTSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加屬性處理程序代碼
m_MyProp2=newVal;
SetModifiedFlag();
}
然后在ActiveX控件測試容器中先調用SetMyProp2給屬性賦值,然后用GetMyProp2就能返回剛才新賦的屬性值了。
另外要注意的是,剛才定義這個屬性的時候,參數列表是留空的,默認得到的就是上面SetMyProp2和GetMyProp2兩個函數,如果在參數列表里添加了其他參數的話,那么新加的參數就會被添加到這兩個函數的參數列表中去。比如我們添加個BSTR型屬性MyProp3,在參數列表里加上一個 LONG arg參數,那么得到的兩個函數將是GetMyProp3(LONG arg)和SetMyProp3(LONG arg, BSTR newVal)。
6.屬性頁
屬性頁使 ActiveX 控件用戶得以查看和更改 ActiveX 控件屬性。可通過調用控件屬性對話框訪問這些屬性。該對話框包含一個或多個屬性頁,這些屬性頁提供自定義的圖形界面用於查看和編輯控件屬性。
使用默認屬性頁
創建ActiveX控件項目后,系統就自動為我們添加了一個屬性頁類,這里就是Cactivexdemo1PropPage。同時在對話框資源里也會有一個屬性頁對話框資源,這里就是IDD_PROPPAGE_ACTIVEXDEMO1。
在ActiveX控件測試容器中點擊工具欄上的屬性按鈕,就會看到這個屬性頁對話框。
比如就像下圖這樣。當然這個上面什么還沒有。
如果是在使用控件開發時,則在選中控件后,在屬性窗口中點擊屬性頁按鈕可以打開這個屬性頁,開發人員可以在這個彈出的屬性頁窗口中設定控件的屬性。
如果要通過屬性頁修改控件屬性,那么就要通過在屬性頁上放置一些控件給用戶來修改屬性值。比如我們上面添加了一個Caption屬性,我們要在屬性頁上提供修改這個屬性的功能一般就是要用一個文本輸入框。這樣我們在屬性頁的對話框上放置一個Edit控件,設id為IDC_EDIT_CAPTION。然后為這個Edit控件綁定一個變量。用右鍵點這個Edit控件,學則添加變量,打開
在添加成員變量向導中添加一個新變量,設為m_caption,這里注意要把類型設為Value,由於屬性是個字符串,所以這個地方變量類型也使用CString。
然后我們來看一下屬性頁類中的一個DoDataExchange函數。這個函數是由系統自動調用的,用來將控件與成員變量進行數據交換。由於我們剛把Edit控件綁定了m_caption變量,在DoDataExchange已經給我們寫入了這么一句DDX_Text(pDX, IDC_EDIT_CAPTION, m_caption);,就是這一句實現了m_caption與Edit控件之間的數據交換。但此時控件Caption屬性還不能自動從Edit控件中填寫的值獲得,還需要一個操作,即DDP_Text(pDX, IDC_EDIT_CAPTION, m_caption, _T(“Caption”));,這樣就把Caption屬性與與屬性頁中的m_caption變量綁定,這樣每當我們在修改了屬性頁窗口中的Edit控件內容后,就能修改控件的Caption。
那么完整的DoDataExchange函數就應該像下面這樣。
void Cactivexdemo1PropPage::DoDataExchange(CDataExchange* pDX)
{
DDX_Text(pDX, IDC_EDIT_CAPTION, m_caption);
DDP_Text(pDX, IDC_EDIT_CAPTION, m_caption, _T(“Caption”));
DDP_PostProcessing(pDX);
}
另外注意這個地方DDP_PostProcessing是系統自動生成的代碼,這句話一定要放在DDX_Text和DDP_Text的后面,否則不能實現控件屬性與屬性頁上控件的綁定。至此,我們就可以在設計時通過這個屬性頁來修改Caption屬性,而不必通過程序代碼來修改了。
添加其他自定義屬性頁
默認情況下只有一個屬性頁,如果需要設置的屬性太多就需要另外添加自定義屬性頁。
新添加屬性頁的方法是這樣的,打開VS的資源視圖,添加一個新的Dialog資源。
在這里我們選擇IDD_OLE_PROPPAGE_SMALL,當然也可以選和Large。給這個新資源ID指定為IDD_OLE_PROPPAGE_SMALL。
然后需要給這個資源新建一個關聯類。這個關聯類應當是MFC類,設類名為CPropPage1,基類應當是COlePropertyPage,對話框ID選擇我們新添加的這個對話框資源ID。
然后,打開控件類Cactivexdemo1Ctrl的cpp文件,找到屬性頁的宏聲明部分。
BEGIN_PROPPAGEIDS(Cactivexdemo1Ctrl, 1)
PROPPAGEID(Cactivexdemo1PropPage::guid)
END_PROPPAGEIDS(Cactivexdemo1Ctrl)
把我們新建的這個屬性頁添加進去,並將屬性頁計數加一。
// TODO: 按需要添加更多屬性頁。請記住增加計數!
BEGIN_PROPPAGEIDS(Cactivexdemo1Ctrl, 2)
PROPPAGEID(Cactivexdemo1PropPage::guid)
PROPPAGEID(CPropPage1::guid)
END_PROPPAGEIDS(Cactivexdemo1Ctrl)
這樣就把新添加的這個屬性頁附加到控件中去了,再打開控件的屬性頁就會看到多了一個屬性頁了。
常用屬性頁
除了可以根據需要自定義屬性頁外,系統還提供給開發人員一些預制的常用屬性頁,如顏色、字體等屬性頁。MFC 提供了三個與 ActiveX 控件一起使用的常用屬性頁:CLSID_CColorPropPage、CLSID_CFontPropPage 和 CLSID_CPicturePropPage。這些頁分別顯示常用顏色、字體和圖片屬性的用戶界面。
要將這些屬性頁合並到控件中,只需要請將它們的 ID 添加到初始化控件的屬性頁 ID 數組的代碼。也就是在類控件Cactivexdemo1Ctrl的cpp文件中的PROPPAGEIDS聲明處修改成如下形式。與自定義屬性頁中相同,也需要增加屬性頁計數。
// TODO: 按需要添加更多屬性頁。請記住增加計數!
BEGIN_PROPPAGEIDS(Cactivexdemo1Ctrl, 3)
PROPPAGEID(Cactivexdemo1PropPage::guid)
PROPPAGEID(CPropPage1::guid)
PROPPAGEID( CLSID_CColorPropPage )
END_PROPPAGEIDS(Cactivexdemo1Ctrl)
這樣就在屬性頁里添加了一個顏色屬性頁,但要想使用這個屬性頁還需要添加幾個常用屬性,比如說我們希望能通過這個屬性頁設定BackColor和 ForeColor屬性,就參照常用屬性一節中的方法添加一個BackColor和一個ForeColor屬性,編譯生成控件后在ActiveX控件測試容器中點擊工具欄中的屬性。
在彈出的屬性窗口中就能看到有關這兩個屬性的設定了。
若要使用顏色屬性,則需要調用COleControl::TranslateColor成員函數。此函數的參數為顏色屬性值和可選的調色板句柄。返回值為 COLORREF 值,可以將它傳遞給 GDI 函數,如 SetTextColor 和 CreateSolidBrush。下例說明如何在繪制控件時使用這兩個顏色屬性。
CBrush bkBrush(TranslateColor(GetBackColor()));
COLORREF clrFore = TranslateColor(GetForeColor());
pdc->FillRect( rcBounds, &bkbrush );
pdc->SetTextColor( clrFore );
pdc->DrawText( InternalGetText(), -1, rcBounds, DT_SINGLELINE | DT_CENTER | DT_VCENTER );