使用Gdi+绘制圆角矩形(CTabCtrl控件记录一)

所在项目中的定位是一个外观为圆角矩形的TabBtn控件,绘制圆角矩形部分的实现:

void CTabBtn::DoPaint(CDCHandle dc)//继承了CDoubleBufferImpl
{
    Graphics graphics(dc);
    DrawTabBtn(&graphics);
}



void CTabBtn::DrawTabBtn(Graphics* graphics)
{
    RECT rect;
    ::GetClientRect(m_hWnd, &rect);

    int nItemCount = m_arrItems.size();
    int nItemWidth = (rect.right - rect.left) / nItemCount;
    int nItemHeight = rect.bottom - rect.top;

    //draw background
    RectF oRect;
    if(m_bmpBkgnd == NULL)
    {
        //draw RoundRect background
        oRect.X = 0;
        oRect.Y = 0;
        oRect.Width = rect.right - rect.left;
        oRect.Height = nItemHeight;
        
        //APen = new Pen(BorderColor, (REAL)PenWidth);
        //ABrush = new LinearGradientBrush(GRect, FromColor, ToColor, LinearGradientModeVertical);
        DrawRoundRect(graphics, NULL, NULL, oRect, 10);
    }
    else
    {
        //HOW to clip the Round Rect area to draw image? //TextureBrush ?
        graphics->DrawImage(m_bmpBkgnd, oRect);  
    }

     //begin to draw Tab Btns
    for(size_t i = 0; i < nItemCount; i++)  
    {
        oRect.X = i * nItemWidth;  //icon covers abt one forth place
        oRect.Y = 0;
        oRect.Width = nItemWidth * 1.0 / 3 ;  
        oRect.Height = nItemHeight;
        if(m_arrItems[i]->icoNormal == NULL || m_arrItems[i]->icoOver ==  NULL || m_arrItems[i]->icoDown == NULL)
        {
        }
        else
        {
            if(m_arrItems[i]->bDown)
            {
                graphics->DrawImage(m_arrItems[i]->icoDown, oRect);
                oRect.X += nItemWidth * 1.0 / 4;
                oRect.Width = nItemWidth  * 1.0 / 4 * 3; //icon covers 1/4 place
                DrawTabBtnTitle(graphics, m_arrItems[i]->title.c_str(), m_arrItems[i]->clrDown, oRect);
                //if not the last item, then draw a gradient vertical line
                //...
            }
            else if(m_arrItems[i]->bOver)
            {
                graphics->DrawImage(m_arrItems[i]->icoOver, oRect);
                oRect.X += nItemWidth * 1.0 / 4;
                oRect.Width = nItemWidth  * 1.0 / 4 * 3;
                DrawTabBtnTitle(graphics, m_arrItems[i]->title.c_str(), m_arrItems[i]->clrOver, oRect);
            }
            else
            {
                graphics->DrawImage(m_arrItems[i]->icoNormal, oRect);
                oRect.X += nItemWidth * 1.0 / 4;
                oRect.Width = nItemWidth  * 1.0 / 4 * 3 -5;
                DrawTabBtnTitle(graphics, m_arrItems[i]->title.c_str(), m_arrItems[i]->clrNormal, oRect);
            }
        }//draw TTabBtnItem

        //if not the last item, then draw the vertical line
        if(i != m_arrItems.size() - 1)
        {
            DrawGradientLine(graphics, (i+1) * nItemWidth-3 , oRect.Y, (i+1)*nItemWidth-3, oRect.Y+oRect.Height, NULL, NULL);
        }//draw the gradient vertical line
    }//traverse all items
}

 

