如何在mfc中用擦除背景消除闪烁
How to eliminate flickering with erase background in mfc
我正在使用 SDI 应用程序通过在视图文件中使用计时器来重绘图形和更新数据。即使我使用 ON_WM_ERASEBKGND 来消除闪烁,但它仍然会发生。下面是我尝试实现的代码。谁有消除闪烁的想法?
这是我的MSG_MAP
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_TIMER()
BOOL CVCDSOView::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
return CView::OnEraseBkgnd(pDC);
}
void CVCDSOView::OnInitialUpdate()
{
CView::OnInitialUpdate();
CRect Rect;
GetClientRect(&Rect);
CRect m_rcDraw = Rect;
// set timer with 200ms
SetTimer(ID_LABEL_COMPANY,200,NULL);
labelCompany.Create(_T("Company"), WS_CHILD | WS_VISIBLE,
CRect(LEFT_SIDE, TOP_SIDE, RIGHT_SIDE+50, BOTTOM_SIDE), this, ID_LABEL_COMPANY);
textboxCompany.Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_NOHIDESEL,
CRect(LEFT_SIDE, TOP_SIDE+VERTICAL_OFFSET, RIGHT_SIDE+50, BOTTOM_SIDE+VERTICAL_OFFSET), this, ID_EDITTEXT_COMPANY);
}
// CVCDSOView message handlers
void CVCDSOView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CRect Rect;
GetClientRect(&Rect);
CDC dcMem;
CBitmap bmpMem;
dcMem.CreateCompatibleDC(&dc);
bmpMem.CreateCompatibleBitmap(&dc,Rect.Width()- GRID_LEFT,Rect.Height()-35);
dcMem.SelectObject(&bmpMem);
dcMem.FillSolidRect(Rect, RGB(255,255,255));
CRect m_rcDraw = Rect;
m_rcDraw.DeflateRect(GRID_LEFT,GRID_TOP,GRID_RIGHT,GRID_BOTTOM);
DrawGrid(&dcMem,m_rcDraw);
dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&dcMem,0,0,SRCCOPY);
dcMem.DeleteDC();
DeleteObject(bmpMem);
// Do not call CView::OnPaint() for painting messages
}
void CVCDSOView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
//
if(nIDEvent==ID_LABEL_COMPANY)
{
CollectData();
Invalidate();
CView::OnTimer(nIDEvent);
}
}
任何想法将不胜感激。
- 在
OnEraseBkgnd
你应该 return FALSE
.
OnPaint
中的所有绘图最好用CMemDC
class完成,因为直接在屏幕上绘图很可能也会导致闪烁:
CMemDC memDC(*pDC, this);
CDC& rDC = memDC.GetDC();
rDC.ActualDrawing`...
您的子控件在绘制背景时可能会导致闪烁。您想要通过向视图 class:
添加 WS_CLIPCHILDREN
标志来从绘画区域中排除子控件
BOOL CVCDSOView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= WS_CLIPCHILDREN;
return CView::PreCreateWindow(cs);
}
与闪烁问题无关:
不要为主矩形减去任何内容。您应该将位图更改为
bmpMem.CreateCompatibleBitmap(&dc, Rect.Width(), Rect.Height());
不需要dcMem.DeleteDC()
并且DeleteObject(bmpMem)
MFC会自动删除这些对象。
请注意,MFC 不会自动取消 select 对象。这通常无关紧要,因为 Windows 将进行必要的清理,如本例中所做的那样。但为了完整起见,添加以下内容:
CBitmap* oldbitmap = (CBitmap*)dcMem.SelectObject(&bmpMem);
...
dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&dcMem,0,0,SRCCOPY);
dcMem.SelectObject(oldbitmap);
我正在使用 SDI 应用程序通过在视图文件中使用计时器来重绘图形和更新数据。即使我使用 ON_WM_ERASEBKGND 来消除闪烁,但它仍然会发生。下面是我尝试实现的代码。谁有消除闪烁的想法?
这是我的MSG_MAP
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_TIMER()
BOOL CVCDSOView::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
return CView::OnEraseBkgnd(pDC);
}
void CVCDSOView::OnInitialUpdate()
{
CView::OnInitialUpdate();
CRect Rect;
GetClientRect(&Rect);
CRect m_rcDraw = Rect;
// set timer with 200ms
SetTimer(ID_LABEL_COMPANY,200,NULL);
labelCompany.Create(_T("Company"), WS_CHILD | WS_VISIBLE,
CRect(LEFT_SIDE, TOP_SIDE, RIGHT_SIDE+50, BOTTOM_SIDE), this, ID_LABEL_COMPANY);
textboxCompany.Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_NOHIDESEL,
CRect(LEFT_SIDE, TOP_SIDE+VERTICAL_OFFSET, RIGHT_SIDE+50, BOTTOM_SIDE+VERTICAL_OFFSET), this, ID_EDITTEXT_COMPANY);
}
// CVCDSOView message handlers
void CVCDSOView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CRect Rect;
GetClientRect(&Rect);
CDC dcMem;
CBitmap bmpMem;
dcMem.CreateCompatibleDC(&dc);
bmpMem.CreateCompatibleBitmap(&dc,Rect.Width()- GRID_LEFT,Rect.Height()-35);
dcMem.SelectObject(&bmpMem);
dcMem.FillSolidRect(Rect, RGB(255,255,255));
CRect m_rcDraw = Rect;
m_rcDraw.DeflateRect(GRID_LEFT,GRID_TOP,GRID_RIGHT,GRID_BOTTOM);
DrawGrid(&dcMem,m_rcDraw);
dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&dcMem,0,0,SRCCOPY);
dcMem.DeleteDC();
DeleteObject(bmpMem);
// Do not call CView::OnPaint() for painting messages
}
void CVCDSOView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
//
if(nIDEvent==ID_LABEL_COMPANY)
{
CollectData();
Invalidate();
CView::OnTimer(nIDEvent);
}
}
任何想法将不胜感激。
- 在
OnEraseBkgnd
你应该 returnFALSE
. OnPaint
中的所有绘图最好用CMemDC
class完成,因为直接在屏幕上绘图很可能也会导致闪烁:CMemDC memDC(*pDC, this); CDC& rDC = memDC.GetDC(); rDC.ActualDrawing`...
您的子控件在绘制背景时可能会导致闪烁。您想要通过向视图 class:
添加WS_CLIPCHILDREN
标志来从绘画区域中排除子控件
BOOL CVCDSOView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= WS_CLIPCHILDREN;
return CView::PreCreateWindow(cs);
}
与闪烁问题无关:
不要为主矩形减去任何内容。您应该将位图更改为
bmpMem.CreateCompatibleBitmap(&dc, Rect.Width(), Rect.Height());
不需要dcMem.DeleteDC()
并且DeleteObject(bmpMem)
MFC会自动删除这些对象。
请注意,MFC 不会自动取消 select 对象。这通常无关紧要,因为 Windows 将进行必要的清理,如本例中所做的那样。但为了完整起见,添加以下内容:
CBitmap* oldbitmap = (CBitmap*)dcMem.SelectObject(&bmpMem);
...
dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&dcMem,0,0,SRCCOPY);
dcMem.SelectObject(oldbitmap);