带超链接的循环滚动静态控件

滚动文字实现已有很多方法

这个控件对 以前的滚动控件进行扩展,能够循环滚动消息,在鼠标停留在消息上时变为超链接

代码如下:

#pragma  once
#include 
< map >
#include 
< vector >
class  CScrollStatic :  public  CStatic
{
public:
    CScrollStatic()
        : m_iExtend(
0)
        , m_iTotal(
0)
        , m_strText(_T(
"初始文字..."))
        , m_colText(RGB(
000))
        , m_sHitMsg(_T(
""))
    
{
        m_bmp.LoadBitmap(IDB_BK);
        BITMAP bit;
        m_bmp.GetBitmap(
&bit);
        m_iBackBmpWidth 
= bit.bmWidth;
        LOGFONT lf;
        ZeroMemory(
&lf, sizeof(LOGFONT));
        lf.lfHeight 
= 12;
        lf.lfWeight 
= 400;
        lf.lfCharSet 
= 134;
        lf.lfPitchAndFamily 
= 2;
        strcpy_s(lf.lfFaceName, LF_FACESIZE, 
"宋体"); 
        m_font.CreateFontIndirect(
&lf);
        lf.lfUnderline 
= 1;
        m_fontU.CreateFontIndirect(
&lf);
        m_hCursor 
= ::LoadCursor(NULL, IDC_HAND);
    }
;
    
~CScrollStatic(){  };

protected:    
    
static const AFX_MSGMAP* PASCAL GetThisMessageMap()
    

        typedef CScrollStatic ThisClass;
        
static const AFX_MSGMAP_ENTRY _messageEntries[] =  
        
{
            ON_WM_CREATE()
            ON_WM_TIMER()
            ON_WM_PAINT()
            ON_WM_MOUSEMOVE()
            ON_WM_LBUTTONDBLCLK()
            
{0000, AfxSig_end, (AFX_PMSG)0 } 
        }

        
static const AFX_MSGMAP messageMap = 
        
&CStatic::GetThisMessageMap, &_messageEntries[0] }
        
return &messageMap; 
    }

    
virtual const AFX_MSGMAP* GetMessageMap() constreturn GetThisMessageMap(); }

public:
    afx_msg 
int CScrollStatic::OnCreate(LPCREATESTRUCT lpCreateStruct)
    
{
        
if (CStatic::OnCreate(lpCreateStruct) == -1)
            
return -1;
        SetTimer(
1100, NULL);//滚动频率时间控制
        SetTimer(2500, NULL);//滚动文字颜色时间控制
        return 0;
    }

    afx_msg 
void CScrollStatic::OnTimer(UINT nIDEvent)
    
