函数://AFX_VIRTUALCAdvButtonpublic:virtual void DrawItemLPDRAWITEMSTRUCT lpDrawItemStructprotected:virtual void PreSubclassWindow//AFX_VIRTUAL其中对于所有的对于按钮的绘制工作都是在 DrawItem 函数中完成的。
2添加创建按钮控件代码 按钮的创建分两步完成。
首先,调用构造函数对按钮对象进行初始化;其次,调用 Create 函数创建按钮。
代码如附录 1 所示。
3设置按钮形状、外观、颜色、标题 PreSubclassWindow 函数在窗口被创建之前就被调用,因此,在 PreSubclassWindow 函数中,将按钮的风格设为BS_OWNERDRAW。
实现代码如下: //修改按钮控件风格 ModifyStyle0BS_OWNERDRAWBS_PUSHBUTTON; 要使按钮能对鼠标的移动与单击作出不同的变化,那么按钮就需要时刻知道鼠标的位置与动作。
所以,必须在鼠标的单击、弹起及移动消息的响应函数中填加相应的代码,以获取鼠标的位置与动作。
在鼠标左键按下时,得到按钮窗口客户区域的屏幕坐标位置和鼠标的屏幕坐标位置。
当鼠标坐标位落于窗口客户区域内,且当前按钮控件处于非选中状态时,将按钮状态标识设为选中状态,即将 m_State 设为 2。
接着,调用Invalidate 函数,使客户区无效,框架会自动调用 DrawItem 函数,重绘客户区。
实现代码如下: //当鼠标在按钮的客户区内按下时改变按钮状态 void CAdvButton::OnLButtonDownUINT nFlags CPoint point CRect rect GetWindowRectamprect //得到按钮客户区域的屏幕坐标位置 GetCursorPosampm_Point //得到鼠标的屏幕坐标位置 ifrect.PtInRectm_Pointampampm_State 2 m_State 2 //2:select state Invalidate //重绘客户区 CButton::OnLButtonDownnFlags point 在鼠标左键抬起时,得到按钮窗口客户区域的屏幕坐标位置和鼠标的屏幕坐标位置。
当鼠标坐标位置落于窗口客户区域内,且当前按钮控件处于选中状态时,将按钮状态标识设为非选中状态,即将 m_State 设为 1。
接着,调用Invalidate 函数,使客区无效,框架会自动调用 DrawItem 函数,重绘客户区。
其代码如附录 1 所示。
在用户移动鼠标时,如果计时器没有启动,则启动计时器,并将计时器启动标识 m_IsTimerOn 设为 TRUE。
其实现代码如下: ifm_IsTimerOn //如果计时器没用启动 SetTimer1000100NULL //启动计时器 m_IsTimerOn TRUE 如果鼠标已经移出了按钮的客户区,则消毁计时器,并将计时器的起始标识m_IsTimerOn 设为 FALSE。
OnTimer 函数的实现代码如附录 1 所示。
实现客户区的绘置函数 DrawItem。
在 DrawItem 函数中,首先得到窗口的有效矩形区域,在此矩形区域内创建椭圆。
调用 SetWindowRgn 函数,设置窗口的有效区域为椭圆。
从参数 lpDrawItemStruct 结构中得到按钮控件客户区域的设备环境变量指针。
根据按钮当前状态,创建不同的画笔。
调用设备环境类的成员函数,设置背景模式为透明,选择画笔,在按钮客户区内绘制椭圆及显示文本。
其实现代码如附录 1 所示。
10 通过上面操作,按钮已经具有对鼠标不同的位置和动作改变不同的颜色。
并且,按钮的客户区域已经是一个椭圆,而不再是一个矩形。
正是下面的代码将按钮的客户区域设定为椭圆形: GetClientRectampm_ClientRect //通到窗口的有效矩形区域 m_ClientRgn.DeleteObject //删除区域对象 m_ClientRgn.CreateEllipticRgnIndirectampm_ClientRect //在矩形区域内创建椭圆 //设置窗口的有效区域为椭圆 SetWindowRgnm_.