# Using Input Text Callbacks for Validation and Custom Processing in Dear ImGui

> Master Dear ImGui input text callbacks for real-time validation and custom processing. Intercept, filter, and transform user input effectively using ImGuiInputTextCallbackData.

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

---

**Dear ImGui’s input text callbacks allow you to intercept, filter, and transform user input in real-time by implementing a custom function that receives an `ImGuiInputTextCallbackData` structure and returns `0` to accept changes or a non-zero value to reject them.**

The `ocornut/imgui` repository provides a sophisticated callback mechanism for the `InputText()` widget that enables immediate validation and custom processing without requiring post-validation loops. By specifying flags when calling `ImGui::InputText()`, you can register a callback function that inspects and manipulates buffer contents during specific lifecycle events, keeping UI logic tight and performant.

## How Input Text Callbacks Work in Dear ImGui

The callback system centers on two core declarations in **[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)** (around line 2658): the `ImGuiInputTextCallback` function pointer type and the `ImGuiInputTextCallbackData` structure. When you invoke `ImGui::InputText()` with specific flags, Dear ImGui dispatches events to your callback function, passing a mutable pointer to an `ImGuiInputTextCallbackData` instance containing the current buffer state and event context.

Your callback must **return 0** to indicate success, or a **negative value** to abort the input operation entirely. For character filtering specifically, returning any **non-zero value** discards the candidate character.

### Callback Flags and Event Types

You combine the following flags to determine when your callback executes:

- **`ImGuiInputTextFlags_CallbackCharFilter`** – Invoked for each typed character before it enters the buffer. Return non-zero to reject the character or replace `EventChar` to substitute it.
- **`ImGuiInputTextFlags_CallbackResize`** – Triggered when text exceeds the current buffer capacity, allowing dynamic reallocation.
- **`ImGuiInputTextFlags_CallbackEdit`** – Called after any insertion, deletion, or paste operation completes. Ideal for validation or formatting transformations.
- **`ImGuiInputTextFlags_CallbackAlways`** – Executed on every frame the widget remains active, regardless of whether editing occurred.

### The ImGuiInputTextCallbackData Structure

The data structure passed to your callback provides comprehensive context for manipulation:

| Member | Purpose |
|--------|---------|
| `Buf` | Pointer to the mutable text buffer (including the terminating `\0`). |
| `BufTextLen` | Current length of the text in bytes, excluding the null terminator. |
| `BufSize` | Total allocated capacity of the buffer. |
| `Flags` | The `ImGuiInputTextFlags` originally passed to `InputText()`. |
| `EventFlag` | Specific flag indicating why the callback was triggered (`CallbackCharFilter`, `CallbackEdit`, etc.). |
| `EventChar` | The character code for `CallbackCharFilter` events. |
| `EventKey` | The key index for keyboard-related events. |
| `DeleteChars()`, `InsertChars()` | Helper functions to modify buffer contents programmatically during `CallbackEdit`. |

## Practical Code Examples for Input Validation

### Filtering Numeric Input with CallbackCharFilter

To restrict input to digits only, inspect `EventChar` during `CallbackCharFilter` events and return `1` to reject non-numeric characters:

```cpp
int MyNumericCallback(ImGuiInputTextCallbackData* data)
{
    if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter)
    {
        if (!isdigit((unsigned char)data->EventChar))
            return 1;  // Discard non-digit characters
    }
    return 0;
}

// Usage
static char buf[64] = "";
ImGui::InputText("##num", buf, IM_ARRAYSIZE(buf),
                 ImGuiInputTextFlags_CallbackCharFilter,
                 MyNumericCallback);

```

### Automatic Text Transformation with CallbackEdit

Use the edit callback to enforce formatting rules, such as converting all text to uppercase after each modification:

```cpp
int UppercaseCallback(ImGuiInputTextCallbackData* data)
{
    if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit)
    {
        for (int i = 0; i < data->BufTextLen; ++i)
            data->Buf[i] = (char)toupper((unsigned char)data->Buf[i]);
    }
    return 0;
}

// Usage
static char name[128] = "";
ImGui::InputText("##name", name, IM_ARRAYSIZE(name),
                 ImGuiInputTextFlags_CallbackEdit,
                 UppercaseCallback);

```

### Dynamic Buffer Resizing with CallbackResize

For inputs with unknown maximum length, implement a resize callback to reallocate memory when the user exceeds the current buffer capacity:

