【发布时间】:2018-07-08 18:15:41
【问题描述】:
我已经阅读了关于这个棘手(利基)主题的所有现有问题,但我被困住了。我有一个带有 OpenGL 上下文的 Win32 窗口。我希望我的窗口部分透明。
到目前为止,我的结果是整个窗口都是透明的。我只希望黑色区域是透明的,这样我就可以绘制一些 3D 对象,它们看起来就像是从窗户里出来的一样。
首先,在我的窗口类中,我将 hbrBackground 设置为黑色。
Windows::WindowClass windowClass;
windowClass.cbSize = sizeof(Windows::WindowClass);
windowClass.style = Windows::CS_VREDRAW | Windows::CS_HREDRAW;
windowClass.lpfnWndProc = WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = moduleHandle;
windowClass.hIcon = Windows::LoadIcon(0u, (X*)Windows::IDI_QUESTION);
windowClass.hCursor = Windows::LoadCursor(0u, (X*)Windows::IDC_ARROW);
windowClass.hbrBackground = Windows::CreateSolidBrush(0x00000000);
windowClass.lpszMenuName = nullptr;
windowClass.lpszClassName = (X*)name;
windowClass.hIconSm = Windows::LoadIcon(0u, (X*)Windows::IDI_QUESTION);
我创建了带有 WS_EX_LAYERED 标志的窗口。
windowHandle = Windows::CreateWindow(Windows::WS_EX_LAYERED, (X*)name, "", Windows::WS_POPUP, w / 4, h / 4, w / 2, h / 2, 0u, 0u, moduleHandle, 0u);
在我的像素格式中,我启用了 alpha 和合成。
PixelFormatDescriptor format;
format.nSize = sizeof(PixelFormatDescriptor);
format.nVersion = 1;
format.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | PFD_SUPPORT_COMPOSITION;
format.iPixelType = PFD_TYPE_RGBA;
format.cColorBits = 32;
format.cRedBits = 0;
format.cRedShift = 0;
format.cGreenBits = 0;
format.cGreenShift = 0;
format.cBlueBits = 0;
format.cBlueShift = 0;
format.cAlphaBits = 8;
format.cAlphaShift = 0;
format.cAccumBits = 0;
format.cAccumRedBits = 0;
format.cAccumGreenBits = 0;
format.cAccumBlueBits = 0;
format.cAccumAlphaBits = 0;
format.cDepthBits = 24;
format.cStencilBits = 8;
format.cAuxBuffers = 0;
format.iLayerType = PFD_MAIN_PLANE;
format.bReserved = 0;
format.dwLayerMask = 0;
format.dwVisibleMask = 0;
format.dwDamageMask = 0;
我尝试过模糊区域“技巧”,但没有效果。我的结果与这段代码无关。
struct DwmBlurBehind
{
U4 dwFlags;
S4 fEnable;
X* blurRegionHandle;
S4 fTransitionOnMaximized;
};
DwmBlurBehind blurBehind;
blurBehind.dwFlags = Windows::DWM_BB_ENABLE | Windows::DWM_BB_BLURREGION;
blurBehind.fEnable = true;
blurBehind.blurRegionHandle = Windows::CreateRectRgn(0, 0, -1, -1);
blurBehind.fTransitionOnMaximized = false;
Windows::DwmEnableBlurBehindWindow(windowHandle, &blurBehind);
最后,我设置了 LWA_COLORKEY 和 LWA_ALPHA 属性。这就是给我展示的效果。但是,似乎没有考虑颜色键(我也尝试过非零值)。
Windows::SetLayeredWindowAttributes(windowHandle, 0, 170, Windows::LWA_COLORKEY | Windows::LWA_ALPHA);
我没有忘记启用混合。
GL::Enable(GL::BLEND);
GL::BlendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA);
【问题讨论】:
-
有一个high-performance technique 禁用了通常在绘制到窗口时使用的重定向表面。它涉及设置
WS_EX_NOREDIRECTION扩展窗口样式并调用CreateSwapChainForComposition()以创建直接呈现给窗口组合模块的交换链。您正在使用 OpenGL,但也许您可以调整此方法。 -
OpenGL 混合与 Windows 中的窗口子系统实现的半透明完全无关。 OpenGL 中的 Alpha 混合在 OpenGL 渲染上下文处结束。