Skip to main content

Windows Fundamentals

In Dear ImGui, windows are the primary containers for UI elements. Every piece of UI must be inside a window.

Begin() and End()

The most important functions are Begin() and End():
ImGui::Begin("My Window");
// Your UI code here
ImGui::Text("Hello, World!");
ImGui::Button("Click Me");
ImGui::End();
Critical Rule: Always call End() to match every Begin() call, even if Begin() returns false!
if (ImGui::Begin("My Window"))
{
    // Window is visible and not collapsed
    ImGui::Text("Content");
}
ImGui::End(); // MUST call End() regardless of return value

Window Flags

You can customize window behavior with flags:
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar 
                       | ImGuiWindowFlags_NoResize
                       | ImGuiWindowFlags_NoMove;
                       
ImGui::Begin("Custom Window", nullptr, flags);
ImGui::Text("This window can't be moved or resized");
ImGui::End();
Common window flags:
FlagDescription
ImGuiWindowFlags_NoTitleBarDisable title bar
ImGuiWindowFlags_NoResizeDisable resizing
ImGuiWindowFlags_NoMoveDisable moving
ImGuiWindowFlags_NoCollapseDisable collapsing
ImGuiWindowFlags_NoScrollbarDisable scrollbars
ImGuiWindowFlags_MenuBarEnable menu bar
ImGuiWindowFlags_AlwaysAutoResizeAuto-resize to contents
ImGuiWindowFlags_NoBackgroundTransparent background

Closable Windows

Pass a bool* to create a window with a close button:
bool show_window = true;

if (show_window)
{
    ImGui::Begin("Closable Window", &show_window);
    ImGui::Text("Click [X] to close this window");
    ImGui::End();
}

// show_window becomes false when user clicks [X]

Window States and Properties

Checking Window State

if (ImGui::Begin("My Window"))
{
    // Window is expanded (not collapsed)
    bool is_focused = ImGui::IsWindowFocused();
    bool is_hovered = ImGui::IsWindowHovered();
    
    ImVec2 pos = ImGui::GetWindowPos();
    ImVec2 size = ImGui::GetWindowSize();
    
    ImGui::Text("Window at (%.0f, %.0f)", pos.x, pos.y);
    ImGui::Text("Window size: %.0fx%.0f", size.x, size.y);
}
ImGui::End();
Begin() returns false when the window is collapsed. This allows you to skip expensive UI code when the window isn’t visible.

Window Appearance States

if (ImGui::Begin("Status Window"))
{
    if (ImGui::IsWindowAppearing())
        LogMessage("Window just appeared");
    
    if (ImGui::IsWindowCollapsed())
        LogMessage("Window is collapsed");
}
ImGui::End();

Controlling Windows

Setting Window Position and Size

Prefer using SetNextWindow* functions before Begin() rather than SetWindow* functions after Begin().
// Set properties for the next Begin() call
ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);

ImGui::Begin("Positioned Window");
// ...
ImGui::End();

Window Conditions

Use ImGuiCond to control when to apply settings:
// Only on first use
ImGui::SetNextWindowPos(pos, ImGuiCond_FirstUseEver);

// Always
ImGui::SetNextWindowPos(pos, ImGuiCond_Always);

// Only when window appears
ImGui::SetNextWindowPos(pos, ImGuiCond_Appearing);

// Once per runtime session
ImGui::SetNextWindowPos(pos, ImGuiCond_Once);

Focusing Windows

// Make next window focused
ImGui::SetNextWindowFocus();
ImGui::Begin("Focused Window");
// ...
ImGui::End();

// Or focus a specific window by name
ImGui::SetWindowFocus("Other Window");

Child Windows

Child windows create scrollable regions within parent windows:
ImGui::Begin("Parent Window");

// Create a scrollable child region
ImGui::BeginChild("ScrollableRegion", ImVec2(0, 300), ImGuiChildFlags_Borders);

for (int i = 0; i < 100; i++)
    ImGui::Text("Line %d", i);

ImGui::EndChild();

// More content in parent window
ImGui::Button("Button outside child");

ImGui::End();

Child Window Sizing

// Fill remaining space (height)
ImGui::BeginChild("Child", ImVec2(0, 0));

// Fixed size
ImGui::BeginChild("Child", ImVec2(200, 300));

// Use remaining width, fixed height
ImGui::BeginChild("Child", ImVec2(0, 300));

