Managing Window Position

Saving Window Position

How can I save the window's position so it opens in the same place next time?

Abstract art representing computer programming

Saving and restoring window positions is a common requirement for professional applications. Here's how to implement this feature using file I/O:

Basic Position Saving

First, let's create a simple system to save and load window positions:

#include <SDL.h>
#include <fstream>
#include <string>
#include "Window.h"

class PersistentWindow : public Window {
public:
  void SavePosition(
    const std::string& Filename) {
    int X, Y;
    SDL_GetWindowPosition(SDLWindow, &X, &Y);

    std::ofstream File{Filename};
    if (File) { File << X << ' ' << Y; }
  }

  bool LoadPosition(
    const std::string& Filename) {
    std::ifstream File{Filename};
    int X, Y;

    if (File >> X >> Y) {
      SDL_SetWindowPosition(SDLWindow, X, Y);
      return true;
    }

    return false;
  }
};

Complete Implementation with Error Handling

Here's a more robust implementation that handles multiple monitors and screen boundaries:

#include <SDL.h>
#include <filesystem>
#include <fstream>
#include <string>

class PersistentWindow : public Window {
public:
  struct WindowState {
    int X, Y;
    int Width, Height;
    bool IsMaximized;
  };

  void SaveState(const std::string& Filename) {
    WindowState State;

    // Get current state
    SDL_GetWindowPosition(
      SDLWindow, &State.X, &State.Y);
    SDL_GetWindowSize(
      SDLWindow, &State.Width, &State.Height);
    State.IsMaximized = SDL_GetWindowFlags(
      SDLWindow) & SDL_WINDOW_MAXIMIZED;

    // Save to file
    std::ofstream File{
      Filename, std::ios::binary};
    if (File) {
      File.write(
        reinterpret_cast<char*>(&State),
        sizeof(WindowState)
      );
    }
  }

  bool RestoreState(
    const std::string& Filename) {
    // Check if file exists
    if (!std::filesystem::exists(Filename)) {
      return false;
    }

    // Read saved state
    WindowState State;
    std::ifstream File{
      Filename, std::ios::binary};
    if (!File.read(reinterpret_cast<char*>(
                     &State),
                   sizeof(WindowState))) {
      return false;
    }

    // Ensure position is on screen
    if (EnsureOnScreen(State)) {
      // Apply state
      SDL_SetWindowSize(
        SDLWindow, State.Width, State.Height);
      SDL_SetWindowPosition(
        SDLWindow, State.X, State.Y);

      if (State.IsMaximized) {
        SDL_MaximizeWindow(SDLWindow);
      }
      return true;
    }

    return false;
  }

private:
  bool EnsureOnScreen(WindowState& State) {
    SDL_DisplayMode Display;
    if (SDL_GetCurrentDisplayMode(
      0, &Display) != 0) { return false; }

    // Ensure window is at least partially visible
    State.X = std::max(
      -State.Width / 2,
      std::min(
        State.X,
        Display.w - State.Width / 2
      )
    );

    State.Y = std::max(
      0, std::min(State.Y, Display.h - 100));

    return true;
  }
};

Usage Example

Here's how to use the persistent window:

#include <SDL.h>
#include "PersistentWindow.h"

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_VIDEO);
  PersistentWindow Window;

  // Try to restore previous position
  if (!Window.RestoreState("window.dat")) {  
    // If no saved position, start centered
    SDL_SetWindowPosition(
      Window.SDLWindow,
      SDL_WINDOWPOS_CENTERED,
      SDL_WINDOWPOS_CENTERED
    );
  }

  SDL_Event E;
  while (true) {
    while (SDL_PollEvent(&E)) {
      if (E.type == SDL_QUIT) {
        // Save position before exit
        Window.SaveState("window.dat");  
        SDL_Quit();
        return 0;
      }
    }
  }
}

This implementation includes several important features:

  • Saves both position and size information
  • Handles maximized state
  • Ensures the window remains visible on screen
  • Uses binary file I/O for efficient storage
  • Includes error handling for file operations

Remember to consider multi-monitor setups and different screen resolutions when restoring window positions. A position that was valid when saved might not be valid when the application is next launched.

Answers to questions are automatically generated and may not have been reviewed.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 62 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved