1
votes

INTRODUCTION AND RELEVANT INFORMATION:

FORMER TITTLE OF THE QUESTION:

Window produces flicker-like ( slow repainting-like ) effect when resized

I have a complex painting to implement in my main window’s WM_PAINT handler. I have submitted a picture bellow.

enter image description here

Logo’s marked with 1 and 2, are drawn using GDI+. Logo marked as 1, is metafile, and logo marked with 2 is PNG.

If I leave out drawing of the second logo, my window doesn’t flicker, yet if I add the drawing of the second logo in my WM_PAINT, the following effect, illustrated with the picture below, occurs ( this is just a sketch made in Paint, but hopefully it will clear things up ):

enter image description here

It seems as if the repainting is slow.

IMPORTANT NOTE: This effect happens on child windows, the background is painted properly.

Just in case it matters, the information about child windows:

All 5 child windows are static controls.

Static controls with blue gradient are painted with double buffering, using GDI, in WM_CTLCOLORSTATIC.

Orange static control is subclassed, and is ownerdrawn.

IMPORTANT NOTE: I must say that this is my first time using GDI+.

In my WM_PAINT handler, I have made compatible memory DC, required for double buffering, like this:

   HDC hdc = BeginPaint( hwnd, &ps), hdcMemImg, MemDC;
   MemDC = CreateCompatibleDC(hdc); // back buffer.

Compatible bitmap has dimensions of main window’s client area.

As I’ve said, everything seems to work fine, since I use GDI and double buffering to paint/draw.

When I need to paint the logo’s marked with 1 and 2, I do it with this code:

    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        Image image(L".\\resources\\BG.emf"), image1(L".\\resources\\RGF.png");
        switch(msg)
        {
        case WM_ERASEBKGND:
           return (LRESULT)1;
        case WM_PAINT:
           {
              PAINTSTRUCT ps;
              HDC hdc = BeginPaint( hwnd, &ps), hdcMemImg, MemDC;
              MemDC = CreateCompatibleDC(hdc); // back buffer.
              // CreateCompatibleBitmap and other usual stuff
              /******************** left logo *******************/
              Graphics graphics( MemDC );
              //============= aspect ratio ================//
              UINT o_height = image.GetHeight(),
                   o_width =  image.GetWidth();
              INT n_width = 80;
              INT n_height = 100;
              double ratio = ( (double)o_width ) / ( (double)o_height );
              if (o_width > o_height)
              {
                  // Resize down by width
                  n_height = static_cast<UINT>( ( (double)n_width ) / ratio );
              }
              else
                  n_width = static_cast<UINT>(n_height * ratio);
              //========== ensure high graphic quality ======================//
              graphics.SetSmoothingMode( SmoothingModeHighQuality );
              graphics.SetInterpolationMode( InterpolationModeHighQualityBicubic );
              graphics.DrawImage( &image, r.left + 5, r.top + 10, n_width, n_height );
              /******************** right logo *******************/
              Graphics graphics1( MemDC );
              //============= aspect ratio ================//
              o_height = image1.GetHeight(), 
              o_width = image1.GetWidth();
              n_width = 90;
              n_height = 100;
              ratio = ( (double)o_width ) / ( (double)o_height );
              if (o_width > o_height)
              {
                  // Resize down by width
                  n_height = static_cast<UINT>( ( (double)n_width ) / ratio );
              }
              else
                 n_width = static_cast<UINT>(n_height * ratio);
              //=========== ensure high graphic quality ============//
              graphics1.SetSmoothingMode( SmoothingModeHighQuality );
              graphics1.SetInterpolationMode( InterpolationModeHighQualityBicubic );
              graphics1.DrawImage( &image1, r.right - r.left - 90, r.top + 10, n_width, n_height );
              // Then do BitBlt of MeDC to hdc, and clean it up

If additional code snippets are required, ask and I will edit my post, but for now, they are omitted to keep the post short and concise.

I work on Windows XP, using MS Visual Studio C++ and pure Win32 API.

My CPU is single core ( 2,67 GHz ), and I have 768 MB of RAM.

IMPORTANT UPDATE:

When I turn on Task Manager, I can see that the memory consumption of my application sky rockets.

It never drops, it always grows, especially when I resize the window.

Detailed description of my efforts to solve this can be found bellow.

I have decided to take the advice of the more experienced and better developers, and will provide link to the demo project.

One note: since Express edition of VS has no resource editor, resource file and resource header were created using ResEdit from here http://www.resedit.net/.

Here is the link to the demo project ( all the necessary comments and explanations are in the projects comments ):http://www.uploadmb.com/dw.php?id=1382012579.

MY EFFORTS TO SOLVE PROBLEM:

Browsing through the Internet, SO archive, CodeProject, and CodeGuru, I was unable to see the problem-it seems ( and I believe too ), that the principles of double buffering in GDI+ and GDI are the same.

IMPORTANT UPDATE:

I have downloaded VLD from http://vld.codeplex.com/, followed their instructions, but VLD didn't detect any memory leaks.

Also, I have made a copy of the project and have deleted static controls, leaving only the window's background to ease my debugging.

Memory consumption described above still happens.

It seems to stop only if I don't draw logos.

QUESTION:

Since this is my first time using GDI+, is there something that I’m missing, in view of releasing/deleting some GDI+ object or something similar ( all the GDI+ code for drawing in WM_PAINT is submitted )?

Again, I believe that my other painting code works well, but I will post it if required.

UPDATE:

Regarding the updates provided above, what should I do to fix the problem of excessive memory consumption described above?

Can someone review small demo project provided above, and try to give me useful advice?

Thank you.

Regards.

2

2 Answers

1
votes

The problem was solved with great detailed explanations in this link: http://www.codeproject.com/Questions/666738/Window-produces-flicker-like-slow-repainting-like

In case that link becomes dead, this is what I had to do:

  1. Resize my left logo to proper dimensions;

  2. Remove some memory leaks that I have missed;

  3. Make Image objects global;

The 3rd action is what matters the most, since I load huge images repeatedly each time main window's procedure is called, which eventually completely consumes up memory.

Hope that this will help someone in the future.

0
votes

Don't use more than one Graphics objects of GDI+. Also be arware that the the deconstruction of this Graphics objects run after you copied the Bitmap back to the real DC. Thios also might cause side effects.

Place all use of the Graphics objects in own blocks so that the deconstruction occurs before you are copying the mem DC back to the paint DC.