I am listening to the ON_WM_ERASEBKGND()
msg, inside the fired function relative to that event called OnEraseBackground(CDC* pDC)
. I am changing a background color like the following:
if (pDC)
{
pDC->SetBkColor(BlackColor);
}
else if (GetDC())
{
GetDC()->SetBkColor(BlackColor);
}
My question is, should I call ReleaseDC()
after GetDC()
?
CodePudding user response:
A device context returned from GetDC
or CWnd::GetDC
should always be released by passing it either to ReleaseDC
or CWnd::ReleaseDC
(doesn't matter which one). The documentation is a fair bit lenient towards situations where this isn't strictly necessary, though establishing those preconditions is complex in itself.
If you call either of the ReleaseDC
functions on a device context that doesn't strictly need to be released, the operation has no adverse effect.
The consequences of not releasing device contexts (a GDI resource) is far worse than a memory leak. GDI resources are severely limited, and shared across all processes running in the same user session. One program's GDI resource leak can easily cause any other program to malfunction.
Note that you are calling GetDC
twice in your code so you will want to release it twice as well. Alternatively, only call it once, e.g.
if (pDC)
{
pDC->SetBkColor(BlackColor);
}
else
{
auto myDC = GetDC();
myDC->SetBkColor(BlackColor);
ReleaseDC(myDC);
}
or, using an if
statement with initializer (introduced in C 17):
if (pDC)
{
pDC->SetBkColor(BlackColor);
}
else if (auto myDC = GetDC())
{
myDC->SetBkColor(BlackColor);
ReleaseDC(myDC);
}
Though, really, I would probably just scrap the entire else
-arm. If your WM_ERASEBKGND
message handler doesn't receive a device context, then there's no reason to go hunting for one yourself.
CodePudding user response:
Win32 API
According to this article for GetDC
it states:
After painting with a common DC, the
ReleaseDC
function must be called to release the DC. Class and private DCs do not have to be released.ReleaseDC
must be called from the same thread that calledGetDC
. The number of DCs is limited only by available memory.
CWnd
If it is a CWnd::GetDC
then:
Unless the device context belongs to a window class, the
ReleaseDC
member function must be called to release the context after painting.
Under normal circumstances you would do this:
CDC *pDC = GetDC();
if (pDC != nullptr)
{
pDC->SomeFunc(...);
}
// etc..
The linked article refers to some samples here.
Does that help?