LKN2019 error when compiling a UUserWidget extended class

Hello guys!

I have implemented a class derived from UUserWidget, and I’m stuck in the following error:

And here is the output:


1>------ Build started: Project: PRJ_UI_Test, Configuration: Development_Editor x64 ------
1>Building PRJ_UI_TestEditor...
1>Using Visual Studio 2019 14.22.27905 toolchain (D:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.22.27905) and Windows 10.0.18362.0 SDK (C:\Program Files (x86)\Windows Kits\10).
1>Building 3 actions with 12 processes...
1> [1/3] UE4Editor-PRJ_UI_Test-0011.lib
1> Creating library D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Intermediate\Build\Win64\UE4Editor\Development\PRJ_UI_Test\UE4Editor-PRJ_UI_Test-0011.lib and object D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Intermediate\Build\Win64\UE4Editor\Development\PRJ_UI_Test\UE4Editor-PRJ_UI_Test-0011.exp
1> [2/3] UE4Editor-PRJ_UI_Test-0011.dll
1> Creating library D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Intermediate\Build\Win64\UE4Editor\Development\PRJ_UI_Test\UE4Editor-PRJ_UI_Test-0011.suppressed.lib and object D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Intermediate\Build\Win64\UE4Editor\Development\PRJ_UI_Test\UE4Editor-PRJ_UI_Test-0011.suppressed.exp
1>RngWidget.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static class FReply __cdecl FReply::Handled(void)" (__imp_?Handled@FReply@@SA?AV1@XZ) referenced in function "protected: virtual class FReply __cdecl URngWidget::NativeOnKeyDown(struct FGeometry const &,struct FKeyEvent const &)" (?NativeOnKeyDown@URngWidget@@MEAA?AVFReply@@AEBUFGeometry@@AEBUFKeyEvent@@@Z)
1>RngWidget.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl FReply::~FReply(void)" (__imp_??1FReply@@QEAA@XZ) referenced in function "protected: virtual class FReply __cdecl URngWidget::NativeOnKeyDown(struct FGeometry const &,struct FKeyEvent const &)" (?NativeOnKeyDown@URngWidget@@MEAA?AVFReply@@AEBUFGeometry@@AEBUFKeyEvent@@@Z)
1>D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Binaries\Win64\UE4Editor-PRJ_UI_Test-0011.dll : fatal error LNK1120: 2 unresolved externals
1>D:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160\Microsoft.MakeFile.Targets(44,5): error MSB3073: The command ""D:\Program Files\Epic Games\UE_4.25\Engine\Build\BatchFiles\Build.bat" PRJ_UI_TestEditor Win64 Development -Project="D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\PRJ_UI_Test.uproject" -WaitMutex -FromMsBuild" exited with code 6.
1>Done building project "PRJ_UI_Test.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I think that, for some reason, when creating the .OBJ, the linker isn’t finding the implementation for the FReply::Handled() and can’t match both .h and .cpp

When I comment the entire NativeOnKeyDown and its declaration in the header, there’s no issues, as expected:


Candidate modules for hot reload:
PRJ_UI_Test
Launching UnrealBuildTool... [D:/Program Files/Epic Games/UE_4.25/Engine/Binaries/DotNET/UnrealBuildTool.exe -ModuleWithSuffix=PRJ_UI_Test,4370 PRJ_UI_TestEditor Win64 Development -Project="D:/GAME DEVELOPMENT/PROJECTS/UDEMY/LATEST/PRJ_UI_Test/PRJ_UI_Test.uproject" "D:/GAME DEVELOPMENT/PROJECTS/UDEMY/LATEST/PRJ_UI_Test/PRJ_UI_Test.uproject" -IgnoreJunk]
Warning: Starting HotReload took 0.1s.
CompilerResultsLog: New page: Compilation - Aug 18, 2020, 12:44:23 AM
CompilerResultsLog: Building PRJ_UI_TestEditor...
CompilerResultsLog: Using Visual Studio 2019 14.22.27905 toolchain (D:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.22.27905) and Windows 10.0.18362.0 SDK (C:\Program Files (x86)\Windows Kits\10).
CompilerResultsLog: Building 3 actions with 12 processes...
CompilerResultsLog: [1/3] UE4Editor-PRJ_UI_Test-4370.lib
CompilerResultsLog: Creating library D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Intermediate\Build\Win64\UE4Editor\Development\PRJ_UI_Test\UE4Editor-PRJ_UI_Test-4370.lib and object D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Intermediate\Build\Win64\UE4Editor\Development\PRJ_UI_Test\UE4Editor-PRJ_UI_Test-4370.exp
CompilerResultsLog: [2/3] UE4Editor-PRJ_UI_Test-4370.dll
CompilerResultsLog: Creating library D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Intermediate\Build\Win64\UE4Editor\Development\PRJ_UI_Test\UE4Editor-PRJ_UI_Test-4370.suppressed.lib and object D:\GAME DEVELOPMENT\PROJECTS\UDEMY\LATEST\PRJ_UI_Test\Intermediate\Build\Win64\UE4Editor\Development\PRJ_UI_Test\UE4Editor-PRJ_UI_Test-4370.suppressed.e
xp
CompilerResultsLog: [3/3] PRJ_UI_TestEditor.target
CompilerResultsLog: Total time in Parallel executor: 0.86 seconds
CompilerResultsLog: Total execution time: 1.38 seconds
LogMainFrame: MainFrame: Module compiling took 1.458 seconds
LogContentBrowser: Native class hierarchy updated for 'PRJ_UI_Test' in 0.0012 seconds. Added 5 classes and 2 folders.
Display: HotReload successful (3 functions remapped 0 scriptstructs remapped)
LogContentBrowser: Native class hierarchy populated in 0.0117 seconds. Added 3432 classes and 823 folders.
Display: HotReload took 2.5s.
LogRenderer: Reallocating scene render targets to support 1212x572 Format 10 NumSamples 1 (Frame:5348).
LogRenderer: Reallocating scene render targets to support 1272x572 Format 10 NumSamples 1 (Frame:5350).
LogRenderer: Reallocating scene render targets to support 1288x572 Format 10 NumSamples 1 (Frame:5352).
LogRenderer: Reallocating scene render targets to support 1320x572 Format 10 NumSamples 1 (Frame:5354).
LogRenderer: Reallocating scene render targets to support 1344x572 Format 10 NumSamples 1 (Frame:5356).
LogRenderer: Reallocating scene render targets to support 1356x572 Format 10 NumSamples 1 (Frame:5358).
LogRenderer: Reallocating scene render targets to support 1360x572 Format 10 NumSamples 1 (Frame:5360).
LogRenderer: Reallocating scene render targets to support 1364x572 Format 10 NumSamples 1 (Frame:5362).
LogRenderer: Reallocating scene render targets to support 1372x572 Format 10 NumSamples 1 (Frame:5364).
LogRenderer: Reallocating scene render targets to support 1376x572 Format 10 NumSamples 1 (Frame:5366).
LogRenderer: Reallocating scene render targets to support 1384x572 Format 10 NumSamples 1 (Frame:5368).
LogRenderer: Reallocating scene render targets to support 1392x572 Format 10 NumSamples 1 (Frame:5370).
LogRenderer: Reallocating scene render targets to support 1400x572 Format 10 NumSamples 1 (Frame:5372).
LogRenderer: Reallocating scene render targets to support 1404x572 Format 10 NumSamples 1 (Frame:5374).

Can you point the issue here? I couldn’t find the problem here, and any help will be appreciated :slight_smile:

Did you added all the necessary modules in the Build.cs file?

2 Likes

Yes, I had them in my Build.cs, like explained here https://docs.unrealengine.com/en-US/…tup/index.html.

But the PrivateDependencYModuleNames were commented, God knows why I comment those. That is the cause.

Thanks for your time and support! :slight_smile:

1 Like

Btw, now that this problem is.gone, two new appeared.

First, if the FInputMode is set to FInputModeUIOnly (in the APRJ_UI_TestHUD::HandleMenu()), and the RngWidget is handling the keyboard event through the URngWidget::NativeOnKeyDown(), I have to click once or the viewport or the widget itself to be able to press tab and execute what is inside URngWidget::NativeOnKeyDown() implementation.

Whats is going on here?

Also, besides the fact that the widget layout have been made on a BP parented to the class URngWidget, the GenerateButton (inside the RngWidget.cpp) focus is still on, even after setting the GenerateButton->IsFocusable to false, in the URngWidget::NativeConstruct(). I have to open the BP and manually uncheck the IsFocusable GenerateButton’s checkbox; it should receive false when the widget is added to the viewport, but no, doesn’t happen.

Do you guys have any ideas why this two issues are happening?

Thanks!

Here is the code:

RngWidget.h


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

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "RngWidget.generated.h"

DECLARE_DYNAMIC_DELEGATE(FCustomOnKeyDownSignature);

/**
*
*/
UCLASS()
class PRJ_UI_TEST_API URngWidget : public UUserWidget
{
GENERATED_BODY()

protected:
UPROPERTY(BlueprintReadOnly, meta = (BindWidget))
class UButton* GenerateButton;

UPROPERTY()
FCustomOnKeyDownSignature CustomOnKeyDown;

UPROPERTY(BlueprintReadOnly, meta = (BindWidget))
class UTextBlock* RandomNumberLabel;

UPROPERTY()
class APRJ_UI_TestHUD* TestHUD;

protected:
void GenerateRandom();

UFUNCTION()
void OnGenerateButtonClicked();

virtual void NativeConstruct() override;

virtual FReply NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override;

};


RngWidget.cpp


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


#include "RngWidget.h"
#include "Components/TextBlock.h"
#include "Components/Button.h"
#include "Input/Reply.h"
#include "PRJ_UI_TestHUD.h"

void URngWidget::NativeConstruct()
{
Super::NativeConstruct();

GenerateRandom();
bIsFocusable = true;
SetKeyboardFocus();
GenerateButton->IsFocusable = false;
if(ensureMsgf(GenerateButton, TEXT("The GenerateButton is NULL.")) && !GenerateButton->OnClicked.IsBound())
{
GenerateButton->OnClicked.AddDynamic(this, &URngWidget::OnGenerateButtonClicked);
}
if (!CustomOnKeyDown.IsBound())
{
TestHUD = Cast<APRJ_UI_TestHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
CustomOnKeyDown.BindDynamic(TestHUD, &APRJ_UI_TestHUD::HandleMenu);
}

}

void URngWidget::GenerateRandom()
{
int32 RandomNumber = FMath::RandRange(0, 100);
if (ensureMsgf(RandomNumberLabel, TEXT("The RandomNumberLabel widget is NULL.")))
{
RandomNumberLabel->SetText(FText::AsNumber(RandomNumber));
}

}

void URngWidget::OnGenerateButtonClicked()
{
GenerateRandom();

}

FReply URngWidget::NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
Super::NativeOnKeyDown(InGeometry,InKeyEvent);

if(InKeyEvent.GetKey() == EKeys::Tab)
{
UE_LOG(LogTemp, Warning, TEXT("Executing NativeOnKeyDown() event."));
CustomOnKeyDown.Execute();
}

return FReply::Handled();
}


PRJ_UI_TestHUD.h


// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "PRJ_UI_TestHUD.generated.h"

class URngWidget;

