简体   繁体   English

setROP2(R2_XORPEN) win11下闪烁

[英]SetROP2(R2_XORPEN) flickering under win11

I have a program to draw a rubber band line, I use classic XOR , in Win32 GDI , this is SetROP2(R2_XORPEN) method, it works in xp/vista/win7/win8/win10 , but recently, after I update win11, found the rubber band line become flickering.我有一个画橡皮筋线的程序,我使用经典的 XOR ,在Win32 GDI中,这是 SetROP2(R2_XORPEN) 方法,它适用于xp/vista/win7/win8/win10 ,但最近,在我更新 win11 后,发现橡皮筋线变得闪烁。 this never happen before, is it a win11 bug?以前从来没有过,是win11的bug吗? how to fix this?如何解决这个问题?

I write a simple demo program, you can build and run it under win11 , and see flickering我写了一个简单的demo程序,你可以在win11下编译运行,看到闪烁

note: I know handling WM_ERASEBKGND and using a double buffer can avoid window flickering, but this is only rubber band line flickering, not the entire window.注意:我知道处理 WM_ERASEBKGND 和使用双缓冲区可以避免 window 闪烁,但这只是橡皮筋线闪烁,而不是整个 window。

 #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;
 }

You are right.你是对的。 Drawing lines using SetROP2(hdc, R2_XORPEN) where hdc is device context of the window generally causes flickering.使用 SetROP2(hdc, R2_XORPEN) 绘制线条,其中 hdc 是 window 的设备上下文,通常会导致闪烁。 However, the flickering is almost negligible under Windows 7 and Windows 10. The flickering is much more noticeable with Windows 11. Instead of drawing in hdc, which is device context of the window, draw in compatible memory device context (hMemDC=CreateCompatibleDC(hdc);) and just BitBlt(hdc,0,0...) hMemDC to hdc.但是,闪烁在 Windows 7 和 Windows 10 下几乎可以忽略不计。闪烁在 Windows 11 下更加明显。而不是在 hdc 中绘制,这是 window 的设备上下文,而是在兼容的 883933302533388 设备中绘制(创建兼容的 883933302533388 设备);) 和只是 BitBlt(hdc,0,0...) hMemDC 到 hdc。 You will not lose speed of drawing and flickering is completely eliminated.您不会失去绘图速度,并且完全消除了闪烁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM