How to do it...

  1. Create a new GameModeBase subclass called ClickEventGameMode:

  1. From the ClickEventGameMode.h file, add the following functions and private members to the class:
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "SlateBasics.h"
#include "ClickEventGameMode.generated.h"

UCLASS()
class CHAPTER_14_API AClickEventGameMode : public AGameModeBase
{
GENERATED_BODY()

private:
TSharedPtr<SVerticalBox> Widget;
TSharedPtr<STextBlock> ButtonLabel;

public:
virtual void BeginPlay() override;
FReply ButtonClicked();
};
  1. Within the .cpp file, add the implementation for BeginPlay:
void AClickEventGameMode::BeginPlay()
{
Super::BeginPlay();

Widget = SNew(SVerticalBox)
+ SVerticalBox::Slot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SButton)
.OnClicked(FOnClicked::CreateUObject(this, &AClickEventGameMode::ButtonClicked))
.Content()
[
SAssignNew(ButtonLabel, STextBlock)
.Text(FText::FromString(TEXT("Click me!")))
]
];

auto player = GetWorld()->GetFirstLocalPlayerFromController();

GEngine->GameViewport->AddViewportWidgetForPlayer(player, Widget.ToSharedRef(), 1);

GetWorld()->GetFirstPlayerController()->bShowMouseCursor = true;

auto pc = GEngine->GetFirstLocalPlayerController(GetWorld());

EMouseLockMode lockMode = EMouseLockMode::DoNotLock;

auto inputMode = FInputModeUIOnly().SetLockMouseToViewportBehavior(lockMode).SetWidgetToFocus(Widget);

pc->SetInputMode(inputMode);

}
  1. Also, add an implementation for ButtonClicked():
FReply AClickEventGameMode::ButtonClicked()
{
ButtonLabel->SetText(FString(TEXT("Clicked!")));
return FReply::Handled();
}
  1. Compile your code and launch the editor.
  2. Override the game mode in World Settings to be ClickEventGameMode.
  3. Preview this in the editor and verify that the UI shows a button that changes from Click Me! to Clicked! when you use the mouse cursor to click on it:

Button displays Clicked! after being clicked