MFC绘制圆角矩形(MFC)

61 篇文章 0 订阅
1 篇文章 0 订阅

CgdiplusTools.h

#pragma once

#include <afxwin.h>
#include <gdiplus.h>

namespace CgdiplusTools
{
    enum RoundType
    {
        leftTop = 1 << 0,
        rightTop = 1 << 1,
        leftBottom = 1 << 2,
        rightBottom = 1 << 3,
        left = leftTop | leftBottom,
        right = rightTop | rightBottom,
        top = leftTop | rightTop,
        bottom = leftBottom | rightBottom,
        all = leftTop | rightTop | leftBottom | rightBottom
    };

    void GetRoundPath(Gdiplus::GraphicsPath& path, 
        const CRect& rect, 
        int nRound, 
        RoundType type = RoundType::all);

    void DrawRoundRect(CDC& dc, 
        const CRect& rect, 
        int nRound, 
        Gdiplus::Color rectColor = Gdiplus::Color(255,255,255,255), 
        float lineSize = 0.0f,
        Gdiplus::Color lineColor = Gdiplus::Color(0,0,0,0), 
        RoundType type = RoundType::all, 
        bool isFill = true);
};

CgdiplusTools.cpp

#include "CgdiplusTools.h"

namespace CgdiplusTools
{
    void GetRoundPath(
        Gdiplus::GraphicsPath& RoundRectPath, 
        const CRect& rect, 
        int nRound, 
        RoundType type
    )
    {
        int left = rect.left;
        int top = rect.top;
        int right = rect.right;
        int bottom = rect.bottom;

        int nMaxSize = max(rect.Height(), rect.Width());

        if ((nRound * 2) > nMaxSize)
        {
            nRound = nMaxSize / 2;
        }

        {
            int lineTop = top;
            int lineBottom = bottom;

            if (RoundType::rightTop & type)
            {
                lineTop += nRound;
            }
            if (RoundType::rightBottom & type)
            {
                lineBottom -= nRound;
            }

            //右
            RoundRectPath.AddLine(right, lineTop, right, lineBottom);

            //右下
            if (RoundType::rightBottom & type)
            {
                RoundRectPath.AddArc(right - nRound * 2, bottom - nRound * 2, nRound * 2, nRound * 2, 0, 90);
            }
        }

        {
            int lineLeft = left;
            int lineRight = right;

            if (RoundType::leftBottom & type)
            {
                lineLeft += nRound;
            }
            if (RoundType::rightBottom & type)
            {
                lineRight -= nRound;
            }

            //下
            RoundRectPath.AddLine(lineRight, bottom, lineLeft, bottom);

            //左下
            if (RoundType::leftBottom & type)
            {
                RoundRectPath.AddArc(left, bottom - nRound * 2, nRound * 2, nRound * 2, 90, 90);
            }
        }

        {
            int lineTop = top;
            int lineBottom = bottom;

            if (RoundType::leftTop & type)
            {
                lineTop += nRound;
            }
            if (RoundType::leftBottom & type)
            {
                lineBottom -= nRound;
            }

            //左
            RoundRectPath.AddLine(left, lineBottom, left, lineTop);

            //左上
            if (RoundType::leftTop & type)
            {
                RoundRectPath.AddArc(left, top, nRound * 2, nRound * 2, 180, 90);
            }
        }

        {
            int lineLeft = left;
            int lineRight = right;

            if (RoundType::leftTop & type)
            {
                lineLeft += nRound;
            }
            if (RoundType::rightTop & type)
            {
                lineRight -= nRound;
            }

            //上
            RoundRectPath.AddLine(lineLeft, top, lineRight, top);

            //右上
            if (RoundType::rightTop & type)
            {
                RoundRectPath.AddArc(right - nRound * 2, top, nRound * 2, nRound * 2, 270, 90);
            }
        }

        RoundRectPath.CloseFigure();
    }

    void DrawRoundRect(
        CDC& dc, 
        const CRect& rect, 
        int nRound,
        Gdiplus::Color rectColor,
        float lineSize,
        Gdiplus::Color lineColor,
        RoundType type, 
        bool isFill
    )
    {
        Gdiplus::GraphicsPath RoundRectPath;
        Gdiplus::Graphics grap(dc);
        grap.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);

        GetRoundPath(RoundRectPath, rect, nRound, type);

        if (isFill)
        {
            Gdiplus::SolidBrush brush(rectColor);
            grap.FillPath(&brush, &RoundRectPath);
        }

        if (lineSize > 0)
        {
            Gdiplus::Pen pen(lineColor, lineSize);
            grap.DrawPath(&pen, &RoundRectPath);
        }

        grap.ReleaseHDC(dc);
    }
}

mfc.h

#pragma once

#include <afxwin.h>
#include <gdiplus.h>

class CMyApp: public CWinApp
{
public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
};

class CMyFrame : public CFrameWnd
{
public:
    CMyFrame();

    DECLARE_MESSAGE_MAP()

private:
    afx_msg void OnLButtonDown(UINT, CPoint);
    afx_msg int OnCreate(LPCREATESTRUCT);
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnPaint();
    afx_msg void OnDestroy();

private:
    CString m_strInfo;
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
};

mfc.cpp

#include "mfc.h"
#include "CgdiplusTools.h"
#pragma comment(lib, "gdiplus.lib")

CMyApp cApp;

Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_pGdiToken;

BOOL CMyApp::InitInstance()
{
    CMyFrame* frame = new CMyFrame();

    frame->ShowWindow(SW_SHOW);
    frame->UpdateWindow();

    m_pMainWnd = frame;

    return TRUE;
}

