lineDDA
是从不知道哪个博客抄下来的孔令德
老师讲课挺好的,建议看看在windows上要想让SDL_Window
和linux不太一样(linux可以直接读取css设置)
经过多次google终于在这个网址找到了做法http://5.9.10.113/67609916/fully-transparent-window-with-opaque-elements-in-sdl-2
链接
以下为代码网址上copy的代码
#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; }
观察到应该是windowColorKey()
函数起了作用,于是把这段代码提取封装一下
// 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); }
封装TransparentWindow.hpp
,实现全透明窗口
// // Created by majiao on 2021/8/22. // #ifndef MAIN_TRANSPARENTWINDOW_HPP #define MAIN_TRANSPARENTWINDOW_HPP #include <SDL.h> #include <SDL_syswm.h> #include <SDL_video.h> #include <windows.h> #include <cairo.h> #include <cmath> #include "stdlib.h" class TransparentWindow { public: SDL_Window *window; SDL_Renderer *renderer; SDL_Surface *winSurface; SDL_Texture *texture; SDL_Event event; SDL_Rect rectRect = {0, 0, 50, 50}; SDL_Rect backRect = {0}; SDL_Rect mRect = {SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480}; SDL_SysWMinfo info; HWND hwnd; COLORREF defaultTransparentColor = RGB(255, 0, 255); cairo_t *pen; void *pixels; int pitch = 0; TransparentWindow() { init(); } // 欲将SDL_Window背景透明 colorKey需传入RGB(255, 0, 255) // 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); } void init() { //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", mRect.x, mRect.y, mRect.w, mRect.h, SDL_WINDOW_SHOWN /**| SDL_WINDOW_BORDERLESS 取消sdl_window边框*/); if (window == NULL) { printf("Window could not be created! SDL Error: %s\n", SDL_GetError()); return; } // 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; } this->windowColorKey(this->window, this->defaultTransparentColor); this->texture = SDL_CreateTexture(this->renderer, SDL_PIXELFORMAT_RGBA8888, /**SDL_TEXTUREACCESS_TARGET |*/ SDL_TEXTUREACCESS_STREAMING, this->mRect.w, this->mRect.h); this->pen = initCairoPen(this->pixels, this->pitch); draw(); } // 这里使用cairo画图没有显示出效果,后面查一下原因 cairo_t *initCairoPen(void *&pixels, int &pitch) const { SDL_LockTexture(texture, NULL, &(pixels), &pitch); cairo_surface_t *cairo_surface = cairo_image_surface_create_for_data( (unsigned char *) pixels, CAIRO_FORMAT_ARGB32, // 与 SDLSDL_PIXELFORMAT_ARGB8888 对应 mRect.w, mRect.h, pitch); cairo_t *tpen = cairo_create(cairo_surface); cairo_set_line_width(tpen, 10); cairo_set_source_rgba(tpen, 0.6, 0.6, 0.6, 0.6); SDL_UnlockTexture(texture); return tpen; } void draw() { SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255); SDL_RenderClear(renderer); // 绘图逻辑 drawRectAndCircle(); // 更新texture reDrawTexture(); } void drawRectAndCircle() { // 画一个圆在中心,和一个移动的矩形,并把圆心和矩形4点连线 rectRect.x++; rectRect.x %= mRect.w; SDL_SetRenderDrawColor(renderer, 255, 0, 0, 0); SDL_RenderDrawRect(renderer, &rectRect); int circleX = mRect.w / 2, circleY = mRect.h / 2; drawCircle(renderer, circleX, circleY, 30); SDL_RenderDrawLine(renderer, circleX, circleY, rectRect.x, rectRect.y); SDL_RenderDrawLine(renderer, circleX, circleY, rectRect.x + rectRect.w, rectRect.y); SDL_RenderDrawLine(renderer, circleX, circleY, rectRect.x + rectRect.w, rectRect.y + rectRect.h); SDL_RenderDrawLine(renderer, circleX, circleY, rectRect.x, rectRect.y + rectRect.h); } void reDrawTexture() const { SDL_RenderCopy(renderer, texture, &mRect, &rectRect); SDL_RenderPresent(renderer); } // 不知道从哪里抄下来的画圆算法 void drawCircle(SDL_Renderer *renderer, int32_t centreX, int32_t centreY, int32_t radius) { const int32_t diameter = (radius * 2); int32_t x = (radius - 1); int32_t y = 0; int32_t tx = 1; int32_t ty = 1; int32_t error = (tx - diameter); while (x >= y) { // Each of the following renders an octant of the circle SDL_RenderDrawPoint(renderer, centreX + x, centreY - y); SDL_RenderDrawPoint(renderer, centreX + x, centreY + y); SDL_RenderDrawPoint(renderer, centreX - x, centreY - y); SDL_RenderDrawPoint(renderer, centreX - x, centreY + y); SDL_RenderDrawPoint(renderer, centreX + y, centreY - x); SDL_RenderDrawPoint(renderer, centreX + y, centreY + x); SDL_RenderDrawPoint(renderer, centreX - y, centreY - x); SDL_RenderDrawPoint(renderer, centreX - y, centreY + x); if (error <= 0) { ++y; error += ty; ty += 2; } if (error > 0) { --x; tx += 2; error += (tx - diameter); } } } }; #endif //MAIN_TRANSPARENTWINDOW_HPP
main.cpp里就很简单了
#include <stdio.h> #include <SDL.h> #include <SDL_image.h> #include <SDL_syswm.h> #include <iostream> #include <Windows.h> #include <string> #include "TransparentWindow.hpp" int main(int argc, char *args[]) { bool windowActive = true; SDL_Event event; // 创建一个背景透明的窗口 TransparentWindow win; while (windowActive) { while (SDL_PollEvent(&event) != 0) { if (event.type == SDL_QUIT || event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { windowActive = false; } SDL_Log("event.type=%d \n", event.type); } // 绘图 win.draw(); SDL_Delay(1000/60); } return 0; }
运行结果如下,由于是透明的,所以就看到了背后的代码
备忘,项目本地硬盘地址为G:\Xubuntu_Work_Space\From_Xubuntu\codeTest_2019_2_21\SDL2\win\clionWorkspace\study04_window_transparent_01_texture_draw_rect_and_circle