Using the Dear ImGui Multi-Select API for List Selection Patterns
The Dear ImGui multi-select API provides BeginMultiSelect() and EndMultiSelect() functions that handle complex selection bookkeeping—including Ctrl-click toggles, shift-range selection, and box-select—without requiring manual state management.
Dear ImGui (ocornut/imgui) includes a dedicated multi-select API designed specifically for implementing robust list-selection patterns in graphical user interfaces. This API eliminates boilerplate code by automatically handling keyboard modifiers, range selections, and selection visuals through scope-based functions declared in imgui.h and imgui_internal.h.
Core Architecture of the Multi-Select API
The multi-select system centers on the ImGuiMultiSelectIO structure, which acts as the communication bridge between Dear ImGui and your application code.
ImGuiMultiSelectIO and State Management
The ImGuiMultiSelectIO struct, defined in [imgui.h at line 3076](https://github.com/ocornut/imgui/blob/master/imgui.h#L3076), stores the current selection state and pending selection requests. When you call BeginMultiSelect(), Dear ImGui creates a temporary ImGuiMultiSelectTempData object (stored in g.MultiSelectTempData) and returns a pointer to the IO struct that you use for the duration of the frame.
BeginMultiSelect and EndMultiSelect
BeginMultiSelect(flags, selection_size, items_count), declared in [imgui.h at line 776](https://github.com/ocornut/imgui/blob/master/imgui.h#L776), initializes the multi-select scope and prepares the internal state. You must pair this with EndMultiSelect() ([imgui.h line 777](https://github.com/ocornut/imgui/blob/master/imgui.h#L777)), which flushes pending requests (such as SetAll or SetRange) and applies changes to your selection storage.
Selection State Detection
The IsItemToggledSelection() function, documented in [imgui_widgets.cpp at line 7539](https://github.com/ocornut/imgui/blob/master/imgui_widgets.cpp#L7539), detects whether the user changed an item's selection state during the current frame. Call this immediately after Selectable() or TreeNode() to react to selection changes.
Configuration Flags for Selection Behavior
Configure the multi-select behavior by passing ImGuiMultiSelectFlags to BeginMultiSelect(). The flag definitions reside in [imgui.h around line 3044](https://github.com/ocornut/imgui/blob/master/imgui.h#L3044).
Key flags include:
- SingleSelect: Restricts selection to exactly one item at a time.
- NoSelectAll: Disables the Ctrl+A keyboard shortcut for selecting all items.
- BoxSelect1d and BoxSelect2d: Enable rectangular box selection for 1D lists or 2D grids.
- ClearOnEscape: Automatically clears the entire selection when the user presses Escape.
Implementing List Selection Patterns
Basic List Selection with Ctrl and Shift Support
To implement standard list selection, wrap your item loop with the multi-select scope and use SetNextItemSelectionUserData() to associate each item with an identifier:
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_BoxSelect2d |
ImGuiMultiSelectFlags_ClearOnEscape;
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, items.size());
for (int i = 0; i < items.size(); ++i) {
ImGui::SetNextItemSelectionUserData(i); // imgui.h line 282
bool selected = ms_io->Selection.Contains(i);
if (ImGui::Selectable(items[i].label, selected)) {
// Click handling is managed automatically by the API
}
if (ImGui::IsItemToggledSelection()) {
bool now_selected = ImGui::IsItemSelected();
// Update your data model here
}
}
ImGui::EndMultiSelect();
Optimized Large Lists with ImGuiListClipper
For large datasets, combine multi-select with ImGuiListClipper as demonstrated in [imgui_demo.cpp lines 2868-2875](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp#L2868):
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, item_count);
ImGuiListClipper clipper(item_count);
while (clipper.Step()) {
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; ++i) {
ImGui::SetNextItemSelectionUserData(i);
bool selected = ms_io->Selection.Contains(i);
ImGui::Selectable(item_labels[i], selected);
if (ImGui::IsItemToggledSelection()) {
UpdateSelectionModel(i, ImGui::IsItemSelected());
}
}
}
ImGui::EndMultiSelect();
Processing Selection Requests Manually
If your application uses custom storage backends, process raw selection requests directly using ApplyRequests(), declared in [imgui.h at line 3139](https://github.com/ocornut/imgui/blob/master/imgui.h#L3139):
ImGui::ApplyRequests(ms_io);
// Iterate through ms_io->IO.Requests to handle ImGuiSelectionRequest types:
// - SetAll: Clear or select all items
// - SetRange: Select a contiguous range (used for shift-selection)
Internal Implementation Details
When BeginMultiSelect() executes, Dear ImGui allocates temporary storage in g.MultiSelectTempData and links it to persistent state in g.MultiSelectStorage. Each Selectable() automatically checks for the ImGuiItemFlags_IsMultiSelect flag (set by the API) in [imgui_widgets.cpp at line 8003](https://github.com/ocornut/imgui/blob/master/imgui_widgets.cpp#L8003), forwarding interaction events to the multi-select logic.
The internal helpers MultiSelectItemHeader and MultiSelectItemFooter, declared in [imgui_internal.h around line 3680](https://github.com/ocornut/imgui/blob/master/imgui_internal.h#L3680), render selection visuals and inject the appropriate item flags automatically.
Summary
- Scope-based API: Wrap list items with
BeginMultiSelect()andEndMultiSelect()to activate multi-select behavior. - Automatic bookkeeping: The API handles Ctrl-click toggling, shift-range selection, and box-select without manual state tracking.
- User data association: Use
SetNextItemSelectionUserData()to identify items for range and box selection operations. - Change detection: Call
IsItemToggledSelection()after item widgets to detect selection changes and update your data model. - Performance optimization: Combine with
ImGuiListClipperfor efficient handling of large datasets, following the patterns inimgui_demo.cpplines 2716-3057.
Frequently Asked Questions
How do I enable box selection in my Dear ImGui list?
Pass the ImGuiMultiSelectFlags_BoxSelect2d flag to BeginMultiSelect() for two-dimensional selection, or ImGuiMultiSelectFlags_BoxSelect1d for one-dimensional lists. These flags allow users to click and drag a rectangle to select multiple items automatically without additional code.
What is the difference between IsItemToggledSelection and IsItemSelected?
IsItemToggledSelection() returns true only during the frame when the user actually changed the item's selection state, making it ideal for triggering data model updates. IsItemSelected() merely reports the current selection state and can be called anytime to query whether an item is currently selected.
How do I handle selection in a list with millions of items?
Use ImGuiListClipper to render only visible items, as shown in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp). Call SetNextItemSelectionUserData() with the actual item index (not the visible index) so that range selections work correctly across the entire dataset, not just the visible portion.
Where can I find complete working examples of the multi-select API?
The Dear ImGui repository contains comprehensive demonstrations in [imgui_demo.cpp lines 2716-3057](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp#L2716), including examples of basic lists, clipped large lists, and dynamic item deletion scenarios.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →