从CStatic继承一个控件做checkbox,但背景并不是纯色的。
所以需要在绘制背景里画出应有的背景
代码:BOOL XXX::OnEraseBkGnd(CDC *pDC)
{
    if(!m_dcBk.GetSafeHandle())
    {
      //创建兼容DC
    }
    if(!m_bmpBk)
    {
      //创建兼容位图
    }
    m_dcBk.SelectObject(&m_bmp);
    //代码记不清,基本是复制整个区域
    m_dcBk.BitBlt(xxxxxxxxxxxx,pDC,....);
    pDC->BitBlt(xxxxxx,&m_dcBk....);
}问题:
现在发现如果窗口启动时该控件没有完全显示出来,比如被最前窗口遮挡了或是在屏幕外,则拖出来时会看到一块块黑的。
个人觉得是绘制背景是PDC的内容不完全,需要再次拷贝。
解决方法:
不知道有没有这样的函数,直到当整个控件都被显示出来时再去拷贝PDC的内容。不是IsWindowVisible(),可能是类似的。
又或者还有其他的解决方法?如果有知道的朋友还请指教,多谢!

解决方案 »

  1.   

    在OnPaint处理试试看.OnEraseBkGnd直接返回TRUE
    别人写的一个参考示例
    #if !defined(AFX_ColorStatic_H__4CCD6BDB_9694_47EC_A643_42A2CEBF62DF__INCLUDED_)
    #define AFX_ColorStatic_H__4CCD6BDB_9694_47EC_A643_42A2CEBF62DF__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000class CColorStatic : public CStatic   //可设置背景颜色的静态框
    {public:// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CColorStatic)
    protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUALpublic:
    void SetText(LPCTSTR lpszText);protected:
    CFont m_font;
    CRect m_rc;
    CString m_strText;

    //{{AFX_MSG(CColorStatic)
    afx_msg void OnPaint();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    };///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_ColorStatic_H__4CCD6BDB_9694_47EC_A643_42A2CEBF62DF__INCLUDED_)
    #include "stdafx.h"
    #include "resource.h"
    #include "ColorStatic.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endifBEGIN_MESSAGE_MAP(CColorStatic, CStatic)
    //{{AFX_MSG_MAP(CColorStatic)
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()void CColorStatic::OnPaint() 
    {
    CPaintDC dc(this);  dc.FillSolidRect(m_rc,RGB(123,156,235)); //绘制背景 dc.SelectObject(&m_font);  
    dc.SetBkMode(TRANSPARENT); //设置背景透明
    dc.SetTextColor(RGB(255,255,255)); //设置文字颜色为白色
    dc.DrawText(m_strText.GetBuffer(0),m_strText.GetLength(),&m_rc,DT_SINGLELINE | DT_VCENTER | DT_LEFT | DT_PATH_ELLIPSIS);
    }void CColorStatic::SetText(LPCTSTR lpszText)
    {
    m_strText = lpszText;
    Invalidate();  
    }
    /********************************************************************/
    /* */
    /* Function name : PreSubclassWindow */
    /* Description   : Initialize control variables */
    /* */
    /********************************************************************/
    void CColorStatic::PreSubclassWindow() 
    {
    GetClientRect(m_rc); m_font.CreateFont(12, 0,0,0,FW_BOLD, 0,0,0,
    DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
    DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "宋体");

    CStatic::PreSubclassWindow();
    }
      

  2.   

    BOOL XXX::OnEraseBkGnd(CDC *pDC)
    这个函数是用来擦除背景的,在这里改变背景的话,窗体刷新时,原背景就会被
    擦除,不如写在OnPaint()函数中,
      

  3.   

    OnPaint处理?关键是要和父窗口的背景一致,这样处理除非得到父窗口dc拷贝一次。这样透明的原理就和CButtonST一样了,不过照它的做法,还得每个控件都必须在父窗口的绘图里SetBk一次,感觉封装的并不很好。
      

  4.   

    当然要擦除默认背景,这里绘制背景后,调用onpaint再绘制里面的内容也没什么不妥啊
      

  5.   

    关键是要和父窗口的背景一致
    这个的话就使用
    HBRUSH CXXX::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
        HBRUSH hbr = CStatic::OnCtlColor(pDC, pWnd, nCtlColor);
        
        // TODO: Change any attributes of the DC here
         
            pDC->SetBkMode(TRANSPARENT); 
            return   (HBRUSH)::GetStockObject(HOLLOW_BRUSH);   
          // TODO: Return a different brush if the default is not desired
       // return hbr;}就可以了
      

  6.   

    下面的代码就可以了,和对话框的背景是一致的.HBRUSH C*Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

    // TODO: Change any attributes of the DC here
    if(nCtlColor == CTLCOLOR_STATIC)
    {
    hbr = (HBRUSH) GetStockObject(NULL_BRUSH);
    }
    // TODO: Return a different brush if the default is not desired
    return hbr;
    }
      

  7.   

    if (nCtlColor == CTLCOLOR_STATIC)
    {
    //pDC->SetTextColor(RGB(255,0,0));
    pDC->SetBkMode(TRANSPARENT);
    hbr = (HBRUSH) GetStockObject(NULL_BRUSH);
    }
      

  8.   

    感觉你的控件没及时把位图贴上去
    可以这样做,先在ResourceView内设置控件为隐藏,然后,
    在对话框出来后,再利用ShowWindow操作对应控件ID显示控件.
      

  9.   

    这就是控件子类化,应该是可行的,我曾经用EDIT做过类似的工作,没有任何问题的。
      

  10.   

    给个更简单实用的例子:
    HBRUSH C*Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 

      HBRUSH hbr=CDialog::OnCtlColor(pDC,pWnd,nCtlColor);
      
      if(nCtlColor==CTLCOLOR_STATIC)
      {
         pDC->SetBkColor(RGB(255,0,0));
         pDC->SetTextColor(RGB(255,255,0));
      }
    }
      

  11.   

    上面源代码最后忘了写返回语句return hbr;
      

  12.   

    在onctlcolor中处理没什么用的。
    整个是用gdi+画的,如果不用个背景刷去首先填充的画,
    在相应鼠标点击后刷新该区域,会造成在那个区域多次绘制文字,导致颜色越来越浓。。
    BOOL xxxx::OnEraseBkgnd(CDC* pDC)
    {
    CRect rcText(GetCheckControlRect().left ,\
    GetCheckControlRect().top ,\
    GetCheckControlRect().right ,\
    GetCheckControlRect().bottom);
    if (!m_dcBk.GetSafeHdc())
    m_dcBk.CreateCompatibleDC(pDC);
    if (!m_bmpBk.GetSafeHandle()){
    m_bmpBk.CreateCompatibleBitmap(pDC ,rcText.Width() ,rcText.Height());
    m_pBmpOld = m_dcBk.SelectObject(&m_bmpBk);

    m_dcBk.BitBlt(0 ,0 ,rcText.Width(),rcText.Height() ,pDC ,rcText.left ,rcText.top ,SRCCOPY);
    m_dcBk.Rectangle(0,0,rcText.right,rcText.bottom);
    } pDC->BitBlt(0 ,0 ,rcText.Width() ,rcText.Height() ,&m_dcBk ,0 ,0 ,SRCCOPY);
    return TRUE;
    }
    //Onpaint里处理的基本就是Drawstring和drawimage的函数
    在鼠标点击后使得整个客户区无效。
    void xxxxxx::OnLButtonUp(UINT nFlags, CPoint point)
    {
    __super::OnLButtonUp(nFlags, point);
            //m_pMySelf是鼠标按下时赋值
    if (!m_pMySelf || m_pMySelf->GetSafeHwnd() != GetSafeHwnd())
    return;
    m_pMySelf = NULL; BOOL bChecked = (m_uState == UNCHECKED?TRUE:FALSE);
    if(m_bModify)
    {
    if(m_rcText.PtInRect(point))
    {
    GetParent()->SendMessage(WM_MODIFY_STYLE,(WPARAM)GetDlgCtrlID());//just need the id of control
    }
    }
    else
    {
    if (m_uState == DISABLED)
    SetCheck(DISABLED);
    else if (m_uState == UNCHECKED)
    SetCheck(CHECKED);
    else if (m_uState == CHECKED)
    SetCheck(UNCHECKED);
    GetParent()->SendMessage(BM_SETCHECK ,(WPARAM)GetDlgCtrlID() ,(LPARAM)m_pNodeData);//send messate to parent.
    Invalidate();
    }
    }
      

  13.   

    BOOL xxxx::OnEraseBkgnd(CDC* pDC)
    {
        CRect rcText(GetCheckControlRect().left ,\
            GetCheckControlRect().top ,\
            GetCheckControlRect().right ,\
            GetCheckControlRect().bottom);
        pDC->Rectangle(0,0,rcText.right,rcText.bottom);
        return TRUE;
    }
      

  14.   

    谢谢回复。
    不过您可能没看清楚,这个checkbox的背景不是纯色,不能直接画一个了事。我已经解决,
    关键就是点了checkbox只让那个打勾的框框区域无效,文字部分则不必。
    设置新文本时则通过父窗口使得子控件的区域无效。