首页 > 学院 > 开发设计 > 正文

MFC:三角形按钮(重绘CButton)

2019-11-14 08:53:40
字体:
来源:转载
供稿:网友

头文件 TriangleButton.h:

#ifndef __TRIANGLEBUTTON_H__INCLUDED#define __TRIANGLEBUTTON_H__INCLUDEDenum POINTDIRECTION { POINT_UP, POINT_DOWN, POINT_LEFT, POINT_RIGHT };class CTriangleButton : public CButton{public:    CTriangleButton();    virtual ~CTriangleButton();PRotected:    POINTDIRECTION PointDirection;    CRgn CurrentRegion;public:    public:    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);    protected:    virtual void PreSubclassWindow();    BOOL SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags );public:    void SetDirection(POINTDIRECTION PointDirection);    //sets the direction of triangle    POINTDIRECTION GetDirection();                        //gets the direction of triangleprotected:    DECLARE_MESSAGE_MAP()};#endif

源文件 TriangleButton.cpp:

#include "stdafx.h"#include "math.h"#include "TriangleButton.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCTriangleButton::CTriangleButton(){    PointDirection = POINT_RIGHT;}CTriangleButton::~CTriangleButton(){}BEGIN_MESSAGE_MAP(CTriangleButton, CButton)    ON_WM_NCHITTEST()END_MESSAGE_MAP()void CTriangleButton::SetDirection(POINTDIRECTION Direction){    PointDirection = Direction;    PreSubclassWindow();}POINTDIRECTION CTriangleButton::GetDirection(){    return PointDirection;}BOOL CTriangleButton::SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags){    //Size must be dividable by two (else triangle will look strange when drawn)    cx -= cx % 2;     cy -= cy % 2;    return CButton::SetWindowPos(pWndInsertAfter, x, y, cx, cy, nFlags);}// CRoundButton message handlersvoid CTriangleButton::PreSubclassWindow() {    CButton::PreSubclassWindow();    CRect rect;    GetClientRect(rect);    rect.bottom = rect.right = min(rect.bottom, rect.right);    //make it square    rect.bottom -= rect.bottom % 2;     rect.right  -= rect.right % 2;    SetWindowPos(NULL, 0, 0, rect.right, rect.bottom, SWP_NOMOVE | SWP_NOZORDER);    CPoint Head, RightLeg, LeftLeg;    switch (PointDirection)    {        case POINT_UP :            {                Head.x = rect.right / 2;                 Head.y = 0;                RightLeg.x = rect.right;                 RightLeg.y = rect.bottom;                LeftLeg.x = 0;                 LeftLeg.y = rect.bottom;            }            break;        case POINT_DOWN :            {                Head.x = rect.right / 2;                 Head.y = rect.bottom;                RightLeg.x = 0;                 RightLeg.y = 0;                LeftLeg.x = rect.right;                LeftLeg.y = 0;            }            break;        case POINT_LEFT :            {                Head.x = 0;                 Head.y = rect.bottom / 2;                RightLeg.x = rect.right;                 RightLeg.y = 0;                LeftLeg.x = rect.right;                 LeftLeg.y = rect.bottom;            }            break;        case POINT_RIGHT :            {                Head.x = rect.right;                 Head.y = rect.bottom / 2;                RightLeg.x = 0;                 RightLeg.y = rect.bottom;                LeftLeg.x = 0;                 LeftLeg.y = 0;            }            break;        default :            ASSERT(FALSE);    }//switch                                CPoint points[3];    points[0] = Head;     points[1] = RightLeg;     points[2] = LeftLeg;        SetWindowRgn(NULL, FALSE);    CurrentRegion.DeleteObject();    CurrentRegion.CreatePolygonRgn(points, 3, ALTERNATE);    SetWindowRgn(CurrentRegion, TRUE);            ModifyStyle(0, BS_OWNERDRAW);}void CTriangleButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {    ASSERT(lpDrawItemStruct != NULL);    CRect rect = lpDrawItemStruct->rcItem;    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);    UINT state = lpDrawItemStruct->itemState;    UINT nStyle = GetStyle();    int nSavedDC = pDC->SaveDC();    //make the rect a square    rect.bottom = rect.right = min(rect.bottom, rect.right);    pDC->FillSolidRect(rect, ::GetSysColor(COLOR_BTNFACE));        rect.right -= 1; rect.bottom -= 1;    //avoid drawing outside area    CPen HighlightPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT));    CPen DarkShadowPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW));    CPen ShadowPen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));    CPen BlackPen(PS_SOLID, 1, RGB(0,0,0));    CPen FocusPen(PS_DOT, 0, RGB(0,0,0));    //Draw button    switch (PointDirection)     {        case POINT_UP :         {            if (nStyle & BS_FLAT)             {                pDC->SelectObject(BlackPen);                pDC->MoveTo(rect.right / 2, 0);                pDC->LineTo(0, rect.bottom);                pDC->LineTo(rect.right, rect.bottom);                pDC->LineTo(rect.right / 2, 0);                pDC->SelectObject(HighlightPen);                pDC->MoveTo(rect.right / 2, 2);                pDC->LineTo(2, rect.bottom - 1);                pDC->LineTo(rect.right - 2, rect.bottom - 1);                pDC->LineTo(rect.right / 2, 2);            }            else             {                if ((state & ODS_SELECTED))                    {                    pDC->SelectObject(HighlightPen);                    pDC->MoveTo(0, rect.bottom);                    pDC->LineTo(rect.right - 1, rect.bottom);                    pDC->LineTo(rect.right / 2, 0);                    pDC->SelectObject(ShadowPen);                    pDC->LineTo(0, rect.bottom);                                                    pDC->SelectObject(DarkShadowPen);                    pDC->MoveTo(rect.right / 2 - 1, 4);                    pDC->LineTo(1, rect.bottom);                }                else                {                    pDC->SelectObject(HighlightPen);                    pDC->MoveTo(rect.right /2, 0);                    pDC->LineTo(0, rect.bottom - 1);                                        pDC->SelectObject(ShadowPen);                    pDC->LineTo(rect.right - 1, rect.bottom - 1);                    pDC->LineTo(rect.right / 2, 0);                    pDC->SelectObject(DarkShadowPen);                    pDC->MoveTo(rect.right / 2 + 2, 3);                    pDC->LineTo(rect.right + 1, rect.bottom + 1);                                        pDC->MoveTo(rect.right - 1, rect.bottom);                    pDC->LineTo(1, rect.bottom);                }            }        }        break;        case POINT_DOWN :         {            if (nStyle & BS_FLAT)            {                pDC->SelectObject(BlackPen);                pDC->MoveTo(rect.right / 2, rect.bottom);                pDC->LineTo(0, 0);                pDC->LineTo(rect.right, 0);                pDC->LineTo(rect.right / 2, rect.bottom);                                pDC->SelectObject(HighlightPen);                pDC->MoveTo(rect.right / 2, rect.bottom - 2);                pDC->LineTo(2, 1);                pDC->LineTo(rect.right - 2, 1);                pDC->LineTo(rect.right / 2, rect.bottom - 2);            }            else            {                if ((state & ODS_SELECTED))                {                    pDC->SelectObject(ShadowPen);                    pDC->MoveTo(rect.right, 1);                    pDC->LineTo(1, 1);                    pDC->LineTo(rect.right / 2, rect.bottom - 1);                                        pDC->SelectObject(BlackPen);                    pDC->MoveTo(rect.right - 2, 2);                    pDC->LineTo(1, 2);                                        pDC->SelectObject(HighlightPen);                    pDC->MoveTo(rect.right + 1, 0);                    pDC->LineTo(rect.right / 2 + 1, rect.bottom + 1);                }                else                {                    pDC->SelectObject(ShadowPen);                    pDC->MoveTo(0, 0);                    pDC->LineTo(rect.right / 2, rect.bottom);                    pDC->LineTo(rect.right, 0);                    pDC->MoveTo(1, 1);                    pDC->LineTo(rect.right / 2 + 1, rect.bottom);                                        pDC->SelectObject(DarkShadowPen);                    pDC->MoveTo(rect.right, 2);                    pDC->LineTo(rect.right / 2 + 1, rect.bottom + 1);                                        pDC->SelectObject(HighlightPen);                    pDC->MoveTo(0, 0);                    pDC->LineTo(rect.right, 0);                                }            }        }        break;        case POINT_LEFT :        {            if (nStyle & BS_FLAT)            {                pDC->SelectObject(BlackPen);                pDC->MoveTo(rect.right, 0);                pDC->LineTo(0, rect.bottom / 2);                pDC->LineTo(rect.right, rect.bottom);                pDC->LineTo(rect.right, 0);                                pDC->SelectObject(HighlightPen);                pDC->MoveTo(rect.right - 1, 2);                pDC->LineTo(3, rect.bottom / 2);                pDC->LineTo(rect.right - 1, rect.bottom - 2);                pDC->LineTo(rect.right - 1, 2);            }            else            {                if ((state & ODS_SELECTED))                {                    pDC->SelectObject(ShadowPen);                    pDC->MoveTo(rect.right, 0);                    pDC->LineTo(0, rect.bottom / 2);                    pDC->SelectObject(DarkShadowPen);                    pDC->MoveTo(rect.right, 1);                    pDC->LineTo(2, rect.bottom / 2);                                        pDC->SelectObject(HighlightPen);                    pDC->MoveTo(rect.right, 0);                    pDC->LineTo(rect.right, rect.bottom);                    pDC->LineTo(0, rect.bottom / 2);                }                else                {                    pDC->SelectObject(ShadowPen);                    pDC->MoveTo(rect.right - 1, 0);                    pDC->LineTo(rect.right - 1, rect.bottom - 1);                    pDC->LineTo(0, rect.bottom / 2);                    pDC->MoveTo(1, rect.bottom / 2 + 1);                    pDC->LineTo(6, rect.bottom / 2 + 4);                    pDC->SelectObject(DarkShadowPen);                    pDC->MoveTo(rect.right, 1);                    pDC->LineTo(rect.right, rect.bottom);                    pDC->LineTo(2, rect.bottom / 2 + 2);                                        pDC->SelectObject(HighlightPen);                    pDC->MoveTo(0, rect.bottom / 2);                    pDC->LineTo(rect.right, 0);                }            }        }        break;        case POINT_RIGHT :        {            if (nStyle & BS_FLAT)            {                pDC->SelectObject(BlackPen);                pDC->MoveTo(0, 0);                pDC->LineTo(rect.right, rect.bottom / 2);                pDC->LineTo(0, rect.bottom);                pDC->LineTo(0, 0);                                pDC->SelectObject(HighlightPen);                pDC->MoveTo(1, 2);                pDC->LineTo(rect.right - 2, rect.bottom / 2);                pDC->LineTo(1, rect.bottom - 2);                pDC->LineTo(1, 2);            }            else            {                if ((state & ODS_SELECTED))                {                    pDC->SelectObject(ShadowPen);                    pDC->MoveTo(0, rect.bottom);                    pDC->LineTo(0, 0);                    pDC->LineTo(rect.right, rect.bottom / 2);                    pDC->SelectObject(DarkShadowPen);                    pDC->MoveTo(1, rect.bottom - 2);                    pDC->LineTo(1, 1);                    pDC->MoveTo(rect.right - 3, rect.bottom / 2);                    pDC->LineTo(0, 1);                                        pDC->SelectObject(HighlightPen);                    pDC->MoveTo(0, rect.bottom);                    pDC->LineTo(rect.right, rect.bottom / 2);                                    }                else                {                    pDC->SelectObject(ShadowPen);                    pDC->MoveTo(0, rect.bottom);                    pDC->LineTo(rect.right, rect.bottom / 2);                    pDC->SelectObject(DarkShadowPen);                    pDC->MoveTo(0, rect.bottom + 1);                    pDC->LineTo(rect.right, rect.bottom / 2 + 1);                                        pDC->SelectObject(HighlightPen);                    pDC->MoveTo(0, rect.bottom);                    pDC->LineTo(0, 0);                    pDC->LineTo(rect.right, rect.bottom / 2);                }            }        }        break;        default :            ASSERT(FALSE);    }//switch    //Draw text    CString strText;    GetWindowText(strText);    if (!strText.IsEmpty())    {        CSize TextExtent = pDC->GetTextExtent(strText);        CPoint TextPos;        pDC->SetBkMode(TRANSPARENT);        switch (PointDirection)        {            case POINT_UP :            {                TextPos = CPoint((int)(rect.right / 2.0 - TextExtent.cx / 2.0), rect.bottom - (int)(rect.bottom / 5.0 + TextExtent.cy));                int iXLimit = (int)((rect.bottom / 5.0 + TextExtent.cy) * 4.0 / 7.0);                CRgn rgn;                 rgn.CreateRectRgn(iXLimit, TextPos.y, rect.right - iXLimit, rect.bottom - 2);                pDC->SelectClipRgn(&rgn);                        }            break;            case POINT_DOWN :            {                TextPos = CPoint((int)(rect.right / 2.0 - TextExtent.cx / 2.0), (int)(rect.bottom / 5.0));                int iXLimit = (int)((rect.bottom / 5.0 + TextExtent.cy) * 4.0 / 7.0);                CRgn rgn; rgn.CreateRectRgn(iXLimit, (int)(rect.bottom / 5.0), rect.right - iXLimit, (int)(rect.bottom / 5.0) + TextExtent.cy + 2);                pDC->SelectClipRgn(&rgn);            }            break;            case POINT_LEFT :            {                TextPos = CPoint((int)((rect.right / 2.0 - TextExtent.cx / 2.0) + (rect.right / 8.0)), (int)(rect.bottom / 2.0 - TextExtent.cy / 2.0) );                int iXLimitLeft = (int)(TextExtent.cy / 2.0 * 7.0 / 4.0) + 4;                int iXLimitRight = rect.right - 4;                            CRgn rgn; rgn.CreateRectRgn(iXLimitLeft, (int)(rect.bottom / 2.0 - TextExtent.cy / 2.0), iXLimitRight, (int)(rect.bottom / 2.0 + TextExtent.cy / 2.0) );                pDC->SelectClipRgn(&rgn);            }            break;            case POINT_RIGHT :            {                TextPos = CPoint((int)((rect.right / 2.0 - TextExtent.cx / 2.0) - (rect.right / 8.0)), (int)(rect.bottom / 2.0 - TextExtent.cy / 2.0) );                int iXLimitLeft = 4;                int iXLimitRight = rect.right - (int)(TextExtent.cy / 2.0 * 7.0 / 4.0) - 4;                                    CRgn rgn; rgn.CreateRectRgn(iXLimitLeft, (int)(rect.bottom / 2.0 - TextExtent.cy / 2.0), iXLimitRight, (int)(rect.bottom / 2.0 + TextExtent.cy / 2.0) );                pDC->SelectClipRgn(&rgn);            }            break;            default :                ASSERT(FALSE);        }//switch        //common for all directions        if (state & ODS_SELECTED)        {            TextPos.Offset(1,1);        }        if (state & ODS_DISABLED)        {            pDC->DrawState(TextPos, TextExtent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);        }        else        {            pDC->TextOut(TextPos.x, TextPos.y, strText);        }    }    //Draw the focus triangle on the inside of the button if we have focus    if ((state & ODS_FOCUS))    {        CRgn rgn;         rgn.CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);        pDC->SelectClipRgn(&rgn);        pDC->SelectObject(FocusPen);        switch (PointDirection)        {            case POINT_UP:            {                pDC->MoveTo(rect.right / 2, 12);                pDC->LineTo(9, rect.bottom - 6);                pDC->LineTo(rect.right - 9, rect.bottom - 6);                pDC->LineTo(rect.right / 2, 12);            }            break;            case POINT_DOWN:            {                pDC->MoveTo(rect.right / 2 + 1, rect.bottom - 13);                pDC->LineTo(10, 6);                pDC->LineTo(rect.right - 9, 6);                pDC->LineTo(rect.right / 2 + 1, rect.bottom - 13);            }            break;            case POINT_LEFT:            {                pDC->MoveTo(12, rect.bottom / 2);                pDC->LineTo(rect.right - 6, 9);                pDC->LineTo(rect.right - 6, rect.bottom - 9);                pDC->LineTo(12, rect.bottom / 2);            }            break;            case POINT_RIGHT:            {                pDC->MoveTo(6, 9);                pDC->LineTo(rect.right - 12, rect.bottom / 2);                pDC->LineTo(6, rect.bottom - 9);                pDC->LineTo(6, 9);            }            break;            default:                ASSERT(FALSE);        }//switch    }    pDC->RestoreDC(nSavedDC);}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表