首    页 界面/窗口 网络/通讯 数据库 组件开发 图像/多媒体 NET/Web 其它技术 源码下载 资料下载 软件共享 软件外包 曲艺杂谈
栏目导航:  首    页  |  界面/窗口  |  按钮   


设计XP风格的按钮


原作者:郑恒(lbird)    源出处:VC知识库    发布者:施昌权    发布类型:转载    发布日期:2008-09-19

             

       论坛上许多人都在讨论如何编写具有XP风格的界面,其实网上有设计好的类库,可以直接拿来使用。但这些终归是别人写的,能不能转化成自已的呢。于是笔者就对这些代码进行研究,算是偷一点吧:)
       研究了几种控件,这里就把其中最简单的按钮控件拿来供大家一起讨论。
       这是程序的运行效果:

       步骤:
       1、创建一个派生自CButton的新类CButtonXp
       2、重载PreSubClassWindow()函数,在该函数内修改按钮的风格为自绘制(owner):
       添加如下代码:ModifyStyle(0,BS_OWNERDRAW);
       3、因为XP风格按钮具有鼠标感应的效果,当鼠标移动到按钮上方时,按钮的颜色会改变。所以就必须跟踪鼠标。当鼠标移到按钮上方时,窗口会收到WM_MOUSEMOVE消息,但怎么才能得知鼠标离开按钮呢?
       这里我们使用 TrackMouseEvent() Api函数:

       BOOL TrackMouseEvent( LPTRACKMOUSEEVENT lpEventTrack );

       参数:
       typedef struct tagTRACKMOUSEEVENT {
              DWORD cbSize; //结构大小
              DWORD dwFlags; //设定为TME_LEAVE
              HWND hwndTrack; //要跟踪鼠标的窗口句柄
              DWORD dwHoverTime;} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;
       调用该函数可以在鼠标离开指定窗口时收到WM_MOUSELEAVE消息。

       添加成员变量:m_bOver ,初始化为FALSE。m_bOver=true用来表示鼠标在按钮区域。
       添加WM_MOUSEMOVE消息处理函数:

       void CButtonXp::OnMouseMove(UINT nFlags, CPoint point)
        {
               if(m_bOver ==FALSE)
               {
                      //鼠标在按钮之上
                      m_bOver =TRUE;
                      //按钮重绘
                      InvalidateRect(NULL,FALSE);
                      //跟踪鼠标
                      //当鼠标离开按钮区域会收到WM_MOUSELEAVE,该消息直接调用OnMouseOut()
                      TRACKMOUSEEVENT tme;
                      tme.cbSize =sizeof(TRACKMOUSEEVENT);
                      tme.dwFlags =TME_LEAVE;
                      tme.dwHoverTime=0;
                      tme.hwndTrack =m_hWnd;
                      ::TrackMouseEvent(&tme);
               }
               CButton::OnMouseMove(nFlags, point);
        }

       再添加一成员函数OnMouseOut(), 并在BEGIN_MESSAGE_MAP(CButtonXp, CButton)和END_MESSAGE_MAP()之间添加宏        
       ON_MESSAGE(WM_MOUSELEAVE,OnMouseOut)

       在OnMouseOut()中写入以下代码

       void CButtonXp::OnMouseOut ()
        {
               //鼠标已离开按钮区域
               m_bOver =FALSE;
               //重绘按钮
               InvalidateRect(NULL,FALSE);
        }

       4、添加成员函数 MouseOver()

       //返回鼠标是否在按钮区域内
        BOOL CButtonXp::MouseOver()
        {
               return m_bOver;
        }

       5、最后重载DrawItem(LPDRAWITEMSTRUCT lpDIS)

       void CButtonXp::DrawItem(LPDRAWITEMSTRUCT lpDIS)
        {
               CDC *pDC =CDC::FromHandle(lpDIS->hDC);
               CRect rtControl(lpDIS->rcItem);
               CPen pen,*old_pen;
               CBrush brush,*old_brush;
               CString strText;
               HFONT hOldFont = (HFONT)pDC->SelectObject ((HFONT)::GetStockObject (DEFAULT_GUI_FONT));
               UINT state =lpDIS->itemState;
               if(state & ODS_FOCUS)
               {
                      rtControl.DeflateRect(1,1); //拥有焦点矩形变小
               }
               if((state & ODS_DISABLED) || (!MouseOver() &&!(state & ODS_SELECTED)))
               {
                      //普通状态、禁用、拥有焦点三种情况下
                      pen.CreatePen (PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));                      
                      brush.CreateSolidBrush(HLS_TRANSFORM(::GetSysColor(COLOR_3DFACE),-10,0));
               }
               else
               {
                      COLORREF crBorder =::GetSysColor(COLOR_HIGHLIGHT);
                      pen.CreatePen(PS_SOLID, 1, crBorder);
                      if( state & ODS_SELECTED)
                      {
                             //按钮按下时
                             brush.CreateSolidBrush(HLS_TRANSFORM(crBorder,+50,-50));
                             pDC->SetTextColor(RGB(240,240,240));
                      }
                      else
                      {
                             //鼠标在区域内
                             brush.CreateSolidBrush(HLS_TRANSFORM(crBorder,+80,-66));
                             pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
                      }
               }
               if(state &ODS_DISABLED)
                      pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));//灰色字:禁用状态
               else if(state & ODS_SELECTED)
                      pDC->SetTextColor(RGB(240,240,240)); //白色字:PUSH状态
               else if(MouseOver())
                      pDC->SetTextColor(0); //黑色字:热感应状态
               else pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT)); //黑色字:普通状态
                      old_brush=pDC->SelectObject(&brush);
                      old_pen =pDC->SelectObject(&pen);
                      pDC->Rectangle(rtControl);
                      pDC->SetBkMode(TRANSPARENT);
                      GetWindowText(strText);
                      pDC->DrawText(strText,rtControl,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
                      if(state & ODS_FOCUS)
                      {
                             rtControl.DeflateRect(3,3);
                             pDC->DrawFocusRect(rtControl);
                      }
                      pDC->SelectObject(old_pen);
                      pDC->SelectObject(old_brush);
                      pDC->SelectObject(hOldFont);
        }

       还有一个要注意的是,要使用TrackMouseEvent(),必须在加入头文件winuser.h 和extern "C" WINUSERAPI BOOL WINAPI TrackMouseEvent(LPTRACKMOUSEEVENT lpEventTrack);

       本程序在win98 + Visual C++ 6.0环境下编译通过.

       点击这里下载源码

 

关于我们 版权声明 广告服务 联系我们 友情链接 加入收藏
站长:施昌权    Email:scq2099yt@163.com    MSN:scq2099yt@live.cn    QQ:14046300    本站QQ群:67202409
Copyright © 2008     卓为VC(www.joyvc.cn)    All Rights Reserved    建议分辨率 1024×768
本站由施昌权制作维护
京ICP备09012297号