前言
本文以撲克控件的制作過程為實例,介紹了MFC ActiveX控件的詳細制作過程,希望對學習控件編寫的朋友有所幫助。
一、撲克控件的制作
1、新建一個“MFC ActiveX ControlWizard”工程。為工程名起名為Cards,然後用向導的默認值一路OK生成工程。
2、為工程中添加五十四張撲克牌位圖以及撲克背景位圖資源。注意位圖中有一張IDB_CARDS位圖為控件顯示時的圖標,可以自行修改成自己喜歡的圖樣。
3、為控件填加屬性值,打開View—>ClassWizard。點擊Automation標簽。從類名下拉框中選擇CCardsCtrl,點擊“Add Property”按鈕彈出屬性添加對話框。在External name中輸入value,Type選擇為short類型。同時在Implementation一項中選擇Get/Set methods,還有兩項不管它,就用它自己設置的函數就行了。現在我們已經為控件添加好了一個屬性,它是用來處理撲克牌的點數的。
4、按照第三步的方法,我們再依次設置幾個屬性,分別是backbmp,類型為short,用來處理背景圖案是什麼;background,類型為BOOL,用來處理顯示牌正面還是反面。
5、屬性添加好了,下面為這些屬性設置初始值:打開CardsCtl.cpp文件,在構造函數CCardsCtrl::CCardsCtrl()中加入代碼:value=1;backbmp=1;
6、為了使控件能夠在程序中正常顯示出來,我們還需要對CCardsCtrl::OnDraw進行修改。修改後的內容如下:
void CCardsCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
CBitmap *pOldBitmap;
CBitmap bitmap;
CRect rect;
GetClientRect(rect);
CDC ppdc;
CClientDC dc(this);
ppdc.CreateCompatibleDC(&dc);
if(background)//背景圖案
{
if(backbmp==1)bitmap.LoadBitmap(255);
if(backbmp==2)bitmap.LoadBitmap(256);
}
else//前景圖案
bitmap.LoadBitmap(IDB_BITMAP1+value-1);
pOldBitmap=ppdc.SelectObject(&bitmap);
dc.BitBlt(0,0,rect.Width(),rect.Height(),&ppdc,0,0,SRCCOPY);
ppdc.SelectObject(pOldBitmap);
}
在上面的代碼中,要注意的是bitmap.LoadBitmap(IDB_BITMAP1+value-1);語句,一定要保證你在資源中插入的位圖資源連續。可以打開Resource.h文件看一看,你的位圖資源是否是連續的。
7、接下來要修改屬性函數了。修改前在CardsCtl.h中加入成員變量(有些在後面能夠用得上):
protected:
short value,backbmp;
BOOL background;
BOOL IsMove,m_IsMove;
BOOL IsGoHome;
CPoint OldPoint;
CRect rect;
long xx,yy;
修改後的函數如下:
short CCardsCtrl::GetValue()
{
return value;
}
void CCardsCtrl::SetValue(short nNewValue)
{
value=nNewValue;
SetModifiedFlag();
InvalidateControl();//立即刷新
}
BOOL CCardsCtrl::GetBackground()
{
return background;
}
void CCardsCtrl::SetBackground(BOOL bNewValue)
{
background=bNewValue;
SetModifiedFlag();
InvalidateControl();
}
short CCardsCtrl::GetBackbmp()
{
return backbmp;
}
void CCardsCtrl::SetBackbmp(short nNewValue)
{
backbmp=nNewValue;
SetModifiedFlag();
InvalidateControl();
}
可以看出,這些函數的修改都是大同小異,GetXXXXX()是用來得到屬性值,SetXXXXX()用來設置屬性值。InvalidateControl()函數用來刷新控件,使修改屬性後的控件能立刻反映在屏幕上。
8、為了能使控件能夠被隨意拖動,我們還需要做下面的准備工作,首先按照第三步的方法添加兩個屬性:IsMove,類型為BOOL,用來處理控件是否能被拖動;IsGoHome,類型為BOOL,用來處理控件拖動後是否回到原位置。之後為這兩個屬性設置初始值,也是在構造函數CCardsCtrl::CCardsCtrl()中增加代碼
IsMove=false;
m_IsMove=false;
IsGoHome=true;
9、使控件能被拖動,需要處理鼠標左鍵按下、鼠標拖動以及鼠標左鍵抬起三個消息。在ClassWizard的“Message Maps”標簽中,為WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP增加消息處理函數,然後修改這三個函數如下: void CCardsCtrl::OnLButtonDown(UINT nFlags, CPoint point)
10、到了這一步,此控件的主要工作已經完成了,現在我們為控件添加屬性頁,以使它和用戶的交流更友好。首先在ResourceView中修改默認的屬性頁對話框為你需要的(詳見程序源代碼)。然後在ClassWizard的“Member Variables”中。從類中選擇CCardsPropPage,點擊“Add Variable…”按鈕分別為你加入在屬性頁中的控件添加變量。這裡添加變量的方法大致和為普通對話框添加變量相同,唯一有區別的是這裡多了一項可選屬性名(Optional property name),用於選擇和變量相連的屬性。具體設置詳見下表:
{
if(IsMove)//是否是允許拖動鼠標
{
m_IsMove=true;
SetCapture();//捕獲鼠標
xx=point.x;//得到鼠標(相對於控件左上角)的坐標
yy=point.y;
GetClientRect(&rect);//保存拖動前的撲克位置
::ClientToScreen(m_hWnd,&rect.TopLeft());
OldPoint=rect.TopLeft();
MoveWindow(0,0,0,0);//得到相對量
GetClientRect(&rect);
::ClientToScreen(m_hWnd,&rect.TopLeft());
}
COleControl::OnLButtonDown(nFlags, point);
}
void CCardsCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CPoint MyPoint=point;
if(m_IsMove)
{
ClientToScreen(&MyPoint);
MoveWindow(MyPoint.x-xx-rect.left,MyPoint.y-yy-rect.top,71,96);
}
COleControl::OnMouseMove(nFlags, point);
}
void CCardsCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(m_IsMove)
{
ReleaseCapture();
m_IsMove=false;
if(IsGoHome)
MoveWindow(OldPoint.x-rect.left,OldPoint.y-rect.top,71,96);//還原到撲克牌拖動前的位置
}
COleControl::OnLButtonUp(nFlags, point);
}
控件名 變量名 組件 變量類型 可選屬性名 IDC_CHECK1 m_check1 value BOOL background IDC_CHECK2 m_check2 value BOOL IsMove IDC_CHECK4 m_check4 value BOOL IsGoHome IDC_EDIT1 m_edit1 value short value IDC_EDIT2 m_edit2 value short backbmp
11、最後,為了使屬性頁和控件關聯起來,我們再在void CCardsCtrl::DoPropExchange(CPropExchange* pPX)函數中添加代碼: PX_Short(pPX,"value",value,1);
補充:控件中的右鍵單擊處理因為和制作此控件無關,這裡沒有解釋,若想知詳情請看源代碼。
PX_Short(pPX,"backbmp",backbmp,1);
PX_Bool(pPX,"background",background,false);
PX_Bool(pPX,"IsMove",IsMove,false);
PX_Bool(pPX,"IsGoHome",IsGoHome,false);
二、控件測試
1、新建一“MFC AppWizard(exe)”工程,取名為test,建立完畢,在Project(工程)中選擇“Add Project(添加工程)”,再選“Components and Controls…”選項。 之後從彈出的對話框中雙擊“Registered ActiveX Controls”目錄。從目錄中選擇剛才我們編的控件“Cards Control”,點“Insert”按鈕把此控件插入到test工程中。
2、打開對話框資源,把控件拖動至對話框中,用鼠標右鍵單擊Cards控件,進行屬性設置,完畢後就可以運行了。
另外你也可以通過調用SetValue(short propVal)來手工設置撲克點數。好了,一切都OK了!
本文配套源碼