-1

I am writing a windowing library for C and C++ to handle borderless and non rectangular windows for OpenGL. I have a problem : I want the library to let the user draw to RGBA, i mean there is no background then the window can have any shape. I've done a lot of researches and i think i have to use the DWM api and blur behind window (see the code below) i use glClearColor(0.0f, 0.0f, 0.0f. 0.0f); which should display a fully transparent window (so nothing), but it still see a black semi transparent rectangle (like if the alpha chanel was ~0.1f), if i change the colour the coulour of the window changes and if i set a higher alpha chanel, the window is more visible so it seems that it works but not correcly. And this is a problem, I want to be able to have fully transparent window. I am using DWM but if there is a better solution please tell me. The problem could also come from OpenGL blending states, i don't know.

The code :

#define UNICODE

#define GLEW_STATIC

#include <windows.h>
#include <dwmapi.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

#include <glew.h>

LRESULT CALLBACK wnd_proc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp);

int main(void){
    int initial_clock = clock();

    WNDCLASSEX wcx = {};
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.lpszClassName = L"win32_class";
    wcx.lpfnWndProc = wnd_proc;
    RegisterClassEx(&wcx);

    HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, L"win32_class", L"Title",
        WS_POPUP, 100, 100, 800, 400, NULL, NULL, NULL, NULL);

    ShowWindow(hWnd, 1);

    HDC device_context = GetDC(hWnd);

    PIXELFORMATDESCRIPTOR pfd = {};
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;

    int pixel_format = ChoosePixelFormat(device_context, &pfd);
    SetPixelFormat(device_context, pixel_format, &pfd);
    HGLRC rendering_context = wglCreateContext(device_context);
    wglMakeCurrent(device_context, rendering_context);

    glewInit();

    DWM_BLURBEHIND blur = {};
    blur.dwFlags = DWM_BB_ENABLE;
    blur.fEnable = 1;
    blur.hRgnBlur = NULL;
    DwmEnableBlurBehindWindow(hWnd, &blur);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0)){
        DispatchMessage(&msg);
        glClear(GL_COLOR_BUFFER_BIT);
        wglSwapLayerBuffers(device_context, WGL_SWAP_MAIN_PLANE);
    }
}

LRESULT CALLBACK wnd_proc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
    switch(uMsg){
        case WM_NCHITTEST: return HTCAPTION;
        default:           return DefWindowProc(hWnd, uMsg, wp, lp);
    }
}
genpfault
  • 51,148
  • 11
  • 85
  • 139

1 Answers1

-1

You can use SetLayeredWindowAttributes function.

Sets the opacity and transparency color key of a layered window.

Add:

LONG Style = GetWindowLong(hWnd, GWL_EXSTYLE); 
SetWindowLong(hWnd, GWL_EXSTYLE, Style | WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd, 0, 10, LWA_ALPHA);

When bAlpha is 0, the window is completely transparent. When bAlpha is 255, the window is opaque.

Debug(bAlpha = 10):

1

Complete code:

#define UNICODE

#define GLEW_STATIC

#include <windows.h>
#include <dwmapi.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

#include <glew.h>

LRESULT CALLBACK wnd_proc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp);

int main(void){
    int initial_clock = clock();

    WNDCLASSEX wcx = {};
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.lpszClassName = L"win32_class";
    wcx.lpfnWndProc = wnd_proc;
    RegisterClassEx(&wcx);

    HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, L"win32_class", L"Title",
        WS_POPUP, 100, 100, 800, 400, NULL, NULL, NULL, NULL);

    ShowWindow(hWnd, 1);

    HDC device_context = GetDC(hWnd);

    PIXELFORMATDESCRIPTOR pfd = {};
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;

    int pixel_format = ChoosePixelFormat(device_context, &pfd);
    SetPixelFormat(device_context, pixel_format, &pfd);
    HGLRC rendering_context = wglCreateContext(device_context);
    wglMakeCurrent(device_context, rendering_context);

    glewInit();

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0)){
        DispatchMessage(&msg);
        glClear(GL_COLOR_BUFFER_BIT);
        wglSwapLayerBuffers(device_context, WGL_SWAP_MAIN_PLANE);
    }
}

LRESULT CALLBACK wnd_proc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
    switch(uMsg){
        case WM_CREATE:
        {
            LONG Style = GetWindowLong(hWnd, GWL_EXSTYLE); 
            SetWindowLong(hWnd, GWL_EXSTYLE, Style | WS_EX_LAYERED);
            SetLayeredWindowAttributes(hWnd, 0, 10, LWA_ALPHA);
        }
        break;
        case WM_NCHITTEST: return HTCAPTION;
        default:           return DefWindowProc(hWnd, uMsg, wp, lp);
    }
}
Strive Sun
  • 5,988
  • 1
  • 9
  • 26
  • That is not whatI needed this blends all the pixels with the same alpha. but i found how to do it now. thank you anyway. –  Apr 01 '20 at 20:33
  • @linternetsansfil OK, you can post your answer and mark it. – Strive Sun Apr 02 '20 at 01:16