Solved

How can i minimize flicker of a bitmap blitted to awindow in API code (not MFC)

Posted on 2007-11-28
10
425 Views
Last Modified: 2012-06-27
Hi,
I have searched for ages trying to find a way to remove the flicker from a bitmap, rendered into a window with the below code (it is rendered on a WM_PAINT message within an owner-drawn tab control. It works but flickers really badly when resizing the window. I have tried returning false on WM_ERASEBKGND in both the main wndproc and the tab controls proc too, but its still rubbish. I read about the CMemDC, but my app is API, not MFC. Can anyone help?
Much appreciated,
DumbMonkey.
VOID CImage::Draw(HWND hWnd, LPRECT rect)

{

hDC = GetDC(hWnd);

    hCompatibleDC = CreateCompatibleDC(hDC);

    hOldBitmap = (HBITMAP) SelectObject(hCompatibleDC, hImageBitmap);

    GetObject(hImageBitmap, sizeof(imageBitmap), &imageBitmap);

    StretchBlt(hDC, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, hCompatibleDC, 0, 0, imageBitmap.bmWidth, imageBitmap.bmHeight, SRCCOPY);

    SelectObject(hCompatibleDC, hOldBitmap);

    DeleteDC(hCompatibleDC)

}

Open in new window

0
Comment
Question by:DumbMonkey
  • 3
  • 3
  • 2
  • +1
10 Comments
 
LVL 3

Accepted Solution

by:
wizrr earned 125 total points
ID: 20367788
Maybe you should not call default WndProc on WM_ERASEBKGND message? Just catch WM_ERASEBKGND and do not put it in DefaultWndProc.

Maybe somewhere in your WM_PAINT Clear(BRUSH_WHITE) or something?

Try to paint only changed region.
0
 
LVL 11

Expert Comment

by:jgordos
ID: 20367804
There are several things I would try...

    HDC memDC = CreateCompatibleDC ( hDC );
    HBITMAP memBM = CreateCompatibleBitmap ( hDC, nWidth, nHeight );
    SelectObject ( memDC, memBM );

So, the DC you pass to the CreateCompatibleBitmap can be either the screen DC, or the memory DC.  When you create it using the memory DC, select your color bitmap into it, so it has the same basic layout as the screen.

The other things I'd do, if it's constantly flashing and such, are
1) use a tool like WinSpy to see the messages that are being sent to the window....  This is from memory so forgive me if it's not exactly right, but the messages are like WM_RESIZE WM_PAINT WM_RESIZE WM_PAINT
Try adding the blit code you have there to the other messages, too, like the resize handler...
2) Don't constantly select the bitmaps in and out and all around... after you've selected your bitmap in there, don't put back (ie select it back) the old crapy thing we didn't care about in the first place
3) Save your CompatibleDC... you don't need to release that back all the time


0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20367898
>>>> It works but flickers really badly when resizing the window.
You could try to prevent from drawing while resizing. After a small delay - say 1 second - you can make a deferred drawing of the image.

One method to solve that like that is to have a handler for WM_SIZING  (not WM_SIZE) message. WM_SIZING is sent *prior* to drawing. In the handler you set a bool member of the CImage class, e. g.  'm_isSizing' to 'true' and update the CImage::Draw by

VOID CImage::Draw(HWND hWnd, LPRECT rect)
{
      if (m_isSizing)
      {
             // put her your current drawing code
      }
}

With that there is one problem left how to reset the m_isSizing to false after the sizing ended. That can be done by setting up a timer when setting the m_isSizing to true

void CMyDialogOrView::OnSizing()
{
       if (!m_imageCtrl.m_isSizing)  // do it only once
       {
            m_imageCtrl.m_isSizing = true;
            SetTimer(99, 1000);
       }
}

That invokes a timer with the id = 99 and a period of 1 second. You can catch it by writing a handler for the WM_TIMER message:

   void CMyDialogOrView::OnTimer(UINT eventId)
   {
         if (eventId == 99)
         {
                m_imageCtrl.m_isSizing = false;
                KillTimer(99);
         }
   }

So, That would prevent from flickering at least the first second.

But, as you would get more than one WM_SIZING message if the user continues sizing the 'game' would go on and you'll got a refresh of the image only for every second. That should be fine but you can play with the timeout parameter to improve the behavior. You also could have a handler for the WM_SIZE message (you'll get after sizing) and save the current timestamp in a further member. Then the OnTimer could check how much time was elapsed since the last WM_SIZE and can decide whether to allow drawing based on that.

Regadrs, Alex

 
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20367911
>>>> VOID CImage::Draw(HWND hWnd, LPRECT rect)
>>>> {
>>>>      if (m_isSizing)

Of course it has to be

       if (!m_isSizing)


0
 
LVL 11

Expert Comment

by:jgordos
ID: 20368304
uh, he's not MFC...

And i think he needs the image to blit during the resize, although he really doesn't say that.

0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:DumbMonkey
ID: 20368773
Hi,
Yes jgordos, thats exactly what i want to do, it looks terrible when the window is resized.
Thanks all.
0
 

Author Closing Comment

by:DumbMonkey
ID: 31411444
Thanks all,
To fix the problem i just returned FALS to the WM_ERASEBKD. It didnt work originally as I had to do this in both the main WndProc and the tab controls WndProc. That fixed it. Thanks to jgordos for the good advice too.
0
 
LVL 3

Expert Comment

by:wizrr
ID: 20369622
DumbMonkey what you actually did to solve this problem?
0
 

Author Comment

by:DumbMonkey
ID: 20370140
Hi wizrr,
Well i just returned FALSE to WM_ERASEBGND. It was failing as I was doing the blitting from another wndproc (belonging to the tab control). So i added the WM_ERASEBKGND: return FALSE for both wndprocs and it worked.
Cheers,
DumbMonkey
0
 
LVL 3

Expert Comment

by:wizrr
ID: 20370157
Thanks DumbMonkey. And good luck)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Navigation is an important part of web design from a usability perspective. But it is often a pain when it comes to a developer’s perspective. By navigation, it often means menuing. This is less theory and more practical of how to get a specific gro…
How to remove superseded packages in windows w60 or w61 installation media (.wim) or online system to prevent unnecessary space. w60 means Windows Vista or Windows Server 2008. w61 means Windows 7 or Windows Server 2008 R2. There are various …
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

911 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now