In fact, the principle that hikers follow, "Leave gates as you found them", is important in DC management. When you write a function that takes an incoming DC, you have to make sure that every change you make is restored. Note that every operation that modifies a DC returns an object (or value) that can be used to restore the state of the DC (the MFC calls wrap certain values, such as HFONT values, in a corresponding "wrapper class", such as CFont, and return a pointer to that MFC object). However, there are a lot of parameters to a DC, and this means you end up, in a serious drawing routine, having a lot of odd variables to keep track of.
However, it is simpler than this. There is a serious underappreciated function, ::SaveDC, and its partner, ::RestoreDC, which are available as methods CDC::SaveDC and CDC::RestoreDC. Using these you can now change the code to avoid the use of any gratuitous variables:
void CMyView::OnPaint() { CPaintDC dc(this); CFont f; f.CreateFont(...); // parameters not shown int save = dc.SaveDC(); dc.SelectObject(&f); dc.TextOut(...); // whatever... dc.RestoreDC(save); } // destructors called here... |
Actually, it doesn't matter how many changes you made in the DC; when you do the RestoreDC call, the DC is restored to whatever state it was just before the SaveDC. This means that all the objects selected into it after the SaveDC, all the changes in the text color, background color, styles, etc. are all erased.
There are interesting ways of using the integers to SaveDC in creative ways, but I'm not going to go into those, primarily because I don't do them myself. Instead, I'm going to show a class that makes all this very easy. There's no download for this code; it is so simple you can copy-and-paste it into your own file.
Comments