• VC++中对话框界面重绘3按钮的重绘


    在MFC下编程,很多时候对于标准的按钮控件不是很满意,想要弄的美观些。这就需要按钮重绘。重绘按钮一般的实现方法就是重写CButton类。

           首先给工程添加一个自绘按钮类MyDrawButton,基类为CButton。要想让按钮具备自绘功能,就要为按钮添加BS_OWNERDRAW属性。为类CButton重载PreSubclassWindow虚函数。在该函数中添加如下一行代码:

          SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);

           当按钮控件具有了自绘功能之后,每次控件状态改变都会触发DrawItem函数,在该函数中来绘制按钮的形态外观,所以第二步就要重载DrawItem虚函数。在这个函数中就可以自由发挥了,比如绘制背景,底色,按钮标题,绘制文本字体样式等等。

           一般都会为按钮定义几种不同状态时的外观,比如光标滑过时的状态,按钮按下时的状态,按钮禁用时的状态,以及按钮的正常状态等等。这就要为新的按钮添加几种重要的消息响应。比如WM_MOUSELEAVE消息,WM_MOUSEHOVER消息和WM_MOUSEMOVE消息等等,值得一提的是前两个消息的响应函数需要自己手动添加,微软提供了一个TrackMouseEvent函数在光标离开一个窗口时投递WM_MOUSELEAVE消息,光标滑过窗口时投递WM_MOUSEHOVER消息。一般来说可以在WM_MOUSEMOVE消息响应函数中调用TrackMouseEvent函数来投递WM_MOUSELEAVE消息和WM_MOUSEHOVER消息。然后在WM_MOUSELEAVE消息的响应函数中标记“光标已经离开按钮”,然后调用InvalidateRect函数让按钮重绘。在WM_MOUSEHOVER消息的响应函数中标记“光标正在按钮上方”,并调用InvalidateRect函数让按钮重绘。

           在本文中,重绘按钮分为3个部分。

    (1)绘制按钮背景样式,即绘制背景bmp位图,使得按钮具有自定义的样式,同时在绘制按钮背景的输出位图时采用TransparentBlt()函数,该函数的作用是使窗体上显示位图的背景与窗体背景色融为一体,不仅可以显示按钮bmp位图样式,而且还可以使背景透明。

    (2)就是绘制按钮上的文本。主要绘制按钮上文本的样式,包括字体大小,字体样式,字体颜色等属性。

    (3)实现不同状态下的按钮的外观样式,主要包括WM_MOUSEMOVE和WM_MOUSELEAVE两个消息的消息处理函数。分别实现鼠标在按钮区域上和不在按钮区域上的状态。为了标记鼠标移动到按钮区域内停留,需要用到一个定时器来标记鼠标是否还在按钮区域内停留。在WM_MOUSEMOVE内启动定时器,触发WM_MOUSELEAVE消息时结束定时器即销毁定时器。定时器的主要代码如下:

    void MyDrawButton::OnTimer(UINT_PTR nIDEvent)

    {

        // TODO: 在此添加消息处理程序代码和/或调用默认值

        if(nIDEvent != 24)

            return;

        CPoint  point;

        CRect   rect;

        GetWindowRect(&rect);  

        GetCursorPos(&point);

        // 如果鼠标离开按钮区域,重绘按钮

        if (!rect.PtInRect(point) && m_bMove)

        {

            KillTimer (24);

            m_DrawState=ST_MOVEOUT;

            m_bMove=FALSE;

            Draw();

        }

        CButton::OnTimer(nIDEvent);

    }

    重绘按钮类MyDrawButton的主要实现代码如下:

    定义的一些重绘用到的变量:

    #define ST_MOVEIN       0//绘制状态—在按钮区域上

    #define ST_MOVEOUT      1 //绘制状态—不在按钮区域上

    int m_DrawState;//绘制状态 

        int m_nBmpID;//当前显示的背景bmp位图的资源ID

        bool m_bMove;//鼠标是否进入按钮区域

        COLORREF m_clText;//当前文本颜色

        COLORREF m_clActiveText;//鼠标进入按钮区域时文本颜色

        COLORREF m_clNormalText;//鼠标离开按钮区域时文本颜色

       

    消息处理函数和定义的函数:

    void MyDrawButton::PreSubclassWindow()

    {

        SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);

    }

    void MyDrawButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

    {

        Draw();//绘制按钮

    }

    void MyDrawButton::Draw()//绘制按钮

    {

        DrawBackground();//绘制按钮bmp位图,并使背景透明化

        DrawText();//绘制按钮上的文本

    }

    void MyDrawButton::DrawText()

    {//绘制按钮上的文本的字体大小、样式等

        CString     itemString;

        CRect  clientRect;

        CClientDC  dc(this);

        GetClientRect(&clientRect);

        GetWindowText(itemString);

        if(itemString)

        {

            CSize size=dc.GetTextExtent (itemString);//获得所选字体中指定字符串的高度和宽度

            int rectwidth=clientRect.Width();

            int rectheight=clientRect.Height();

            int textwidth=size.cx ;

            int textheight=size.cy ;       

            int x,y; // 文本的位置

            // 计算文本的输出位置

            x=(rectwidth-textwidth)/2;//水平居中

            y=(rectheight-textheight)/2;//垂直居中         

            switch(m_DrawState)

            {

            case ST_MOVEIN://鼠标进入按钮区域

                m_clText=m_clActiveText;

                break;

            case ST_MOVEOUT://鼠标离开按钮区域

                m_clText=m_clNormalText;

                break;

            default:

                m_clText=m_clNormalText;

                break;

            }

            dc.SetTextColor(m_clText);

            dc.SetBkMode(TRANSPARENT);

            CFont *font ;

            font =new CFont();

            int fontSize = 14;  font->CreateFont(fontSize,0,0,0,FW_BOLD,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_SWISS,_T("宋体"));

            dc.SelectObject(font);

            dc.TextOut (x,y,itemString);

        }

    }

    void MyDrawButton::SetBkBmp(int nBmpID)

    {//设置按钮bmp位图样式

        m_nBmpID = nBmpID;

    }

    void MyDrawButton::DrawBackground()

    {//绘制按钮bmp位图,并使背景透明化

        CRect winRC;

        CDC* pDC=GetWindowDC();

        CDC memDC;

        memDC.CreateCompatibleDC(pDC);

        BITMAPINFO bmpInfo;

        CBitmap bmp;   

        GetWindowRect(&winRC);

       

        bmp.LoadBitmap(m_nBmpID);

        bmp.GetObject(sizeof(BITMAPINFO),&bmpInfo);

        int nBmpCX = bmpInfo.bmiHeader.biWidth;

        int nBmpCY = bmpInfo.bmiHeader.biHeight;

        memDC.SelectObject(bmp);

        pDC->TransparentBlt(0,0,nBmpCX,nBmpCY,&memDC,0,0,

            nBmpCX,nBmpCY,RGB(14,94,157));//在窗口中绘制位图,RGB(14,94,157)是透明色

        bmp.DeleteObject();

        ReleaseDC(pDC);

    }

    到此,按钮的自定义重绘完成了,接下来就可以使用自己重绘的按钮类MyDrawButton了。首先往对话框中添加一个按钮控件,假设它的ID值为IDC_TEST。进入类向导(Class Wizard)的成员变量属性页,为IDC_ TEST添加一个变量m_ testButton。如下:

    MyDrawButton m_testButton;

    然后就可以调用MyDrawButton的方法来设置按钮的样式了。如下:

    m_testButton.SetBkBmp(IDB_TEST);//IDB_TEST为所设置的bmp位图资源ID。

    到现在为止,按钮类的重绘完成了,可以随意定义自己喜欢的样式的按钮了。带有自定义按钮的对话框重绘效果图如下:

    好了,到此,对话框的重绘基本完成了,希望对需要的人有所帮助吧。

    想要下载源代码的可以到我的CSDN上下载:http://download.csdn.net/detail/jczmdeveloper/5004541 

  • 相关阅读:
    UVA 10604 Chemical Reaction
    UVA 10635 Prince and Princess
    UVA 607 Scheduling Lectures
    Create Maximo Report
    安裝及配置Maximo Report步驟
    check blocking
    數據據類型縮寫
    .net
    poj3522
    poj1286
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/2964931.html
Copyright © 2020-2023  润新知