【问题标题】:Draw semitransparently in invisible layered window在不可见的分层窗口中半透明地绘制
【发布时间】:2017-09-28 11:54:27
【问题描述】:

我的目标是有一个全屏覆盖不可见的“画布”,我可以在上面使用 win32 的各种绘图功能进行绘制。

我目前尝试的方式是这样的:

WNDCLASSA myclass = { 0 };
myclass.lpfnWndProc = WindowProc3;
myclass.hInstance = GetModuleHandle(0);
myclass.lpszClassName = "MyCanvas";
myclass.hbrBackground = CreateSolidBrush(0xFEEDBEEF);
myclass.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassA(&myclass);

...

HWND wnd = CreateWindowExA(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT, "MyCanvas", 0, WS_POPUP | WS_VISIBLE, 0, 0, screen_width, screen_height, 0, 0, GetModuleHandle(0), 0);
SetLayeredWindowAttributes(wnd, 0xFEEDBEEF, 0, LWA_COLORKEY);

虽然这可以用作画布,但经过数小时的谷歌搜索,我仍然无法半透明地在其上绘制。

在我写这篇文章时,我添加了我的程序当前显示的屏幕截图。例如,我希望能够将右上角的黑框(用Rectangle 绘制)半透明,以便显示其下方的stackoverflow 页面内容。

This 是我发现的一个让我充满希望的问题,但生成的文本只是背景颜色((COLORREF)0xFEEDBEEF) 和文本颜色的混合组合。我发现的其他事情要么只是使元素完全不可见,什么都不做,要么需要像 MFC 这样的库。我希望尽可能只使用 win32 函数,因为我希望能够实现尽可能高的 FPS。

我不在乎这是否不适用于所有 Windows 版本,只要它适用于 7 到 10。

【问题讨论】:

  • 来吧 - 看看这篇文章:codeproject.com/Articles/13550/XCPClock-CodeProject-Clock 我不会在这里发布代码,因为我在阅读并实现之后懒得回顾和压缩我写的代码..
  • @enhzflep 当我意识到我一直在使用 SetLayeredWindowAttributes 时,我感到非常兴奋,但不久之后我意识到你似乎只能有一个颜色键(意思是,不可能同时使用使背景不可见并同时具有半透明元素)。我可能在这方面是错的,但我不这么认为。 :(((((
  • 显示的代码绘制了一个圆形钟面。此圆圈之外的矩形窗口部分是完全透明的(颜色键控),而 所有其余部分 具有相同的透明度 - 此透明度的范围可以从 0% 到 100% - 即可以使所有绿色文本半透明(但它们都具有相同的透明度)。希望这就是您感兴趣的内容。否则,您必须弄乱并复制您后面的窗口并使用预乘 alpha 自己执行透明效果 - 可能,但并不完全有趣。 ;)
  • “我发现的其他东西 [...] 需要像 MFC 这样的库。” - 那么,这就是你的答案。 MFC 是围绕 Windows API 的资源管理包装器。如果您需要 Windows API 代码,只需从那里撕掉它。不像 MFC 是某种神奇的工具,它可以做的比操作系统通过其 API 提供的更多。此外,您可以结合颜色键控和 Alpha 透明度 (LWA_ALPHA | LWA_COLORKEY)。这是每个窗口的属性。但是,您不能将其限制在子区域中。
  • 您对 (0xFEEDBEEF) 的意图是什么? COLORREF 的高位字节通常必须为 0(只有非常特殊的例外)。

标签: c++ windows winapi


【解决方案1】:

如果您只需要一个矩形区域的透明度,其中所有像素都具有相同的透明度(也称为 alpha)值或完全透明,您可以将SetLayeredWindowAttributes() 与 alpha 值和/或颜色键。

UpdateLayeredWindow() 是您需要能够定义每像素透明度的方法。

为此,您必须创建memory DC 并在其中选择一个 32bpp 位图。您可以使用buffered paint API 来简化任务。 Raymond Chen 对此有一个blog post with a code sample

您可以在内存 DC 中绘制,但不能为此使用大部分 GDI API,因为 GDI 忽略了 alpha 通道(透明度)。我建议使用GDI+,它允许您指定 alpha 值。

完成向内存 DC 的绘制后,您将调用 UpdateLayeredWindow() 并将该内存 DC 作为参数传递给 hdcSrc 参数,以使结果在屏幕上可见。

可能的影响说明:

SetLayeredWindowAttributes( hwnd, 0, 176, LWA_ALPHA ); 

SetLayeredWindowAttributes( hwnd, colorkey, 0, LWA_COLORKEY ); 

SetLayeredWindowAttributes( hwnd, colorkey, 176, LWA_ALPHA|LWA_COLORKEY ); 

UpdateLayeredWindow( ... )

请注意上一个示例中形状的抗锯齿边缘和透明度渐变。只有UpdateLayeredWindow() 才能实现这样的事情。

【讨论】:

  • 很多有用的信息,谢谢。我会尽快按照您所说的对UpdateLayeredWindow 进行操作。能否详细说明如何使用SetLayeredWindowAttributes影响矩形区域?
  • @Lupe 我添加了一些图片用于说明。
  • 我让它工作了。非常感谢!一旦我有一个很好的例子,我会添加工作代码。
猜你喜欢
  • 2021-04-10
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
相关资源
最近更新 更多