BeginCombo vs Combo in ImGui: Key Differences and When to Use Each

The legacy Combo function is a one-shot helper that automatically creates selectable items, while BeginCombo/EndCombo provides an explicit API for fully custom dropdown content with unlimited flexibility.

Dear ImGui (ocornut/imgui) provides two distinct approaches for creating combo box widgets. Understanding the differences between BeginCombo/EndCombo and the legacy Combo function in ImGui is essential for choosing the right tool based on your UI complexity requirements. While both methods render dropdown controls, they differ fundamentally in API style, customization capabilities, and control granularity.

API Architecture Comparison

Legacy Combo: The Convenience Wrapper

The legacy Combo function acts as a high-level convenience wrapper that internally handles the entire combo lifecycle. Located in imgui.h at lines 664-666, this helper automatically calls BeginCombo, populates the popup with Selectable items based on your input array, and closes with EndCombo. You provide a current_item index pointer, and the function manages preview text generation and state synchronization without exposing the underlying popup construction.

BeginCombo/EndCombo: Explicit Manual Construction

Declared at imgui.h lines 662-663, the BeginCombo/EndCombo pair follows Dear ImGui's explicit "begin/end" pattern. You call BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0) to open the popup, manually populate its contents using any ImGui widgets (not just Selectable), and explicitly close with EndCombo(). This approach requires you to manage the selected value storage and preview string independently, offering complete control over the dropdown's internal layout and behavior.

Key Differences

Content Flexibility

The legacy Combo restricts you to simple text arrays, zero-terminated strings, or getter callbacks that return string pointers. It automatically generates a vertical list of text-only selectable items.

BeginCombo/EndCombo imposes no content restrictions. You can embed images, checkboxes, separators, nested menus, or complex layouts within the popup window. This makes it ideal for icon-based selectors, multi-column dropdowns, or combo boxes containing interactive widgets.

State Management and Preview Control

With the legacy API, the preview displayed in the combo button always corresponds to the text of the currently selected index. The function handles preview_value internally based on your current_item pointer.

Using BeginCombo, you explicitly specify the preview_value parameter on every call, allowing dynamic preview generation independent of the popup contents. For advanced customization, you can pass ImGuiComboFlags_CustomPreview (defined in imgui_internal.h lines 1090-1092) and use BeginComboPreview()/EndComboPreview() to draw arbitrary widgets—such as icons, colors, or formatted text—inside the combo button itself.

Flag Support and Configuration

BeginCombo accepts ImGuiComboFlags for fine-tuned behavior control:

  • ImGuiComboFlags_HeightSmall / ImGuiComboFlags_HeightRegular / ImGuiComboFlags_HeightLarge / ImGuiComboFlags_HeightLargest control popup height
  • ImGuiComboFlags_PopupAlignLeft aligns the popup to the left edge
  • ImGuiComboFlags_CustomPreview enables manual preview rendering

The legacy Combo offers no flag parameter, only a popup_max_height_in_items integer for basic height limiting.

Implementation Details

According to the ocornut/imgui source code, all legacy Combo overloads in imgui.cpp internally reduce to the same pattern:

if (BeginCombo(label, preview_value, flags))
{
    // Generate Selectable items based on array/callback
    EndCombo();
}

This confirms that BeginCombo/EndCombo constitutes the underlying primitive, while Combo is a helper layered on top. The internal combo state tracking occurs through BeginComboDepth and related structures defined in imgui_internal.h.

Code Examples

Legacy Combo (Simplest Implementation)

Use this when you need a standard text list with minimal code:

int current = 0;
const char* items[] = { "Apple", "Banana", "Cherry" };
ImGui::Combo("Fruit", &current, items, IM_ARRAYSIZE(items));

BeginCombo/EndCombo (Full Control)

Use this for custom selection logic or non-standard content:

int current = 0;
const char* items[] = { "Apple", "Banana", "Cherry" };

if (ImGui::BeginCombo("Fruit", items[current]))
{
    for (int i = 0; i < IM_ARRAYSIZE(items); ++i)
    {
        const bool is_selected = (current == i);
        if (ImGui::Selectable(items[i], is_selected))
            current = i;
            
        if (is_selected)
            ImGui::SetItemDefaultFocus();
    }
    ImGui::EndCombo();
}

Custom Preview with Icons

Use this to render images or styled text in the combo button:

int current = 0;
const char* items[] = { "Apple", "Banana", "Cherry" };

if (ImGui::BeginCombo("Fruit", nullptr, ImGuiComboFlags_CustomPreview))
{
    // Draw custom preview in the combo button area
    ImGui::BeginComboPreview();
    ImGui::Image(fruit_icons[current], ImVec2(16, 16));
    ImGui::SameLine();
    ImGui::TextUnformatted(items[current]);
    ImGui::EndComboPreview();

    // Popup contents
    for (int i = 0; i < IM_ARRAYSIZE(items); ++i)
    {
        if (ImGui::Selectable(items[i], current == i))
            current = i;
    }
    ImGui::EndCombo();
}

Summary

  • Legacy Combo provides the fastest implementation for simple text arrays but limits you to standard lists without customization options.
  • BeginCombo/EndCombo requires more code but enables unlimited content flexibility, including images, custom layouts, and interactive widgets inside the dropdown.
  • Custom previews are only possible through BeginCombo using the ImGuiComboFlags_CustomPreview flag and the BeginComboPreview()/EndComboPreview() API.
  • Flag-based configuration (height control, alignment) is exclusive to the BeginCombo API.
  • Both functions ultimately reside in imgui.h and are implemented in imgui.cpp, with the legacy version calling the explicit API internally.

Frequently Asked Questions

Can I use images inside a combo box using the legacy Combo function?

No, the legacy Combo function only supports text-based items through string arrays or callbacks. To display images, icons, or other visual elements inside the dropdown, you must use BeginCombo/EndCombo and render ImGui::Image widgets manually between the begin and end calls.

How do I control the height of the combo popup?

With BeginCombo, pass height flags such as ImGuiComboFlags_HeightSmall, ImGuiComboFlags_HeightLarge, or ImGuiComboFlags_HeightLargest to the flags parameter. The legacy Combo function only supports the popup_max_height_in_items parameter, which specifies height in terms of item count rather than pixel dimensions.

Is there a performance difference between the two approaches?

No significant performance difference exists because the legacy Combo internally calls BeginCombo and constructs identical Selectable items. The overhead of manual iteration in BeginCombo/EndCombo is negligible; choose based on required functionality rather than optimization concerns.

Can I change what appears in the combo button without changing the selected item?

Yes, but only with BeginCombo. By providing a custom preview_value string or using ImGuiComboFlags_CustomPreview with BeginComboPreview(), you can display formatted text, icons, or dynamic content in the collapsed combo button that differs from the popup's selected item text.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →