当前位置: 代码迷 >> VC/MFC >> OnPaint显示图像刷新惊人滞后
  详细解决方案

OnPaint显示图像刷新惊人滞后

热度:85   发布时间:2016-05-02 03:45:23.0
OnPaint显示图像刷新严重滞后
MFC,在OnPaint()中,在dialog上直接绘图,有一Timer 600ms周期性地触发一次绘图消息。
图像来自一个采集卡。 
图像也在刷新,但是有明显滞后,有时延迟十几秒,有时二十多秒、有时40多秒。很诡异! 
求指点,谢谢! 
 页面上其他处图像、曲线刷新就没有问题。即使把界面所有其他(图像、曲线)刷新停掉,采集图区域刷新还是滞后。
 
【代码如下】: 
  
voaltile int g_iShowDataBmpPutIdx; // 图像队列存入下标 
volatile unsigned char *g_pShowDataBmp; // 图像队列(N_IMG_LIST_SIZE张),其他线程追加图像数据,修改g_iShowDataBmpPutIdx 
  
  
对话框类节选: 
// COvfSpectrumChk_V01Dlg 对话框 
class COvfSpectrumChk_V01Dlg : public CDialog 

     /// the main show bmp 
     BITMAPINFO *m_MainShow_pbmi; 
     int m_MainShowWidth; // display size 
     int m_MainShowWidthBmpStyle; // display size in bmp style (32-bit / 4 bytes) 
     int m_MainShowHeight;// display size 
     int m_MainShowRowStart; // start row for vertical data 
     int m_MainShowPos_x; // display position in UI 
     int m_MainShowPos_y; // display position in UI 
     unsigned char *m_pMainShowData; 
     unsigned char *m_pMainShowDataRangeBmp; // bmp style, for display 

  
  
void COvfSpectrumChk_V01Dlg::OnPaint() 

     if (IsIconic()) 
     { 
         CPaintDC dc(this); // 用于绘制的设备上下文 
  
         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 
  
         // 使图标在工作区矩形中居中 
         int cxIcon = GetSystemMetrics(SM_CXICON); 
         int cyIcon = GetSystemMetrics(SM_CYICON); 
         CRect rect; 
         GetClientRect(&rect); 
         int x = (rect.Width() - cxIcon + 1) / 2; 
         int y = (rect.Height() - cyIcon + 1) / 2; 
  
         // 绘制图标 
         dc.DrawIcon(x, y, m_hIcon); 
     } 
     else 
     { 
  
         static HDC hDc,hMemDC; 
  
         hDc=0; // 2015-06-23 
         hDc = ::GetDC(m_hWnd); 
         if(hDc==0)return; // 2015-06-23 
  
         hMemDC=0; // 2015-06-23 
         hMemDC = CreateCompatibleDC(hDc); 
         if(hMemDC==0)return; // 2015-06-23 
  
  
         CreateCompatibleBitmap(hMemDC, GetDeviceCaps(hMemDC, HORZRES), GetDeviceCaps(hMemDC, VERTRES));  // 2015-06-23 
  
  
  
         { 
             // 创建位图 
             HBITMAP hBitmap=0; // 2015-06-23 
  
             // 拷贝最新图像数据 
             int showImgIdx=g_iShowDataBmpPutIdx-1; 
             if(showImgIdx<0)showImgIdx=N_IMG_LIST_SIZE-1; 
             memcpy((void *)m_pMainShowDataRangeBmp,(void *)(g_pShowDataBmp+m_MainShowWidthBmpStyle*m_MainShowHeight*showImgIdx),m_MainShowWidthBmpStyle*m_MainShowHeight); 
  
             hBitmap=CreateDIBitmap(hDc,(BITMAPINFOHEADER *)&(m_MainShow_pbmi->bmiHeader), CBM_INIT, (void *)m_pMainShowDataRangeBmp,  
  
m_MainShow_pbmi, DIB_RGB_COLORS); // 2015-06-23 
             if(hBitmap==0)return; 
  
             //将位图选入内存设备上下文 
             if(SelectObject(hMemDC, hBitmap)==0)return; // 2015-06-23 
      
             if(BitBlt(hDc, m_MainShowPos_x, m_MainShowPos_y, m_MainShow_pbmi->bmiHeader.biWidth, m_MainShow_pbmi->bmiHeader.biHeight, hMemDC, 0,  
  
0, SRCCOPY)==false)return; // 2015-06-23 
         } 
  
  
         DeleteDC(hMemDC); 
  
         ::ReleaseDC(m_hWnd,hDc); 
     } 
  
     CDialog::OnPaint(); 
     return; 


