Link to home
Start Free TrialLog in
Avatar of cipeciop
cipeciop

asked on

Amimated bitmap

I need to animate 2 bitmaps: my idea is to switch from first one to second one using a timer.
Every tick of timer I show the other bitmap (that I've previously loaded from file)

And it works, but with Win95 after a while the window refresh stops and I must restart the application.

Avatar of nietod
nietod

answer coming.
It sounds like you have a resource leak.  For example, if you select the bitmap into a DC for drawing and then don't select the original bitmap back in, the original bitmap won't be deleted.  This will cause a slow, but steady consumption of GDI resources until GDI or your application can't function.

If you post your code, I might be able spot your error.  Otherwise, you should look for instances where you application does not clean up as it should.
What is wrong with my answer?  You've rejected it, but not indicated why you think it is wrong or what additinal information you would like.  I suspect, in fact, that it is still right.
cipeciop,

1. It is customary to leave a comment when rejecting an answer. The reason is that another expert comes along, sees that someone gave an answer and you rejected him/her without any a comment or further information and figures Why try and help if this person isn't going to give any feedback on proposed answers/comments.

2. I would be really interested in hearing why you rejected nietod's answer since it is definitely the first thing that I would think of as well.

Tom

Avatar of cipeciop

ASKER

I'm sorry, but I was sure to have added this information: with
Windows NT works (that's why I rejected: it gave no hints
about this difference, NT OK, 95 NOK)
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I think to deselect all resources..

here's my code

VOID
CMyBitmap::MyDrawBitmap(CDC * pDC, CBitmap & bitmap, CPalette * pPal)
{
      // Create a compatible memory DC
      CDC memDC;
      BOOL fRes;
      fRes = memDC.CreateCompatibleDC( pDC );
      ASSERT (fRes != FALSE);
      CBitmap *oldbitmap=NULL;
      oldbitmap = memDC.SelectObject( &bitmap );
      ASSERT (oldbitmap != NULL);
      CPalette *oldpalette=NULL;

      // Select and realize the palette
      if( pPal != NULL && pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
      {
            oldpalette = pDC->SelectPalette( pPal, FALSE );
            ASSERT (oldpalette != NULL);
            pDC->RealizePalette();
      }

      BITMAP bm;
      bitmap.GetBitmap( &bm );

      //pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memDC, 0, 0,SRCCOPY);
      fRes = pDC->BitBlt(m_Newx, m_Newy, bm.bmWidth, bm.bmHeight, &memDC, 0, 0,SRCCOPY);
      ASSERT (fRes != FALSE);

      
      if (oldpalette != NULL)
            memDC.SelectPalette(oldpalette, FALSE );
      
      if (oldbitmap != NULL)
            memDC.SelectObject(oldbitmap);
}

First of all.  Never accept an answer until you have a working solution.  My answer was just a guess.  You should wait until we get it worked out.

The code above seeems to clean up correctly.  Does the code that uses it?  The three objects passed to it all need to be (eventually) deleted.  Can you post that code?

One small point.  The lines at the end that select back to original palette and bitmap don't need to be in if's, somce you have asserts to make sure these are not NULL above.  In addition, if you didn't select back the original objects, it would leave your objects selected in and that would be as bad an error as selected in a NULL pointer.  

Try to post the code that uses this.
Your answer seems to be THE correct guess (now the program
is working since yesterday without problems).
Yes, the objects are attributes of the class containing the
function I've sent, they are (implicitly) deleted in the destructor.
I've put the Asserts after the if just to check everything.
I don't understand the "if you didn't select back...." period.
>> Your answer seems to be THE correct guess (now the program  is working since yesterday without problems).

I proposed something to look for.  But I didn't see any examples of that problem in the source you sent.  Did you fix something before you sent it?  

My last point is that what you get back fromf SelectObject has to be selected back in at the end.  You have those statements inside if's.  However you can assume that those if's will allways execute their code.   So you don't neeed the if's, just the SelectObjects inside them.  That will be faster and shorter.
The function I've modified is

VOID
CNIMMIView::DrawBackGround(CDC & pDC)
{
      CRect rect;
      CBrush *oldbru=NULL;
      CPen *oldpen=NULL;
      GetClientRect (&rect);
      CBrush bru(clSilver);
      CPen pen(PS_NULL, 1, clSilver);

      oldbru = pDC.SelectObject (&bru);
      ASSERT (oldbru != NULL);
      oldpen = pDC.SelectObject (&pen);
      ASSERT (oldpen != NULL);

      pDC.Rectangle (&rect);

      pDC.SelectObject (oldpen);
      pDC.SelectObject (oldbru);
}// end of DrawBackGround()

I had forgot the last 2 SelectObject(): that was the error.
About the if's: but the do the asserts work even in release build ? (if they do work
only with debug build I must avoid to Select() a NULL object isn't it ?


Okay so it was the problem I suggested.

The asserts don't work int he release code (they are not included in the code).  However, that;'s not the issue.  The if's I suggested you remove, protect you from one error by causing another one.  (one that will harder to track down.)

Take a look at
{
   CBrush newbru(clSilver);
   CBrush *oldbru = pDC.SelectObject (&newbru);

   if (oldbrh)
      pDC.SelectObject (oldbru)
}

Now say that oldbrh is set to NULL but the select object.  So you don't select in a NULL pointer.  That prevents an error their.  However, it leaves in the pointer to the "newbru".  That newbrh is then destroyed, but the pDC contains a pointer to it.  Thus you still have an error.

You can safely assume that selectobject will not return a NULL pointer.  If it does return a NULL pointer things are going to h**l anyways, so don't bother trying to prevent an error.