# How to Serialize and Deserialize UI State Using Dear ImGui's .ini File System

> Learn to serialize and deserialize UI state with Dear ImGui's .ini file system using LoadIniSettingsFromDisk and SaveIniSettingsToDisk for persistent window configurations.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-25

---

**Dear ImGui persists window positions, sizes, and collapsed states to a human-readable .ini file using `LoadIniSettingsFromDisk()`, `SaveIniSettingsToDisk()`, and the extensible `ImGuiSettingsHandler` system.**

Dear ImGui provides a built-in serialization mechanism that captures UI layout state—including window geometry and visibility—into a simple text-based .ini format. Located in the `ocornut/imgui` repository, this system allows you to serialize and deserialize UI state using either automatic file I/O or manual memory buffers. The architecture relies on registered settings handlers that read and write specific data sections, enabling both default window management and custom application persistence.

## Understanding the .ini Serialization Architecture

The serialization pipeline operates through **settings handlers** registered in the global `ImGuiContext`. Each handler implements callbacks for reading and writing specific data types—the built-in window handler manages `[Window][...]` sections, while you can register custom handlers for application-specific data.

When you invoke `ImGui::LoadIniSettingsFromDisk()` or `LoadIniSettingsFromMemory()`, Dear ImGui iterates over all registered handlers and executes their `ReadAllFn` callbacks. Conversely, `SaveIniSettingsToDisk()` and `SaveIniSettingsToMemory()` trigger each handler's `WriteAllFn` to aggregate data into a zero-terminated string or write directly to disk.

According to the source code in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), the implementation follows this flow:

- **`LoadIniSettingsFromDisk`** (line 15759): Opens the specified file, reads its contents into memory, and forwards the buffer to `LoadIniSettingsFromMemory`.
- **`LoadIniSettingsFromMemory`** (line 15772): Parses the ini text line-by-line, dispatching to each handler's `ReadOpenFn` and `ReadLineFn` callbacks.
- **`SaveIniSettingsToDisk`** (line 15848): Generates the complete ini string via `SaveIniSettingsToMemory`, then writes it to the file system.
- **`SaveIniSettingsToMemory`** (line 15865): Clears the internal text buffer, requests each handler to append its data via `WriteAllFn`, and returns the resulting string.

## Loading UI State from Disk and Memory

You can initialize Dear ImGui with previously saved layout data either by letting the framework handle file I/O automatically or by manually feeding it memory buffers from your own storage system.

### Automatic Loading on Startup

By default, Dear ImGui attempts to load settings automatically during the first `ImGui::NewFrame()` call if `io.IniFilename` is set. This is the simplest approach for most applications:

```cpp
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = "my_app_layout.ini";  // Default is "imgui.ini"

// First call to NewFrame() triggers LoadIniSettingsFromDisk()
while (!quit) {
    ImGui::NewFrame();
    // ... UI code ...
    ImGui::Render();
}

```

### Manual Loading from Custom Storage

For applications that manage their own persistence layers (such as user profile databases or encrypted storage), disable automatic file I/O by setting `io.IniFilename` to `nullptr`, then manually invoke the memory-based loader:

```cpp
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = nullptr;  // Disable automatic file operations

// Load from your own storage system
std::string savedState = LoadFromDatabase();
ImGui::LoadIniSettingsFromMemory(savedState.c_str(), savedState.size());

```

## Saving UI State to Disk and Memory

Dear ImGui can persist state changes automatically after a short delay, or you can trigger saves manually to control exactly when and where data gets stored.

### Automatic Saving via io.IniFilename

When `io.IniFilename` is non-NULL, the framework monitors `io.WantSaveIniSettings` and automatically calls `SaveIniSettingsToDisk()` a few seconds after any UI change occurs:

```cpp
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = "app_state.ini";

// Inside your main loop, ImGui handles saving automatically
while (!quit) {
    ImGui::NewFrame();
    // ... UI modifications trigger WantSaveIniSettings ...
    ImGui::Render();
}

```

### Manual Saving to Memory Buffers

To store ini data in custom locations (cloud sync, embedded resources, or databases), check the `WantSaveIniSettings` flag and retrieve the buffer manually:

```cpp
if (io.WantSaveIniSettings) {
    size_t dataSize = 0;
    const char* iniData = ImGui::SaveIniSettingsToMemory(&dataSize);
    
    // Persist to your storage backend
    SaveToDatabase(std::string(iniData, dataSize));
    
    io.WantSaveIniSettings = false;  // Reset flag after handling
}

```

## Implementing Custom Settings Handlers

The `ImGuiSettingsHandler` API allows you to serialize custom application data alongside Dear ImGui's window sections. Register handlers after creating the context but before loading settings.

The handler structure requires three key callbacks: `ReadOpenFn` allocates storage for your data section, `ReadLineFn` parses individual key-value pairs, and `WriteAllFn` serializes your data back to the text buffer:

```cpp
struct MyAppSettings {
    int magicNumber = 42;
    bool showDemo = true;
};

void RegisterCustomHandler() {
    ImGuiSettingsHandler handler;
    handler.TypeName = "MyApp";
    handler.TypeHash = ImHashStr("MyApp");
    
    handler.ReadOpenFn = [](ImGuiContext*, ImGuiSettingsHandler*, const char*) -> void* {
        static MyAppSettings settings;
        return &settings;
    };
    
    handler.ReadLineFn = [](ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) {
        MyAppSettings* s = (MyAppSettings*)entry;
        sscanf(line, "MagicNumber=%d", &s->magicNumber);
        sscanf(line, "ShowDemo=%d", (int*)&s->showDemo);
    };
    
    handler.WriteAllFn = [](ImGuiContext*, ImGuiSettingsHandler* h, ImGuiTextBuffer* buf) {
        MyAppSettings* s = (MyAppSettings*)h->UserData;
        buf->appendf("[MyApp][Main]\n");
        buf->appendf("MagicNumber=%d\n", s->magicNumber);
        buf->appendf("ShowDemo=%d\n", s->showDemo);
    };
    
    ImGui::GetCurrentContext()->SettingsHandlers.push_back(handler);
}

```

Once registered, your `[MyApp]` sections will automatically appear in the generated .ini output and be parsed during loading.

## Summary

- **Dear ImGui** uses a text-based .ini format to persist window positions, sizes, and collapsed states between application sessions.
- **Four core functions** control the process: `LoadIniSettingsFromDisk()`, `LoadIniSettingsFromMemory()`, `SaveIniSettingsToDisk()`, and `SaveIniSettingsToMemory()`, implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) (lines 15759–15865).
- **Automatic I/O** occurs when `io.IniFilename` points to a valid path, triggering loads on the first frame and saves a few seconds after changes.
- **Manual control** requires setting `io.IniFilename` to `nullptr` and using the memory-based APIs to integrate with custom storage backends.
- **Custom data** persists via the `ImGuiSettingsHandler` structure, which provides callbacks for reading and writing application-specific sections within the same .ini file.

## Frequently Asked Questions

### Where does Dear ImGui store window positions by default?

By default, Dear ImGui creates an [`imgui.ini`](https://github.com/ocornut/imgui/blob/main/imgui.ini) file in the current working directory. You can inspect or modify this path via `ImGuiIO::IniFilename` before the first `NewFrame()` call, as defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) (lines 1136–1139).

### How do I prevent automatic .ini file creation?

Set `io.IniFilename = nullptr` immediately after creating the context. This disables both automatic loading and saving, allowing you to manage persistence manually using `LoadIniSettingsFromMemory()` and `SaveIniSettingsToMemory()`.

### Can I store custom application data in the ImGui .ini file?

Yes. Register an `ImGuiSettingsHandler` with `TypeName`, `ReadOpenFn`, `ReadLineFn`, and `WriteAllFn` callbacks. Your handler will receive read calls during `LoadIniSettingsFromMemory()` and write calls during `SaveIniSettingsToMemory()`, letting you serialize arbitrary data alongside window state.

### When should I call LoadIniSettingsFromMemory?

Call it after `ImGui::CreateContext()` but before the first `ImGui::NewFrame()`. Loading after the first frame may result in default window positions being applied before your saved state overrides them.