• 用VC6扩展CButton类制*格独特的按钮


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

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


    图一

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


    图二

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


    图三

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

    在VC6的IDE环境中,生成一个基于对话框的PROJECT。 将对话框资源中按钮的属性页打开,在“Style”标签页中选取按钮的“Owner Draw”(自绘)属性。 将光标引入到应用程序的资源中。 利用CLASSWIZARD,用CButton为基类,派生一个新类:CLinkButton。 在派生类中重载基类CButton的虚函数:
    1.virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

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

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

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

    1、重载函数  DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)。

    01.void CLinkButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
    02.{
    03.    // 获取一个CDC指针
    04.    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    05.    //定义按钮区域并初始化
    06.    CRect rect(lpDrawItemStruct->rcItem);
    07.    //设置背景模式
    08.    COLORREF oc = pDC->GetTextColor();
    09.    int iObk = pDC->SetBkMode(TRANSPARENT);
    10.    //初始化按钮状态
    11.    UINT state = lpDrawItemStruct->itemState;
    12.    CFont * pOldFont = NULL;
    13.    int iYOffset = 0, iXOffset = 0;
    14.    CString strText;
    15.    GetWindowText(strText);
    16.    rect.top  += iYOffset;
    17.    rect.left += iXOffset;
    18.  
    19.    if (state & ODS_DISABLED)
    20.    {       
    21.        //按钮置灰(DISABLED)
    22.        CBrush grayBrush;
    23.        grayBrush.CreateSolidBrush (GetSysColor (COLOR_GRAYTEXT));
    24.        CSize sz = pDC->GetTextExtent(strText);
    25.        int x = rect.left + (rect.Width() - sz.cx)/2;
    26.        int y = rect.top + (rect.Height() - sz.cy)/2;
    27.        rect.top  += 2;
    28.        rect.left += 2;
    29.        pDC->SetTextColor(GetSysColor(COLOR_3DHIGHLIGHT));
    30.        pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    31.        rect.top  -= 2;
    32.        rect.left -= 2;
    33.        pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
    34.        pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    35.    }
    36.    else
    37.    {
    38.        if (bHighlight)//光标在按钮上
    39.        {
    40.            if (state & ODS_SELECTED)
    41.                //按下按钮
    42.                pDC->Draw3dRect(rect,GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
    43.            else
    44.                //未按下按钮
    45.                pDC->Draw3dRect(rect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
    46.                  
    47.            //字体颜色
    48.            pDC->SetTextColor(RGB(0,0,255));
    49.  
    50.            //加下画线(也可以用其他字体)
    51.            if (fUnderline.GetSafeHandle() == NULL)
    52.            {
    53.                CFont * pFont = GetFont();
    54.                ASSERT(pFont);
    55.                LOGFONT lf;
    56.                pFont->GetLogFont(&lf);
    57.                lf.lfUnderline = TRUE;
    58.                fUnderline.CreateFontIndirect(&lf);     
    59.            }
    60.            pOldFont = pDC->SelectObject(&fUnderline);
    61.        }
    62.        else pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
    63.  
    64.        pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    65.          
    66.        if (pOldFont) pDC->SelectObject(pOldFont);
    67.    }
    68.}

    2、定制的消息处理函数

    1.void CLinkButton::OnMouseMove(UINT nFlags, CPoint point) 
    2.{
    3.    //设置一个定时器
    4.    SetTimer(1,10,NULL);
    5.      
    6.    CButton::OnMouseMove(nFlags, point);
    7.}

    当鼠标光标移到按钮上时,执行此函数,定时器将发送一个 WM_TIMER消息到消息队列。由OnTimer(UINT nIDEvent)函数处理这个消息。

    01.void CLinkButton::OnTimer(UINT nIDEvent) 
    02.{
    03.    static bool pPainted = false;
    04.    POINT pt;
    05.    GetCursorPos(&pt);
    06.    CRect rect;
    07.    GetWindowRect (rect);
    08.    if (bLBtnDown)  
    09.    {       
    10.        KillTimer (1);
    11.        if (pPainted) InvalidateRect (NULL);        
    12.        pPainted = FALSE;       
    13.        return
    14.    }
    15.  
    16.    if (!rect.PtInRect (pt))    
    17.    {       
    18.        bHighlight = false;
    19.        KillTimer (1);
    20.  
    21.        if (pPainted)           
    22.            InvalidateRect(NULL);
    23.  
    24.        pPainted = false;
    25.        return
    26.    }
    27.    else
    28.    {
    29.        bHighlight = true;
    30.        if (!pPainted)
    31.        {
    32.            pPainted = true;
    33.            InvalidateRect(NULL);
    34.        }
    35.    }
    36.  
    37.    CButton::OnTimer(nIDEvent);
    38.}
    39.  
    40.  
    41.BOOL CLinkButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
    42.{
    43.    if (bHighlight) 
    44.    {
    45.        ::SetCursor(hHand);
    46.        return true;
    47.    }
    48.      
    49.    return CButton::OnSetCursor(pWnd, nHitTest, message);
    50.}
    51.  
    52.  
    53.int CLinkButton::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    54.{
    55.    if (CButton::OnCreate(lpCreateStruct) == -1)
    56.        return -1;
    57.      
    58.    CFont * pFont = GetFont();
    59.    ASSERT(pFont);
    60.  
    61.    LOGFONT lf;
    62.    pFont->GetLogFont(&lf);
    63.    lf.lfUnderline = TRUE;
    64.  
    65.    fUnderline.CreateFontIndirect(&lf);
    66.      
    67.    return 0;
    68.}

    这个函数由框架在显示出按钮之前自动调用,我在这里初始化按钮上显示的字体。

    01.void CLinkButton::OnLButtonUp(UINT nFlags, CPoint point) 
    02.{
    03.    bLBtnDown = false;
    04.    if (bHighlight) 
    05.    {
    06.        bHighlight = false;
    07.        InvalidateRect(NULL);
    08.    }
    09.      
    10.    CButton::OnLButtonUp(nFlags, point);
    11.}

    当按下按钮又放开时调用这个函数。

    1.void CLinkButton::OnLButtonDown(UINT nFlags, CPoint point) 
    2.{
    3.    bLBtnDown = true;
    4.      
    5.    CButton::OnLButtonDown(nFlags, point);
    6.}

    当按下按钮时调用这个函数。

    01.BOOL CLinkButton::OnEraseBkgnd(CDC* pDC) 
    02.{
    03.    COLORREF cr = GetSysColor(COLOR_3DFACE);
    04.    int r = GetRValue(cr);
    05.    int g = GetGValue(cr);
    06.    int b = GetBValue(cr);
    07.    if (r > 1) r -= 2;
    08.    if (g > 1) g -= 2;
    09.    if (r < 3 && g < 3 && b < 253) b += 2;
    10.    COLORREF cr1 = RGB(r,g,b);
    11.    CRect rc;
    12.    GetClientRect(rc);
    13.    pDC->FillSolidRect(rc, cr1);
    14.      
    15.    return CButton::OnEraseBkgnd(pDC);
    16.}

    当按钮的背景需要重画时,应用程序框架调用此函数。

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

    from:http://www.vckbase.com/index.php/wv/8

  • 相关阅读:
    网页中让flash在最底层显示
    在asp.net mvc模式下怎么实现导出Excel文件
    Tomcat的内存溢出(PermGen space)
    CentOS下安装7zip
    CentOS安装keychain
    HTML中添加水平滚动文字
    getOutputStream() has already been called for this response的解决方法
    小型服务器的分区方案
    Mysql导出存储过程
    CentOS安装FileZilla时找不到libtasn1.so.3
  • 原文地址:https://www.cnblogs.com/lidabo/p/2821128.html
Copyright © 2020-2023  润新知