作者:刘树伟
www.iuishop.com
LibUIDK界面库系列文档
日期:2017-09-14 11:04
使用代码绘制CheckBox
DWORD FormsDrawDiagonalLine(HDC hdc, LPRECT lprc, int iDirection, int iThickness, UINT flags)
{
RECT rc;
LPINT py;
int cx;
int cy;
int dx;
int dy;
LPINT pc;
int cxBorder = GetSystemMetrics(SM_CXBORDER);
int cyBorder = GetSystemMetrics(SM_CYBORDER);
if (IsRectEmpty(lprc))
{
return (0L);
}
CopyRect(&rc, lprc);
//
// We draw slopes < 1 by varying y instead of x.
//
--iThickness;
// HACK HACK HACK. REMOVE THIS ONCE MARLETT IS AROUND
cy = rc.bottom - rc.top;
cx = rc.right - rc.left;
if (!flags && (cy != cx))
{
cy -= iThickness * cyBorder;
}
if (cy >= cx)
{
// "slope" is >= 1, so vary x by 1
cy /= cx;
pc = &cy;
cx = cxBorder;
}
else
{
// "slope" is < 1, so vary y by 1
cx /= cy;
pc = &cx;
cy = cyBorder;
}
dx = cx;
dy = iDirection * cy;
*pc = (*pc + iThickness) * cyBorder;
rc.right -= cx;
rc.bottom -= cy;
// For negative slopes, start from opposite side.
if (iDirection < 0)
{
py = (int *)&rc.top;
}
else
{
py = (int *)&rc.bottom;
}
while ((rc.left <= rc.right) && (rc.top <= rc.bottom))
{
if (!(flags & BF_MIDDLE))
{
PatBlt(hdc, rc.left, *py, cx, cy, PATCOPY);
}
else
{
// Fill interior. We can determine vertex in interior
// by vector define.
if (cy > cyBorder)
{
if (flags & BF_LEFT)
{
PatBlt(hdc, rc.left, lprc->top, cx, *py - lprc->top + cy, PATCOPY);
}
else
{
PatBlt(hdc, rc.left, *py, cx, lprc->bottom - *py, PATCOPY);
}
}
else
{
if (flags & BF_TOP)
{
PatBlt(hdc, rc.left, *py, lprc->right - rc.left, cy, PATCOPY);
}
else
{
PatBlt(hdc, lprc->left, *py, rc.left - lprc->left + cx, cy, PATCOPY);
}
}
}
rc.left += dx;
*py -= dy;
}
return (MAKELONG(cx, cy));
}
BOOL FormsDrawCheckMark(HDC hdc, LPRECT lprc, int iThickness)
{
int i = (lprc->right - lprc->left + 2) / 3;
int saveRight = lprc->right;
lprc->top += ((lprc->bottom - lprc->top - (i * 2)) / 2) + i - 1;
lprc->bottom = lprc->top + i + (iThickness - 1);
lprc->left += (lprc->right - lprc->left - ((i * 3) - 1)) / 2;
lprc->right = lprc->left + i - 1;
FormsDrawDiagonalLine(hdc, lprc, -1, iThickness, 0);
lprc->top -= i;
lprc->left = lprc->right;
lprc->right = saveRight;
FormsDrawDiagonalLine(hdc, lprc, 1, iThickness, 0);
return (TRUE);
}
GraphicsPath *CreateRoundRectRgnGp(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse)
{
int nLeft = min(nLeftRect, nRightRect);
int nRight = max(nLeftRect, nRightRect);
int nTop = min(nTopRect, nBottomRect);
int nBottom = max(nTopRect, nBottomRect);
GraphicsPath *pPathRet = ::new GraphicsPath();
// 右上角的圆弧,第5个参数表示圆弧的起始角度(x轴向右为0度,顺时针为正);第6个参数表示圆弧扫过的角度。
pPathRet->AddArc(nRight - nWidthEllipse, nTop, nWidthEllipse, nHeightEllipse, 270, 90);
// 右下角
pPathRet->AddArc(nRight - nWidthEllipse, nBottom - nHeightEllipse, nWidthEllipse, nHeightEllipse, 0, 90);
// 左下角
pPathRet->AddArc(nLeft, nBottom - nHeightEllipse, nWidthEllipse, nHeightEllipse, 90, 90);
// 左上角
pPathRet->AddArc(nLeft, nTop, nWidthEllipse, nHeightEllipse, 180, 90);
// 封闭Path
pPathRet->CloseFigure();
return pPathRet;
}
// lprcCheckMarkMargin: 对勾相对于CheckBox边距
// nLineWidth, 对钩的线宽
int DrawCheckBox(HDC hDC, LPCRECT lprc, COLORREF crBk,
COLORREF crBorder, int nBorderWeight, int nBorderCorner, LPCRECT lprcCheckMarkMargin, int nLineWidth)
{
Graphics g(hDC);
g.SetSmoothingMode(SmoothingModeAntiAlias);
int nWidth = lprc->right - lprc->left;
int nHeight = lprc->bottom - lprc->top;
// 画背景
Color crBackground;
crBackground.SetFromCOLORREF(crBk);
SolidBrush crBrush(crBackground);
GraphicsPath *pgp = CreateRoundRectRgnGp(lprc->left, lprc->top, lprc->right, lprc->bottom, nBorderCorner, nBorderCorner);
g.FillPath(&crBrush, pgp);
// 画边框
if (nBorderWeight > 0)
{
Color cr;
cr.SetFromCOLORREF(crBorder);
Pen pen(cr, (REAL)nBorderWeight);
g.DrawPath(&pen, pgp);
}
::delete pgp;
// 画对勾
CRect rc(lprc);
if (lprcCheckMarkMargin != NULL)
{
rc.DeflateRect(lprcCheckMarkMargin);
}
FormsDrawCheckMark(hDC, rc, nLineWidth);
return 0;
}
用法:
DrawCheckBox(hDC, CRect(50, 50, 100, 100), RGB(26, 188, 156), RGB(255, 0, 0), 0, 5, CRect(9, 9, 9, 9), 5);