// Negative values: align to right/bottom edge
ImGui::BeginChild("Child", ImVec2(-100, -50)); // Leave 100px right, 50px bottom

Child Window Flags

ImGuiChildFlags flags = ImGuiChildFlags_Borders       // Draw border
                      | ImGuiChildFlags_AutoResizeX   // Auto-resize width
                      | ImGuiChildFlags_AutoResizeY;  // Auto-resize height

ImGui::BeginChild("Child", ImVec2(0, 0), flags);
// ...
ImGui::EndChild();

Layout System

Dear ImGui uses a simple top-to-bottom, left-to-right automatic layout system.

Vertical Layout (Default)

ImGui::Begin("Vertical Layout");

// Widgets stack vertically by default
ImGui::Text("First line");
ImGui::Button("Button 1");
ImGui::Button("Button 2");
ImGui::Text("Last line");

ImGui::End();

Horizontal Layout

Use SameLine() to place widgets horizontally:
ImGui::Begin("Horizontal Layout");

ImGui::Button("Button 1");
ImGui::SameLine();
ImGui::Button("Button 2");
ImGui::SameLine();
ImGui::Button("Button 3");

// Back to vertical
ImGui::Text("Next line");

ImGui::End();

SameLine with Spacing

// Default spacing
ImGui::Button("A");
ImGui::SameLine();
ImGui::Button("B");

// Custom spacing (offset from left edge)
ImGui::Button("C");
ImGui::SameLine(200.0f); // 200 pixels from left
ImGui::Button("D");

// Custom spacing (additional offset)
ImGui::Button("E");
ImGui::SameLine(0, 20.0f); // 20 pixels extra spacing
ImGui::Button("F");

Spacing and Separators

ImGui::Text("Section 1");
ImGui::Spacing();        // Add vertical space
ImGui::Text("Section 2");
ImGui::Separator();      // Add horizontal line
ImGui::Text("Section 3");

Cursor Position

The “cursor” is the position where the next widget will be placed.

Getting Cursor Position

// Position relative to window
ImVec2 pos = ImGui::GetCursorPos();

// Position in screen coordinates
ImVec2 screen_pos = ImGui::GetCursorScreenPos();

// Start position of window contents
ImVec2 start_pos = ImGui::GetCursorStartPos();

Setting Cursor Position

ImGui::Begin("Cursor Demo");

// Move cursor 100 pixels down
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x, cursor.y + 100));
ImGui::Text("This is 100px down");

// Or use helper functions
ImGui::SetCursorPosX(50.0f);   // Set X only
ImGui::SetCursorPosY(200.0f);  // Set Y only

ImGui::End();
Using SetCursorPos() without placing an item won’t extend parent boundaries! Add Dummy(ImVec2(0,0)) to validate the position:
ImGui::SetCursorPos(ImVec2(200, 200));
ImGui::Dummy(ImVec2(0, 0));  // Validate position
ImGui::Text("At 200, 200");

Dummy Widgets

Use Dummy() to reserve space:
// Reserve 200x100 pixels of space
ImGui::Dummy(ImVec2(200, 100));

// Reserve vertical space
ImGui::Dummy(ImVec2(0, 50));

Groups

Groups allow you to treat multiple widgets as a single item:
ImGui::BeginGroup();
ImGui::Button("Button 1");
ImGui::Button("Button 2");
ImGui::Button("Button 3");
ImGui::EndGroup();

// Place something to the right of the entire group
ImGui::SameLine();
ImGui::Text("This is next to the group");

// You can also check if the group is hovered
if (ImGui::IsItemHovered())
    ImGui::SetTooltip("Hovering the group");

Indentation

ImGui::Text("Not indented");

ImGui::Indent();
ImGui::Text("Indented once");

ImGui::Indent();
ImGui::Text("Indented twice");

ImGui::Unindent();
ImGui::Text("Indented once");

ImGui::Unindent();
ImGui::Text("Not indented");

// Custom indent amount
ImGui::Indent(40.0f);
ImGui::Text("Custom indent");
ImGui::Unindent(40.0f);

Content Region

Get available space for laying out widgets:
// Available space in current window
ImVec2 avail = ImGui::GetContentRegionAvail();

// Use it to size a widget
ImGui::Button("Full Width", ImVec2(avail.x, 0));

