Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Some HDC questions

13 views
Skip to first unread message

UO

unread,
Aug 5, 2008, 11:54:34 AM8/5/08
to
Hi,

I have some inconsistent knowledge about device contexts from different
textbooks.

1st question:
One of them is Petzold's book.
It says: "Except for a device context created with a call to CreateDC you
should not keep a device context handle
around from one message to another. "
Here, does the word "CreateDC" include "CreateCompatibleDC?"
I've seen some examples in the book: CreateCompatibleDC is called in
WM_CREATE, used in WM_PAINT,
and destroyed in WM_DESTROY, which is what I had been doing until I read
Petzold's book.

What about GetDC/GetWindowDC?
I've been using it as:
1) g_hdc = GetDC(hwnd); (in WM_CREATE)
2) use it elsewhere, (currently only for CreateCompatibleDC and
GetDeviceCaps)
3) ReleaseDC(hwnd, g_hdc); (in WM_DESTROY)
Is my way correct?

-------------------------------
2nd question, about GDI memory leaks:

Until I started reading Petzold's book I had used SelectObject() as:

hBrush = CreateSolidBrush(RGB(0xFF, 0x00, 0x00));
RECT rect;

case WM_PAINT:
hdc = GetDC(hwnd);
hBrushOld = SelectObject(hdc, hBrush);
GetClientRect(&rect);
Rectangle(hdc, 10, 20, 30, 40);
SelectObject(hdc, hBrushOld); //1
break;

When do I have to save / restore old attributes, here the hBrushOld?
Is the line marked with //1 necessary?


Another book gives the following code for BitBlt function as an example:
// Create a DC that matches the device.
hdcMem = CreateCompatibleDC (hdc);

// Select the bitmap into the compatible device context.
hOldSel = SelectObject (hdcMem, hBitmap);

// Get the bitmap dimensions from the bitmap.
GetObject (hBitmap, sizeof (BITMAP), &bmp);

// Copy the bitmap image from the memory DC to the screen DC.
BitBlt (hdc, rect.left, rect.top, bmp.bmWidth, bmp.bmHeight,
hdcMem, 0, 0, SRCCOPY);

// Restore original bitmap selection and destroy the memory DC.
SelectObject (hdcMem, hOldSel); //2
DeleteDC (hdcMem);Is the line marked with //2 necessary? This book restores
all GDI objects, not just bitmaps.
For example:

PAINTSTRUCT ps;
RECT rect;
HDC hdc;
POINT ptArray[6];
HBRUSH hBr, hOldBr;
TCHAR szText[128];

GetClientRect (hWnd, &rect);
hdc = BeginPaint (hWnd, &ps);

// Draw ellipse.
hBr = (HBRUSH) GetStockObject (DKGRAY_BRUSH);
hOldBr = (HBRUSH) SelectObject (hdc, hBr);
Ellipse (hdc, 10, 50, 90, 130);
SelectObject (hdc, hOldBr);

// Draw round rectangle.
hBr = (HBRUSH) GetStockObject (LTGRAY_BRUSH);
hOldBr = (HBRUSH) SelectObject (hdc, hBr);
RoundRect (hdc, 95, 50, 150, 130, 30, 30);
SelectObject (hdc, hOldBr);


Another material, a tutorial actually, gives the following code:
case WM_PAINT:
{
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = SelectObject(hdcMem, g_hbmBall);
GetObject(g_hbmBall, sizeof(bm), &bm);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld); //3
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
}

The default bitmap is restored again.

In the Petzold's book I couldn't see restoring GDI objects for a given DC.
So, when is it necessary to restore default attributes? When does a memory
leak occur?


I know, GDI objects should not be deleted when they are selected in a device
contexts.
Assume the following code:

hBitmap = LoadFromFile(...);
hdcMem = CreateCompatibleDC(...);
SelectObject(hdc, hBitmap);
BitBlt(hdc,...,hdcMem...)
//...
DeleteDC(hdcMem);
DeleteObject(hBitmap);
PostQuitMessage(0);

Is it ok to delete hdcMem while hBitmap is selected into hdcMem(this is what
Petzold's book does)
or should I use the following code?

hBitmap = LoadFromFile(...);
hdcMem = CreateCompatibleDC(...);
hBitmapOld = (HBITMAP)SelectObject(hdc, hBitmap);
BitBlt(hdc,...,hdcMem...)
//...
SelectObject(hdcMem, hBitmapOld); //////////////////
DeleteDC(hdcMem);
DeleteObject(hBitmap);
PostQuitMessage(0);

Thanks...


Remy Lebeau (TeamB)

unread,
Aug 5, 2008, 1:46:43 PM8/5/08
to

"UO" <uo@uott> wrote in message news:489877b5$1...@newsgroups.borland.com...

> Here, does the word "CreateDC" include "CreateCompatibleDC?"

CreateDC() and CreateCompatibleDC() are unique and unrelated functions. But
in this particular context, you are being warned the same thing. Do not
hold on to any HDC that you do not explicitally create yourself.

> What about GetDC/GetWindowDC?

Do not hold on to those HDCs between messages.

> Until I started reading Petzold's book I had used SelectObject() as:

That is the correct way to use it. Always re-select any previous GDI
resources you replace when you are done using them.

> case WM_PAINT:
> hdc = GetDC(hwnd);

You should be looking at the wParam value. If not 0, it contains an HDC
that you need to draw to instead.

> SelectObject(hdc, hBrushOld); //1

> When do I have to save / restore old attributes, here the hBrushOld?

When you are done using them before exiting.

> Is the line marked with //1 necessary?

Yes.

> Another book gives the following code for BitBlt function as an example:

<snip>


> Is the line marked with //2 necessary?

Yes, for the same reason.

> This book restores all GDI objects, not just bitmaps.

That is the correct thing to do. If you replace any GDI object with your
own, restore the old one when you are done.

> Another material, a tutorial actually, gives the following code:

<snip>


> The default bitmap is restored again.

As it should be.

> So, when is it necessary to restore default attributes?

Always.

> Assume the following code:
<snip>


> Is it ok to delete hdcMem while hBitmap is selected into hdcMem

No.

> or should I use the following code?

Yes.


Gambit


UO

unread,
Aug 5, 2008, 3:16:18 PM8/5/08
to
"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:489892df$1...@newsgroups.borland.com...


>Do not hold on to any HDC that you do not explicitally create yourself.

Then, yes, CreateCompatibleDC/DeleteDC can be used between messages


> That is the correct way to use it. Always re-select any previous GDI
> resources you replace when you are done using them.
>
>> case WM_PAINT:
>> hdc = GetDC(hwnd);
>
> You should be looking at the wParam value. If not 0, it contains an HDC
> that you need to draw to instead.

Sorry, my mistake. The code should be:

case WM_PAINT:
hdc = BeginPaint(hdc, &ps);


hBrushOld = SelectObject(hdc, hBrush);
GetClientRect(&rect);
Rectangle(hdc, 10, 20, 30, 40);
SelectObject(hdc, hBrushOld); //1

EndPaint(hdc, &ps);
break;


>> So, when is it necessary to restore default attributes?
>
> Always.

It's quite weird that a textbook which is considered as "classic" or "best"
by many people,
can contain so arguable material.

Thanks again...


Remy Lebeau (TeamB)

unread,
Aug 5, 2008, 4:49:22 PM8/5/08
to

"UO" <uo@uott> wrote in message news:4898a6fd$1...@newsgroups.borland.com...

> Sorry, my mistake. The code should be:

Your code is still not looking at the wParam value. And it is passing an
invalid HWND to both BeginPaint() and EndPaint() as well. Try this instead:

case WM_PAINT:
if( wParam == 0 )
hdc = BeginPaint(hwnd, &ps);

else
hdc = reinterpret_cast<HDC>(wParam);
...
if( wParam == 0 )
EndPaint(hwnd, &ps);
break;


Gambit


Alan Bellingham

unread,
Aug 5, 2008, 6:29:29 PM8/5/08
to
"UO" <uo@uott> wrote:

>It's quite weird that a textbook which is considered as "classic" or "best"
>by many people, can contain so arguable material.

Petzold (at least the earliest editions) were the best purely by dint of
being pretty much the *only* books with the requisite information in.
They were lousy so far as the quality of their C++ went, but they did
give examples which worked, even if the results were not production code
quality.

(Once you've got something which makes the APIs work, it's your job to
see how it works, and then produce the good stuff. Not everyone did ...)

Alan Bellingham
--
Team Browns
<url:http://www.borland.com/newsgroups/> Borland newsgroup descriptions
<url:http://www.borland.com/newsgroups/netiquette.html> netiquette

UO

unread,
Aug 6, 2008, 2:42:39 AM8/6/08
to

"Alan Bellingham" <al...@episys.com>, haber iletisinde sunlari
yazdi:brkh94lo4g60fric1...@4ax.com...

> "UO" <uo@uott> wrote:
>
> (Once you've got something which makes the APIs work, it's your job to
> see how it works, and then produce the good stuff. Not everyone did ...)

The main concern of my messages was gdi memory leak. I think it is
quite hard to produce a memory leak and "see how it works" in recent
Windows systems. So, I still think everyone needs theoretical-correct
information, a theoretical-correct book.

UO


UO

unread,
Aug 6, 2008, 3:36:08 AM8/6/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com>, haber iletisinde şunları
yazdı:4898bd3c$1...@newsgroups.borland.com...

Sorry, I've made a typing mistake again. It should:
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);


hBrushOld = SelectObject(hdc, hBrush);
GetClientRect(&rect);
Rectangle(hdc, 10, 20, 30, 40);
SelectObject(hdc, hBrushOld); //1

EndPaint(hwnd, &ps);
break;
(But appearently you understood what I meant)

I'm not using common controls currently.

Anyway, should I use a ReleaseDC() or something after
"hdc = reinterpret_cast<HDC>(wParam);" ?

UO


Remy Lebeau (TeamB)

unread,
Aug 6, 2008, 12:37:34 PM8/6/08
to

"UO" <uo@uott> wrote in message news:48995465$1...@newsgroups.borland.com...

> Anyway, should I use a ReleaseDC() or something after
> "hdc = reinterpret_cast<HDC>(wParam);" ?

No. The sender of the message owns that HDC and will release it accordingly
after the WM_PAINT message handler exits.


Gambit


0 new messages