首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自FillRectangle的轻微的不期望的透明度

来自FillRectangle的轻微的不期望的透明度
EN

Stack Overflow用户
提问于 2013-10-06 22:54:31
回答 2查看 1.5K关注 0票数 2

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

下面是我的代码片段:

代码语言:javascript
复制
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%不透明,但我也希望画一些不是。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-07 02:47:07

似乎有一些与FillRectangle有关的qwerk。当我们观察到使用FillEllipse与α分量为255的SolidBrush一起使用时,就会发现形状呈现得非常完美(不透明)。

以下是我提出的两项工作,每一项都为我解决了这个问题:

  • 调用 FillRectangle SolidBrush b(颜色(254,255,0,0);gfx.FillRectangle(&b,Rect(0,0,宽度,高度));gfx.FillRectangle(&b,Rect(0,0,宽度,高度)); 由于同一区域被填充了两次,它们将混合并创建RGB(255,0,0),而不管窗口后面的内容(现在是100%不透明的)。我不喜欢这种方法,因为它要求每个矩形绘制两次。
  • 使用 FillPolygon 代替 就像FillEllipse一样,FillPolygon似乎没有颜色问题,,除非你这样称呼它,: SolidBrush b(颜色( 255,255,0,0);点points4;点=点(0,0);points1 =点(宽度,0);points2 =点(宽度,高度);points4 =点(0,高度);gfx.FillPolygon(&b,点,4);//不要复制和粘贴-这是行不通的 以上代码将产生100%透明的窗口。我猜想,这要么是由于某种形式的优化,而是将调用传递给FillRectangle。或者--很可能-- FillPolygon存在一些问题,这是由FillRectangle调用的。但是,如果在数组中添加一个额外的Point,则可以绕过它: SolidBrush b(颜色( 255,255,0,0);点points5;点=点(0,0);points1 =点(0,0);//<- points2 =点(宽度,0);points3 =点(宽度,高度);points4 =点(0,高度);gfx.FillPolygon(&b,点,5); 以上代码将确实绘制一个100%不透明的形状,这解决了我的问题。
票数 3
EN

Stack Overflow用户

发布于 2013-10-06 23:14:48

UpdateLayeredWindow()需要一个位图,其中包含预乘的alpha:

请注意,API使用预乘alpha,这意味着位图中的红色、绿色和蓝色通道值必须与alpha通道值进行预乘。例如,如果alpha通道值为x,则红色、绿色和蓝色通道必须乘以x,并在调用之前除以0xff。

您可以使用Bitmap::ConvertFormat()将位图转换为预乘(格式为PixelFormat32bppPARGB)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19214921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档