Winapi - 如何在MS Edge浏览器中实现LWA_COLORKEY的等价物。

问题描述 投票:0回答:1

我的目标是选择一种在Microsoft Edge浏览器上透明的颜色(即我们可以看到Edge上出现该颜色的窗口后面)。过去,我曾用以下几行Python代码在Mathematica窗口上实现了我想要的效果。

win32gui.SetWindowLong(hwnd,win32con.GWL_EXSTYLE,
                       win32gui.GetWindowLong(hwnd,win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
winxpgui.SetLayeredWindowAttributes(hwnd,win32api.RGB(*transparentColor),50,win32con.LWA_COLORKEY)

其中hwnd是窗口的句柄,transparentColor是所需颜色的RGB值。现在我正在用Jupyter做实验,想在Edge上做同样的事情,因为Jupyter是在浏览器上运行的,但在Edge上,上述内容几乎被忽略了(根据颜色的不同,菜单的某些部分可能会变成透明的,但窗口的主体不会)。迄今为止,我的研究使我相信,这是因为Edge(或任何其他现代浏览器)不使用GDI,并忽略了LWA_COLORKEY请求。我试过用LWA_ALPHA代替LWA_COLORKEY,确实有效(使整个窗口半透明),但这不是我想要的效果。如果我使用 win32gui.SetLayeredWindowAttributes.

外部应用程序是否有可能以任何方式实现上述Edge浏览器应用程序代码的意图?根据Rita Han的研究,在她的回答和评论中,这显然是可能的,因为这对她来说是可行的。问题是为什么在我的系统上行不通(我在两台电脑上试过)。

在要求提供更多信息后更新。

我的Edge版本是44.18362.449.0,但我现在已经更新到81.0.416.72,结果还是一样。下面的屏幕截图显示了两个窗口,左边的一个是MS Paint,我在那里创建了一个名为 "almostBlack_010000.png "的图像,右边的一个是Edge,显示同样的图像。我已经用上面的代码在这两个窗口上设置了WS_EX_LAYERED和LWA_COLORKEY,使用颜色(1,0,0)作为键(即非常深的红色)。正如你所看到的,Paint窗口通过 "黑色 "矩形显示了我的桌面,而Edge没有。

PC desktop showing MS Paint and MS Edge windows

一些额外的说明。

  • 我也试过用Internet Explorer和Chrome浏览器,结果也是一样。

  • MS Paint上的透明区域是可以点击的,也就是说,在该区域点击就像点击桌面或任何刚好在后面的窗口一样。

  • 当我使用RGB颜色(0,0,0)作为键时,整个窗口都变成了点击式。在Edge上也会发生这种情况,但黑色像素仍然不会变得透明。

  • 如果出现错误,上面的代码会抛出一个Python跟踪。例如,如果我在调用SetLayeredWindowAttributes时提供了一个不存在的窗口句柄,我得到了一个带有以下最后一行的回溯。error: (1400, 'SetLayeredWindowAttributes', 'Invalid window handle.')

我用下面的c++代码进行了尝试,得到了同样的结果,即在Paint和其他应用程序中,我可以让选定的颜色变得透明,但在Edge中却不行。

#include <iostream>
#include <Windows.h>

int main(int argc, char *argv[])
{
    HWND hwnd;
    COLORREF color;

    if (argc != 3)
    {
        printf("Usage: %s <HWND> <color>",argv[0]);
    }
    else
    {
        hwnd = (HWND)strtoul(argv[1],NULL,16);
        color = (COLORREF)strtoul(argv[2],NULL,16); // Note: order is reverse than usual. Use 0xBBGGRR
        printf("Setting window %x to %x", (unsigned int)hwnd, (unsigned int)color);

        if (!SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED))
            printf("SetWindowLong error: %d\n", GetLastError());
        if (!SetLayeredWindowAttributes(hwnd,color,50,LWA_COLORKEY))
            printf("SetLayeredWindowsAttributes error: %d\n", GetLastError());
    }

}

我发现LWA_COLORKEY和LWA_ALPHA可以被ORed,在这种情况下,SetLayeredWindowAttributes的alpha和colorkey参数可以同时使用。因此,我可以在同一个Edge窗口上看到整体的alpha效果是可见的,但关键颜色的透明度却不可见。

winapi
1个回答
0
投票

我按照你的步骤,使用MS Paint创建一个黑色的图像,并运行以下代码的MS Paint和Edge,都为我工作。确保你使用正确的目标窗口句柄,并添加错误检查,以确保功能成功执行。

HWND hwnd = (HWND)0x00070948; // The window handle I found via Spy++ for testing purpose.

if (!SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED))
    printf("SetWindowLong error: %d\n", GetLastError());
if (!SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 50, LWA_COLORKEY))
    printf("SetLayeredWindowAttributes error: %d\n", GetLastError());

用MS Paint打开的黑色图像。

enter image description here

用Edge打开的黑色图像在执行后变成了透明图像 SetLayeredWindowAttributes. 从透明区域你可以看到我的桌面(蓝色)。

enter image description here


0
投票

我终于找到了一个解决方案,这可能会或可能不会有不良的性能副作用,但我怀疑这是唯一的方法,使它与我的问题中的代码工作。

问题是Edge默认使用的是硬件加速,而使用GPU进行渲染,要么导致无法使用我的代码造成透明,要么至少让我现在想不通。

诸如 SetLayeredWindowAttributes使一个窗口透明化只是部分时间有效。 让我开始关注硬件加速。

感谢Rita至少证明了这是可以做到的,这让我一直在寻找为什么它在我的系统上不起作用。

我找到了在Edge中关闭硬件加速的方法,地址是 十论坛.

我还是很想知道是否有其他方法可以实现同样的效果,同时可能保持硬件加速。请留言!

© www.soinside.com 2019 - 2024. All rights reserved.