如何统计SDL2中打开窗口的数量?能否获取SDL2现有窗口?
Great question! Unfortunately, SDL2 doesn't provide a public API to directly retrieve a list of all existing windows or get their count out of the box—its internal window-tracking structures are hidden from the public interface. But don't worry, there are reliable workarounds you can implement yourself.
Recommended Workaround: Track Windows Manually
The most stable and future-proof approach is to maintain your own list of windows. You'll update this list every time you create or destroy a window, and handle window close events to keep the list accurate.
Example Implementation (C)
Here's a simple dynamic array-based tracker you can adapt:
#include <SDL2/SDL.h> #include <stdlib.h> #include <string.h> // Global window tracking variables SDL_Window** g_tracked_windows = NULL; int g_window_count = 0; // Create a window and add it to the tracked list SDL_Window* create_and_track_window(const char* title, int x, int y, int w, int h, Uint32 flags) { SDL_Window* window = SDL_CreateWindow(title, x, y, w, h, flags); if (!window) return NULL; // Resize the tracked array to fit the new window SDL_Window** temp = realloc(g_tracked_windows, sizeof(SDL_Window*) * (g_window_count + 1)); if (!temp) { SDL_DestroyWindow(window); return NULL; } g_tracked_windows = temp; g_tracked_windows[g_window_count++] = window; return window; } // Destroy a window and remove it from the tracked list void destroy_and_untrack_window(SDL_Window* window) { if (!window) return; // Find the window's index in the tracked list int target_index = -1; for (int i = 0; i < g_window_count; i++) { if (g_tracked_windows[i] == window) { target_index = i; break; } } if (target_index != -1) { // Shift elements to fill the gap for (int i = target_index; i < g_window_count - 1; i++) { g_tracked_windows[i] = g_tracked_windows[i + 1]; } g_window_count--; // Shrink the array (optional, but reduces memory overhead) SDL_Window** temp = realloc(g_tracked_windows, sizeof(SDL_Window*) * g_window_count); if (temp || g_window_count == 0) { g_tracked_windows = temp; } } SDL_DestroyWindow(window); } // Get the current number of open windows int get_open_window_count() { return g_window_count; } // Get a copy of all tracked windows (remember to free the copy when done!) SDL_Window** get_all_tracked_windows(int* out_count) { if (!out_count) return NULL; *out_count = g_window_count; if (g_window_count == 0) return NULL; SDL_Window** window_copy = malloc(sizeof(SDL_Window*) * g_window_count); if (window_copy) { memcpy(window_copy, g_tracked_windows, sizeof(SDL_Window*) * g_window_count); } return window_copy; }
Key Notes for This Approach:
- Handle Window Close Events: When a user closes a window via the OS (e.g., clicking the X button), SDL sends an
SDL_WINDOWEVENTwithSDL_WINDOWEVENT_CLOSE. You should calldestroy_and_untrack_windowin your event loop to keep the list accurate. - Thread Safety: If you're using multiple threads, add mutex locks around access to the tracked list to avoid race conditions.
- Memory Management: Always free the copy returned by
get_all_tracked_windowswhen you're done with it.
Why Avoid Internal SDL Structures?
You might be tempted to dig into SDL's internal code to access its window-tracking list. While this might work for a specific SDL version, it's not recommended:
- SDL's internal structures are undocumented and subject to change between versions. Code that relies on them will break when you update SDL.
- Directly accessing internal memory violates SDL's API contract and can cause crashes, memory leaks, or undefined behavior.
Summary
Stick to manual tracking—it's the only reliable, cross-platform way to keep tabs on your SDL windows and get an accurate count.
内容的提问来源于stack exchange,提问作者Konrad