UCLASS()
class APRJ_UI_TestHUD : public AHUD
{
GENERATED_BODY()

protected:
TSubclassOf<URngWidget> RngWidgetClass;

URngWidget* RngWidget;

bool bIsMenuOpen;

APlayerController* PlayerController;

public:
APRJ_UI_TestHUD();

void BeginPlay() override;

/** Primary draw call for the HUD */
virtual void DrawHUD() override;

UFUNCTION()
void HandleMenu();

private:
/** Crosshair asset pointer */
class UTexture2D* CrosshairTex;

};



PRJ_UI_TestHUD.cpp


// Copyright Epic Games, Inc. All Rights Reserved.

#include "PRJ_UI_TestHUD.h"
#include "Engine/Canvas.h"
#include "Engine/Texture2D.h"
#include "TextureResource.h"
#include "CanvasItem.h"
#include "UObject/ConstructorHelpers.h"
#include "RngWidget.h"
#include "Kismet/GameplayStatics.h"

APRJ_UI_TestHUD::APRJ_UI_TestHUD()
{
// Set the crosshair texture
static ConstructorHelpers::FObjectFinder<UTexture2D> CrosshairTexObj(TEXT("/Game/FirstPerson/Textures/FirstPersonCrosshair"));
CrosshairTex = CrosshairTexObj.Object;

static ConstructorHelpers::FClassFinder<URngWidget> RngWidgetAsset(TEXT("/Game/FirstPersonCPP/Blueprints/BP_RNG_UI"));
if(ensureMsgf(RngWidgetAsset.Succeeded(), TEXT("The RngWidgetClass extraction failed.")))
{
RngWidgetClass = RngWidgetAsset.Class;
}
bIsMenuOpen = false;

}

void APRJ_UI_TestHUD::BeginPlay()
{
Super::BeginPlay();

if (RngWidgetClass && !RngWidget)
{
RngWidget = CreateWidget<URngWidget>(GetWorld(), RngWidgetClass);
if (RngWidget)
{
RngWidget->AddToViewport();
RngWidget->SetVisibility(ESlateVisibility::Hidden);
PlayerController = UGameplayStatics::GetPlayerController(this, 0);
PlayerController->SetInputMode(FInputModeGameOnly());
PlayerController->bShowMouseCursor = false;
}
}
}

void APRJ_UI_TestHUD::DrawHUD()
{
Super::DrawHUD();

// Draw very simple crosshair

// find center of the Canvas
const FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f);

// offset by half the texture's dimensions so that the center of the texture aligns with the center of the Canvas
const FVector2D CrosshairDrawPosition( (Center.X),
(Center.Y + 20.0f));

// draw the crosshair
FCanvasTileItem TileItem( CrosshairDrawPosition, CrosshairTex->Resource, FLinearColor::White);
TileItem.BlendMode = SE_BLEND_Translucent;
Canvas->DrawItem( TileItem );
}

void APRJ_UI_TestHUD::HandleMenu()
{
UE_LOG(LogTemp, Warning, TEXT("bIsMenuOen is %s."), bIsMenuOpen ? TEXT("true") : TEXT("false"));
if (!bIsMenuOpen)
{
UE_LOG(LogTemp, Warning, TEXT("Chaging input mode to UI only"));
RngWidget->SetVisibility(ESlateVisibility::Visible);
PlayerController->SetInputMode(FInputModeUIOnly());
PlayerController->bShowMouseCursor = true;
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Chaging input mode to Game only"));
RngWidget->SetVisibility(ESlateVisibility::Hidden);
PlayerController->SetInputMode(FInputModeGameOnly());
PlayerController->bShowMouseCursor = false;
}
bIsMenuOpen = !bIsMenuOpen;
UE_LOG(LogTemp, Warning, TEXT("bIsMenuOen is %s."), bIsMenuOpen ? TEXT("true") : TEXT("false"));

}


UPDATE: about the previous question, the solution was pretty easy: I just had to insert SetKeyboardFocus() in the IF statement inside APRJ_UI_TestHUD::HandleMenu(), my bad :slight_smile:

But I still don’t know why the GenerateButton doesn’t have its IsFocusable variable changed in the RgnWidget::NativeConstruct().