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