int CMyApp::ExitInstance()
{
    return 0;
}

BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)
    ON_WM_LBUTTONDOWN()
    ON_WM_CREATE()
    ON_WM_KEYDOWN()
    ON_WM_PAINT()
    ON_WM_DESTROY()
END_MESSAGE_MAP()

CMyFrame::CMyFrame()
{
    Create(NULL, _T("mfc"), WS_OVERLAPPED);
}

void CMyFrame::OnLButtonDown(UINT msg, CPoint point)
{
    m_strInfo.Format(_T("Msg: %d, X:%d, Y: %d"), msg, point.x, point.y);
    Invalidate(TRUE);
}

BOOL CMyFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: 在此添加专用代码和/或调用基类
    //cs.dwExStyle = WS_EX_LAYERED;
    return CFrameWnd::PreCreateWindow(cs);
}

int CMyFrame::OnCreate(LPCREATESTRUCT)
{
    //SetLayeredWindowAttributes(0, (255 * 50) / 100, LWA_ALPHA);
    Gdiplus::GdiplusStartup(&m_pGdiToken, &m_gdiplusStartupInput, NULL);

    return 0;
}

void CMyFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    m_strInfo.Format(_T("Msg: 0x%X, nRepCnt:%d, nFlags: %d"), nChar, nRepCnt, nFlags);
    Invalidate(TRUE);
}

void CMyFrame::OnPaint()
{
    CPaintDC dc(this);
    dc.SetBkMode(TRANSPARENT);
    dc.TextOut(0, 0, m_strInfo);
    CRect rtBg{100, 100, 200, 150};

    Gdiplus::Color rectColor(255, 255, 0, 0);
    Gdiplus::Color lineColor(255, 0, 255, 0);

    CgdiplusTools::DrawRoundRect(dc, rtBg, 6, rectColor, 4, lineColor);

    rtBg.MoveToX(300);
    CgdiplusTools::DrawRoundRect(dc, rtBg, 6, rectColor, 4, lineColor, CgdiplusTools::leftTop);

    rtBg.MoveToX(500);
    CgdiplusTools::DrawRoundRect(dc, rtBg, 6, rectColor, 4, lineColor, CgdiplusTools::rightTop);

    rtBg.MoveToX(700);
    CgdiplusTools::DrawRoundRect(dc, rtBg, 6, rectColor, 4, lineColor, CgdiplusTools::leftBottom);

    rtBg.MoveToX(900);
    CgdiplusTools::DrawRoundRect(dc, rtBg, 6, rectColor, 4, lineColor, CgdiplusTools::rightBottom);

    rtBg.MoveToX(300);
    rtBg.MoveToY(200);
    CgdiplusTools::DrawRoundRect(dc, rtBg, 6, rectColor, 4, lineColor, CgdiplusTools::left);

    rtBg.MoveToX(500);
    CgdiplusTools::DrawRoundRect(dc, rtBg, 6, rectColor, 4, lineColor, CgdiplusTools::right);

    rtBg.MoveToX(700);
    CgdiplusTools::DrawRoundRect(dc, rtBg, 16, rectColor, 4, lineColor, CgdiplusTools::top);

    rtBg.MoveToX(900);
    CgdiplusTools::DrawRoundRect(dc, rtBg, 16, rectColor, 4, lineColor, CgdiplusTools::bottom);

}

void CMyFrame::OnDestroy()
{
    Gdiplus::GdiplusShutdown(m_pGdiToken);
}

运行效果: 

a6a5e3712353497c8d8a45ac156d52ba.png

 

 

 

MFC 中创建圆角矩形按钮,可以使用 `CButton` 类的派生类,自定义绘制函数来实现。下面是一份示例代码: 1. 创建一个自定义按钮类 `CRoundRectButton` ```c++ class CRoundRectButton : public CButton { public: CRoundRectButton(); virtual ~CRoundRectButton(); protected: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); }; ``` 2. 在 `CRoundRectButton` 类中实现 `DrawItem` 函数,用于绘制圆角矩形按钮 ```c++ void CRoundRectButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect rect = lpDrawItemStruct->rcItem; if (lpDrawItemStruct->itemState & ODS_SELECTED) // 按下状态 { pDC->FillSolidRect(rect, ::GetSysColor(COLOR_BTNFACE)); pDC->DrawEdge(rect, EDGE_SUNKEN, BF_RECT); } else // 正常状态 { pDC->FillSolidRect(rect, ::GetSysColor(COLOR_BTNFACE)); pDC->DrawEdge(rect, EDGE_RAISED, BF_RECT); } // 绘制圆角矩形 int nRound = 10; // 圆角大小 CRect roundRect(rect.left + 2, rect.top + 2, rect.right - 2, rect.bottom - 2); pDC->RoundRect(roundRect, CPoint(nRound, nRound)); } ``` 3. 在对话框类中添加 `CRoundRectButton` 控件,并设置样式 ```c++ CRoundRectButton m_btnRound; m_btnRound.Create(_T("圆角按钮"), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, CRect(50, 50, 150, 80), this, IDC_BTN_ROUNDRECT); ``` 在上面的代码中,`m_btnRound` 是一个 `CRoundRectButton` 类的对象,通过 `Create` 函数创建一个圆角矩形按钮,并设置样式为 `WS_CHILD | WS_VISIBLE | BS_OWNERDRAW`,其中 `BS_OWNERDRAW` 表示该按钮使用自定义绘制函数。 运行程序后即可看到一个圆角矩形按钮
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值