2

It seems the flickering is generated by the CombineRgn function, but I really have no idea why this happens, since i've never used regions that much I'm possibly missing some knowledge on the matter.

Some events in the program triggers the addition of little rectangles to the main region, here's the code that handles that:

        HRGN ActualRegion = CreateRectRgn(0, 0, 0, 0);
        GetWindowRgn(hwnd, ActualRegion);
        HRGN AddedRect = CreateRectRgn(//long code that creates a rectangle)
        CombineRgn(ActualRegion, ActualRegion, AddedRect, RGN_OR);

        SetWindowRgn(hwnd, ActualRegion, FALSE);
        InvalidateRect(hwnd, NULL, FALSE);

White Flickering appears only after the invalidation if new regions where combined to the main one.

Here's how I'm implementing double buffering in WM_PAINT:

PLEASE NOTE that on creation i'm enabling the DWM blur behind function with an invalid region (different from the Main one) which means that everything painted with BLACK_BRUSH will result in a 100% "invisible" portion of the program

        RECT r; GetClientRect(hwnd, &r);

        PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps);
        HDC MemDc = CreateCompatibleDC(hdc);
        HBITMAP hBmp = CreateCompatibleBitmap(hdc, r.right, r.bottom);
        HBITMAP hOld = (HBITMAP)SelectObject(MemDc, hBmp);

        //Making sure this dc is filled with "invisible" pixels to display
        SelectObject(MemDc, GetStockObject(BLACK_BRUSH));
        Rectangle(MemDc, //arbitrary values that matches the entire screen);

        BitBlt(hdc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), MemDc, 0, 0,        SRCCOPY);

        //clean-up
        SelectObject(MemDc, hOld);
        DeleteObject(hBmp);
        DeleteDC(MemDc);
        EndPaint(hwnd, &ps);

WM_ERASEBKGND obviously returns TRUE without further handling, the WNDCLASSEX instance of the window has a default BLACK_BRUSH as the hbrBackground field.

I also tried to intercept and return TRUE from WM_NCPAINT message.

I'm doing everything necessary to avoid intermediate drawcalls, everything handled inside the WM_PAINT uses a backbuffer, also i'd like to mention i'm not working with images/bitmaps. Everything is drawn with gdi/gdi+, and in no place i'm actually issuing a "white" redraw that may possibly cause said flicker. I'm a bit lost here

Is it something that i'm possibly missing ? I can't really understand what may be causing white flickering in this scenario

Row Rebel
  • 267
  • 3
  • 11
  • I can not understand what you are trying to do but in win7 parts of the window that you **do not** draw or erase (WM_ERASEBKGND) they are not going to be invisible. The system draws them with white color. This can be seen clearly when you resize a window and dont draw anything (empty `BeginPaint, EndPaint` and returning TRUE in `WM_ERASEBKGND ` message). Maybe that is the problem. – γηράσκω δ' αεί πολλά διδασκόμε May 06 '15 at 19:54
  • I'm actually using win7 and I can ensure that there's no empty paint code inside WM_PAINT. I'm asking for a redraw right after OR-ing the two regions togheter as you can see in the code above, and in the newest regions white flicker appears. It doesn't in "older" ones. – Row Rebel May 06 '15 at 20:10
  • Try temporarily turning off DWM to help determine if it's a bug in your code or an interaction with DWM. – Adrian McCarthy May 06 '15 at 20:41
  • Looks like DWM doesn't have any role in this, tested without it just now. I'm making tests with the bare minumum now. Whenever I press the "r" button, a new rectangle is added to the original region and then everything gets invalidated. If I keep the "R" button pressed, the call to the combineRgn function gets called fastly enough to show the white flicker continuosly – Row Rebel May 06 '15 at 20:57
  • http://pastebin.com/db43c2Vu Raw paste of the minimal testing i'm doing now. If you hold down "R" button new regions are fastly created and painted and you should see the white flickering in the newer ones – Row Rebel May 07 '15 at 11:46
  • Just a comment. I have had this problem with every window control I draw (click a button and it flickers white.) I was unable to find a solution. – Evan Carslake May 08 '15 at 22:38

1 Answers1

1

The problem is not the CombineRgn function but the SetWindowRgn function which you call before the system draws the window for the first time. If you call SetWindowRgn after the first draw, no flicker. Unfortunatelly I don't know why. So, a way to counter that is to set the window region after the first draw (take the code that sets window region from WM_CREATE and leave only the DwmEnableBlurBehindWindow):

static int stc = 0;

//in WM_PAINT after the EndPaint(hwnd, &ps); add
HRESULT lr = DefWindowProc(hwnd, message, wParam, lParam);

if( stc == 0 ){
    OnlyOnce();
    stc++;
}

return lr;

and the OnlyOnce:

void OnlyOnce(void){
    int X_Screen = GetSystemMetrics(SM_CXSCREEN);
    int Y_Screen = GetSystemMetrics(SM_CYSCREEN);

    HRGN ActualRegion = CreateRectRgn(X_Screen - 100, Y_Screen - 100, X_Screen - 100 + 40, Y_Screen - 100 + 40);
    SetWindowRgn(hWnd, ActualRegion, true);

    return;
}
  • Indeed, **it works**. No more flicker and I can't thank you enough. It's incredible how many little facets you have to know to use correctly winAPI, I really have no idea why using SetWindowRgn inside WM_CREATE could possibly interfer with new regions rendering – Row Rebel May 09 '15 at 11:36