C ++ Win32 API GDI:矩形抗锯齿在透明背景下无法正常工作

问题描述

我使用扩展框架来渲染自定义标题和窗口边框。

<!DOCTYPE html>
<head>    
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    
        <script>
            L_NO_TOUCH = false;
            L_DISABLE_3D = false;
        </script>
    
    <script src="https://cdn.jsdelivr.net/npm/leaflet@1.5.1/dist/leaflet.js"></script>
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.5.1/dist/leaflet.css"/>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css"/>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"/>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css"/>
    <link rel="stylesheet" href="https://rawcdn.githack.com/python-visualization/folium/master/folium/templates/leaflet.awesome.rotate.css"/>
    <style>html,body {width: 100%;height: 100%;margin: 0;padding: 0;}</style>
    <style>#map {position:absolute;top:0;bottom:0;right:0;left:0;}</style>
    
            <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
            <style>
                #map_c3b171654ca34f70ae3e417bb5685916 {
                    position: relative;
                    width: 100.0%;
                    height: 100.0%;
                    left: 0.0%;
                    top: 0.0%;
                }
            </style>
        
    
                <style>
                    .leaflet-image-layer {
                        /* old android/safari*/
                        image-rendering: -webkit-optimize-contrast;
                        image-rendering: crisp-edges; /* safari */
                        image-rendering: pixelated; /* chrome */
                        image-rendering: -moz-crisp-edges; /* firefox */
                        image-rendering: -o-crisp-edges; /* opera */
                        -ms-interpolation-mode: nearest-neighbor; /* ie */
                    }
                </style>
            
</head>
<body>    
    
            <div class="folium-map" id="map_c3b171654ca34f70ae3e417bb5685916" ></div>
        
</body>
<script>    
    
            var map_c3b171654ca34f70ae3e417bb5685916 = L.map(
                "map_c3b171654ca34f70ae3e417bb5685916",{
                    center: [37.510284,15.092042],crs: L.CRS.EPSG3857,zoom: 8,zoomControl: true,preferCanvas: false,}
            );

            

        
    
            var tile_layer_422d20328f5a49e8891a1a5863d4c7f4 = L.tileLayer(
                "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png",{"attribution": "\u0026copy; \u003ca href=\"http://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors \u0026copy; \u003ca href=\"http://cartodb.com/attributions\"\u003eCartoDB\u003c/a\u003e,CartoDB \u003ca href =\"http://cartodb.com/attributions\"\u003eattributions\u003c/a\u003e","detectRetina": false,"maxNativeZoom": 18,"maxZoom": 18,"minZoom": 0,"noWrap": false,"opacity": 1,"subdomains": "abc","tms": false}
            ).addTo(map_c3b171654ca34f70ae3e417bb5685916);
        
    
            var image_overlay_38ae38a401d9460fad332f027ec64fd4 = L.imageOverlay(
                "data:image/png;base64,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",[[35.493948101997375,11.891264481977984],[38.849444372313364,15.684762434525926]],{}
            ).addTo(map_c3b171654ca34f70ae3e417bb5685916);
        
</script>

<!-- begin snippet: js hide: false console: false babel: false -->

我还使用分层窗口使背景透明。我的 COLORKEY RGB(0,0)

hr = DwmExtendFrameIntoClientArea(hWnd,&margins);

我使用分层窗口的原因是,我想使窗口的底部边框的角变圆。

问题是我想做些漂亮的事情,我试图用GDI在客户区域中绘制一个“抗锯齿”窗口边框。但是,它可以在带有已绘背景(纯色)的情况下用作“抗锯齿”,而不能在“透明”背景下使用。

图像:https://ibb.co/fD9GsFg

该如何解决?

如果尝试,请使用VS调试器,因为我没有放置功能窗口按钮。

SetLayeredWindowAttributes(hWnd,RGB(0,0),255,LWA_COLORKEY);

解决方法

好吧,在寻找解决方案之后,我想我终于找到了答案。

解决方案: 解决锯齿问题的一种解决方案是捕获整个窗口的背景,方法是从捕获中排除。此时,由于使用位图绘制背景,因此不需要分层窗口。 HDC将能够将其与背景混合。希望Windows 10 2004版本中有一个名为:

WDA_EXCLUDEFROMCAPTURE

用法:

SetWindowDisplayAffinity(hWnd,WDA_EXCLUDEFROMCAPTURE); //在创建时

来源: https://blogs.windows.com/windowsdeveloper/2019/09/16/new-ways-to-do-screen-capture/

之后,您可以使用位图绘制背景,然后在其上绘制所有内容。但是,这导致性能低下,我没有受益。尽管如此,在绘制时它仍然可以工作并产生反别名外观。对于性能问题,Direct2D可用于从返回的位图进行绘制。

示例:

int DsktpBkSS(HWND hWnd) {

    HDC hdcScreen;
    HDC hdcWindow;
    HDC hdcMemDC = NULL;
    HBITMAP hbmScreen = NULL;
    BITMAP bmpScreen;
    RECT windowPos;
    SetWindowDisplayAffinity(hWnd,WDA_EXCLUDEFROMCAPTURE);
    GetWindowRect(hWnd,&windowPos);

    // Retrieve the handle to a display device context for the client 
    // area of the window. 
    hdcScreen = GetDC(NULL);
    hdcWindow = GetDC(hWnd);

    // Create a compatible DC which is used in a BitBlt from the window DC
    hdcMemDC = CreateCompatibleDC(hdcWindow);

    if (!hdcMemDC)
    {
        MessageBox(hWnd,L"CreateCompatibleDC has failed",L"Failed",MB_OK);
    }

    // Get the client area for size calculation
    RECT rcClient;
    GetClientRect(hWnd,&rcClient);

    //This is the best stretch mode
    SetStretchBltMode(hdcWindow,HALFTONE);

    //The source DC is the entire screen and the destination DC is the current window (HWND)
    if (!StretchBlt(hdcWindow,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),hdcScreen,windowPos.left+1,windowPos.top,SRCCOPY))
    {
        MessageBox(hWnd,L"StretchBlt has failed",MB_OK);
    }

    // Create a compatible bitmap from the Window DC
    hbmScreen = CreateCompatibleBitmap(hdcWindow,rcClient.right - rcClient.left,rcClient.bottom - rcClient.top);

    if (!hbmScreen)
    {
        MessageBox(hWnd,L"CreateCompatibleBitmap Failed",MB_OK);
    }

    // Select the compatible bitmap into the compatible memory DC.
    if(hdcMemDC && hbmScreen){
    SelectObject(hdcMemDC,hbmScreen);
    }
    // Bit block transfer into our compatible memory DC.
    if(hdcMemDC)
    if (!BitBlt(hdcMemDC,rcClient.bottom - rcClient.top,hdcWindow,L"BitBlt has failed",MB_OK);
    }

    // Get the BITMAP from the HBITMAP
    if(hbmScreen)
    GetObjectW(hbmScreen,sizeof(BITMAP),&bmpScreen);

    if (hbmScreen)DeleteObject(hbmScreen);
    if (hdcMemDC)DeleteObject(hdcMemDC);
    ReleaseDC(NULL,hdcScreen);
    ReleaseDC(hWnd,hdcWindow);

    return 0;
}

稍后

(...){
if(message==WM_PAINT)
{
PAINTSTRUCT ps;
BeginPaint(hWnd,&ps);
Graphics graphics(ps.hdc);
/*SET SMOOTHING (AA)*/
graphics.SetSmoothingMode(SmoothingMode::SmoothingModeHighQuality);
if(DsktpBkSS(hWnd))
{
/*DRAW ROUNDED RECTANGLE*/
}
}
//...
};

对于使用“ 桌面窗口管理器”绘制的窗口,从左到右连续调整大小时,另一重要事项是一段时间后会产生“ 闪烁”。在Microsoft文档上,建议使用 StretchBlt(...)进行绘图,因为GDI +会导致这种情况。

为DWM提到的闪烁https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-stretchblt

”使用BitBlt或StretchBlt函数代替Windows GDI +进行演示 您的绘图进行渲染。 GDI +一次渲染一条扫描线 软件渲染。这可能会导致应用程序闪烁。”

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...