用VC6扩展CButton类制作风格独特的按钮

超级明天辉煌

超级明天辉煌

2016-02-19 21:44

下面,图老师小编带您去了解一下用VC6扩展CButton类制作风格独特的按钮,生活就是不断的发现新事物,get新技能~

  一、 本文介绍一个CButton的派生类CLinkButton,用此派生类制作的按钮具有以下特点:

  1、按钮的外观类似静态控件类CStatic 产生的对象。(参见图一)

 
  图一

  2、当鼠标的光标移到按钮上,但并未按下时,光标改变形状,字体改变形状;按钮类似应用在工具条和菜单上的扁平钮效果。(参见图二)

 
  图二

  3、当按钮按下的情形:(参见图三)

 
  图三

  二、下面具体描述这种按钮的实现方法和步骤:

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  在VC6的IDE环境中,生成一个基于对话框的PROJECT。

  将对话框资源中按钮的属性页打开,在“Style”标签页中选取按钮的“Owner Draw”(自绘)属性。

  将光标引入到应用程序的资源中。

  利用CLASSWIZARD,用CButton为基类,派生一个新类:CLinkButton。

  在派生类中重载基类CButton的虚函数: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

  之所以要重载这个函数是因为选择了按钮的 “Owner Draw”属性后,当按钮的可视行为发生变化时,应用程序的框架要调用这个函数来重新绘制按钮。

  定制以下的消息处理:afx_msg void OnMouseMove(UINT nFlags, CPoint point);
   afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
   afx_msg void OnTimer(UINT nIDEvent);
   afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
   afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
   afx_msg BOOL OnEraseBkgnd(CDC* pDC);
