Trying to reduce Flickering when using SetTimer

How do i avoid this?

[code]

case WM_CREATE:
{
/* Create timer to refresh screen */
SetTimer(hwnd, IDT_REFRESH, 50,(TIMERPROC) NULL);

............
............

case WM_TIMER:
{
// Refresh screen
InvalidateRect (hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
break;
[/code]

My whole window is flickering and when selecting menu, sometimes menu is black (wont see text on menu) until i move mouse over menu then text clears out.. Lets just say the window operations would not function properly if i use timer as shown... I just wanna refresh screen every 50ms

Comments

  • Did you set up double buffering?

    Basically, you render to an offscreen DC. After every frame of animation, do a single BitBlt() to copy the backbuffer to your windows DC. Double, Triple buffering, and Page flipping are very common techniques used to eliminate flicker.

    [link=http://www.codeproject.com/KB/cpp/DoubleBuffering.aspx]Heres a nice tutorial[/link]
    [hr][size=1][leftbr].:EvolutionEngine[rightbr][leftbr].:MicroOS Operating System[rightbr][leftbr][link=http://www.brokenthorn.com]Website :: OS Development Series[rightbr][/link][/size]
  • : Did you set up double buffering?
    :
    : Basically, you render to an offscreen DC. After every frame of
    : animation, do a single BitBlt() to copy the backbuffer to your
    : windows DC. Double, Triple buffering, and Page flipping are very
    : common techniques used to eliminate flicker.
    :
    : [link=http://www.codeproject.com/KB/cpp/DoubleBuffering.aspx]Heres a
    : nice tutorial[/link]
    : [hr][size=1][leftbr].:EvolutionEngine[rightbr][leftbr].:MicroOS
    : Operating
    : System[rightbr][leftbr][link=http://www.brokenthorn.com]Website ::
    : OS Development Series[rightbr][/link][/size]
    :
    Ok, here's my attempt

    [code]
    case WM_PAINT:
    {
    hdc=BeginPaint(hwnd, &pntS);

    /* Create memory DC and add hdc (paint) to it */
    CreateBuffer(0, hdc);

    /* *** User Interface Now draw on the new memDC *** */
    DrawArea(hwnd, my_DC_Buffer[0], colors);
    RadioButtonsText(hwnd, my_DC_Buffer[0], polarLbl, stdFont);
    TargetText(hwnd, targetLbl, sqm, mtrs, my_DC_Buffer[0], stdFont);
    GenParams(hwnd, genPara, fareRng, dpRng, my_DC_Buffer[0], stdFont);
    RadaAntennaText(hwnd, rdrAntenaLbl, deg, db, halfMin, mtrs, my_DC_Buffer[0], stdFont);
    DisplayResultsBox(hwnd, my_DC_Buffer[0], rdrTrans_recv, targetLbl, rsltFont);
    RadarReceiverText(hwnd, rdrTrans_recv, hz, mhz, mtrs, kw, usec, db, wvlnthFig, my_DC_Buffer[0], stdFont);

    // Calculate & show results
    output = ProcessData(hwnd);
    DisplayResults(hwnd, my_DC_Buffer[0], &output, rsltFont);

    CopyToScreen(hdc, 0);
    EndPaint(hwnd, &pntS);
    }
    return 0;
    [/code]

    CreateBuffer(0)....

    [code]
    /* Create Device Context on buffer for client window */
    void CreateBuffer(int which, HDC hDc)
    {
    GetWindowRect(my_handle,&dc_rect[which]);
    // my_DC = GetDC(my_handle);
    my_DC_Buffer[which] = CreateCompatibleDC(hDc);
    hbm_Buffer[which] = CreateCompatibleBitmap(hDc,dc_rect[which].right ,
    dc_rect[which].bottom );
    hbm_oldBuffer[which] = (HBITMAP) SelectObject(my_DC_Buffer[which],
    hbm_Buffer[which]);
    }
    [/code]

    CopyToScreen()

    [code]
    /* Copy Device Context from buffer to screen */
    void CopyToScreen(HDC hdc, int which)
    {
    BitBlt(hdc,0,0,dc_rect[which].right,dc_rect[which].bottom,my_DC_Buffer[which],0,0,SRCCOPY);
    }
    [/code]

    Problems...
    Now the entire window background is black....

    Questions

    I've removed

    [code]
    InvalidateRect (hwnd, NULL, TRUE);
    UpdateWindow(hwnd);
    [/code]

    .. cause the screen was doing worse than flickering... This is not an easy excersize
  • Do your painting in your main loop. Have WM_PAINT only repaint the window via BeginPaint/EndPaint.

    You still seem to be rendering to the main parent window--dont do this. Do *all* of your rendering to an offscreen DC. At the end of each frame, use BitBlt to copy the backbuffer to your windows DC in one shot.

    The only other thing I dont like is your CreateBuffer routine, as you should only have a single backbuffer per window.
    [hr][size=1][leftbr].:EvolutionEngine[rightbr][leftbr].:MicroOS Operating System[rightbr][leftbr][link=http://www.brokenthorn.com]Website :: OS Development Series[rightbr][/link][/size]
  • : Do your painting in your main loop. Have WM_PAINT only repaint the
    : window via BeginPaint/EndPaint.

    [color=Blue]
    Could you explain a bit further...[/color]

    :
    : You still seem to be rendering to the main parent window--dont do
    : this. Do *all* of your rendering to an offscreen DC. At the end of
    : each frame, use BitBlt to copy the backbuffer to your windows DC in
    : one shot.
    :

    [color=Blue]Where is off screen? Within WM_CREATE, or WM_TIMER, or where?[/color]

    : The only other thing I dont like is your CreateBuffer routine, as
    : you should only have a single backbuffer per window.

    [color=Blue]@MT2002... I have a single client window and 5 rectangles drawn unto it with lot's of text, some displayed as floating values (using SetWindowText())... I don't have multiple windows or dialog windows
    [/color]

    [color=Blue]Concerns...

    When creating a CompatibleDC, should i use hdc from BeginPaint() or should i rather GetDC() of the ClientArea (note the commented GetDC()), then create a compatible DC from it?[/color]
  • : Where is off screen? Within WM_CREATE, or WM_TIMER, or
    : where?

    The offscreen DC was created with CreateCompatableDC.

    Typically programs create one single offscreen DC and bitmap during initialization. Afterwords, all rendering is done to this offscreen DC rather then the main window.

    For example... (Not tested, but I hope it helps)

    [code]//! your window is created (it is HWND hwnd)

    //! get window dc and create new backbuffer
    HDC hdc = GetDC(hwnd);
    HDC bmapDC = CreateCompatibleDC(hdc);

    //! get client rectangle of our window
    RECT clientRECT;
    GetClientRect(hwnd,&clientRECT);

    //! create new bitmap that we can render to. Select it into the offscreen DC
    HBITMAP hbmap =
    CreateCompatibleBitmap(hdc,clientRECT.right,clientRECT.bottom);
    SelectObject( bmapDC, hbmap );[/code]

    Now, bmapDC is your offscreen DC (Your backbuffer). Every time you want to render, always use bmapDC instead of your main window.

    ...And, at the end of each loop in your main program loop, do a simple BitBlt to copy the backbuffer to your main window:

    [code]while (1) {

    //! clear backbuffer DC
    FillRect(bmapDC,&clientRECT,BackGroundBrush);

    //! program logic code here... Render everything to
    //! bmapDC (As shown in the above FillRect)

    //! done, so copy backbuffer to main window (hwnd is your window)
    BitBlt(GetDC (hwnd),0,0,clientRECT.right,clientRECT.bottom,bmapDC,0,0,SRCCOPY);

    }[/code]

    I hope this clarifies things better :)

    [hr][size=1][leftbr].:EvolutionEngine[rightbr][leftbr].:MicroOS Operating System[rightbr][leftbr][link=http://www.brokenthorn.com]Website :: OS Development Series[rightbr][/link][/size]
  • [color=Blue]In addition you have to clean up. Where are your calls to:

    1. SelectObject(oldBmp) for SelectObject(compatibleBmp)
    2. DeleteDC() for CreateCompatibleDC()
    3. DeleteObject() for CreateCompatibleBitmap()

    All these resources are leaked very fast - because your WM_PAINT is running at 50 milliseconds!!

    Also, to make it even better do the creation of DC and bitmap once and then cache it. That means that your WM_PAINT only draws to memory DC and then BitBlt() it back to screen DC. Faster than you do now. Localize your variables in a function as static members and then use a parameter to tell the function how to proceed.

    Here is how it is done in good old C. You can create C++ class and encapsulate all that there. In your WM_PAINT just call this function with a proper HDC and area sizes and pass cmdAllocateBackBuffer command. When WM_DESTROY is received call the same function with cmdCleanupBackBuffer command.
    [code]
    enum BackBufferCommands
    {
    cmdAllocateBackBuffer,
    cmdCleanupBackBuffer
    };

    HDC MemoryDCForArea
    (
    HDC hDC_from_BeginPaint,
    int iAreaWidth,
    int iAreaHeight,
    int iCommandWhatToDo
    )
    {
    static HDC hMemoryDC = NULL;
    static HGDIOBJ hMemDCBitmap = NULL;
    static HBITMAP hCanvasBitmap = NULL;
    static int iCachedWidth = 0;
    static int iCachedHeight = 0;

    switch (iCommandWhatToDo)
    {
    case cmdAllocateBackBuffer:
    [color=Green]//
    // Check if the cached area size already been done
    //[/color]
    if ( (iAreaWidth == iCachedWidth) &&
    (iAreaHeight == iCachedHeight) )
    {
    [color=Green]//
    // We already have the memory DC
    //[/color]
    return hMemoryDC;
    }
    else
    {
    [color=Green]//
    // Area have changed or we here for the first time.
    // Tell ourselves to clean up.
    //[/color]
    MemoryDCForArea (0, 0, 0, cmdCleanupBackBuffer);

    [color=Green]// Prepare new buffer
    //[/color]
    hMemoryDC = CreateCompatibleDC (hDC_from_BeginPaint);

    hCanvasBitmap = CreateCompatibleBitmap (
    hDC_from_BeginPaint,
    iCachedWidth = iAreaWidth,
    iCachedHeight = iAreaHeight);

    hMemDCBitmap = SelectObject (hMemoryDC, hCanvasBitmap);
    return hMemoryDC;
    }
    break;

    case cmdCleanupBackBuffer:
    [color=Green]//
    // Reverse all we done when creating back buffer.
    //[/color]
    if (hMemoryDC != NULL)
    {
    SelectObject (hMemoryDC, hMemDCBitmap);
    DeleteObject (hCanvasBitmap);
    DeleteDC (hMemoryDC);

    hMemoryDC = NULL;
    hMemDCBitmap = NULL;
    hCanvasBitmap = NULL;
    iCachedWidth = iCachedHeight = 0;
    }
    break;
    }
    }
    [/code]
    [/color]
  • : [color=Blue]In addition you have to clean up. Where are your calls
    : to:
    :
    : 1. SelectObject(oldBmp) for SelectObject(compatibleBmp)
    : 2. DeleteDC() for CreateCompatibleDC()
    : 3. DeleteObject() for CreateCompatibleBitmap()
    :
    : All these resources are leaked very fast - because your WM_PAINT is
    : running at 50 milliseconds!!
    :
    : Also, to make it even better do the creation of DC and bitmap once
    : and then cache it. That means that your WM_PAINT only draws to
    : memory DC and then BitBlt() it back to screen DC. Faster than you do
    : now. Localize your variables in a function as static members and
    : then use a parameter to tell the function how to proceed.
    :
    : Here is how it is done in good old C. You can create C++ class and
    : encapsulate all that there. In your WM_PAINT just call this function
    : with a proper HDC and area sizes and pass cmdAllocateBackBuffer
    : command. When WM_DESTROY is received call the same function with
    : cmdCleanupBackBuffer command.
    : [code]:
    : enum BackBufferCommands
    : {
    : cmdAllocateBackBuffer,
    : cmdCleanupBackBuffer
    : };
    :
    : HDC MemoryDCForArea
    : (
    : HDC hDC_from_BeginPaint,
    : int iAreaWidth,
    : int iAreaHeight,
    : int iCommandWhatToDo
    : )
    : {
    : static HDC hMemoryDC = NULL;
    : static HGDIOBJ hMemDCBitmap = NULL;
    : static HBITMAP hCanvasBitmap = NULL;
    : static int iCachedWidth = 0;
    : static int iCachedHeight = 0;
    :
    : switch (iCommandWhatToDo)
    : {
    : case cmdAllocateBackBuffer:
    : [color=Green]//
    : // Check if the cached area size already been done
    : //[/color]
    : if ( (iAreaWidth == iCachedWidth) &&
    : (iAreaHeight == iCachedHeight) )
    : {
    : [color=Green]//
    : // We already have the memory DC
    : //[/color]
    : return hMemoryDC;
    : }
    : else
    : {
    : [color=Green]//
    : // Area have changed or we here for the first time.
    : // Tell ourselves to clean up.
    : //[/color]
    : MemoryDCForArea (0, 0, 0, cmdCleanupBackBuffer);
    :
    : [color=Green]// Prepare new buffer
    : //[/color]
    : hMemoryDC = CreateCompatibleDC (hDC_from_BeginPaint);
    :
    : hCanvasBitmap = CreateCompatibleBitmap (
    : hDC_from_BeginPaint,
    : iCachedWidth = iAreaWidth,
    : iCachedHeight = iAreaHeight);
    :
    : hMemDCBitmap = SelectObject (hMemoryDC, hCanvasBitmap);
    : return hMemoryDC;
    : }
    : break;
    :
    : case cmdCleanupBackBuffer:
    : [color=Green]//
    : // Reverse all we done when creating back buffer.
    : //[/color]
    : if (hMemoryDC != NULL)
    : {
    : SelectObject (hMemoryDC, hMemDCBitmap);
    : DeleteObject (hCanvasBitmap);
    : DeleteDC (hMemoryDC);
    :
    : hMemoryDC = NULL;
    : hMemDCBitmap = NULL;
    : hCanvasBitmap = NULL;
    : iCachedWidth = iCachedHeight = 0;
    : }
    : break;
    : }
    : }
    : [/code]:
    : [/color]


    [color=Blue]My attempt to your suggestions
    [/color]
    [code]
    case WM_PAINT:
    {
    hdc = BeginPaint(hwnd, &pntS);

    [color=Green]/* Retrieve the client's area width and height */[/color]
    GetClientRect(hwnd, &clientRECT);

    [color=Green]/* Create memory DC on back buffer */[/color]
    MemDC = MemoryDCForArea(hdc,
    clientRECT.right, [color=Green]// width[/color]
    clientRECT.bottom, [color=Green]// height[/color]
    0);

    [color=Green]/* *** Rendering screen data (User Interface) *** */[/color]
    DrawArea(hwnd, MemDC, colors);

    [color=Green]// From menDC to screen[/color]
    BitBlt(hdc,0,0,clientRECT.right,clientRECT.bottom,MemDC,0,0,SRCCOPY);

    [color=Green]/* Calculate & show results
    output = ProcessData(hwnd);
    DisplayResults(hwnd, hdc, &output, rsltFont);*/[/color]

    [color=Green]/* Delete/release memory DC on back buffer */[/color]
    MemDC = MemoryDCForArea( BeginPaint(hwnd, &pntS),
    clientRECT.right, [color=Green]// width[/color]
    clientRECT.top, 1); [color=Green]// height[/color]

    EndPaint(hwnd, &pntS);
    }
    return 0;
    [/code]

    [color=Blue]No improvement on flickering, and now the window background is black....[/color]

    [color=Blue]Below is the function called in WM_PAINT to draw on client MemDC[/color]
    [code]

    [color=Green]// Draw Rectangles on Window Area[/color]
    void DrawArea(HWND hwnd, HDC hdc, RGBColor *colors)
    {
    PaintObject(hwnd,initRecArea(10,10,340,230),colors, hdc, BLACK, GREY); [color=Green]// Left rectangle(RADAR ANTENNA)[/color]
    PaintObject(hwnd,initRecArea(345,10,625,285),colors, hdc, BLACK, GREY); [color=Green]// Right rectangle(RADAR TRANSMITTER/RECEIVER)[/color]
    PaintObject(hwnd,initRecArea(10,235,340,335),colors, hdc, BLACK, GREY); [color=Green]// Second left (TARGET)[/color]
    PaintObject(hwnd,initRecArea(10,340,340,440),colors, hdc, BLACK, GREY); [color=Green]// Third left (GENERAL PARAMETERS)[/color]
    PaintObject(hwnd,initRecArea(10,445,690,780),colors, hdc, BLACK, KHAKI); [color=Green]// Yellow window (RESULTS)[/color]
    PaintObject(hwnd,initRecArea(390,550,680,770),colors, hdc, BLACK, KHAKI); [color=Green]// Yellow mini window (RESULTS)[/color]

    [color=Green]// Ranges small Rectangles[/color]
    PaintObject(hwnd,initRecArea(580,605,640,630),colors, hdc, RED, YELLOW);
    PaintObject(hwnd,initRecArea(580,635,640,660),colors, hdc, RED, YELLOW);
    PaintObject(hwnd,initRecArea(580,665,640,690),colors, hdc, RED, YELLOW);
    PaintObject(hwnd,initRecArea(580,705,640,760),colors, hdc, RED, YELLOW);
    }
    [/code]

    [color=Blue]and my timer[/color]

    [code]
    case WM_TIMER:
    {
    InvalidateRect (hwnd, NULL, TRUE);
    UpdateWindow(hwnd);
    }
    break;
    [/code]
  • : [code]: while (1) {
    :
    : //! clear backbuffer DC
    : FillRect(bmapDC,&clientRECT,BackGroundBrush);
    :
    : //! program logic code here... Render everything to
    : //! bmapDC (As shown in the above FillRect)
    :
    : //! done, so copy backbuffer to main window (hwnd is your window)
    : BitBlt(GetDC (hwnd),0,0,clientRECT.right,clientRECT.bottom,bmapDC,0,0,SRCCOPY);
    :
    : }[/code]:
    [color=Blue]
    Where does this code belong MT? ... WM_PAINT/WM_CREATE/WM_TIMER
    [/color]

  • My attempt to your suggestions
    : [color=Blue]
    You call BeginPaint() twice in one WM_PAINT cycle. Also, why you are releasing MemDC here at the end of drawing? You should do it in WM_DESTROY.

    Also, the enum was there to make the code readable. With 0 and 1 it is confusing now.
    : [/color]
    : [code]:
    : case WM_PAINT:
    : {
    : hdc = [color=Red]BeginPaint[/color](hwnd, &pntS);
    :
    : [color=Green]/* Retrieve the client's area width and height */[/color]
    : GetClientRect(hwnd, &clientRECT);
    :
    : [color=Green]/* Create memory DC on back buffer */[/color]
    : MemDC = MemoryDCForArea(hdc,
    : clientRECT.right, [color=Green]// width[/color]
    : clientRECT.bottom, [color=Green]// height[/color]
    : 0);
    :
    : [color=Green]/* *** Rendering screen data (User Interface) *** */[/color]
    : DrawArea(hwnd, MemDC, colors);
    :
    : [color=Green]// From menDC to screen[/color]
    : BitBlt(hdc,0,0,clientRECT.right,clientRECT.bottom,MemDC,0,0,SRCCOPY);
    :
    : [color=Green]/* Calculate & show results
    : output = ProcessData(hwnd);
    : DisplayResults(hwnd, hdc, &output, rsltFont);*/[/color]
    :
    : [color=Green]/* Delete/release memory DC on back buffer */[/color]
    : MemDC = MemoryDCForArea( [color=Red]BeginPaint[/color](hwnd, &pntS),
    : clientRECT.right, [color=Green]// width[/color]
    : clientRECT.top, 1); [color=Green]// height[/color]
    : [color=Red]// This whole ^^^ statement should be in WM_DESTROY.
    : // Also, when you releasing pass zeros as HDC and size.[/color]
    :
    : EndPaint(hwnd, &pntS);
    : }
    : return 0;
    : [/code]:
  • [color=Blue]My changes to the code, still flickers... Notice am not using the BeginPaint() DC to create MemDC, this according to some advice[/color]

    [code]
    case WM_CREATE:
    {
    [color=Green]/* Retrieve the client's area width and height */[/color]
    GetWindowRect(hwnd, &clientRECT);

    [color=Green]/* Create memory DC on back buffer */[/color]
    MemDC = MemoryDCForArea(hwnd,
    clientRECT.right, [color=Green]// width[/color]
    clientRECT.bottom, [color=Green]// height[/color]
    cmdAllocateBackBuffer);

    [color=Green]/* *** Rendering screen data (User Interface) *** */[/color]
    PaintObject(initRecArea(10,10,340,230),
    colors, MemDC, BLACK, GREY);

    [color=Green]/* Screen refresh time */[/color]
    SetTimer(hwnd, IDT_REFRESH, REFRESHTIME, NULL);

    [color=Green]/* Create edit controls */[/color]
    EditBoxes(hwnd, cs);

    [color=Green]/* Create radio buttons */[/color]
    RadioButtons(hwnd, cs);
    }
    return 0;

    case WM_PAINT:
    {
    hdc = BeginPaint(hwnd, &pntS);
    BitBlt(hdc,0,0,clientRECT.right,clientRECT.bottom,MemDC,0,0,SRCCOPY);
    EndPaint(hwnd, &pntS);
    }
    return 0;

    case WM_TIMER:
    {
    InvalidateRect (hwnd, NULL, TRUE);
    UpdateWindow(hwnd);
    }
    break;
    case WM_DESTROY:
    {
    KillTimer(hwnd, IDT_REFRESH);
    PostQuitMessage(0);

    [color=Green]/* Delete/release memory DC on back buffer */[/color]
    MemoryDCForArea(hwnd,
    0, [color=Green]// width[/color]
    0, [color=Green]// height[/color]
    cmdCleanupBackBuffer);
    }
    return 0;
    [/code]

    [color=Blue]Also, why does the client window losses its background color to black when i do double buffering?[/color]


    [code]

    // Double Buffering function
    HDC MemoryDCForArea (HWND hWnd, int iAreaWidth, int iAreaHeight, int iCommandWhatToDo )
    {
    static HDC hDC = NULL;
    static HDC hMemoryDC = NULL;
    static HGDIOBJ hMemDCBitmap = NULL;
    static HBITMAP hCanvasBitmap = NULL;
    static int iCachedWidth = 0;
    static int iCachedHeight = 0;

    switch (iCommandWhatToDo)
    {
    case cmdAllocateBackBuffer:
    //
    // Check if the cached area size already been done
    //
    if ( (iAreaWidth == iCachedWidth) &&
    (iAreaHeight == iCachedHeight) )
    {
    //
    // We already have the memory DC
    //
    return hMemoryDC;
    }
    else
    {
    //
    // Area have changed or we here for the first time.
    // Tell ourselves to clean up.
    //
    MemoryDCForArea (hWnd, 0, 0, cmdCleanupBackBuffer);

    // Prepare new buffer
    //
    hDC = GetDC(hWnd);
    hMemoryDC = CreateCompatibleDC (hDC);

    hCanvasBitmap = CreateCompatibleBitmap (
    hDC,
    iCachedWidth = iAreaWidth,
    iCachedHeight = iAreaHeight);

    hMemDCBitmap = SelectObject (hMemoryDC, hCanvasBitmap);
    return hMemoryDC;
    }
    break;

    case cmdCleanupBackBuffer:
    //
    // Reverse all we done when creating back buffer.
    //
    if (hMemoryDC != NULL)
    {
    SelectObject (hMemoryDC, hMemDCBitmap);
    DeleteObject (hCanvasBitmap);
    DeleteDC (hMemoryDC);

    hMemoryDC = NULL;
    hMemDCBitmap = NULL;
    hCanvasBitmap = NULL;
    iCachedWidth = iCachedHeight = 0;
    }
    break;
    }
    return hMemoryDC;
    }
    [/code]

  • : [color=Blue]
    : Where does this code belong MT? ... WM_PAINT/WM_CREATE/WM_TIMER
    : [/color]

    Your main program loop. ie, perhaps its the message loop for your main window?
    [hr][size=1][leftbr].:EvolutionEngine[rightbr][leftbr].:MicroOS Operating System[rightbr][leftbr][link=http://www.brokenthorn.com]Website :: OS Development Series[rightbr][/link][/size]
  • : My attempt to your suggestions
    : : [color=Blue]
    : You call BeginPaint() twice in one WM_PAINT cycle. Also, why you are
    : releasing MemDC here at the end of drawing? You should do it in
    : WM_DESTROY.
    :
    : Also, the enum was there to make the code readable. With 0 and 1 it
    : is confusing now.
    : : [/color]
    : : [code]: :
    : : case WM_PAINT:
    : : {
    : : hdc = [color=Red]BeginPaint[/color](hwnd, &pntS);
    : :
    : : [color=Green]/* Retrieve the client's area width and height */[/color]
    : : GetClientRect(hwnd, &clientRECT);
    : :
    : : [color=Green]/* Create memory DC on back buffer */[/color]
    : : MemDC = MemoryDCForArea(hdc,
    : : clientRECT.right, [color=Green]// width[/color]
    : : clientRECT.bottom, [color=Green]// height[/color]
    : : 0);
    : :
    : : [color=Green]/* *** Rendering screen data (User Interface) *** */[/color]
    : : DrawArea(hwnd, MemDC, colors);
    : :
    : : [color=Green]// From menDC to screen[/color]
    : : BitBlt(hdc,0,0,clientRECT.right,clientRECT.bottom,MemDC,0,0,SRCCOPY);
    : :
    : : [color=Green]/* Calculate & show results
    : : output = ProcessData(hwnd);
    : : DisplayResults(hwnd, hdc, &output, rsltFont);*/[/color]
    : :
    : : [color=Green]/* Delete/release memory DC on back buffer */[/color]
    : : MemDC = MemoryDCForArea( [color=Red]BeginPaint[/color](hwnd, &pntS),
    : : clientRECT.right, [color=Green]// width[/color]
    : : clientRECT.top, 1); [color=Green]// height[/color]
    : : [color=Red]// This whole ^^^ statement should be in WM_DESTROY.
    : : // Also, when you releasing pass zeros as HDC and size.[/color]
    : :
    : : EndPaint(hwnd, &pntS);
    : : }
    : : return 0;
    : : [/code]: :
    :
    [color=Blue]Asmguru, remember you once told me to set the window background to NULL [/color][code] wcx.hbrBackground = NULL;[color=Green]//(HBRUSH)(COLOR_BTNFACE+1);[/color] [/code][color=Blue] , i just did this together with the double buffering and now the flickering it's only on the edit controls.. The rectangles and text is stable.. And aslo, i get the black background on the main window... If i can solve these two things, then i'll be super!

    About edit controls, they are not Painted but created using CreateWindowEX, why should they flicker? I mean i can't use any DC to create/paint them
    [/color]

    [b]Updated this post 15min later...![/b]

    [color=Red]
    I've got things wrong, the flickering only stopped because i moved the rendering of my objects to Memory DC within WM_CREATE, which obviously doesn't update... making background NULL only stops the fickering of Window itself, not the objects... So i'm back to square 1[/color]
  • [color=Blue]When the flickering occurs? When your timer fires or when you resize the window?

    Also, why GetDC()?

    You can avoid black background if you paint it (background) yourself BEFORE you paint all the rectangles. Use FillRect() and you are done.[/color]
  • : When the flickering occurs? When your timer fires or
    : when you resize the window?

    [color=Blue]
    When my timer fires....[/color]

    : Also, why GetDC()?

    [color=Blue]Didn't make a difference but noticed lot of references using the BeginPaint() DC, so will change back[/color]

    : You can avoid black background if you paint it (background) yourself
    : BEFORE you paint all the rectangles. Use FillRect() and you are
    : done.

    [color=Blue]I have with no difference... I think this has to do with painting on the back buffer (off-screen DC) and returning a non-zero on WM_ERASEBKGND...[/color]

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories