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);
}
运行效果: