CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Apr 2008
    Posts
    214

    C++ Winapi - Flicker on Resize

    When I resize the main window, manually, after everything has been created, I find some of the controls flicker. I have just recently added: "case WM_ERASEBKGND: return 1;" and though it helps significantly, there is still a slight flicker (not as annoying). Also, though it helps significantly with the flicker, as I resize the main window, it captures images from whatever is running behind my program.
    Attached Images Attached Images  

  2. #2
    Join Date
    Dec 2008
    Posts
    29

    Re: C++ Winapi - Flicker on Resize

    there are several methods for that but all need time,

    - Try to remove any gaps between your child windows(even one pixel), otherwise you need to stop repainting the background when you resize it.

    - as you said you can use WM_ERASEBKGND (return 1 )for this purpose, but after that you must fill the background of the main window by a solid color or any other brush. for example with FillRect in wm_paint.
    FillRect(hdc, &rect, (HBRUSH) (COLOR_WINDOW+1));

    - Also change WNDCLASSEX.style to NULL and experiment it.

  3. #3
    Join Date
    Apr 2008
    Posts
    214

    Re: C++ Winapi - Flicker on Resize

    cool thanks.

  4. #4
    Join Date
    May 2009
    Posts
    2

    Angry Re: C++ Winapi - Flicker on Resize

    I've done everything what you have said here, but my window flickers.

    Can you tell me, what's wrong?

    If you click in the window in the left top corner (like in 1x1 or 2x2 pixel) one of the lifts start to go upwards (it's a hidden programmer's testing functionality), so you can see how annoying the flickering is.

    My programm:
    www.wewnatrz.com/beta2/gfx/lifts.rar

  5. #5
    Join Date
    Nov 2006
    Posts
    1,611

    Re: C++ Winapi - Flicker on Resize

    Flicker is a common problem.

    The most complete and common solution is to draw onto an offscreen buffer, then blit the results into place. The problem comes when you use common controls; it can run counter to the common solution - the use of offscren/blit combination is usually used with custom controls or applications where painting is performed by the application, not a standard control.

    This issue is also affecting the background of a dialog or window with child controls. Anytime a standard painting algorithm paints on the display surface, this flicker can happen.

    You could cause the entire window/dialog paint in a 'standard' way to an offscreen buffer, instead of the display - then blit (or selectively blit in the case of optimized output of portions of the area) when that painting is completed.

    In other words, if anything is going to paint on the display surface directly, you're going to witness drawing progress over time. This is mitigated somewhat by the batching that Windows does with GDI commands, but it doesn't eliminate it - it only minimizes by drawing a group of GDI commands so fast you can't see it happen. The more is to be drawn, and the longer that takes, the more likely you'll see a moment of partially displayed results, which is the completed - in a rapidly repeated succession as you resize the window (or do anything that causes repaints - like slide a window over your application).

    A generalized solution is not found on most frameworks like MFC, QT, wxWidgets or others, to my knowledge - though it is certainly possible to craft one that you can implement throughout application development. There are a variety of tributaries required to get it right. For example, if a repaint is called for, and the dialog is already held in an offscreen buffer, the repaint may be nothing more than a blit of the current hidden buffer. One can imagine various solutions to expanding vs shrinking the window, at that depends on how your application handles such a thing. If you reposition controls for a smaller window - something like a webpage is re-rendered - then, of course, the entire window content is redrawn first, then the offscreen buffer is blitted to the display.

    Offscreen buffers are common, they do take up RAM, and depending on how you handle the problem, generalized solutions can be suboptimal for some kinds of windows compared to others. The subject is not that in-depth, but more than can be described in posts here.

    I haven't loaded your application as of this post - perhaps I'll have time to check into that later and post again with something more specifically relevant.
    If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).

  6. #6
    Join Date
    Apr 2009
    Location
    Cochin
    Posts
    83

    Smile Re: C++ Winapi - Flicker on Resize

    The Flickering most commonly occurs due to Poorly handled WM_PAINT messages, or the applications failure t propcess the WM_PAINT message properly.

    you may try this WM_PAINT block in your code :

    Code:
    case WM_PAINT:
    			
                            {
    				PAINTSTRUCT ps;
    				BeginPaint(appWindow, &ps); //appWindow is Handle to Window(Parent)
    				EndPaint(appWindow, &ps);
    			}
    			
    			break;
    And, also use the WS_CLIPCHILDREN Style in the CreateWindow() for Parent Window...
    "I studied everything but never topped. Today, toppers of the world's best universities are my employees"

    -William Henry Gates (Bill Gates)

  7. #7
    Join Date
    May 2009
    Posts
    2

    Re: C++ Winapi - Flicker on Resize

    Quote Originally Posted by JVene View Post

    I haven't loaded your application as of this post - perhaps I'll have time to check into that later and post again with something more specifically relevant.
    it would be really nice of you, since I don't have any idea how to put into practice what you have written.

  8. #8
    Join Date
    Nov 2006
    Posts
    1,611

    Re: C++ Winapi - Flicker on Resize

    I loaded the application, but I'm not sure where to go next.

    The window that's presented can't be resized, and I otherwise don't witness flicker (probably because I can't resize as you've indicated).

    Obviously, as I seen in main.cpp, you can handle blitting bitmaps.

    The main idea behind the most common flicker cure is to draw in a bitmap that's the size of the window - all drawing that you are now doing on the window would be directed to the bitmap (it's called an offscreen buffer in this case, and is usually created as a DIBSection).

    When you've painted the entire contents of the window on this bitmap, you then blit the result to the display. This blit happens fast, so flicker isn't visible, if you also disable background erasure of the underlying window during repaint (if it is erased, there will be a 'massive' flicker instead).

    Most often this means that the blit is re-displaying identical content from the previous 'view' of this bitmap, which is not a visible act. If one part of the dialog changed, it will simply appear as if that change happened instantly, with no underlying erasure or time related drawing artifacts.

    You can also use several techniques for drawing only portions of the hidden surface (the bitmap you're using instead of the display window for your drawing). For example, if you've updated a control on the display, you can draw your update on the hidden surface, the blit only the region of that control onto the display.

    If a more current version of your application is resizable, then upload it for review too. Also, since the hidden bitmap is created to match the dimensions of the display, there is, naturally, a need to respond to a resize message so as to drop the existing hidden surface and create a new one that matches the larger size.

    More detail than this is beyond the scope of posts here - it's a chapter or two in a book or more, and the technique is widely discussed under various titles such has off screen buffer, hidden buffer, etc.

    Several "skinning" frameworks do this too - which looks like what you're doing, essentially, in your interface - a skinned dialog approach (looks nice, too).

    BTW, CoolPG has some points that are related to my general thrust of hidden buffer display technique. It is quite true that the "environment" of the window must be compatible with the solution; that is, clipchildren, handling the erase message so you DON'T let Windows erase the display as part of painting, as if there's a null background.

    One problem I have in describing Windows oriented details to you is that I use frameworks (generally platform independent) that do all this for me. I wrote the framework (or much of it), but it's been a while - and now I don't have to even consider the problem anymore. As such, I'm reaching for memory of what I wrote perhaps 10 years ago, when I finally got around to realizing I shouldn't have to repeat the solution. Several "little details" that are Windows oriented are likely to slip my mind, and vex you on your way to a solution, but then what is new about writing for Win32 (or any other) anyway?

    Now, I'm going to argue from another perspective.

    Your dialog appears to be displayed using several small bitmaps, which are displayed in a grid (with others forming a left and top 'header' to the grid). Arguably, this is display blitting, just not of a single underlying hidden surface.

    Let's argue that you have, say, 5 colums of 20 rows, each 'cell' being a blit of a bitmap image, forming a grid (loosely what I see here). From the time you blit the first, upper left bitmap to the time you blit the last one in row 20 of column 5, there is a delay. This delay is very short, and depending on hardware, can be as fast as the refresh of the monitor, or on slower hardware, slow enough to actually see the display loop play out over time.

    In the former, if you allowed the background to erase - the entire window would flash to the background color, then the display loop would fill the display with bitmaps. It is the flash of the erasure that causes one type of common flicker.

    One reason to erase the background is to clear it WITH a background, then draw a collection of controls that have space between them. If you didn't clear the background in such a situation, then you'd see content bleed through from behind your application's window.

    However, even this won't cause flicker on child controls where the parent is told to clip to it's children (CoolPG points this out). That is, the parent will erase IT'S face (the background), but not the region where the child controls are placed - as a result, they're not 'flashed over' with background prior to repainting, and there's no apparent flicker in that situation (CoolPG's point).

    On your display, however, you're drawing the entire display surface yourself (it seems on very quick skimming of your code and the visual of your app). In this case, there's no child to clip to, and so the underlying erase is going to flash over the whole dialog with a background color, then draw again - causing flicker (fast flicker on fast hardware, very slow on lesser hardware).

    If you eliminate the background erase, set the background brush to null, then since you're drawing the entire surface of the dialog itself, there will be no flicker for that sequence of events!

    You wouldn't need a hidden buffer.

    Remember I said if you don't stop the background erase, there would be massive flicker? Even on a hidden display blit, this is true. The only real difference between a hidden surface display technique and yours (painting the entire surface with a collection of bitmaps) - is the number of bitmaps being blit to the dispaly.

    If you stay with your existing technique, bliting the component bitmaps that comprise your display, and if there is no other means of display (no controls, etc) - this should be all you need.

    If, however, you incorporate controls or text, you'll want to do what I think you're already doing in the glowing check boxes at the top - draw in a bitmap, or substitute bitmaps for state. This is so similar to hidden buffer techniques that the only real difference, again, is the size and nature of the underlying bitmap support. You're doing "tiles" - whereas the 'standard' hidden buffer technique uses a bitmap for the entire window, and draws on THAT instead of the window.

    I haven't done Win32 API like you're application is doing in so long I don't have the reference handy. The background brush is set to null in the window class, if memory serves. Override the WM_ERASE (or is that WM_ERASEBACKGROUND - Yish, I'm glad not to HAVE to think of this in my coding, but I have had to do it) - anyway, you're basically responding to that message by NOT erasing anything.
    Last edited by JVene; May 4th, 2009 at 04:06 PM.
    If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured