我有一个使用WS_EX_LAYERED窗口样式创建的窗口。目前,我正在使用GDI +绘制内存位图,并使用 UpdateLayeredWindow 更新分层窗口的图形内容。
这是我的代码片段:

void Redraw(HWND hWnd, int width, int height) {
    static bool floppy = true;

    floppy = !floppy;

    HDC hScreenDC = GetDC(HWND_DESKTOP);
    HDC hMemDC = CreateCompatibleDC(hScreenDC);
    HBITMAP hBmp = CreateCompatibleBitmap(hScreenDC, width, height);
    HGDIOBJ hObj = SelectObject(hMemDC, hBmp);

    Graphics gfx(hMemDC);

    SolidBrush b(Color(254, (floppy ? 255 : 0), (floppy ? 0 : 255), 0));
    gfx.FillRectangle(&b, Rect(0, 0, width, height));

    BLENDFUNCTION blend;
    blend.BlendOp = AC_SRC_OVER;
    blend.BlendFlags = 0;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;

    POINT src = { 0, 0 };

    SIZE size;
    size.cx = width;
    size.cy = height;

    Assert(UpdateLayeredWindow(
        hWnd,
        hScreenDC,
        NULL,
        &size,
        hMemDC,
        &src,
        RGB(0, 0, 0),
        &blend,
        ULW_ALPHA
    ));

    SelectObject(hMemDC, hObj);
    DeleteObject(hBmp);
    DeleteDC(hMemDC);
    ReleaseDC(HWND_DESKTOP, hScreenDC);
}
创建SolidBrush时,我为alpha组件指定了254的值。这导致99.6%的不透明填充,这不是我想要的。
当我将255指定为alpha分量时,似乎没有填充。我的窗口变得完全透明。这是一个问题,因为我希望绘制100%不透明的形状,但我也希望绘制不透明的形状。

最佳答案

似乎有一些带有FillRectangle的qwerks。当我们观察到将FillEllipse与alpha分量为255的SolidBrush一起使用时,会导致形状完美呈现(不透明),这变得显而易见。

我提出了两个解决方法,分别为我解决了这个问题:

  • 调用 FillRectangle 两次

    SolidBrush b(Color(254, 255, 0, 0));
    gfx.FillRectangle(&b, Rect(0, 0, width, height));
    gfx.FillRectangle(&b, Rect(0, 0, width, height));
    

    由于同一区域被填充两次,因此它们将混合并创建RGB(255,0,0),而不管窗口后面的内容如何(现在它是100%不透明的)。我不喜欢这种方法,因为它要求每个矩形都要绘制两次。
  • 使用 FillPolygon 代替

    FillEllipse一样,FillPolygon似乎没有颜色问题,除非您这样称呼:
    SolidBrush b(Color(255, 255, 0, 0));
    Point points[4];
    points[0] = Point(0, 0);
    points[1] = Point(width, 0);
    points[2] = Point(width, height);
    points[4] = Point(0, height);
    gfx.FillPolygon(&b, points, 4); //don't copy and paste - this won't work
    

    上面的代码将导致100%透明的窗口。我猜这是由于某种形式的优化,而是将调用传递给FillRectangle所致。或者-很有可能-FillPolygon出现了问题,被FillRectangle调用。但是,如果向数组添加额外的Point,则可以解决该问题:
    SolidBrush b(Color(255, 255, 0, 0));
    Point points[5];
    points[0] = Point(0, 0);
    points[1] = Point(0, 0); //<-
    points[2] = Point(width, 0);
    points[3] = Point(width, height);
    points[4] = Point(0, height);
    gfx.FillPolygon(&b, points, 5);
    

    上面的代码确实将绘制100%不透明的形状,从而解决了我的问题。
  • 关于c++ - 来自FillRectangle的不希望有的透明性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19214921/

    10-11 22:47
    查看更多