Chinaunix首页 | 论坛 | 博客
  • 博客访问: 459642
  • 博文数量: 62
  • 博客积分: 1312
  • 博客等级: 中尉
  • 技术积分: 1555
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 18:10
文章分类

全部博文(62)

文章存档

2014年(1)

2013年(5)

2012年(56)

分类: C/C++

2012-11-02 08:25:28

一、准备工作
    按钮控件的集中基本状态:
    Normal:按钮一开始就显示的样子
    Over:鼠标指针移动到按钮上显示的样子
    Down:按下按钮时显示的样子
    Focus:按钮按下后松开的样子,例如:标准按钮按下之后松开会显示一个虚线框
    Disable:按钮被设置为无效的时候的显示的样子

二、实现过程
    1、新建一个类CXPButton,该类继承于CButton
        说明:自绘控件说白了就是画图,故而在需要添加的成员变量中可以看到与画图相关的各种数据类型,一般来说成员变量都会在构造函数中初始化,在类的析构函数中销毁。

        按钮的实现原理:
        (1)在控件初始化的时候为控件添加Owner_Draw的属性。因为在MFC中想要激活控件的自绘功能,要求在该控件的属性中必须包含属性值BS_OWNERDRAW,这一步的具体实现方法可以通过类向导为CXPButton类添加PreSubclassWindow()函数,在该函数中完成属性值的设置。当激活控件的自绘功能之后,每次控件的状态改变之后都会运行函数DrawItem(),这个函数的功能就在于绘制控件在各种状态下的外观。
        (2)添加WM_MOUSELEAVE消息函数,当鼠标指针离开按钮时,触发该消息函数,我们在函数中添加代码,通知DrawItem函数鼠标指针已经离开,让按钮重绘。
        (3)添加WM_MOUSEHOVER消息函数,当鼠标指针位于按钮之上的时候,触发该消息函数,我们在函数中添加代码,通知DrawItem函数鼠标指针在按钮上,让按钮重绘。
        (4)添加DrawItem函数。在该函数中根据按钮的当前状态绘制按钮的外观。可以说绘制按钮的大部分功能都是在这个函数中实现的。在该函数中有一个很关键的指针:LPDRAWITEMSTRUCT

        说明:事实上WM_MOUSELEAVE和WM_MOUSEHOVER两个Windows消息是通过WM_MOUSEMOVE消息触发的,而WM_MOUSEMOVE是标准的Windows消息,因此我们可以通过类向导来为CXPButton类添加WM_MOUSEMOVE消息函数。
代码如下:
void CXPButton::OnMouseMove(UINT nFlags, CPoint point) 
{
// TODO: Add your message handler code here and/or call default
if (!m_bTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTracking = _TrackMouseEvent(&tme);
}
CButton::OnMouseMove(nFlags, point);
}
        这段代码很重要,在其它自绘控件中,如果想触发WM_MOUSELEAVE和WM_MOUSEHOVER消息,也使用类似的方法去实现。

    2、接着添加WM_MOUSELEAVE和WM_MOUSEHOVER消息消息函数。在CXPButton类的声明中(即在XPButton.h文件中)找到afx_msg void OnMouseMove(UINT nFlags, CPoint point);的函数声明,紧接其下输入:
afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);

        然后在XPButton.cpp文件中找到ON_WM_MOUSEMOVE(),紧接其后输入
ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)

        再就是函数的实现了代码如下:
LRESULT CXPButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
m_bOver = FALSE;
m_bTracking = FALSE;
InvalidateRect(NULL, FALSE);
return 0;
}

LRESULT CXPButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
m_bOver = TRUE;
InvalidateRect(NULL);
return 0;
}

难点一:
    DRAWITEMSTRUCT结构体为我们提供了哪些信息呢?
typedef struct tagDRAWITEMSTRUCT { UINT ;         //控件类型 UINT ;          //控件ID UINT ;          //菜单项、列表框或者组合框中某一项的索引值 UINT ;      //控件行为 UINT ;      //控件状态 HWND ;      //父窗口句柄或菜单句柄 HDC ;             //控件对于的绘图设备句柄 RECT ;          //控件占据的矩形区域 ULONG_PTR ;      //列表框或者组合框中某一项的值 } DRAWITEMSTRUCT;
实际上自绘按钮本身的函数结构都是差不多的,它们显示效果的区别主要取决于代码编写者对GDI作图函数的运用与掌握程度。可以研究一下CXPButton类中DrawItem函数的数据结构,其实只要修改一下其中GDI绘图函数的部分代码,马上又能做出另一个自绘按钮控件了。

阅读(13641) | 评论(3) | 转发(0) |
0

上一篇:什么是shell

下一篇:敏捷实践

给主人留下些什么吧!~~

陈贞_Rock2012-11-04 18:37:27

ywh147: 按钮好不好看不是程序员该干的活,这事应该由美术来做。
mfc已经落伍了,兄弟,别再搞MFC了.....
呵呵···谢谢大哥啊!我会考虑大哥的建议的!

ywh1472012-11-04 12:10:57

这篇文章如果放在十年前肯定很有用,但现在已经明显落后时代了

ywh1472012-11-04 12:08:38

按钮好不好看不是程序员该干的活,这事应该由美术来做。
mfc已经落伍了,兄弟,别再搞MFC了