void CTabBtn::DrawRoundRect(Graphics* g, Pen* pen, Brush* brush, RectF rect, int nCornerRadius)
{
    ATLASSERT(g != NULL);
    ATLASSERT(&rect != NULL);
    if(pen == NULL)
        pen = new Pen(Color::DimGray);
    if(brush == NULL)
        brush = new LinearGradientBrush(rect, Color::Gainsboro, Color::Gray, LinearGradientModeVertical);

    GraphicsPath* pRRPath = CreateRoundRectPath(rect, nCornerRadius);
    g->DrawPath(pen, pRRPath);
    g->FillPath(brush, pRRPath);
}
GraphicsPath* CTabBtn::CreateRoundRectPath(RectF& oRect, int nCornerRadius)
{
    if(nCornerRadius > oRect.Width || nCornerRadius > oRect.Height)
        return NULL;

    GraphicsPath* path = new GraphicsPath;  
        
    path->StartFigure();

    path->AddArc((REAL)oRect.X, (REAL)oRect.Y, (REAL)nCornerRadius*2, (REAL)nCornerRadius*2, 180.0, 90.0);
    //path->AddLine(oRect.X+nCornerRadius, oRect.Y, oRect.X+oRect.Width-nCornerRadius*2, oRect.Y);//not necessary for draw profile but if fill maybe must(didn't test)
    path->AddArc((REAL)oRect.X+oRect.Width-nCornerRadius*2, (REAL)oRect.Y, (REAL)nCornerRadius*2, (REAL)nCornerRadius*2, 270.0, 90.0);
    //path->AddLine(oRect.X+oRect.Width, oRect.Y+nCornerRadius*2, oRect.X+oRect.Width, oRect.Y+oRect.Height-nCornerRadius*2);
    path->AddArc((REAL)oRect.X+oRect.Width-nCornerRadius*2, (REAL)oRect.Y+oRect.Height-nCornerRadius*2, (REAL)nCornerRadius*2, (REAL)nCornerRadius*2, 0.0, 90.0);
    //path->AddLine(oRect.X+oRect.Width-nCornerRadius*2, oRect.Y+oRect.Height, oRect.X+nCornerRadius*2, oRect.Y+oRect.Height);
    path->AddArc((REAL)oRect.X, (REAL)oRect.Y+oRect.Height-nCornerRadius*2, (REAL)nCornerRadius*2, (REAL)nCornerRadius*2, 90.0, 90.0);
    //path->AddLine(oRect.X, oRect.Y+oRect.Height-nCornerRadius*2, oRect.X, oRect.Y+nCornerRadius*2);
    
    path->CloseFigure();

    return path;
}


这样绘制出来的效果有瑕疵,圆角部分的颜色与父窗口的颜色存在不一致的情况。后来摒弃了这种方法,采用直接绘制矩形,然后SetWindowRgn的方法,更简单且有效。

抽出时间,把相关代码添加到Git上去。

转载于:https://www.cnblogs.com/tupx/p/3453524.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、创建窗口         * zc窗口类         * 窗口消息循环         * 窗口消息过程         * 窗口界面绘画         * 窗口随意移动         * 绑定鼠标事件         * 窗口阴影效果 -支持圆角矩形阴影效果 二、创建控件         * 绑定鼠标事件         * 控件层级绘画         * 控件区域焦点         * 控件风格定义 三、控件属性         * 左边         * 顶边         * 宽度         * 高度         * 边框         * 标题         * 标记         * 可视         * 动画 -Gif图片         * 图形 -控件图形样式:正常、点燃、按下、禁止         * 色彩 -控件色彩样式:正常、点燃、按下、禁止         * 字体         * 圆角         * 样式 -可扩增控件样式,定义样式风格         * 绑定 -即绑定鼠标事 四、事件特性         * 控件和窗口用类事件来绑定接收鼠标(点击、放开、进入、离开);支持一个事件类绑定所有控件和窗口         * 每个事件消息都有对应的控件对象句柄。便于读写相关更高级操作。 五、简要说明 MyEvent 用于创建完成后的控件事件绑定使用 hwEvent 是提供给创建控件成功后 作为基类创建控件事件使用 如同(MyEvent) 控件事件,支持,一个空间一个类事件,也可以所有空间共用一个类事件 HwControl类 是通用的控件类。也可以自行扩展更多功能 自绘这方面还是颇有心得;若爱自绘易友们可以一起研究共同进步。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值