You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SDL2中如何实现窗口调整大小时同步调整窗口Surface?

解决SDL2窗口调整时SDL_Surface无法适配尺寸的问题

问题描述

我正在开发一款支持窗口调整的SDL2应用,但窗口尺寸改变时,对应的SDL_Surface并未随之调整。以下是复现问题的最小示例代码:

#include <SDL2/SDL.h>
#include <iostream>

int main(int argc, char **argv) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window *mainWindow = SDL_CreateWindow(
      "Debugging This", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 700,
      400, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
  SDL_Surface *mainWindowSurface = SDL_GetWindowSurface(mainWindow);
  int quit = 0;
  SDL_Event e;
  while (!quit) {
    while (SDL_PollEvent(&e)) {
      switch (e.type) {
        case SDL_QUIT:
          quit = 1;
          break;

        case SDL_WINDOWEVENT:
          if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
            std::cout << "Window dimensions (w/h): " << e.window.data1 << "/"
                      << e.window.data2 << "\n";
            std::cout << "surface dimensions (w/h): " << mainWindowSurface->w
                      << "/" << mainWindowSurface->h << "\n";
          }
          break;
      }
    }
    SDL_FillRect(mainWindowSurface, NULL,
                 SDL_MapRGB(mainWindowSurface->format, 0xFF, 0xFF, 0xFF));
    SDL_UpdateWindowSurface(mainWindow);
  }

  SDL_FreeSurface(mainWindowSurface);
  mainWindowSurface = NULL;

  SDL_DestroyWindow(mainWindow);
  mainWindow = NULL;

  SDL_Quit();

  return 0;
}

运行程序调整窗口时,控制台输出的窗口尺寸正常变化,但Surface的尺寸始终保持初始值。由于需要频繁修改Surface,无法改用渲染器和纹理,请问如何实现窗口调整时Surface自动适配窗口大小?


解决方案

问题核心:窗口尺寸改变后,原有的SDL_Surface会失效,必须重新获取新的窗口Surface。SDL不会自动更新你之前保存的Surface指针,需要在窗口尺寸变化事件中手动更新。

修改后的代码如下:

#include <SDL2/SDL.h>
#include <iostream>

int main(int argc, char **argv) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window *mainWindow = SDL_CreateWindow(
      "Fixed Resize", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 700,
      400, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
  SDL_Surface *mainWindowSurface = SDL_GetWindowSurface(mainWindow);
  int quit = 0;
  SDL_Event e;
  while (!quit) {
    while (SDL_PollEvent(&e)) {
      switch (e.type) {
        case SDL_QUIT:
          quit = 1;
          break;

        case SDL_WINDOWEVENT:
          if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
            // 释放旧的Surface,避免内存泄漏
            SDL_FreeSurface(mainWindowSurface);
            // 重新获取适配新窗口尺寸的Surface
            mainWindowSurface = SDL_GetWindowSurface(mainWindow);
            // 验证新尺寸
            std::cout << "Window dimensions (w/h): " << e.window.data1 << "/"
                      << e.window.data2 << "\n";
            std::cout << "surface dimensions (w/h): " << mainWindowSurface->w
                      << "/" << mainWindowSurface->h << "\n";
          }
          break;
      }
    }
    // 确保Surface有效再执行绘制操作
    if (mainWindowSurface != nullptr) {
      SDL_FillRect(mainWindowSurface, NULL,
                   SDL_MapRGB(mainWindowSurface->format, 0xFF, 0xFF, 0xFF));
      SDL_UpdateWindowSurface(mainWindow);
    }
  }

  SDL_FreeSurface(mainWindowSurface);
  mainWindowSurface = NULL;

  SDL_DestroyWindow(mainWindow);
  mainWindow = NULL;

  SDL_Quit();

  return 0;
}

关键说明

  • Surface失效机制:窗口尺寸改变时,SDL会销毁旧的窗口Surface并创建新的,之前保存的指针会指向无效内存,必须调用SDL_GetWindowSurface重新获取新指针。
  • 内存管理:每次resize时先释放旧Surface,退出时只需释放最后一次获取的Surface即可。
  • 安全检查:添加mainWindowSurface != nullptr判断,避免极端场景下的崩溃。

内容的提问来源于stack exchange,提问作者Stressed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 11:55:31