网上找到一段代码可以实现static背景透明,但是调用频繁的话闪的很厉害,不知道如何解决。
LRESULT CTransparentStatic::OnSetText(WPARAM wParam,LPARAM lParam)
{
   LRESULT Result = Default();
   CRect Rect;
   GetWindowRect(&Rect);
   GetParent()->ScreenToClient(&Rect);
   GetParent()->InvalidateRect(&Rect);
   GetParent()->UpdateWindow();
   return Result;
}HBRUSH CTransparentStatic::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
{
   pDC->SetBkMode(TRANSPARENT);
   return (HBRUSH)GetStockObject(NULL_BRUSH);
}BOOL CTransparentStatic::OnEraseBkgnd(CDC* pDC)
{
   if (m_Bmp.GetSafeHandle() == NULL)
   {
      CRect Rect;
      GetWindowRect(&Rect);
      CWnd *pParent = GetParent();
      ASSERT(pParent);
      pParent->ScreenToClient(&Rect);  //convert our corrdinates to our parents
      
      //copy what's on the parents at this point
      CDC *pDC = pParent->GetDC();
      CDC MemDC;
      MemDC.CreateCompatibleDC(pDC);
      m_Bmp.CreateCompatibleBitmap(pDC,Rect.Width(),Rect.Height());
      CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp);
      MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),pDC,Rect.left,Rect.top,SRCCOPY);
      MemDC.SelectObject(pOldBmp);
      pParent->ReleaseDC(pDC);
   }
   else //copy what we copied off the parent the first time back onto the parent
   {
   //if(m_bFlag)
   {
  CRect Rect;
  GetClientRect(Rect);
  CDC MemDC;
  MemDC.CreateCompatibleDC(pDC);
  CBitmap *pOldBmp = MemDC.SelectObject(&m_Bmp);
  pDC->BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);
  MemDC.SelectObject(pOldBmp);
   }
   }
   return TRUE;
}
BOOL CTransparentStatic::ClearBackGround(BOOL bFlag)
{
//m_bFlag = bFlag;
if(m_Bmp.GetSafeHandle())
{
m_Bmp.DeleteObject();
}
}