```cpp
int ResizeCallback(ImGuiInputTextCallbackData* data)
{
    if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
    {
        size_t new_size = data->BufSize;
        char* new_buf = (char*)malloc(new_size);
        memcpy(new_buf, data->Buf, data->BufTextLen);
        new_buf[data->BufTextLen] = '\0';
        data->Buf = new_buf;  // ImGui adopts this new pointer
    }
    return 0;
}

// Usage with heap-allocated buffer
char* dynamic_buf = (char*)malloc(128);
dynamic_buf[0] = '\0';
ImGui::InputTextMultiline("##dyn", dynamic_buf, 128,
                          ImVec2(0,0),
                          ImGuiInputTextFlags_CallbackResize,
                          ResizeCallback);

```

### Complex Validation: Character Filtering and Length Constraints

Combine multiple validation rules within a single callback to enforce both content type and length restrictions:

```cpp
int NumericAndLengthCallback(ImGuiInputTextCallbackData* data)
{
    if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter)
    {
        if (!isdigit((unsigned char)data->EventChar))
            return 1;  // Reject non-digits
        if (data->BufTextLen >= 5)
            return 1;  // Enforce maximum length of 5 characters
    }
    return 0;
}

// Usage
static char pin[8] = "";
ImGui::InputText("##pin", pin, IM_ARRAYSIZE(pin),
                 ImGuiInputTextFlags_CharsDecimal |
                 ImGuiInputTextFlags_CallbackCharFilter,
                 NumericAndLengthCallback);

```

## Core Implementation Files

Understanding where these mechanisms reside helps when debugging or extending functionality:

- **[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)** – Declares `ImGuiInputTextCallback`, `ImGuiInputTextCallbackData`, and all related flags.
- **[`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp)** – Contains the `InputText()` widget implementation and the dispatch logic that invokes your callbacks based on the active `EventFlag`.
- **[`misc/cpp/imgui_stdlib.cpp`](https://github.com/ocornut/imgui/blob/main/misc/cpp/imgui_stdlib.cpp)** – Provides `std::string` overloads that handle `CallbackResize` automatically, eliminating the need for manual memory management when using C++ strings.

## Summary

- **Input text callbacks** in Dear ImGui provide real-time interception of user input through the `ImGuiInputTextCallback` function pointer and `ImGuiInputTextCallbackData` structure.
- **Four distinct flags** control callback timing: `CallbackCharFilter` for per-character filtering, `CallbackEdit` for post-modification processing, `CallbackResize` for dynamic memory management, and `CallbackAlways` for per-frame updates.
- **Return values** determine flow: return `0` to proceed, non-zero for `CallbackCharFilter` to discard characters, or negative values to abort the widget entirely.
- **Buffer manipulation** occurs through direct pointer access (`Buf`) or helper methods (`InsertChars`, `DeleteChars`) within [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)’s callback data structure.

## Frequently Asked Questions

### How do I reject specific characters in `ImGui::InputText`?

Implement a `CallbackCharFilter` callback and inspect the `EventChar` member of the `ImGuiInputTextCallbackData` structure. Return any non-zero value (typically `1`) to discard the character, or modify `EventChar` to substitute a different character before it enters the buffer.

### Can I use `std::string` with input text callbacks instead of raw char buffers?

Yes. Include [`misc/cpp/imgui_stdlib.h`](https://github.com/ocornut/imgui/blob/main/misc/cpp/imgui_stdlib.h) and use the `InputText` overloads that accept `std::string` references. These implementations automatically handle the `CallbackResize` event by resizing the underlying string, eliminating the need for manual memory management in your callback code.

### What is the difference between `CallbackEdit` and `CallbackAlways`?

`CallbackEdit` fires only after the buffer content actually changes due to insertion, deletion, or paste operations, making it efficient for validation and formatting. `CallbackAlways` executes on every frame while the widget is active, regardless of whether editing occurred, which is useful for implementing time-dependent features or continuous validation checks.

### How do I enforce a maximum input length when using callbacks?

Check the `BufTextLen` member during `CallbackCharFilter` events and return non-zero if the current length already meets your limit. This prevents additional characters from entering the buffer. Alternatively, use the built-in `ImGuiInputTextFlags_CharsDecimal` or `ImGuiInputTextFlags_CharsHexadecimal` flags for common cases, and reserve the callback for custom business logic.