Win32 прозрачный полноэкранный режим работает только в том случае, если размер окна выходит за пределы рабочего стола - PullRequest
2 голосов
/ 05 апреля 2019

Я пытаюсь сделать полноэкранное прозрачное окно на рабочем столе, которое я могу визуализировать с помощью opengl.
Я не хочу переполнять экран, но пока, похоже, это единственный способ, которым я могу.Это довольно грязный хак, и я надеюсь, что кто-то знает о профессиональном решении.

Вот код:

// 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;
}

1 Ответ

0 голосов
/ 10 мая 2019

При запуске вашего кода у меня фактически нет никакой прозрачности, поэтому я не могу понять, почему вам нужно переполнить экран.Но вот как я изменил твой код, чтобы он работал на меня, и без переполнения экрана.

// 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 без флагов, потому что мы не используем ни одну из этих многоуровневых оконных функций, но нам нужно вызвать функцию, чтобы окно стало видимым.

...