flickering in GDI drawing under win11

嘉德 石 6 Reputation points
2022-12-17T08:10:29.78+00:00

hello, i have a program to draw a rubber band line, i use classic XOR, in Win32 GDI, this is SetROP2(R2_XORPEN) method, it workd in xp/vista/win7/win8/win10, but recently, after i update win11, found the rubber band line become flickering. this never happen before, is it a win11 bug? how to fix this? thanks!

i write a simple demo program, you can build and run it under win11, and see flickering

#define WIN32_LEAN_AND_MEAN  
#include <windows.h>  
#include <tchar.h>  
  
LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);  
  
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,  
                     _In_opt_ HINSTANCE hPrevInstance,  
                     _In_ LPWSTR    lpCmdLine,  
                     _In_ int       nCmdShow)  
{  
    UNREFERENCED_PARAMETER(hPrevInstance);  
    UNREFERENCED_PARAMETER(lpCmdLine);  
  
	WNDCLASSEX wcex;  
	wcex.cbSize = sizeof(WNDCLASSEX);  
	wcex.style = CS_HREDRAW | CS_VREDRAW;  
	wcex.lpfnWndProc = MyWndProc;  
	wcex.cbClsExtra = 0;  
	wcex.cbWndExtra = 0;  
	wcex.hInstance = hInstance;  
	wcex.hIcon = NULL;  
	wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);  
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);  
	wcex.lpszMenuName = NULL;  
	wcex.lpszClassName = _T("MyRubberBandLine");  
	wcex.hIconSm = NULL;  
	RegisterClassEx(&wcex);  
  
	HWND hWnd = CreateWindow(_T("MyRubberBandLine"), _T("RubberBandLine"), WS_OVERLAPPEDWINDOW,  
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);  
  
	ShowWindow(hWnd, nCmdShow);  
	UpdateWindow(hWnd);  
  
    MSG msg;  
    while (GetMessage(&msg, nullptr, 0, 0))  
    {  
        TranslateMessage(&msg);  
        DispatchMessage(&msg);  
    }  
  
    return (int) msg.wParam;  
}  
  
//  
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)  
//  
//  PURPOSE: Processes messages for the main window.  
//  
//  WM_COMMAND  - process the application menu  
//  WM_PAINT    - Paint the main window  
//  WM_DESTROY  - post a quit message and return  
//  
//  
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
    switch (message)  
    {  
    case WM_PAINT:  
        {  
            PAINTSTRUCT ps;  
            HDC hdc = BeginPaint(hWnd, &ps);  
  
            RECT rect;  
            GetClientRect(hWnd, &rect);  
            COLORREF clrbak = SetBkColor(hdc, RGB(255, 0, 0));  
            ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);  
  
            int x = (rect.right - rect.left ) / 8;  
            int y = (rect.bottom - rect.top) / 8;  
            rect.left += x; rect.right -= x;  
            rect.top += y; rect.bottom -= y;  
            SetBkColor(hdc, RGB(0, 255, 0));  
            ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);  
  
			rect.left += x; rect.right -= x;  
			rect.top += y; rect.bottom -= y;  
			SetBkColor(hdc, RGB(0, 0, 255));  
			ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);  
  
			rect.left += x; rect.right -= x;  
			rect.top += y; rect.bottom -= y;  
			SetBkColor(hdc, RGB(0, 0, 0));  
			ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);  
  
            SetBkColor(hdc, clrbak);  
            EndPaint(hWnd, &ps);  
        }  
        break;  
    case WM_DESTROY:  
        PostQuitMessage(0);  
        break;  
    case WM_MOUSEMOVE:  
        {  
           static POINT ptPrev1{ -1,-1 };  
           static POINT ptPrev2{ -1,-1 };  
  
           HDC hdc = GetDC(hWnd);  
           int modebak = SetROP2(hdc, R2_XORPEN);  
  
           HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));  
           HGDIOBJ hOld = SelectObject(hdc, hPen);  
  
           // erase prev line  
           if (ptPrev1.x != -1 && ptPrev2.x != -1)  
           {  
               MoveToEx(hdc, ptPrev1.x, ptPrev1.y, NULL);  
               LineTo(hdc, ptPrev2.x, ptPrev2.y);  
			   ptPrev1.x = ptPrev1.y = ptPrev2.x = ptPrev2.y = -1;  
		   }  
  
           // draw new line  
           RECT rect;  
           GetClientRect(hWnd, &rect);  
           POINT ptCenter{ (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 };  
           POINT ptMouse{ LOWORD(lParam), HIWORD(lParam) };  
           if ((ptMouse.x != ptCenter.x) || (ptMouse.y != ptCenter.y))  
           {  
               MoveToEx(hdc, ptCenter.x, ptCenter.y, NULL);  
               LineTo(hdc, ptMouse.x, ptMouse.y);  
  
               ptPrev1 = ptCenter;  
               ptPrev2 = ptMouse;  
           }  
  
           SelectObject(hdc, hOld);  
           SetROP2(hdc, modebak);  
           ReleaseDC(hWnd, hdc);  
           DeleteObject(hPen);  
        }  
        break;  
    default:  
        return DefWindowProc(hWnd, message, wParam, lParam);  
    }  
    return 0;  
}  
  
Windows development | Windows API - Win32
Windows for business | Windows Client for IT Pros | User experience | Other
Developer technologies | C++
Developer technologies | C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
{count} vote

2 answers

Sort by: Most helpful
  1. Limitless Technology 45,151 Reputation points
    2022-12-20T08:29:40.593+00:00

    Hi. Thank you for your question and reaching out. My name is John and I’d be more than happy to help you with your query.

    As what Raymond Chen on this thread https://stackoverflow.com/questions/7633672/how-to-avoid-excessive-screen-flickering-with-gdi

    Your WM PAINT should write to the window DC precisely once to reduce flicker. This single operation is typically a BitBlt:

    HDC hdc = BeginPaint(m_hwnd, &m_PaintStruct);
    ... paint to bitmap ...
    BitBlt(hdc, ...); // blt from bitmap to screen
    EndPaint(m_hwnd, &m_PaintStruct);

    If the reply was helpful, please don’t forget to upvote or accept as answer, thank you.

    1 person found this answer helpful.

  2. Xiaopo Yang - MSFT 12,736 Reputation points Microsoft External Staff
    2022-12-19T06:24:42.82+00:00

    Hello,

    Welcome to Microsoft Q&A!

    It's recommended to Send feedback to Microsoft with the Feedback Hub app about the issue.

    Thank you.

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.