ActiveX控件的概念 (COM組件的應用)
1 什麼是ActiveX控件
基於COM組件技術的,使用與一般控件一樣方便。與一般控件的區別是,它可以被任何支持COM標準的計算機程序使用。
2 什麼是COM組件
組件實現了某種功能的一些小的二進制文件,通過接口對外提供服務。
一個項目生成一個exe文件
一個項目由 一個或者多個exe文件 + 一個或者多個組件。組件與組件直接通過接口交互。有更好的複用性和可維護性。
3 什麼是接口?
C 語言 - 接口就是函數
C++語言 - 接口就是公有的成員函數
COM組件 - 接口就是一組純虛函數的集合(純虛類)。因爲純虛函數只有聲明沒有實現,所以,接口是穩定的。
void sort (參數) = 0;
ActiveX控件的開發、註冊、測試和使用
1 瞭解微軟提供的ActiveX控件的測試工具
ActiveX Control Test Container
ActiveX控件的開發測試包括控件的 : 事件、屬性、方法
2 使用MFC嚮導開發ActiveX控件
2.1 嚮導生成的接口和類的介紹
第一個接口 - 添加屬性和方法
第二個接口 - 添加事件。
App - 應用程序類
Ctrl - 控件類,包含了各種屬性、方法的實現。另外,控件的外觀在OnDraw()函數中完成。
PropPage - 屬性頁類,添加控件的屬性設置
這裏將開發一個求兩個數的最大公約數的組件
運行如下:
新建一個工程,選擇"MFC ActiveX ControlWizard",工程建立完畢後
選中工程的第一個接口通過右鍵選擇"Addd Method"添加一個方法(函數)
函數原型:void SetNumber (int m_num1, int m_num2), 主要用來接受用戶傳入(通過調用我們提供的該函數接口)的兩個計算數據
具體操作:
添加完畢後會發現在第一個接口中以及在我們的Ctrl類中都出現了該函數, 接口中的函數數對外提供服務,Ctrl中的函數需要我們去實現。
接着爲Ctrl類添加兩個成員變量用以接受用戶傳入的計算數:
int m_a;
int m_b;
然後在第一個接口上右鍵選擇Add Property , 這裏添加一個名爲Direction 的BOOL類型的變量,用來控制結果小球的顯示位置(上方/下方)
添加完Direction屬性後會發現Ctrl類中多了一個OnDirectionChange, 當外部通過Direction(PropPut)設置Direction變量的值時將觸發該函數的調用
void CActiveXMcdCtrl::OnDirectionChanged()
{
// TODO: Add notification handler code
// 重繪控件,重新計算
Invalidate ();
SetModifiedFlag();
}
然後在Ctrl類的構造函數中對它們及控件的大小進行初始化:
CActiveXMyMcdCtrl::CActiveXMyMcdCtrl()
{
InitializeIIDs(&IID_DActiveXMyMcd, &IID_DActiveXMyMcdEvents);
// TODO: Initialize your control's instance data here.
// 設置控件的初始大小
SetInitialSize (230, 230);
m_a = 16;
m_b = 12;
m_direction = FALSE;// 控制結果球的顯示位置
}
接下來回到Ctrl類中實現SetNumber方法。
void CActiveXMyMcdCtrl::SetNumber(long m_num1, long m_num2)
{
// TODO: Add your dispatch handler code here
m_a = m_num1;
m_b = m_num2;
// 引發控件重繪調用我們的MCd函數結算結果並顯示
Invalidate (TRUE);
}
來到Ctrl的OnDraw函數開始繪製我們的控件:首先去掉默認的繪製代碼,然後添加我們的繪製代碼:
void CActiveXMcdCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
// TODO: Replace the following code with your own drawing code.
// pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
// pdc->Ellipse(rcBounds);
// 設置控件的背景顏色
CBrush brush (RGB (255, 255, 0));
pdc->FillRect (&rcBounds, &brush);
// 繪製3個圓
// 設置圓的背景色
CBrush brush2 (RGB (0,0,0));
// 設置圓心位置
POINT p1 = {40, 120};
POINT p2 = {190, p1.y};
POINT p3 = {(p1.x + p2.x) / 2 , m_direction ? p1.y - 50 : p1.y + 50};
// 設置圓的半徑
int radious = 15;
// 畫圓
CBrush *pOldBrush = pdc->SelectObject (&brush2);
pdc->Ellipse (p1.x - radious, p1.y - radious, p1.x + radious, p1.y + radious);
pdc->Ellipse (p2.x - radious, p2.y - radious, p2.x + radious, p2.y + radious);
pdc->Ellipse (p3.x - radious, p3.y - radious, p3.x + radious, p3.y + radious);
// 連接線
pdc->MoveTo (p1);
pdc->LineTo (p3);
pdc->LineTo (p2);
// 設置字體的顏色、對齊方式、背景透明
pdc->SetTextColor (RGB (255,255,255));
pdc->SetTextAlign (TA_CENTER);
pdc->SetBkMode (TRANSPARENT);
// 在圓中寫入數值
CString strMsg;
strMsg.Format ("%d", m_a);
pdc->TextOut (p1.x, p1.y - 9, strMsg);
strMsg.Format ("%d", m_b);
pdc->TextOut (p2.x, p2.y - 9, strMsg);
strMsg.Format ("%d", Mcd (m_a, m_b));
pdc->TextOut (p3.x, p3.y - 9, strMsg);
pdc->SelectObject (pOldBrush);
brush.DeleteObject ();
brush2.DeleteObject ();
}
在Ctrl類中添加求最小公約數的函數及實現:
int CActiveXMyMcdCtrl::Mcd(int a, int b)
{
if (b == 0)
return a;
return Mcd(b, a%b);
}
最後在第二個接口上右鍵選擇:Add Event就可以爲控件添加消息了(事件),控件的消息分爲:Stock(庫存的) 和 Custom(自定義的)
添加庫存的消息選擇Stock後,在External name:組合框中選擇自己感興趣的事件點擊OK即可, 注意,這裏的消息是我們的控件發消息給控件的使用者,也就是說由控件的使用者處理我們的控件消息
這裏我添加一個自定義的消息MyMsg,添加完畢後發現在第二個控件中出現事件的接口,在Ctrl類中出現函數,但是這個消息需要由我們自己發送:
那麼這裏爲Ctrl類添加一個消息處理:WM_LBUTTONDOWN, 就是當左鍵按下觸發我們自定義的消息:
void CActiveXMyMcdCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
FireMyMsg ();
COleControl::OnLButtonDown(nFlags, point);
}
註冊和卸載ActiveX控件:
Win+R :
regsvr32 "組件所在的文件路徑" 註冊組件
regsvr32 /u "組件所在的文件路徑" 卸載組件
注: Winsta及以上系統環境下需要以管理員省份運行該命令
ActiveX控件的測試: 事件、屬性、方法
編譯連接之後: Tools-->Register Contrl
註冊成功之後: Tools-->ActiveX Contrl Test Container
這樣就打開了微軟提供給我們專門用來測試ActiveX控件的容器, 在客戶區右鍵: 選擇Insert New Contrl ,選擇我們自己編寫的ActiveX控件
測試方法: Control-->Invoke Methods... --->這裏在彈出的對話框中選擇:SetNumber (Method),設置完兩個參數的值後點擊Invoke就可以看到結果了
測試屬性: Control-->Invoke Methods... --->這裏在彈出的對話框中選擇:Direction(PropPut),輸入一個數值後Set Value,然後Invoke就可以看到效果了
ActiveX控件的使用:
新建一個基於對話框的程序,在對話框資源上右鍵選擇:Insert ActiveX Control, 選擇我們的控件
Ctrl+W使用類嚮導爲控件綁定成員變量。在綁定時,提示添加控件的包裝類,添加即可,然後就可以像使用一般控件一樣使用ActiveX控件了。
void CUseMcdDlg::OnBtnCompute()
{
// TODO: Add your control notification handler code here
UpdateData ();
m_wndMcd.SetNumber (m_num1, m_num2);
}
void CUseMcdDlg::OnBtnSetdir()
{
// TODO: Add your control notification handler code here
m_wndMcd.SetDirection (! m_wndMcd.GetDirection ());
}
void CUseMcdDlg::OnBtnAbout()
{
// TODO: Add your control notification handler code here
m_wndMcd.AboutBox ();
}
在html中使用控件:
<html>
<head>
<title>Mcd測試頁面</title>
</head>
<body>
<form>
<p>
<object id="McdCtrl" classid="clsid:66C3EA36-7FFE-4674-9C0E-E8ECE3749F19" width="250" height="200"></object>
</p>
<p>
<input type="text" id="a" size="4" value="16">
<input type="text" id="b" size="4" value="12">
<input type="button" value="重新計算" name="Computer" οnclick="C_onclick();">
<input type="button" value="關於" name="About" οnclick="A_onclick();">
</p>
<input type="radio" id="c"name="Direction" >向上
<input type="radio" id="d"name="Direction" >向下
<input type="button" value="設置方向" name="Direct" οnclick="D_onclick();">
<script>
function C_onclick()
{
document.all.McdCtrl.SetNumbers(document.all.a.value,document.all.b.value);
}
function A_onclick()
{
document.all.McdCtrl.AboutBox();
}
function D_onclick()
{
document.all.McdCtrl.Direction=(document.all.c.checked?1:0);
}
</script>
</form>
</body>
</html>
其中的classid唯一標識我們在系統中註冊的控件,雙擊第一個接口可以找到我們的控件ID,