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下编译通过。
Visual C++中AVI按钮的制作
最新推荐文章于 2019-05-24 10:39:30 发布