I’ve managed to create a text box widget purely in C++ in 4.27 and am using it to get input characters. I thought some people, like me, might be interested in this.
The text box is invisible because I have my own text box solution that I feed with the characters gotten from the widget. This is great because I can get characters generated by the platform, keyboard settings and everything, with no work on my side. I haven’t explored what it would take to make the text box visible or usable in the game.
Anyway, here’s a code example:
// H file content
#include "Widgets/Input/SEditableTextBox.h"
TSharedPtr<SEditableTextBox> m_textBox;
FReply OnKeyCharHandler(const FGeometry& geo, const FCharacterEvent& charEvent);
FReply OnKeyDownHandler(const FGeometry& geo, const FKeyEvent& keyEvent);
// CPP content, put this literally anywhere.
// Creates the text box with some settings.
m_textBox = SNew(SEditableTextBox)
.SelectAllTextWhenFocused(true)
.SelectAllTextOnCommit(false)
.ClearKeyboardFocusOnCommit(true)
.RevertTextOnEscape(true)
.IsReadOnly(false);
// Add handlers to catch the characters and even some FKeys(not the mouse ones).
// Use CreateRaw if not in UObject code.
m_textBox->SetOnKeyCharHandler(FOnKeyChar::CreateUObject(this, &AMyUObjectClass::OnKeyCharHandler));
m_textBox->SetOnKeyDownHandler(FOnKeyDown::CreateUObject(this, &AMyUObjectClass::OnKeyDownHandler));
// This gets whatever widget has the focus and puts the text box under it so it actually works.
// I haven't added any widgets to my project, so I expect this to work on any project.
TSharedPtr<SWidget> focusedSlateWidget = FSlateApplication::Get().GetUserFocusedWidget(0);
m_textBox->AssignParentWidget(focusedSlateWidget);
// Call this to start typing. All non-mouse inputs will be directed to the text box instead of your game.
FSlateApplication::Get().SetUserFocus(0, m_textBox, EFocusCause::SetDirectly);
FReply AMyUObjectClass::OnKeyCharHandler(const FGeometry& geo, const FCharacterEvent& charEvent)
{
TCHAR ch = charEvent.GetCharacter();
if(ch == L'a')
// Do something if the character is lowercase a.
// I always return Handled because I don't want the tex box to actually have anything in it.
// If you want the text box to actually receive characters, return Unhandled.
return FReply::Handled();
}
FReply AMyUObjectClass::OnKeyDownHandler(const FGeometry& geo, const FKeyEvent& keyEvent)
{
FKey key = keyEvent.GetKey();
if (key == EKeys::Enter)
{
// Do whatever logic you need to do when Enter is pressed.
// Release the focus from the textbox and put it back on the window(very important).
FSlateApplication::Get().SetUserFocusToGameViewport(0);
}
else if (key == EKeys::Escape)
{
// Do whatever logic you need to do when Escape is pressed.
// Release the focus from the textbox and put it back on the window(very important).
FSlateApplication::Get().SetUserFocusToGameViewport(0);
}
// I always return Handled because I don't want the tex box to actually receive key events.
// If you want the text box to actually receive the key events and commit or revert the text entered, return Unhandled.
return FReply::Handled();
}