孫鑫:第十八講 ActiveX 控件

 

容器和服務器程序
容器應用程序時可以嵌入或鏈接對象的應用程序。Word就是容器應用程序。
服務器應用程序是創建對象並且當對象被雙擊時,可以被啓動的應用程序。Excel就是服務器應用程序。
ActiveX控件不能獨立運行,它必須被嵌入容器應用程序中,和容器應用程序一起運行。

Dispatch maps調度映射,主要是MFC提供讓外部應用程序可以訪問控件的屬性和方法
Event maps事件映射,控件向包含它的容器發送事件通知

接口是外部程序和控件進行通信的協議,可以把接口看作是函數的集合,外部程序通過藉口提供的方法,去訪問控件的屬性和方法。接口中所定義的所有函數都是純虛函數

regsvr32 ...註冊控件  regsvr32 /u....卸載控件

STDAPI DllRegisterServer(void)將控件信息寫入註冊表中
STDAPI DllUnregisterServer(void)卸載註冊信息。

製作一個時間控件,在
void CClockCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,
 const CRect& rcInvalid)中添加以下代碼:
 CBrush brush(TranslateColor(GetBackColor()));
 pdc->FillRect(rcBounds,&brush);
 pdc->SetBkMode(TRANSPARENT);
 pdc->SetTextColor(TranslateColor(GetForeColor()));
 //爲控件設置屬性,必須在MFC ClassWizared中爲控件添加屬性,上面幾 //行代碼纔有用

 CTime time=CTime::GetCurrentTime();
 CString str=time.Format("%H : %M : %S");
 pdc->TextOut(0,0,str);
這樣就能做出一個靜態的時間控件,如果我們想使控件實時顯示時間,需要添加兩個消息響應函數  WM_CREATE,WM_TIMER.
代碼:
int CClockCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (COleControl::OnCreate(lpCreateStruct) == -1)
  return -1;

 // TODO:  在此添加您專用的創建代碼

 SetTimer(1,1000,NULL); 
 return 0;
}

void CClockCtrl::OnTimer(UINT nIDEvent)
{
 // TODO: 在此添加消息處理程序代碼和/或調用默認值
 Invalidate();    //立即引起窗口重繪
   //也可以使用InvalidateControl();  //強制窗口重繪,效果相同
 COleControl::OnTimer(nIDEvent);
}
要修改控件的背景色前景色和字體顏色
在OnDraw中添加
 CBrush brush(TranslateColor(GetBackColor()));
 pdc->FillRect(rcBounds,&brush);
 pdc->SetBkMode(TRANSPARENT);
 pdc->SetTextColor(TranslateColor(GetForeColor()));

ActiveX控件的四種屬性
Stock:爲每個控件提供的標準屬性,如字體或顏色。
Ambient:圍繞控件的環境屬性——已被置入容器的屬性。這些屬性不能被修改,但控件可以使用它們調整自己的屬性。
Extended:這些是由容器處理的屬性,一般包括大小和在屏幕上的位置。
Custom:由控件開發者添加的屬性。

使控件具有多於一個屬性頁
首先在**ctl.cpp中找到Property Pages,代碼如下:
BEGIN_PROPPAGEIDS(CClockCtrl, 2)
 PROPPAGEID(CClockPropPage::guid)
 PROPPAGEID(CLSID_CColorPropPage)
END_PROPPAGEIDS(CClockCtrl)
需要注意的是要顯示幾個屬性頁BEGIN_PROPPAGEIDS(CClockCtrl, 2)中的代碼爲幾,如果沒有修改或修改錯誤,會產生不可預料錯誤。

要增加標準屬性,在_DClock上點擊右鍵,選擇增加屬性,選中Stock,例如選擇背景色和前景色
接下來會在Clock.odl下生成以下代碼:
 dispinterface _DClock
 {
  properties:
  [id(DISPID_BACKCOLOR), helpstring("屬性 BackColor")] OLE_COLOR BackColor;
  [id(DISPID_FORECOLOR), helpstring("屬性 ForeColor")] OLE_COLOR ForeColor;
methods:
   [id(DISPID_ABOUTBOX)] void AboutBox();
 };

接下來新增自定義屬性,方法同上,只是需選中“成員變量”或“get/put”
會自動生成成員變量:m_Interval,和成員函數OnIntervalChanged。
接下來添加代碼:
void CClockCtrl::OnIntervalChanged(void)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState());

 // TODO: 在此添加屬性處理程序代碼
 if(m_Interval<0 || m_Interval>6000)
 {
  m_Interval=2000;
 }
 KillTimer(1);
 SetTimer(1,m_Interval/1000*1000,NULL);

 SetModifiedFlag();
}
測試:運行ActiveX測試器,選擇control---〉Invoke Methods對m_Interval進行修改。

爲編輯框增加成員變量MFC ClassWizard-->Member Variables-->Add Member Variable-->
Optional  property  name:
選擇自定義屬性的外部名,這樣我們不需要增加代碼就能把控件和自定義屬性相關聯。
在void CClockPropPage::DoDataExchange(CDataExchange* pDX)中會生成下面代碼:
 DDP_Text(pDX, ID_EDIT_INTERVAL, m_updateInterval, _T("Interval") );
 DDX_Text(pDX, ID_EDIT_INTERVAL, m_updateInterval);

在.NET2003下我始終找不到“Optional  property  name:”在哪,所以在我屬性頁上的編輯框無效,我只能選擇control---〉Invoke Methods進行修改。

爲控件增加函數,MFC ClassWizard-->Member Variables-->Add Method
Class Name要選擇CClockCtrl
輸入函數名,之後就可以在CClockCtrl類中找到了

我們選擇MFC ClassWizard-->ActiveX Events--->Add Event
之後會在DClockEvents中增加一個事件,DClockEvents接口是源接口,控件將用這個接口發送通知事件,它不是控件本身實現的接口,這個接口是通過容器來實現的


如果要將自定義的控件屬性保存下來,需要在
void CClockCtrl::DoPropExchange(CPropExchange* pPX)加入如下代碼:
PX_Short(pPX,"Interval",m_interval,1000);
之後再在程序中修改代碼:
 PX_Short(pPX,"Interval",m_interval,1000);
如果想使自定義控件屬性實時地顯示在容器屬性列表中,
在void CClockCtrl::OnIntervalChanged() 中加入如下代碼:
 BoundPropertyChanged(0x1);   //調度代碼爲1
如果希望用戶在設計模式時時鐘控件停止運行,而在用戶模式下運行,可以
在void CClockCtrl::OnTimer(UINT nIDEvent)下修改代碼如下:
 if(AmbientUserMode())   //查詢環境屬性
  InvalidateControl();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章