Reputation: 41
I have an application with a completely custom drawn UI (i.e. just a bunch of filled boxes with text). After about 30-60 minutes of running time, the UI elements spontaneously change. For example, the white lines (box borders) disappear, the text resizes, etc.
I have linked to some before and after images of one of the screens. This one shows that all of the white lines have disappeared. Other screens show significant changes in text size.
BEFORE: http://s21.postimg.org/cogqodson/BEFORE.png
AFTER: http://s24.postimg.org/7skx21sid/AFTER.png
This project is written in MS Visual C++ 2010 using MFC, and running on Windows 7 Pro.
Here is my OnPaint() code:
void CMainWindow::OnPaint()
{
CPaintDC dcScreen( this );
CBitmap bitmap;
bitmap.CreateCompatibleBitmap( &dcScreen, m_rect.Width(), m_rect.Height() );
CDC dc;
dc.CreateCompatibleDC( &dcScreen );
CBitmap* pOldBitMap = dc.SelectObject( &bitmap );
dc.FillRect(m_rect, &BGBRUSH);
int bkmode = dc.SetBkMode(TRANSPARENT);
dc.SelectObject(&BGBRUSH);
CPen brightwhitepen(PS_SOLID, 5, RGB(255,255,255));
CPen* pOldPen = dc.SelectObject(&brightwhitepen);
// draw some stuff:
// dc.Rectangle, dc.DrawText, etc.
// ...
// Blit the memory device context to the screen device context
dcScreen.BitBlt
(
0,
0,
m_rect.Width(),
m_rect.Height(),
&dc,
0,
0,
SRCCOPY
);
dc.SetBkMode( bkmode ); // Restore old background mode
dc.SelectObject( pOldPen ); // reselect old pen
dc.SelectObject( pOldBitMap ); // Restore old bitmap
}
Has anyone seen weird behavior like this before? Any tips on where to investigate?
Thanks!
Upvotes: 4
Views: 429
Reputation: 708
I've solved a problem like this once before when I forgot to restore the state of one of the GDI handles. The solution was to use SaveDC
and RestoreDC
, which means you won't have to restore any of the objects in the DC after you're done with them. You can download a really convenient RAII class here that does all the work for you.
A secondary suggestion is to use the stock objects and built-in DC handles rather than creating your own. So replace your brightwhitepen
code like this:
dc.SetDCPenColor(RGB(255,255,255));
CPen* pBrightwhitepen = CPen::FromHandle((HPEN)GetStockObject(DC_PEN));
dc.SetDCBrushColor(RGB(0,0,255));
CBrush* pBgBrush = CBrush::FromHandle((HBRUSH)GetStockObject(DC_BRUSH));
Now use these two pointers to draw your stuff. The advantage is that you didn't allocate anything, so you can't leak anything, and the calls can't fail because the stock objects always exist.
Upvotes: 2