重画的时候,如果上面有很多按钮/CheckBox/RadioButton等的画,如果这些按钮重画速度不是很快(主要是自绘的),就会导致整个画的过程有一个明显的闪动(是一个接一个画导致的结果),不知道那个大侠有比较好的解决方案。
    我的意思是能否用类似“锁住”对话框等方法,让所有的子控件都画完了,然后一次显示出来?
    欢迎大家一起讨论,一起提高。

解决方案 »

  1.   

    BeginDeferWindowPos
    DeferWindowPos
    EndDeferWindowPos 
    这几个windows api函数应该能实现你想要的功能.
    具体使用看msdn帮助
      

  2.   

    msdn的一段示例代码,你改该应该能用
    void CMyPropertySheet::OnSize(UINT nType, int cx, int cy) 
    {
       CRect r1; 
       CPropertySheet::OnSize(nType, cx, cy);   if (m_bNeedInit)
          return;   CTabCtrl *pTab = GetTabControl();
       ASSERT(NULL != pTab && IsWindow(pTab->m_hWnd));
        
       int dx = cx - m_rCrt.Width();
       int dy = cy - m_rCrt.Height();
       GetClientRect(&m_rCrt);   HDWP hDWP = ::BeginDeferWindowPos(5);   pTab->GetClientRect(&r1); 
       r1.right += dx; r1.bottom += dy;
       ::DeferWindowPos(hDWP, pTab->m_hWnd, NULL,
                        0, 0, r1.Width(), r1.Height(),
                        SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);   // Move all buttons with the lower right sides
       for (CWnd *pChild = GetWindow(GW_CHILD);
            pChild != NULL;
            pChild = pChild->GetWindow(GW_HWNDNEXT))
       {
          if (pChild->SendMessage(WM_GETDLGCODE) & DLGC_BUTTON)
          {
             pChild->GetWindowRect(&r1); ScreenToClient(&r1); 
             r1.top += dy; r1.bottom += dy; r1.left+= dx; r1.right += dx;
             ::DeferWindowPos(hDWP, pChild->m_hWnd, NULL,
                              r1.left, r1.top, 0, 0,
                              SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
          }
          // Resize everything else...
          else
          {
             pChild->GetClientRect(&r1); 
     r1.right += dx; r1.bottom += dy;
     ::DeferWindowPos(hDWP, pChild->m_hWnd, NULL, 0, 0, r1.Width(), r1.Height(),SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
          }   }   ::EndDeferWindowPos(hDWP);
    }
      

  3.   

    to lyg_zy(学无止境,宁静致远):
      你说的这几个函数好像在MoveWindow导致的闪烁的时候比较有有,现在我是仅仅重画所有的窗口就有这个问题了。
      

  4.   

    修改窗口的扩展风格
    加一个WS_EX_COMPOSITED属性
      

  5.   

    VC中VIEW类怎么加CMSCOMM类成员,以及创建通讯事件,急谢谢
      

  6.   

    你可以只画一部份的,调用invalidateRect就可以了。另外,重载按钮父窗口的onerasebkg方法,直接返回true,强制窗口不进行自动重画,手工控制重绘。
      

  7.   

    控件之所以会闪,是因为每次重绘窗口时,控件在对话框中所占的位置先被对话框用背景色填充,然后控件再自绘,就会产生闪烁,控件多了之后,被重复绘制的区域更多,闪烁自然就更厉害了。
    所以,如果对话框没有背景图片的话:
    响应WM_ERASEBKGND消息,获得对话框区域CRgn,去除控件所占的区域,然后用背景色填充所剩余的区域,最后返回TRUE。
      

  8.   

    重写对话框的Invalidate函数,如下,你改改就可以用了。/**
    * 刷新函数。刷新除编辑框,背景色选择框,滚动条以外的区域
    */
    void CYourDlg::Invalidate(BOOL bErase)
    {
    /**
    * 整个客户区域
    */
    CRect rcClient;
    GetClientRect(rcClient);
    CRect rcDraw=rcClient;
    CRgn rgn;
    rgn.CreateRectRgnIndirect (rcDraw); /**
    * 减掉编辑框区域
    */
    CRgn rgnCtrl;
    CRect rcWnd;
    if(m_Edit.IsWindowVisible())
    {
    m_Edit.GetWindowRect(rcWnd);
    this->ScreenToClient(rcWnd);
    rgnCtrl.CreateRectRgnIndirect(rcWnd);
    rgn.CombineRgn(&rgn,&rgnCtrl,RGN_DIFF);
    rgnCtrl.DeleteObject();
    } /**
    * 减掉编颜色选择区域
    */
    if(m_StaticClrs.IsWindowVisible())
    {
    m_StaticClrs.GetWindowRect(rcWnd);
    this->ScreenToClient(rcWnd);
    rgnCtrl.CreateRectRgnIndirect(rcWnd);
    rgn.CombineRgn(&rgn,&rgnCtrl,RGN_DIFF);
    rgnCtrl.DeleteObject();
    } /**
    * 减掉滚动条区域
    */
    if(m_ScrollBar.IsWindowVisible())
    {
    m_ScrollBar.GetWindowRect(rcWnd);
    this->ScreenToClient(rcWnd);
    rgnCtrl.CreateRectRgnIndirect(rcWnd);
    rgn.CombineRgn(&rgn,&rgnCtrl,RGN_DIFF);
    rgnCtrl.DeleteObject();
    }
    /**
    * 区域更新
    */
    InvalidateRgn(&rgn,bErase);
    }
      

  9.   

    M_S_D_N() 说的对因为我遇到过,就是那样解决的.
      

  10.   

    控件之所以会闪,是因为每次重绘窗口时,控件在对话框中所占的位置先被对话框用背景色填充,然后控件再自绘,就会产生闪烁,控件多了之后,被重复绘制的区域更多,闪烁自然就更厉害了。
    所以,如果对话框没有背景图片的话:
    响应WM_ERASEBKGND消息,获得对话框区域CRgn,去除控件所占的区域,然后用背景色填充所剩余的区域,最后返回TRUE。
      

  11.   

    利用双缓存定义内存DC:
    CClientDC dc(this);
    CDC pDC;
    pDC.CreateCompatibleDC(&dc); CRect rect;
    GetClientRect(&rect);

    CBitmap bitmap, *pOldBmp;
    bitmap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
    pOldBmp = pDC.SelectObject(&bitmap);
    .
    .
    dc.BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),
    &pDC,rect.left,rect.top,SRCCOPY);.....
      

  12.   

    在OnPaint里写如下代码
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(&rect);
    这是直接从定义OnPaint处获得,因为可能在事件中又把DC使用了,
    主程序定义的DC和你定义的DC会导致绘制对象不一致,可能会闪
    这时候直接使用主程序的DC就不会出现以上的问题
      

  13.   

    ringphone(临风) ( )是个明白人,呵呵。