SDL 2 中带有不透明元素的完全透明窗口

问题描述 投票:0回答:1

我正在尝试创建一个本身完全透明的 SDL 窗口,但是当将图像渲染到其上时,图像完全不透明并且图像的 Alpha 通道被保留(因此图像的透明像素保持透明) 。因此,结果只是屏幕上的图像,周围没有任何容器(想象一下在屏幕上贴一张现实生活中的贴纸)

所以这是简化的代码:

#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_syswm.h>
#include <iostream>
#include <Windows.h>
#include <string>

SDL_Window* window;
SDL_Renderer* renderer;

SDL_Texture* image;
int imageWidth = 0;
int imageHeight = 0;

bool init()
{
    //Initialize SDL
    if (SDL_Init(SDL_INIT_VIDEO) != 0)
    {
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        return false;
    }

    //Set texture filtering to linear
    if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
    {
        printf("Warning: Linear texture filtering not enabled!");
    }

    //Create window
    window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 500, 300, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS);
    if (window == NULL)
    {
        printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
        return false;
    }

    //Create renderer for window
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (renderer == NULL)
    {
        printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
        return false;
    }

    //Initialize renderer color
    SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);

    //Initialize PNG loading
    int imgFlags = IMG_INIT_PNG;
    if (!(IMG_Init(imgFlags) & imgFlags))
    {
        printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
        return false;
    }
    return true;
}

bool loadImage(const std::string& path)
{
    //The final texture
    SDL_Texture* newImage = NULL;

    //Load image at specified path
    SDL_Surface* loadedSurface = IMG_Load(path.c_str());
    if (!loadedSurface)
    {
        printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError());
        return false;
    }

    //Create texture from surface pixels
    newImage = SDL_CreateTextureFromSurface(renderer, loadedSurface);
    if (!newImage)
    {
        printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
        return false;
    }

    imageWidth = loadedSurface->w;
    imageHeight = loadedSurface->h;

    //Get rid of old loaded surface
    SDL_FreeSurface(loadedSurface);

    image = newImage;
    return true;
}


void displayImage()
{
    SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
    SDL_RenderClear(renderer);

    SDL_SetWindowSize(window, imageWidth, imageHeight);
    SDL_Rect renderQuad = { 0, 0, imageWidth, imageHeight };

    SDL_RenderCopy(renderer, image, NULL, &renderQuad);
    SDL_RenderPresent(renderer);
}


// Makes a window transparent by setting a transparency color.
bool windowColorKey(SDL_Window* window, COLORREF colorKey) {

    SDL_SysWMinfo wmInfo;
    SDL_VERSION(&wmInfo.version);  // Initialize wmInfo
    SDL_GetWindowWMInfo(window, &wmInfo);
    HWND hWnd = wmInfo.info.win.window;

    // Change window type to layered
    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* args[]) {

    // Initialize SDL: Create a window and renderer
    init();

    // Load the image 
    loadImage("example.png");

    // Color key the background of the window (magenta)
    windowColorKey(window, RGB(255, 0, 255));

    // Render the image on the widnow with magenta for backround color
    displayImage();

    // Check for events
    bool windowActive = true;
    SDL_Event event;
    while (windowActive)
    {
        while (SDL_PollEvent(&event) != 0)
        {
            if (event.type == SDL_QUIT || event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { windowActive = false; }
        }
    }

    return 0;
}

使用 SDL_SetWindowOpacity() 不起作用,因为窗口的所有元素也是透明的。

目前我知道实现此目标的唯一方法是使用颜色键控,但不幸的是它效果不佳,因为某些图像将包含您用于颜色键控的颜色,此外图像将有一个小用于图像周围颜色键控的颜色边框。虽然很薄但是很烦人。

我正在考虑以其他方式使用分层窗口的功能,但无法找到或理解如何使用。

那么,问题是如何让窗口本身完全透明,同时完全控制窗口元素的透明度?

c++ transparency sdl-2 layered
1个回答
0
投票

SDL 人员似乎已经意识到这一流行的请求和问题:

https://github.com/libsdl-org/SDL/issues/1872

并且不打算在 SDL_SetWindowOpacity() 之外做任何事情,这远没有透明背景那么有用或酷。

© www.soinside.com 2019 - 2024. All rights reserved.