SDL: Fullscreen translucent background

核能气质少年 提交于 2019-12-10 10:41:13

问题


I'm trying to write a program that has a translucent background covering the whole screen. After some research it appeared that SDL would be the way to go.

I've written the code to create a full screen window with a background whose alpha is equal to 100 (out of 255), but for some reason it just draws the solid colour. What have I done wrong?

// Initialise SDL
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
        this->throwSDLError("SDL_Init Error");
}

// Create the window and renderer
if (SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &(this->window), &(this->renderer)) != 0) {
        this->throwSDLError("Could not create the window and renderer");
}

// Set the blend mode to specify how the alpha channel is used
if (SDL_SetRenderDrawBlendMode(this->renderer, SDL_BLENDMODE_BLEND) != 0) {
        this->throwSDLError("Could not set render draw blend mode");
}

// Set the colour to draw
if (SDL_SetRenderDrawColor(this->renderer, 200, 200, 200, 100) != 0) {
        this->throwSDLError("Could not set the drawing colour");
}

// Clear the screen using the colour
if (SDL_RenderClear(this->renderer) != 0) {
        this->throwSDLError("Could not render the screen");
}

// Present the rendered screen
SDL_RenderPresent(this->renderer);

回答1:


On Windows, you can create a transparent window by using SetLayeredWindowAttributes to chroma-key the background color from a borderless SDL window.

Code:

// SDL window with transparent background v1.2
#include <SDL.h>
#include <SDL_syswm.h>
#include <Windows.h>

// Makes a window transparent by setting a transparency color.
bool MakeWindowTransparent(SDL_Window* window, COLORREF colorKey) {
    // Get window handle (https://stackoverflow.com/a/24118145/3357935)
    SDL_SysWMinfo wmInfo;
    SDL_VERSION(&wmInfo.version);  // Initialize wmInfo
    SDL_GetWindowWMInfo(window, &wmInfo);
    HWND hWnd = wmInfo.info.win.window;

    // Change window type to layered (https://stackoverflow.com/a/3970218/3357935)
    SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);

    // Set transparency color
    return SetLayeredWindowAttributes(hWnd, colorKey, 0, LWA_COLORKEY);
}

int main(int argc, char** argv) {
    // Get resolution of primary monitor
    int desktopWidth = GetSystemMetrics(SM_CXSCREEN);
    int desktopHeight = GetSystemMetrics(SM_CYSCREEN);

    SDL_Window* window = SDL_CreateWindow("SDL Transparent Window",
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        desktopWidth, desktopHeight, SDL_WINDOW_BORDERLESS);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

    // Set background color to magenta and clear screen
    SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
    SDL_RenderClear(renderer);

    // Draw blue square in top-left corner
    SDL_Rect rect1 = {0, 0, 100, 100};
    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
    SDL_RenderFillRect(renderer, &rect1);

    // Draw red square in center of the screen
    SDL_Rect rect2 = {(desktopWidth-100)/2, (desktopHeight-100)/2, 100, 100};
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    SDL_RenderFillRect(renderer, &rect2);

    // Add window transparency (Magenta will be see-through)
    MakeWindowTransparent(window, RGB(255, 0, 255));

    // Render the square to the screen
    SDL_RenderPresent(renderer);

    // Loop until user quits
    bool quit = false;
    SDL_Event event;
    while (!quit) {
       while (SDL_PollEvent(&event) != 0) {
           if (event.type == SDL_QUIT) {
               quit = true;
           }
       }
    }

    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

Result:

Explanation:

First, create a borderless window with that covers the entire desktop. Choose a solid masking color and use it as your background. (In my case, I used magenta). You can then key-out your masking color with the Win32 API function SetLayeredWindowAttributes.

Any part of the window with this color will be completely see-through. Other windows behind your program can be interacted with as normal. By default, other applications can be moved on top of your borderless window.

If you want your SDL window to always be on top of other windows, you can set the SDL_WINDOW_ALWAYS_ON_TOP flag when creating your window.

See Also

  • Stack Overflow: Creating a transparent window in C++ Win32
  • Stack Overflow: How detect current screen resolution?
  • Microsoft: Layered Windows


来源:https://stackoverflow.com/questions/23048993/sdl-fullscreen-translucent-background

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!