Duilib中跑马灯效果

作者: 云谁之殇 | 来源:发表于2018-04-20 08:47 被阅读20次

先看效果图

test.gif

实现过程

1、要在Duilib中实现自定义绘图,需要继承一个控件,并重写它的DoPaint函数,这里我们继承CControlUI实现一个绘图的类CPaintUI:

class CPaintUI:public CControlUI
{
public:
    CPaintUI();
    ~CPaintUI();

    LPCTSTR GetClass() const override;
    LPVOID GetInterface(LPCTSTR pstrName) override;

    void Init() override;
    void DoEvent(TEventUI& event) override;

    bool DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl) override;
    void DrawMarqueeText(HDC hDC);

    int g_nControlWidth; //基础宽度

    int m_nStep;   //移动距离
    int m_nHeight; //绘图高度
    int m_nTimer;  //时间间隔
    int m_nLeft;  //第一段话的位置
    int m_nRight//第二段话的位置

    CDuiString m_szText;  //显示的文本

    Gdiplus::SolidBrush*  solidbrush;   // 蓝色画刷  
    Gdiplus::Font*       gdifont; // 字体  
    Gdiplus::StringFormat sf;
};

2、在CPP中实现各个函数:

CPaintUI::CPaintUI()
{
    DUITRACE(L"CPaintUI");

    m_nStep = 2;
    m_nHeight = 30;
    m_nTimer = 20;

    m_szText = _T("这是一段文本...");
    g_nControlWidth = 800;//根据界面宽度自定义
    m_nLeft = 0;
    m_nRight = g_nControlWidth  ;

    solidbrush = new SolidBrush(Color(0xFF, 0, 159, 0));     // 蓝色画刷  
    gdifont = new Gdiplus::Font(L"微软雅黑", 20, FontStyleRegular, UnitPixel);
    sf.SetAlignment(StringAlignmentNear);           // 单行靠左    
    sf.SetLineAlignment(StringAlignmentCenter);     // 文本垂直居中显示  
}

CPaintUI::~CPaintUI()
{   
}

LPCTSTR CPaintUI::GetClass() const
{
    return L"PaintUI";
}

LPVOID CPaintUI::GetInterface(LPCTSTR pstrName)
{
    if (_tcsicmp(pstrName, _T("Paint")) == 0)
        return this;
    return __super::GetInterface(pstrName);
}

void CPaintUI::Init()
{
    __super::Init();
    //设置定时器
    m_pManager->SetTimer(this, 1, m_nTimer);
}

void CPaintUI::DoEvent(TEventUI& event)
{
    if (event.Type == UIEVENT_TIMER)
    {
        this->Invalidate();//定时刷新界面显示
    }
    return CControlUI::DoEvent(event);
}
//绘图
bool CPaintUI::DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl)
{
    PaintBkColor(hDC);//绘制背景,默认背景
    DrawMarqueeText(hDC);//绘制MarqueeText
    return true;
}

3、绘制MarqueeText

void CPaintUI::DrawMarqueeText(HDC hDC)
{
    Gdiplus::Graphics graphics(hDC);
    CDuiRect rect = GetPos();//绘图区域大小

    Gdiplus::RectF gdiRc(m_nLeft, clientRect.top + m_nHeight, clientRect.GetWidth(), m_nHeight);//绘制文本区域

    RectF boundRect;
    graphics.MeasureString(m_szText, wcslen(m_szText), gdifont, gdiRc, &sf, &boundRect);//文本长度

    graphics.DrawString(m_szText, wcslen(m_szText), gdifont, gdiRc, &sf, solidbrush);//绘制第一条文本

    m_nLeft -= m_nStep;     // 从右到左递进  

    if (m_gRestart)//开始绘制第二条文本
    {
        m_nRight -= m_nStep;    // 从右到左递进  

        Gdiplus::RectF secRc(m_nRight, clientRect.top + m_nHeight, clientRect.GetWidth(), m_nHeight);//第二条文本区域
        graphics.DrawString(m_szText, wcslen(m_szText), gdifont, secRc, &sf, solidbrush);

        if (m_nRight <= -boundRect.Width)//当第二条完全消失在左边时,停止绘制
        {
            m_gRestart = FALSE;
        }

        if (m_nRight <= 0)//当第二条开始逐渐消失时,绘制第一条
        {
            if (!m_bEnd)
            {
                m_nLeft = rect.GetWidth();
                m_bEnd = TRUE;
            }
        }
    }

    if (m_nLeft <= 0)      // 第一个字符串已经前进一部分,准备显示第二个字符串  
    {
        if (!m_gRestart)
        {
            m_nRight = rect.GetWidth();
            m_gRestart = TRUE;
            m_bEnd = FALSE;
        }
    }
}

4、这样就得到了一行不断进行的跑马灯效果,如果想实现上图那样的效果,只需要多定义几行数据,随机初始化位置和文本即可。

相关文章

网友评论

    本文标题:Duilib中跑马灯效果

    本文链接:https://www.haomeiwen.com/subject/deookftx.html