// Half width buttons
float button_width = avail.x * 0.5f - ImGui::GetStyle().ItemSpacing.x * 0.5f;
ImGui::Button("Left", ImVec2(button_width, 0));
ImGui::SameLine();
ImGui::Button("Right", ImVec2(button_width, 0));

Columns

Columns are a legacy API. For new code, prefer using Tables which are more powerful.
ImGui::Columns(3, "MyColumns");
ImGui::Separator();

ImGui::Text("Column 1");
ImGui::NextColumn();

ImGui::Text("Column 2");
ImGui::NextColumn();

ImGui::Text("Column 3");
ImGui::NextColumn();

ImGui::Separator();
ImGui::Columns(1); // End columns

Scrolling

Manual Scrolling

// Get scroll position
float scroll_x = ImGui::GetScrollX();
float scroll_y = ImGui::GetScrollY();

// Set scroll position
ImGui::SetScrollX(100.0f);
ImGui::SetScrollY(200.0f);

// Get maximum scroll values
float max_scroll_x = ImGui::GetScrollMaxX();
float max_scroll_y = ImGui::GetScrollMaxY();

Scrolling to Items

ImGui::BeginChild("Scrolling Region", ImVec2(0, 300));

for (int i = 0; i < 100; i++)
{
    ImGui::Text("Item %d", i);
    
    // Scroll to item 50 when button clicked
    if (i == 50 && scroll_to_item)
    {
        ImGui::SetScrollHereY(0.5f); // 0.5f = center in window
        scroll_to_item = false;
    }
}

ImGui::EndChild();

if (ImGui::Button("Scroll to Item 50"))
    scroll_to_item = true;
Windows can have menu bars:
ImGui::Begin("My Window", nullptr, ImGuiWindowFlags_MenuBar);

if (ImGui::BeginMenuBar())
{
    if (ImGui::BeginMenu("File"))
    {
        if (ImGui::MenuItem("Open", "Ctrl+O")) { OpenFile(); }
        if (ImGui::MenuItem("Save", "Ctrl+S")) { SaveFile(); }
        ImGui::Separator();
        if (ImGui::MenuItem("Exit")) { exit(0); }
        ImGui::EndMenu();
    }
    
    if (ImGui::BeginMenu("Edit"))
    {
        if (ImGui::MenuItem("Undo", "Ctrl+Z")) { Undo(); }
        if (ImGui::MenuItem("Redo", "Ctrl+Y")) { Redo(); }
        ImGui::EndMenu();
    }
    
    ImGui::EndMenuBar();
}

ImGui::Text("Window content");
ImGui::End();

Advanced Layout Patterns

Split Layouts

ImGui::Begin("Split Layout");

ImVec2 avail = ImGui::GetContentRegionAvail();

// Left panel
ImGui::BeginChild("LeftPanel", ImVec2(avail.x * 0.3f, 0), ImGuiChildFlags_Borders);
ImGui::Text("Left Panel");
ImGui::EndChild();

ImGui::SameLine();

// Right panel
ImGui::BeginChild("RightPanel", ImVec2(0, 0), ImGuiChildFlags_Borders);
ImGui::Text("Right Panel");
ImGui::EndChild();

ImGui::End();
ImGui::Begin("Footer Example");

// Content with scrolling
ImGuiStyle& style = ImGui::GetStyle();
float footer_height = style.ItemSpacing.y 
                    + style.SeparatorSize 
                    + ImGui::GetFrameHeightWithSpacing();

ImGui::BeginChild("Content", ImVec2(0, -footer_height));
for (int i = 0; i < 100; i++)
    ImGui::Text("Line %d", i);
ImGui::EndChild();

// Fixed footer at bottom
ImGui::Separator();
if (ImGui::Button("Save")) { Save(); }
ImGui::SameLine();
if (ImGui::Button("Cancel")) { Cancel(); }

ImGui::End();

Aligned Buttons

// Right-aligned button
float button_width = 100.0f;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() 
    + ImGui::GetContentRegionAvail().x 
    - button_width);
ImGui::Button("Right", ImVec2(button_width, 0));

// Center-aligned button
ImGui::SetCursorPosX((ImGui::GetContentRegionAvail().x 
    - button_width) * 0.5f);
ImGui::Button("Center", ImVec2(button_width, 0));

Next Steps

Build docs developers (and LLMs) love