🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
8 messages
8 total messages Started by UO Tue, 05 Aug 2008 15:54
Some HDC questions
#36
Author: UO
Date: Tue, 05 Aug 2008 15:54
137 lines
4884 bytes
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...
Re: Some HDC questions
#37
Author: Remy Lebeau (TeamB)
Date: Tue, 05 Aug 2008 17:46
67 lines
2790 bytes
"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 
Re: Some HDC questions
#38
Author: UO
Date: Tue, 05 Aug 2008 19:16
39 lines
1984 bytes
"Remy Lebeau (TeamB)" <no.spam@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... 
Re: Some HDC questions
#39
Author: Remy Lebeau (TeamB)
Date: Tue, 05 Aug 2008 20:49
21 lines
1630 bytes
"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 
Re: Some HDC questions
#40
Author: Alan Bellingham
Date: Tue, 05 Aug 2008 22:29
19 lines
1738 bytes
"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
Re: Some HDC questions
#41
Author: UO
Date: Wed, 06 Aug 2008 06:42
14 lines
1605 bytes
"Alan Bellingham" <alanb@episys.com>, haber iletisinde sunlari 
yazdi:brkh94lo4g60fric1ii9g9uki4af7bul9m@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 
Re: Some HDC questions
#42
Author: UO
Date: Wed, 06 Aug 2008 07:36
43 lines
2134 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com>, haber iletisinde �unlar� 
yazd�:4898bd3c$1@newsgroups.borland.com...
>
> "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

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 
Re: Some HDC questions
#44
Author: Remy Lebeau (TeamB)
Date: Wed, 06 Aug 2008 16:37
11 lines
1417 bytes
"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 
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads