Visual C++ 語言爲控件提供的自繪製功能使程序員能夠充分發揮自己的創造性來設計比較漂亮的程序界面。所謂AVI按鈕是指在按鈕上每當有鼠標經過時就播放一段按鈕提示的AVI,在許多的遊戲程序以及三維動畫軟件中(摩托英豪、Cool 3D等)都廣泛的採用了這種AVI按鈕。它使得程序的用戶界面很具有動感,也使得我們的程序至少看上去更專業,本文講述了藉助Visual C++強大的控件自繪製功能來實現這種AVI按鈕的原理及實現。
首先我們利用 Cool 3D 或者 Xara 3D等三維文字動畫軟件來製作一個簡單的關於“0K”的繞中心軸旋轉的三維文字動畫並輸出爲AVI文件(本例中爲ok.avi)。接下來我們就用Visual C++來在對話框中具體實現一個關於“OK”的AVI按鈕。
a. 運行 AppWizard 創建一個基於對話框的應用程序,取其項目名爲 TestAviButton, 然後按下 Finish 按鈕來完成工程的創建。
b. 執行 View | ClassWizard 菜單命令,以CButton 爲基類創建CAviButton 類,生成類的頭文件 AviButton.h 和實現文件 AviButton.cpp 同時加入類的 Create ,DrawItem 和 WM_MOUSEMOVE的消息映射,然後在其類的頭文件AviButton.h 中加入以下成員變量和成員函數:
public:
UINT m_nAviID;
CAnimateCtrl AnimateCtrl;
BOOL bPlaying;
void LoadAvi(UINT nAviID);
void DrawButton(CDC* pDC, UINT nState, CRect rect);
然後在其類的實現文件AviButton.cpp中類的構造函數中添加初始化代碼並添加成員函數的實現代碼如下:
CAviButton::CAviButton()
{
m_nAviID = 0;
bPlaying = FALSE;
}
void CAviButton::LoadAvi(UINT nAviID)
{
m_nAviID =nAviID;
}
void CAviButton::DrawButton(CDC *pDC, UINT nState, CRect rect)
{
COLORREF upCol,downCol,edgeCol;
edgeCol=RGB(0,0,0);
if ((nState & ODS_SELECTED) == ODS_SELECTED)
{
//設置按鈕被按下時按鈕的顏色
upCol=RGB(0,0,0);
edgeCol=RGB(128,128,128);
downCol=RGB(0,0,0);
}
else
{ //設置按鈕正常時按鈕的顏色
upCol=RGB(255,255,255);
downCol=RGB(128,128,128);
}
CPen* pOldPen = NULL;
BOOL pen1Created;
CPen pen1;
BOOL pen2Created;
CPen pen2;
if (pen1Created = pen1.CreatePen(PS_SOLID, 1, upCol))
pOldPen = pDC->SelectObject( &pen1 );
//畫左上邊緣
pDC->MoveTo(1,rect.Height()-1);
pDC->LineTo(1,1);
pDC->LineTo(rect.Width()-1,1);
pDC->MoveTo(0,rect.Height()-1);
pDC->LineTo(0,0);
pDC->LineTo(rect.Width()-1,0);
if (pen2Created = pen2.CreatePen(PS_SOLID, 1, downCol))
pDC->SelectObject( &pen2 );
if (pen1Created)
{
pen1.DeleteObject();
pen1Created = FALSE;
}
//畫右下邊緣
pDC->MoveTo(rect.Width()-1,0);
pDC->LineTo(rect.Width()-1,rect.Height()-1);
pDC->LineTo(0,rect.Height()-1);
pDC->MoveTo(rect.Width()-2,1);
pDC->LineTo(rect.Width()-2,rect.Height()-2);
pDC->LineTo(0,rect.Height()-2);
if (pen2Created)
{
pen2.DeleteObject();
pen2Created = FALSE;
}
if (pen1Created = pen1.CreatePen(PS_SOLID, 1, edgeCol))
pOldPen = pDC->SelectObject( &pen1 );
if (pen1Created)
{
pen1.DeleteObject();
pen1Created = FALSE;
}
if (pOldPen != NULL)
pDC->SelectObject( pOldPen );
}
c. 打開 Workspace 的 ResourceView 頁,打開ID值爲IDD_TESTAVIBUTTON_DIALOG 的對話框進行編輯,該對話框的提示文本爲“將鼠標移至按鈕上:”刪除“取消”按鈕,將“確定”按鈕的屬性 Styles 改爲 OwnerDraw ,並去掉其提示文本 “確定”;另外執行 Insert | Resource… 命令,在彈出的對話框中按下 Custom… 按鈕,然後輸入“AVI”然後將 ID值爲IDR_AVI1改爲IDR_AVI並將文件名置爲:res/ok.avi。最後在FileView中的Resource Files中添加文件ok.avi。
d. 修改CAviButton 類的Create 函數定義爲:
virtual BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
並修改其實現爲:
BOOL CAviButton::Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
return CButton::Create(lpszWindowName, dwStyle, rect, pParentWnd, nID);
}
在DrawItem函數中添加代碼:
void CAviButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CRect rect;
GetClientRect(rect);
if (!::IsWindow(AnimateCtrl))
{
//在按鈕上生成一個動畫控件
AnimateCtrl.Create(WS_CHILD |WS_VISIBLE,rect,this,0);
//打開avi文件並顯示第一幀
AnimateCtrl.Open(m_nAviID);
AnimateCtrl.GetClientRect(rect);
SetWindowPos(NULL, -1, -1, rect.Width()+4, rect.Height()+4,
SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE);
rect.OffsetRect(2,2);
AnimateCtrl.MoveWindow(rect);
}
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
UINT nState = lpDrawItemStruct->itemState;
CRect buttonRect;
GetClientRect(buttonRect);
//繪製按鈕
DrawButton(pDC, nState, buttonRect);
}
添加類的OnMouseMove函數如下:
void CAviButton::OnMouseMove(UINT nFlags, CPoint point)
{
ClientToScreen(&point);
CRect rcWindow;
GetWindowRect(rcWindow);
//判斷鼠標是否經過按鈕
BOOL bNewMouseOverButton = rcWindow.PtInRect(point);
unsigned long nROnly = ES_READONLY;
BOOL bTest = (GetStyle() & nROnly) != nROnly;
if (bNewMouseOverButton && IsWindowEnabled() && bTest)
{
if (::IsWindow(AnimateCtrl) && !bPlaying)
{
AnimateCtrl.Play(0,-1,1);
bPlaying = TRUE;
SetCapture();
}
}
else
{
bPlaying = FALSE;
ReleaseCapture();
}
CButton::OnMouseMove(nFlags, point);
}
e.執行執行 View | ClassWizard 菜單命令,爲類CtestAviButtonDlg類中的控件ID爲IDOK添加成員變量,變量名爲m_AviButton,類型爲CAviButton;併爲IDOK控件添加BN_CLICKED事件。在OnInitDialog函數中:
改註釋“// TODO: Add extra initialization here”爲
代碼: m_AviButton.LoadAvi(IDR_AVI);
至此我們就完成了整個工程的創建和修改工作,編譯並執行整個程序,每當我們的鼠標經過按鈕時,一個漂亮的AVI按鈕就產生了。本程序在Visual C++ 6.0,中文Windows NT4.0下編譯通過。
轉自:http://blog.csdn.net/prodicom/archive/2009/04/17/4086922.aspx