Create widget in pure C++

Hi guys I will paste some code from my project,I’m using UE 5.3.2 and it works




// POIFullScreenWidget.h
#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/CanvasPanel.h"
#include "POIFullScreenWidget.generated.h"

/**
 * 
 */
UCLASS()
class AMAPLAYERS_API UPOIFullScreenWidget : public UUserWidget
{
	GENERATED_BODY()

public:
	UPOIFullScreenWidget(const FObjectInitializer& ObjectInitializer);
	UCanvasPanel* CanvasPanel;
	virtual void NativeOnInitialized() override;

};

// Fill out your copyright notice in the Description page of Project Settings.


#include "POIFullScreenWidget.h"

#include "Blueprint/WidgetTree.h"
#include "Components/CanvasPanelSlot.h"


UPOIFullScreenWidget::UPOIFullScreenWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{

}

// here we create a simple text 

void UPOIFullScreenWidget::NativeOnInitialized()
{
	Super::NativeOnInitialized();
	CanvasPanel = WidgetTree->ConstructWidget<UCanvasPanel>(UCanvasPanel::StaticClass());
	if (CanvasPanel)
	{
		auto TextBlock = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass());
		TextBlock->SetText(FText::FromString("Hello World!"));
		auto TextSlot = CanvasPanel->AddChildToCanvas(TextBlock);
		TextSlot->SetAnchors(FAnchors(0, 0, 0, 0));
		TextSlot->SetOffsets(FMargin(100, 100));
		TextSlot->SetAlignment(FVector2d(0, 0.5));
		TextSlot->SetAutoSize(true);
		
		WidgetTree->RootWidget = CanvasPanel;
	}
	
}

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();
}