------解决思路----------------------
你能保证600ms的timer触发重绘的时候,能立刻拿到新的图像数据吗,毕竟你的数据来自采集卡,很有可能timer触发的时候没有新数据,这样绘图操作虽然依旧是600ms更新一次,但是却在重复绘制
------解决思路----------------------
void COvfSpectrumChk_V01Dlg::OnPaint() 

     if (IsIconic()) 
     { 
         CPaintDC dc(this); // 用于绘制的设备上下文 
  
         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 
  
         // 使图标在工作区矩形中居中 
         int cxIcon = GetSystemMetrics(SM_CXICON); 
         int cyIcon = GetSystemMetrics(SM_CYICON); 
         CRect rect; 
         GetClientRect(&rect); 
         int x = (rect.Width() - cxIcon + 1) / 2; 
         int y = (rect.Height() - cyIcon + 1) / 2; 
  
         // 绘制图标 
         dc.DrawIcon(x, y, m_hIcon); 
     } 
     else 
     { 
  
         static HDC hDc,hMemDC; 
  
         hDc=0; // 2015-06-23 
         [color=#FF0000]hDc = ::GetDC(m_hWnd); //  错误

[/color]         if(hDc==0)return; // 2015-06-23 
CPaintDC dc(this)   
         hMemDC=0; // 2015-06-23 
         hMemDC = CreateCompatibleDC(hDc); 
         if(hMemDC==0)return; // 2015-06-23 
  
  
         CreateCompatibleBitmap(hMemDC, GetDeviceCaps(hMemDC, HORZRES), GetDeviceCaps(hMemDC, VERTRES));  // 2015-06-23 
  
  
  
         { 
             // 创建位图 
             HBITMAP hBitmap=0; // 2015-06-23 
  
             // 拷贝最新图像数据 
             int showImgIdx=g_iShowDataBmpPutIdx-1; 
             if(showImgIdx<0)showImgIdx=N_IMG_LIST_SIZE-1; 
             memcpy((void *)m_pMainShowDataRangeBmp,(void *)(g_pShowDataBmp+m_MainShowWidthBmpStyle*m_MainShowHeight*showImgIdx),m_MainShowWidthBmpStyle*m_MainShowHeight); 
  
             hBitmap=CreateDIBitmap(hDc,(BITMAPINFOHEADER *)&(m_MainShow_pbmi->bmiHeader), CBM_INIT, (void *)m_pMainShowDataRangeBmp,  
  
m_MainShow_pbmi, DIB_RGB_COLORS); // 2015-06-23 
             if(hBitmap==0)return; 
  
             //将位图选入内存设备上下文 
             if(SelectObject(hMemDC, hBitmap)==0)return; // 2015-06-23 
      
             if(BitBlt(hDc, m_MainShowPos_x, m_MainShowPos_y, m_MainShow_pbmi->bmiHeader.biWidth, m_MainShow_pbmi->bmiHeader.biHeight, hMemDC, 0,  
  
0, SRCCOPY)==false)return; // 2015-06-23 
         } 
  
  
  //       DeleteDC(hMemDC); 
  
 //        ::ReleaseDC(m_hWnd,hDc);
 
     } 
  
//     CDialog::OnPaint(); 
     return; 

更多 0