
#define WINDOW_COUNT 3
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* windows[WINDOW_COUNT];
SDL_Renderer* renderers[WINDOW_COUNT];
const char* titles[WINDOW_COUNT] = {"First Window", "Second Window", "Third Window"};
We can fill the arrays with a loop, we can the same functions as before.
// Create multiple windows and their renderers
for (int i = 0; i < WINDOW_COUNT; i++) {
windows[i] = SDL_CreateWindow(titles[i], 320, 240, SDL_WINDOW_RESIZABLE);
if (!windows[i]) {
SDL_Log("Failed to create window %d: %s", i, SDL_GetError());
return 1;
}
renderers[i] = SDL_CreateRenderer(windows[i], NULL);
if (!renderers[i]) {
SDL_Log("Failed to create renderer %d: %s", i, SDL_GetError());
return 1;
}
}
Here are all the code for the main loop.
The event loop is common for the three windows we will see next how to have separate event loops.
To catch the event for the other windows we use the event type SDL_EVENT_WINDOW_CLOSE_REQUESTED.
while (SDL_PollEvent(&e)) {
if (e.type == SDL_EVENT_QUIT) {
running = false;
}
if (e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
running = false;
}
}
We draw a rectangle in each window to have something.
// Render each window with different color
for (int i = 0; i < WINDOW_COUNT; i++) {
SDL_SetRenderDrawColor(renderers[i], 100 * i, 100, 255 - 100 * i, 255);
SDL_RenderClear(renderers[i]);
// Draw something simple
SDL_SetRenderDrawColor(renderers[i], 255, 255, 255, 255);
SDL_FRect rect = {60, 50, 200, 100};
SDL_RenderFillRect(renderers[i], &rect);
SDL_RenderPresent(renderers[i]);
}
Don't forget to destroy the windows after exiting the main loop
for (int i = 0; i < WINDOW_COUNT; i++) {
SDL_DestroyRenderer(renderers[i]);
SDL_DestroyWindow(windows[i]);
}
We will use the windows id to identify each windows, to stores them we will use a struct:
typedef struct {
SDL_Window* window;
SDL_Renderer* renderer;
Uint32 windowID;
SDL_Color bgColor;
} AppWindow;
Same thing we create a window and a renderer, we also get the id with SDL_GetWindowID.
AppWindow windows[WINDOW_COUNT];
// Initialize each window
for (int i = 0; i < WINDOW_COUNT; i++) {
char title[32];
snprintf(title, sizeof(title), "Window %d", i + 1);
windows[i].window = SDL_CreateWindow(title, 320, 240, SDL_WINDOW_RESIZABLE);
if (!windows[i].window) {
SDL_Log("Failed to create window: %s", SDL_GetError());
return 1;
}
windows[i].renderer = SDL_CreateRenderer(windows[i].window, NULL);
if (!windows[i].renderer) {
SDL_Log("Failed to create renderer: %s", SDL_GetError());
return 1;
}
windows[i].windowID = SDL_GetWindowID(windows[i].window);
windows[i].bgColor = (SDL_Color){(Uint8)(100 * i), 100, (Uint8)(255 - 100 * i), 255};
}
In reality we are polling the event only one time, but we use the window id to differentiate the events.
To test everything is working well, we display a message when the mouse is moving.
while (SDL_PollEvent(&e)) {
if (e.type == SDL_EVENT_QUIT) {
running = false;
}
// Per-window event handling
if (e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
for (int i = 0; i < WINDOW_COUNT; i++) {
if (e.window.windowID == windows[i].windowID) {
SDL_Log("Close requested for window %d", i + 1);
running = false;
}
}
}
if (e.type == SDL_EVENT_MOUSE_MOTION) {
for (int i = 0; i < WINDOW_COUNT; i++) {
if (e.motion.windowID == windows[i].windowID) {
SDL_Log("Mouse moved in window %d: x=%d y=%d", i + 1, e.motion.x, e.motion.y);
}
}
}
}
Don't forget to render everything like before.
for (int i = 0; i < WINDOW_COUNT; i++) {
SDL_SetRenderDrawColor(windows[i].renderer,
windows[i].bgColor.r,
windows[i].bgColor.g,
windows[i].bgColor.b,
255);
SDL_RenderClear(windows[i].renderer);
SDL_SetRenderDrawColor(windows[i].renderer, 255, 255, 255, 255);
SDL_FRect rect = {60, 50, 200, 100};
SDL_RenderFillRect(windows[i].renderer, &rect);
SDL_RenderPresent(windows[i].renderer);
}
Need another OS ? => Windows, Mac, Linux