解决方案 »

  1.   

    用双缓存,
    也就是在刷新的时候不要清空背景,直接的把想要画的结果画到一个内存的DC中,然后直接的覆盖。 
    因为清空背景的画,肯定要插入一个空白的,在0.1秒的频率下,那是相当的抖动。 下面的链接有代码和例子
    http://www.hellocpp.net/Articles/Article/367.aspx
    http://blog.csdn.net/jemmy/archive/2007/06/18/1657063.aspx
      

  2.   

    static和父窗口公用一个dc,所以你调用父窗口刷新这块区域时,本身父窗口估计没用双缓冲
      

  3.   

    有这么复杂么?settransparent没法实现?
      

  4.   

    BOOL CTransparentDlg::OnEraseBkgnd(CDC* pDC)   
    {  
      // TODO: Add your message handler code here and/or call default  
      CRect rcClient;  
      GetClientRect(rcClient);  
      pDC->FillRect(rcClient, &m_BkBrush);  
      return TRUE;  
      
      //return CDialog::OnEraseBkgnd(pDC);  
    }  这样的方法,invalidaterect还能有用么?
    在onpaint里做,是他的cpaintdc里面有变量指明重回区域
    求解答
      

  5.   

    子控件不能透明,static还好办,你不用它,直接DrawText就好了。
      

  6.   

    在学校时写的,不完善,但还将就,文字宽度超过控件宽度还可以左右移动,每秒调5次都不会闪:
    #pragma once
    // CStaticEXclass CStaticEX : public CStatic
    {
    DECLARE_DYNAMIC(CStaticEX)public: CSize strsize;
    CRect crect;
    BOOL isleft;
    BOOL hastimer;
    CStaticEX();
    virtual ~CStaticEX(); CDC m_dcBk;
    CBitmap m_bmpBk; void DrawTranparaent(HDC hdc);
    int m_xpos;
    BOOL ismove;

    COLORREF textclr;
    CFont m_font;
    CString m_str;
    CString m_oldstr;
    protected:
    DECLARE_MESSAGE_MAP()
    public: void SetText(LPCTSTR str);
    void SetColor(COLORREF color);
    void SetFont(short size,CString strfont); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg HBRUSH CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/);
    afx_msg void OnPaint();
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    };
    ///////
    //CPP// StaticEX.cpp : 实现文件
    //#include "stdafx.h"
    #include "TwinkingMusic.h"
    #include "StaticEX.h"
    // CStaticEXIMPLEMENT_DYNAMIC(CStaticEX, CStatic)CStaticEX::CStaticEX()
    {textclr=RGB(0,0,0);m_str=_T("");
    m_font.CreatePointFont(90,_T("宋体"));
    m_xpos=0;
    ismove=FALSE;
    isleft=TRUE;
    hastimer=FALSE;
    }CStaticEX::~CStaticEX()
    {
    }
    BEGIN_MESSAGE_MAP(CStaticEX, CStatic) ON_WM_ERASEBKGND()ON_WM_CTLCOLOR_REFLECT()
    ON_WM_PAINT()
    ON_WM_CTLCOLOR()
    ON_WM_TIMER()
    END_MESSAGE_MAP()
    BOOL CStaticEX::OnEraseBkgnd(CDC* pDC)
    { return FALSE;
    //return CStatic::OnEraseBkgnd(pDC);
    }HBRUSH CStaticEX::CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/)
    {

    return NULL;

    }
    void CStaticEX::OnPaint()
    {
    GetWindowRect(&crect);
    GetParent()->ScreenToClient(crect);
    CPaintDC dc(this); 
    dc.SetBkMode(TRANSPARENT);
    if (m_dcBk.m_hDC == NULL)
    {
    CDC* parent =GetParent()->GetDC();
    m_dcBk.CreateCompatibleDC(parent);
    m_bmpBk.CreateCompatibleBitmap(parent, crect.Width(), crect.Height());
    m_dcBk.SelectObject(m_bmpBk);
    m_dcBk.BitBlt(0,0,crect.Width(), crect.Height(), parent, crect.left, crect.top, SRCCOPY);
    ReleaseDC(parent);
    }
    dc.BitBlt(0, 0, crect.Width(), crect.Height(), &m_dcBk, 0, 0, SRCCOPY); dc.SelectObject(&m_font);
    dc.SetTextColor(textclr); strsize=dc.GetTextExtent(m_str); if (strsize.cx>crect.Width())
    {
    dc.BeginPath();
    dc.Rectangle(0,0,crect.Width(),crect.Height());
    dc.EndPath();
    dc.SelectClipPath(RGN_AND);
    if (!ismove)
    {
    KillTimer(1);
    SetTimer(1,200,NULL);
    hastimer=TRUE;
    ismove=TRUE;
    }


    dc.TextOut(m_xpos,0,m_str); }
    else

    dc.TextOut(0,0,m_str);
    }
    void CStaticEX::SetText(LPCTSTR str)
    {

    if (hastimer)
    {
    KillTimer(1);
    hastimer=FALSE;
    } m_str=str;
    if (m_oldstr==m_str)
    return;
    m_oldstr=str; m_xpos=0;
    ismove=FALSE;
        InvalidateRect(NULL,FALSE);
    }void CStaticEX::SetColor(COLORREF color)
    {
    textclr=color;
    InvalidateRect(NULL,FALSE);
    }void CStaticEX::SetFont(short size,CString strfont)
    {
    if (m_font.m_hObject)  m_font.DeleteObject();

    m_font.CreatePointFont(size,strfont);
    InvalidateRect(NULL,FALSE);
    }HBRUSH CStaticEX::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    HBRUSH hbr = CStatic::OnCtlColor(pDC, pWnd, nCtlColor);
    return hbr;
    }
    void CStaticEX::OnTimer(UINT_PTR nIDEvent)
    {

    if (isleft)
    {
    m_xpos-=1;
    }
    else
    m_xpos+=1; if (abs(m_xpos)+crect.Width()==strsize.cx)
    {
    isleft=FALSE;
    }

    if (m_xpos==5)
    {
    isleft=TRUE;
    }
    InvalidateRect(NULL,FALSE);

    CStatic::OnTimer(nIDEvent);
    }
      

  7.   

    说实话,没见过你这种实现方法的,一般是重载DrawItem,在这里面画图,而OnEraseBkgnd是重绘系统的灰色背景时调用的,一般直接RETURN TRUE。