{    
        
if (nIDEvent == 2)
        
{
            
if (m_colText >= RGB(255255255))
            
{
                m_colText 
= RGB(000);
            }

            
else
            
{
                m_colText 
+= RGB(121);
            }

        }


        
if (nIDEvent == 1)
        
{
            CDC
* pDC = GetDC();  
            pDC
->SelectObject(m_font);  
            CRect rect;  
            GetClientRect(rect);  

            
if (m_vMsg.size() == 0// 没有消息时
            {    
                CSize size 
= pDC->GetTextExtent(m_strText);  

                
if (m_iExtend <= -size.cx)  
                
{    
                    m_iExtend 
= rect.Width();   
                }
 
                
else
                
{    
                    m_iExtend 
-= 1;
                }

            }

            
else //  有消息时逐条消息计算偏移
            {
                
int iCount = (int)m_vMsg.size();
                
for ( int iOffset(0), i(0); i < iCount; i++ )
                
{
                    MsgOut 
&msg = m_vMsg[i];
                    
                    CSize size 
= pDC->GetTextExtent(msg.sMsg); 
                    iOffset 
+= size.cx + 20;
                    
if (msg.iOffset < (rect.Width() > m_iTotal ? 
                         
-size.cx:rect.Width() - m_iTotal))
                    
{        
                        
if (i > 0)
                            msg.iOffset 
= m_vMsg[i-1].iOffset + size.cx + 20;
                        
else
                            msg.iOffset 
= rect.Width(); 
                    }

                    
else
                    
{
                        msg.iOffset 
-= 1;
                    }
    

                }

            }

            Invalidate(FALSE);  
            ReleaseDC(pDC);  
        }

    }


    afx_msg 
void CScrollStatic::OnPaint()
    
{
        CPaintDC dc(
this); // device context for painting
        
// TODO: 在此处添加消息处理程序代码
        CRect rc;  
        GetClientRect(rc);  
        CDC memDC, textDC;  
        memDC.CreateCompatibleDC(
&dc);  
        memDC.SelectObject(
&m_bmp);

        textDC.CreateCompatibleDC(
&dc);
        CBitmap bmpBack;
        bmpBack.CreateCompatibleBitmap(
&dc, rc.Width(), rc.Height());
        textDC.SelectObject(
&bmpBack);
        textDC.FillSolidRect(rc, RGB(
192192192));
        textDC.SetBkMode(TRANSPARENT);
        textDC.SetTextColor(m_colText);
        textDC.SelectObject(
&m_font);
        
        
if (m_vMsg.size() == 0)
        
{    
            CSize size 
= textDC.GetTextExtent(m_strText); 
            textDC.TextOut(rc.left 
+ m_iExtend, rc.top + (rc.Height() - size.cy)/2, m_strText);  
        }

        
else // 逐条消息输出
        {
            vMsg::iterator iter 
= m_vMsg.begin();
            
for ( ; iter != m_vMsg.end(); iter++ )
            
{
                MsgOut msg 
= *iter;
                CSize size 
= textDC.GetTextExtent(msg.sMsg);
                
                CRect rect;
                rect.CopyRect(rc);
                rect.left 
+= msg.iOffset;
                rect.top 
+= (rect.Height() - size.cy)/2;
                rect.right 
= rect.left + size.cx;

                
if ( rect.right > rc.left ) //已超出
                {    
                    CPoint pt;
                    GetCursorPos(
&pt);
                    ScreenToClient(
&pt);
                    
if (rect.PtInRect(pt))
                    
{
                        SetCapture();
                        KillTimer(
1);
                        SetCursor(m_hCursor);
                        m_rcHitIn.CopyRect(rect);
                        textDC.SelectObject(
&m_fontU);
                        m_sHitMsg 
= msg.sMsg;
                    }

                    
else
                    
{
                        textDC.SelectObject(
&m_font);
                    }

                    textDC.TextOut(rect.left, rect.top, msg.sMsg);  
                }

            }

        }


        dc.StretchBlt(
00, rc.Width(), rc.Height(), &memDC, 00, m_iBackBmpWidth, rc.Height(), SRCCOPY);  
        dc.TransparentBlt(
0 ,0, rc.Width(), rc.Height(), &textDC, 00, rc.Width(), rc.Height(), RGB(192192192));
        
        memDC.DeleteDC();
        textDC.DeleteDC();      
        bmpBack.DeleteObject();
    }

    afx_msg 
void OnMouseMove(UINT nFlags, CPoint point)
    
{
        
if (!m_rcHitIn.PtInRect(point))
        
{
            SetTimer(
1100, NULL);
            ReleaseCapture();
        }

    }

    afx_msg 
void OnLButtonDblClk(UINT nFlags, CPoint point)
    
{
        
if (!m_sHitMsg.IsEmpty())
        
{
            CStringW wStr 
= CA2W(m_sHitMsg);
            
int iLength = wStr.GetLength();

            
int i(0);
            
while (!iswdigit(wStr.GetAt(i++)) && i <= iLength);
            
int iBeg = i;
            
while (iswdigit(wStr.GetAt(i++)) && i <= iLength);
            
int iEnd = i;
            CString sID 
= CW2A(wStr.Mid(iBeg-1, iEnd - iBeg));

            wrkMap::iterator mapiter 
= m_mapWork.find(m_sHitMsg);
            
if (mapiter != m_mapWork.end())
            
{
//在此进行超链接处理,处理后移出消息
                m_mapWork.erase(mapiter);
            }


            vMsg::iterator iter 
= m_vMsg.begin();
            
for ( int i(0); iter != m_vMsg.end(); i++, iter++)
            
{
                MsgOut 
&msg = *iter;
                
if (msg.sMsg == m_sHitMsg)
                
{    
                    
int iPreOffset = msg.iOffset;
                    CDC 
* pDC = GetDC();
                    pDC
->SelectObject(m_font);    
                    CSize sz 
= pDC->GetTextExtent(m_vMsg[i].sMsg);
                    m_iTotal 
-= sz.cx + 20;
                    
                    CRect rect;
                    GetClientRect(rect);
                    m_vMsg.erase(iter);
                    
int iCount = (int) m_vMsg.size();
                    
for (; i < iCount; i++)
                    
{
                        sz 
= pDC->GetTextExtent(m_vMsg[i].sMsg);
                        
int iTemp = m_vMsg[i].iOffset;    
                        m_vMsg[i].iOffset 
= iPreOffset;
                        iPreOffset 
= iTemp;
                    }

                    
break;
                }

            }

        }

    }

protected:
    CFont m_font, m_fontU;
    
int m_iExtend;
    
int m_iTotal;
    CString m_strText;
    CBitmap m_bmp;
    
int m_iBackBmpWidth;
    COLORREF m_colText;
    
struct MsgOut 
    
{
        CString sMsg;
        
int iOffset;
        MsgOut() : sMsg(_T(
"")), iOffset(0){};
    }
;
    typedef std::map
<CString, CString> wrkMap;
    wrkMap    m_mapWork;
    typedef std::vector
<MsgOut> vMsg;
    vMsg m_vMsg;
    CRect m_rcHitIn;
    HCURSOR m_hCursor;
    CString m_sHitMsg;
public:
    
void AddText(CString sText, CString sWorkID) // 添加消息
    {
        CRect rect;
        GetClientRect(rect);
        CDC 
* pDC = GetDC();
        pDC
->SelectObject(m_font);
        CSize sz 
= pDC->GetTextExtent(sText);
        MsgOut msg;
        msg.sMsg 
= sText;
        
if (m_vMsg.size() > 0)
            msg.iOffset 
= ((MsgOut)*m_vMsg.rbegin()).iOffset + sz.cx + 20;
        
else
            msg.iOffset 
= rect.Width();    
        
        m_iTotal 
+= sz.cx + 20;
        m_vMsg.push_back(msg);
        m_mapWork[sText] 
= sWorkID;

        
if (m_vMsg.size() > 10//保留10条信息
        {
            wrkMap::iterator iter 
= m_mapWork.find(((MsgOut)*m_vMsg.begin()).sMsg);
            
if (iter != m_mapWork.end())
                m_mapWork.erase(iter);
            m_vMsg.erase(m_vMsg.begin());
            m_iTotal 
-= sz.cx + 20;
        }

        ReleaseDC(pDC);
    }

}
;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值