zoukankan      html  css  js  c++  java
  • SDL2笔记05_SDL2透明背景窗口_windows10_使用sdl_texture绘图

    1. 本节课学习使用SDL2封装一个透明背景的window,并在window上使用SDL_Renderer和SDL_Texture进行绘图
      1. 圆形没有反走样
      2. 计算机几何算法B站有个孔令德老师讲课挺好的,建议看看
        (我只看了两节课,后面工作不忙了再认真看,图论与网络流还没开始看,把SDL和GTK大致学一下再去看把,档期可能要排到明年才能开始看了)

    1. 在windows上要想让SDL_Window和linux不太一样(linux可以直接读取css设置)

      1. 经过多次google终于在这个网址找到了做法http://5.9.10.113/67609916/fully-transparent-window-with-opaque-elements-in-sdl-2链接

      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
        ", 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
        ", 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
        ", 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
        ", 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
        ", 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
        ", 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;
              }
        

      3. 观察到应该是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);
         }
        
    2. 封装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
      ", 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
      ", 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
      
    3. 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    
      ", event.type);
               }
               // 绘图
               win.draw();
               SDL_Delay(1000/60);
           }
      
           return 0;
       }
      
    4. 运行结果如下,由于是透明的,所以就看到了背后的代码

    5. 备忘,项目本地硬盘地址为G:Xubuntu_Work_SpaceFrom_XubuntucodeTest_2019_2_21SDL2winclionWorkspacestudy04_window_transparent_01_texture_draw_rect_and_circle

  • 相关阅读:
    自我介绍 Self Introduction
    HDU1864 最大报销额
    HDU2955 Robberies
    Sicily 1509. Rails
    Sicily 1031. Campus
    Sicily 1090. Highways
    Sicily 1034. Forest
    Sicily 1800. Sequence
    Sicily 1150. 简单魔板
    CodeVS4919 线段树练习4
  • 原文地址:https://www.cnblogs.com/majiao61/p/15172624.html
Copyright © 2011-2022 走看看