【问题标题】:Win32 LayeredWindow gives bad visual effectWin32 LayeredWindow 提供糟糕的视觉效果
【发布时间】:2015-06-22 12:29:51
【问题描述】:

我正在开发一个 UI 系统,它具有所有智能功能,例如面板撕下和对接等。现在我的任务是在屏幕上创建一个覆盖层,显示撕下或可对接面板的位置.与视觉工作室几乎相同的东西。 为此,我使用了一个自定义的分层窗口类,它会在需要时显示出来。之后我开始挖掘以达到所需的效果。 我以前使用标准的 GDI 函数,基本上它们没问题。但是这次我按照文档建议使用 UpdateLayeredWindow 来完成我的任务,并从位图中加载 32 位图像,而不是使用 GDI 函数绘制它。 所以这里我有一个 128x128pixel 宽的 bmp,alpha 通道为 222,RGB 通道为 255 0 0

这是我用于初始化和绘图的方法。

void Init(HDC in_hdc,HWND in_hwnd)
    {
        bf = { 0, 0, 200, AC_SRC_ALPHA };
        hwnd = in_hwnd;
        hdc_mem = CreateCompatibleDC(in_hdc);
        hBitmap_mem = CreateCompatibleBitmap(in_hdc, canvas_size.cx, canvas_size.cy);
        hBitmap_mem_default = (HBITMAP)SelectObject(hdc_mem, hBitmap_mem);
        hdc_bitmap = CreateCompatibleDC(in_hdc);
    }
    void DrawArea(RECT& in_rect)
    {
        hBitmap_area_default = (HBITMAP)SelectObject(hdc_bitmap, hBitmap_area);
        AlphaBlend(hdc_mem, in_rect.left, in_rect.top, in_rect.right, in_rect.bottom, hdc_bitmap, 0, 0, 2, 2, bf);
        hBitmap_area = (HBITMAP)SelectObject(hdc_bitmap, hBitmap_area_default);
    }
    void Update()
    {
        POINT p = { 0, 0 };
        HDC hdc_screen = GetDC(0);
        UpdateLayeredWindow(hwnd, hdc_screen, &p, &canvas_size, hdc_mem, &p, 0, &bf, ULW_ALPHA);
    }

窗口样式有这个额外的 WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOPMOST

这就是我得到的。 所以你可以看到发生的混合确实考虑了每像素的 alpha,但它的混合工作很糟糕。 任何想法如何调整它?

【问题讨论】:

  • 为什么在你的混合函数结构中使用 200。对于每像素 alpha 值,您需要使用 255。

标签: user-interface winapi gdi alpha-transparency layered-windows


【解决方案1】:

我怀疑问题出在源位图中。这是当 RGB 值没有与 alpha 预乘时得到的那种效果。但请忽略这一点,因为有一种更简单的方法可以做到这一点。

  • 通过在WNDCLASSEX 结构中设置hbrBackground,创建具有纯色背景色的分层窗口。

  • 调用SetLayeredWindowAttributes使窗口部分透明。

  • 将窗口定位在您想要的位置。

就是这样。

This answer 的代码说明了用于稍微不同目的的技术。

【讨论】:

  • 感谢您的提示。如果我需要一些带有透明效果的象形图和图标怎么办。 (VS 编辑器中的 NavigationDiamond
  • 那么你需要修复位图。我不知道你是如何创建它的,所以我不能添加太多。
  • 谢谢。实际上预乘法已经奏效了。然而,我看不到这种预乘的想法。因此,例如,如果我有纯红色,即 255 0 0 和 222 alpha,然后将 255 乘以 222(0,87) 我得到〜222 0 0 和 alpha 与 222,所以当我将它乘以 1/0.87 我得到返回想要的颜色但是如果我不预乘,那么 255 x 1/.087 就会超出一个字节范围,并且会发生不同的错误情况。为什么不首先采用原始 RGB 值?
  • 原因很简单:Alpha 混合与 Porter-Duff 组合(可能没有;IDK)涉及大量乘法,从硬件的角度来看这很慢。通过提前将红色、绿色和蓝色分量与 alpha 分量相乘,您可以减少混合代码的乘法次数,从而使事情变得更快、更高效。
猜你喜欢
  • 1970-01-01
  • 2016-11-02
  • 1970-01-01
  • 2014-06-30
  • 2011-03-01
  • 2014-09-07
  • 2018-08-12
  • 1970-01-01
  • 2013-11-14
相关资源
最近更新 更多