From: Woody on
I am having difficulty displaying bitmaps

When I start my app, everything works as expected; the screen is
painted with the corrected bitmaps

But after the app has run for 20 min or so, I get an error when I
create a compatible device context. As far as I can tell, there is no
error information available; the DC just comes back NULL.

Here is an outline of the OnPaint code that fails. This code is
supposed to paint part of the screen using some precalculated bitmaps
and masks.

void CBoard::OnPaint()
{
CPaintDC dc(this); // device context for painting

CDC dcMem; dcMem.CreateCompatibleDC(&dc); // make a "memory DC"
if(dcMem==NULL)
{
return; // UNEXPECTED ERROR
}
CBitmap *oldBM=dcMem.SelectObject(&bitmap[0]);
... several iterations of ...
dcMem.SelectObject(&mask[i]);

ok=dc.BitBlt(x,y,w,h,&dcMem,0,0,SRCAND);
dcMem.SelectObject(&bitmap[i]);
ok=dc.BitBlt(x,y,w,h,&dcMem,0,0,SRCPAINT);

dcMem.SelectObject(&oldBM);
dcMem.DeleteDC();
}

Can anyone see what I am doing wrong? This fails under WinXP and
WinXP64.
From: Joseph M. Newcomer on
See below...
On Sun, 30 May 2010 16:36:28 -0700 (PDT), Woody <ols6000(a)sbcglobal.net> wrote:

>I am having difficulty displaying bitmaps
>
>When I start my app, everything works as expected; the screen is
>painted with the corrected bitmaps
>
>But after the app has run for 20 min or so, I get an error when I
>create a compatible device context. As far as I can tell, there is no
>error information available; the DC just comes back NULL.
>
>Here is an outline of the OnPaint code that fails. This code is
>supposed to paint part of the screen using some precalculated bitmaps
>and masks.
>
>void CBoard::OnPaint()
>{
> CPaintDC dc(this); // device context for painting
>
> CDC dcMem; dcMem.CreateCompatibleDC(&dc); // make a "memory DC"
****
Put a newline after every semicolon; the code above is essentially unreadable.
****
> if(dcMem==NULL)
****
This doesn't even make sense; dcMem is a CDC and will NEVER be NULL. If you checked the
return code for CreateCompatibleDC it would be more useful!

if(!CreateCompatibleDC(&dc))
****
> {
> return; // UNEXPECTED ERROR
> }
> CBitmap *oldBM=dcMem.SelectObject(&bitmap[0]);
> ... several iterations of ...
> dcMem.SelectObject(&mask[i]);
>
> ok=dc.BitBlt(x,y,w,h,&dcMem,0,0,SRCAND);
> dcMem.SelectObject(&bitmap[i]);
> ok=dc.BitBlt(x,y,w,h,&dcMem,0,0,SRCPAINT);
>
> dcMem.SelectObject(&oldBM);
> dcMem.DeleteDC();
****
There is no need to call DeleteDC; this happens automatically when the dcMem variable
leaves scope.
****
>}
>
>Can anyone see what I am doing wrong? This fails under WinXP and
>WinXP64.
****
You are almost certainly leaking GDI handles, and it is probably not in this code. Or it
may be in the parts of the code you never showed.
joe
***
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Woody on
On May 30, 6:11 pm, Joseph M. Newcomer <newco...(a)flounder.com> wrote:
> This doesn't even make sense; dcMem is a CDC and will NEVER be NULL.  If you checked the
> return code for CreateCompatibleDC it would be more useful!

I agree, it doesn't make sense. But it is happening. You are right,
though, I should also check the return code.

> You are almost certainly leaking GDI handles, and it is probably not in this code.  Or it
> may be in the parts of the code you never showed.

That is a good suggestion. I'll see if I can test that. ...and... YES,
this process shows 9999 GDI objects.

Now to find out who's hoarding them.
From: Joseph M. Newcomer on
Pretty much look at any place that creates bitmaps. That's the first and best place to
look. OnCtlColor handlers often generate brushes (erroneously), so that's another
candidate.
joe

On Sun, 30 May 2010 19:54:53 -0700 (PDT), Woody <ols6000(a)sbcglobal.net> wrote:

>On May 30, 6:11�pm, Joseph M. Newcomer <newco...(a)flounder.com> wrote:
>> This doesn't even make sense; dcMem is a CDC and will NEVER be NULL. �If you checked the
>> return code for CreateCompatibleDC it would be more useful!
>
>I agree, it doesn't make sense. But it is happening. You are right,
>though, I should also check the return code.
>
>> You are almost certainly leaking GDI handles, and it is probably not in this code. �Or it
>> may be in the parts of the code you never showed.
>
>That is a good suggestion. I'll see if I can test that. ...and... YES,
>this process shows 9999 GDI objects.
>
>Now to find out who's hoarding them.
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Woody on
The culprit was a line

pDC->SelectObject(CreateSolidBrush(color));

It was in the view's OnDraw function, not the OnPaint I showed, which
belonged to a different class.

For some reason, the SelectObject continued to work properly.

I used GDIView to trace the leak.