使用純代碼繪製CheckBox



作者:劉樹偉

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);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章