声明类成员变量定义: //定义字体变量
   CFont fUnderline;
   //定义光标变量
   HCURSOR hHand;
   //决定按钮是否按下
   bool bLBtnDown;
   //决定鼠标是否在按钮上
   bool bHighlight;

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  三、 派生类CLinkButton 的具体实现:

  1、重载函数  DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)。 void CLinkButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  // 获取一个CDC指针
  CDC* pDC = CDC::FromHandle(lpDrawItemStruct-hDC);
  //定义按钮区域并初始化
  CRect rect(lpDrawItemStruct-rcItem);
  //设置背景模式
  COLORREF oc = pDC-GetTextColor();
  int iObk = pDC-SetBkMode(TRANSPARENT);
  //初始化按钮状态
  UINT state = lpDrawItemStruct-itemState;
  CFont * pOldFont = NULL;
  int iYOffset = 0, iXOffset = 0;
  CString strText;
  GetWindowText(strText);
  rect.top += iYOffset;
  rect.left += iXOffset;
  if (state & ODS_DISABLED)
  {    
    //按钮置灰(DISABLED)
    CBrush grayBrush;
    grayBrush.CreateSolidBrush (GetSysColor (COLOR_GRAYTEXT));
    CSize sz = pDC-GetTextExtent(strText);
    int x = rect.left + (rect.Width() - sz.cx)/2;
    int y = rect.top + (rect.Height() - sz.cy)/2;
    rect.top += 2;
    rect.left += 2;
    pDC-SetTextColor(GetSysColor(COLOR_3DHIGHLIGHT));
    pDC-DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    rect.top -= 2;
    rect.left -= 2;
    pDC-SetTextColor(GetSysColor(COLOR_GRAYTEXT));
    pDC-DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  }
  else
  {
    if (bHighlight)//光标在按钮上
    {
      if (state & ODS_SELECTED)
        //按下按钮
        pDC-Draw3dRect(rect,GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
      else
        //未按下按钮
        pDC-Draw3dRect(rect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
       //字体颜色
      pDC-SetTextColor(RGB(0,0,255));
      //加下画线(也可以用其他字体)
      if (fUnderline.GetSafeHandle() == NULL)
      {
        CFont * pFont = GetFont();
        ASSERT(pFont);
        LOGFONT lf;
        pFont-GetLogFont(&lf);
        lf.lfUnderline = TRUE;
        fUnderline.CreateFontIndirect(&lf);    
      }
      pOldFont = pDC-SelectObject(&fUnderline);
    }
    else pDC-SetTextColor(GetSysColor(COLOR_BTNTEXT));
    pDC-DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    if (pOldFont) pDC-SelectObject(pOldFont);
  }
}2、定制的消息处理函数 void CLinkButton::OnMouseMove(UINT nFlags, CPoint point)
{
  //设置一个定时器
  SetTimer(1,10,NULL);
  CButton::OnMouseMove(nFlags, point);
}     当鼠标光标移到按钮上时,执行此函数,定时器将发送一个 WM_TIMER消息到消息队列。由OnTimer(UINT nIDEvent)函数处理这个消息。 void CLinkButton::OnTimer(UINT nIDEvent)
{
  static bool pPainted = false;
  POINT pt;
  GetCursorPos(&pt);
  CRect rect;
  GetWindowRect (rect);
  if (bLBtnDown)  
  {    
    KillTimer (1);
    if (pPainted) InvalidateRect (NULL);    
    pPainted = FALSE;    
    return;  
  }
  if (!rect.PtInRect (pt))  
  {    
    bHighlight = false;
    KillTimer (1);
    if (pPainted)      
      InvalidateRect(NULL);
    pPainted = false;
    return;  
  }
  else
  {
    bHighlight = true;
    if (!pPainted)
    {
      pPainted = true;
      InvalidateRect(NULL);
    }
  }
  CButton::OnTimer(nIDEvent);
}
BOOL CLinkButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
  if (bHighlight)
  {
    ::SetCursor(hHand);
    return true;
  }
  return CButton::OnSetCursor(pWnd, nHitTest, message);
}
int CLinkButton::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CButton::OnCreate(lpCreateStruct) == -1)
    return -1;
  CFont * pFont = GetFont();
  ASSERT(pFont);
  LOGFONT lf;
  pFont-GetLogFont(&lf);
  lf.lfUnderline = TRUE;
  fUnderline.CreateFontIndirect(&lf);
  return 0;
}   这个函数由框架在显示出按钮之前自动调用,我在这里初始化按钮上显示的字体。 void CLinkButton::OnLButtonUp(UINT nFlags, CPoint point)
{
  bLBtnDown = false;
  if (bHighlight)  
  {
    bHighlight = false;
    InvalidateRect(NULL);
  }
  CButton::OnLButtonUp(nFlags, point);
}   当按下按钮又放开时调用这个函数。 void CLinkButton::OnLButtonDown(UINT nFlags, CPoint point)
{
  bLBtnDown = true;
  CButton::OnLButtonDown(nFlags, point);
}   当按下按钮时调用这个函数。 BOOL CLinkButton::OnEraseBkgnd(CDC* pDC)
{
  COLORREF cr = GetSysColor(COLOR_3DFACE);
  int r = GetRValue(cr);
  int g = GetGValue(cr);
  int b = GetBValue(cr);
  if (r 1) r -= 2;
  if (g 1) g -= 2;
  if (r 3 && g 3 && b 253) b += 2;
  COLORREF cr1 = RGB(r,g,b);
  CRect rc;
  GetClientRect(rc);
  pDC-FillSolidRect(rc, cr1);
  return CButton::OnEraseBkgnd(pDC);
}   当按钮的背景需要重画时,应用程序框架调用此函数。

  其他实现细节请下载源代码。运行程序的效果图见图一、图二和图三。

展开更多 50%)
分享

猜你喜欢

用VC6扩展CButton类制作风格独特的按钮

编程语言 网络编程
用VC6扩展CButton类制作风格独特的按钮

VC6几个技巧

编程语言 网络编程
VC6几个技巧

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

用VC6编写注册表管理程序

编程语言 网络编程
用VC6编写注册表管理程序

VC用Win API实现自绘按钮类

编程语言 网络编程
VC用Win API实现自绘按钮类

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

VC6中设定命令行参数

编程语言 网络编程
VC6中设定命令行参数

一例奇怪的编译错误(VC6)

编程语言 网络编程
一例奇怪的编译错误(VC6)

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

wps文字查找和替换功能

wps文字查找和替换功能

Visual C++环境下DBGrid控件的使用

Visual C++环境下DBGrid控件的使用
下拉加载更多内容 ↓