我已经阅读了关于这个棘手(利基)主题的所有现有问题,但我被卡住了。我有一个带有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 _颜色和LWA _阿尔法属性。这就是我所展示的效果。但是,色键似乎没有考虑在内(我也尝试过非零值)。
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);
你想做的事情需要窗口合成,这从Windows Vista开始就已经存在了,所以基本上每个版本的Windows你都必须关心(Windows XP和更早的版本都已寿终正寝)。
要采取的关键步骤是,通过启用“窗口后模糊”启用DWM窗口内合成,并使用WM_POPUP
窗口;如果您不使用WM_POPUP
样式,窗口管理器将绘制装饰,您的OpenGL渲染将“悬停”在其上方。
DWM_BLURBEHIND bb = {0};
bb.dwFlags = DWM_BB_ENABLE;
bb.fEnable = TRUE;
bb.hRgnBlur = NULL;
DwmEnableBlurBehindWindow(hWnd, &bb);
MARGINS margins = {-1};
impl_DwmExtendFrameIntoClientArea(hWnd, &margins);
接下来,您必须使用较新的“属性”API而不是使用像素格式描述符选择来创建OpenGL上下文。使用属性API,您可以选择alpha窗口格式的透明。
int attribs[] = {
WGL_DRAW_TO_WINDOW_ARB, TRUE,
WGL_DOUBLE_BUFFER_ARB, TRUE,
WGL_SUPPORT_OPENGL_ARB, TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_TRANSPARENT_ARB, TRUE,
WGL_COLOR_BITS_ARB, 32,
WGL_RED_BITS_ARB, 8,
WGL_GREEN_BITS_ARB, 8,
WGL_BLUE_BITS_ARB, 8,
WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0, 0
};
INT iPF;
UINT num_formats_choosen;
if( !wglChoosePixelFormatARB(
hDC,
attribs,
NULL,
1,
&iPF,
&num_formats_choosen) ) {
fprintf(stderr, "error choosing proper pixel format\n");
return NULL;
}
if( !num_formats_choosen ) {
return NULL;
}
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
/* now this is a kludge; we need to pass something in the PIXELFORMATDESCRIPTOR
* to SetPixelFormat; it will be ignored, mostly. OTOH we want to send something
* sane, we're nice people after all - it doesn't hurt if this fails. */
DescribePixelFormat(hDC, iPF, sizeof(pfd), &pfd);
if( !SetPixelFormat(hDC, iPF, &pfd) ) {
fprintf(stderr, "error setting proper pixel format\n");
ReleaseDC(hWnd, hDC);
DestroyWindow(hWnd);
return NULL;
}
我在GitHub的wglarb
包装器存储库中有一个完整的工作示例:
https://github.com/datenwolf/wglarb/blob/master/test/layered.c
您可能错过了对 UpdateLayeredWindow 的调用。IIRC,不调用UpdateLayeredWindow会导致一些奇怪的行为。新浪网.
更多详情请点击此处
根据您需要通过的SetLayeredWindow属性文档
一个COLORREF结构,指定构成分层窗口时要使用的透明色键。窗口以这种颜色绘制的所有像素都将是透明的。要生成COLORREF,请使用RGB宏。
查看调用此函数的第二个参数。