我正在尝试在桌面上制作一个全屏透明窗口,我可以在上面使用 opengl 渲染。
我不想溢出屏幕,但到目前为止,这似乎是我唯一的方法。这是一个非常肮脏的黑客imo,希望有人知道专业的解决方案。
代码如下:
// libs needed to compile: opengl32 gdi32 dwmapi
#include <windows.h>
#include <GL/gl.h>
#include <dwmapi.h>
HDC hDC;
HGLRC hRC;
HWND hWnd;
bool running=true;
int w=GetSystemMetrics(SM_CXSCREEN),h=GetSystemMetrics(SM_CYSCREEN);
void CreateContext(){
PIXELFORMATDESCRIPTOR pfd; hDC=GetDC(hWnd);
SetPixelFormat(hDC,ChoosePixelFormat(hDC,&pfd),&pfd);
hRC=wglCreateContext(hDC); wglMakeCurrent(hDC,hRC);
}
void EnableTransparency(){DWM_BLURBEHIND b={DWM_BB_ENABLE|DWM_BB_BLURREGION,TRUE,CreateRectRgn(0,0,-1,-1)}; DwmEnableBlurBehindWindow(hWnd,&b);}
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
switch(uMsg){
case WM_CLOSE: running=false; return 0;
case WM_KEYDOWN: if(wParam==VK_ESCAPE){running=false;} return 0;
}return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
void CreateWin(){
WNDCLASS wc={};
wc.lpfnWndProc=WndProc;
wc.hInstance=GetModuleHandle(NULL);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.lpszClassName="OpenGL";
RegisterClass(&wc);
hWnd = CreateWindow(wc.lpszClassName,"Title",WS_POPUP,0,-1,w,h+1,0,0,wc.hInstance,0); // increasing height by 1 pixel
ShowWindow(hWnd,SW_SHOW);
EnableTransparency();
CreateContext();
}
void PumpMessages(){MSG msg; while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))DispatchMessage(&msg);}
int main(){
CreateWin();
glViewport(0,0,w,h); // the visible screen area (excluding h+1 overflow)
while(running){
PumpMessages();
glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); // fill solid black
glBegin(GL_TRIANGLES); // transparent triangular window
glColor4f(1,0,0,0.5f); glVertex3f( 0, 1,0); // red (center)
glColor4f(0,1,0,0.5f); glVertex3f(-1,-1,0); // green (left)
glColor4f(0,0,1,0.5f); glVertex3f( 1,-1,0); // blue (right)
glEnd();
SwapBuffers(hDC);
}
return 0;
}
在运行你的代码时,我实际上没有任何透明度,所以我不明白为什么你需要溢出屏幕。但这是我更改您的代码以适合我的方式,并且不会溢出屏幕。
// libs needed to compile: opengl32 gdi32 dwmapi
#include <windows.h>
#include <GL/gl.h>
#include <dwmapi.h>
HDC hDC;
HGLRC hRC;
HWND hWnd;
bool running = true;
int w = GetSystemMetrics(SM_CXSCREEN), h = GetSystemMetrics(SM_CYSCREEN);
void CreateContext() {
PIXELFORMATDESCRIPTOR pfd; hDC = GetDC(hWnd);
SetPixelFormat(hDC, ChoosePixelFormat(hDC, &pfd), &pfd);
hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC);
}
void EnableTransparency() {
SetLayeredWindowAttributes(hWnd, NULL, NULL, NULL);
const MARGINS margins = { -1 };
DwmExtendFrameIntoClientArea(hWnd, &margins);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE: running = false; return 0;
case WM_KEYDOWN: if (wParam == VK_ESCAPE) { running = false; } return 0;
}return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void CreateWin() {
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = "OpenGL";
RegisterClass(&wc);
hWnd = CreateWindowEx(WS_EX_LAYERED, wc.lpszClassName, "Title", WS_POPUP, 0, 0, w, h, 0, 0, wc.hInstance, 0);
ShowWindow(hWnd, SW_SHOW);
CreateContext();
EnableTransparency();
}
void PumpMessages() { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))DispatchMessage(&msg); }
int main() {
CreateWin();
glViewport(0, 0, w, h); // the visible screen area
while (running) {
PumpMessages();
glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); // fill solid black
glBegin(GL_TRIANGLES); // transparent triangular window
glColor4f(1, 0, 0, 0.5f); glVertex3f(0, 1, 0); // red (center)
glColor4f(0, 1, 0, 0.5f); glVertex3f(-1, -1, 0); // green (left)
glColor4f(0, 0, 1, 0.5f); glVertex3f(1, -1, 0); // blue (right)
glEnd();
SwapBuffers(hDC);
}
return 0;
}
检查错误代码已被省略。本质上,我们使用具有分层样式的窗口来获得透明度。我们调用不带标志的 SetLayeredWindowAttributes,因为我们没有使用这些分层窗口功能中的任何一个,但我们需要调用该函数才能使窗口变得可见。