UE5 运行时捕捉外部窗口并嵌入到主窗口的一种方法
创建一个Slate类用于生成一个窗口
.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
/**
*
*/
class NEWWINDOWTEST0822_API SCreateNewWindow : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SCreateNewWindow)
{}
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
static void CreateAAA();
};
.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "SCreateNewWindow.h"
#include "SlateOptMacros.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SCreateNewWindow::Construct(const FArguments& InArgs)
{
/*
ChildSlot
[
// Populate the widget
];
*/
}
void SCreateNewWindow::CreateAAA()
{
TSharedPtr<SWindow> NewWin = SNew(SWindow).ClientSize(FVector2D(800,600))
.Title(FText::FromString(TEXT("AAAAA")));
FSlateApplication::Get().AddWindow(NewWin.ToSharedRef());
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
创建一个Actor类,用于调用Slate类中的方法
.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class NEWWINDOWTEST0822_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UFUNCTION(BlueprintCallable,Category = "Function")
static void SpawnWindow();
UFUNCTION(BlueprintCallable,Category = "Function")
static void findAAA(FString AAAname);
static void OnMainWindowClosed();
};
.cpp
#include "MyActor.h"
#include "Windows/AllowWindowsPlatformTypes.h"
#include "SCreateNewWindow.h"
FDelegateHandle MainWindowClosedHandle; // 用于存储主窗口关闭事件的句柄
HWND OtherWindowHandle = nullptr; // 嵌入的子窗口句柄
// Sets default values
AMyActor::AMyActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AMyActor::SpawnWindow()
{
SCreateNewWindow::CreateAAA();
}
void AMyActor::findAAA(FString AAAname)
{
void* winhandle = GEngine->GameViewport->GetWindow()->GetNativeWindow()->GetOSWindowHandle();
// 进行类型转换,获取主窗口句柄
HWND MainWindowHwnd = static_cast<HWND>(winhandle);
if (MainWindowHwnd)
{
const WCHAR* WindowName = *AAAname;
HWND otherWindow = FindWindowW(NULL, WindowName);
// 设置子窗口位置
SetWindowPos(otherWindow, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
// 获取子窗口当前样式
LONG style = GetWindowLong(otherWindow, GWL_STYLE);
// 清除窗口边框样式
style &= ~(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
// 添加无边框样式和可移动样式
style |= WS_POPUP | WS_BORDER;
// 设置子窗口样式
SetWindowLong(otherWindow, GWL_STYLE, style);
// 将子窗口嵌入到主窗口中
SetParent(otherWindow, MainWindowHwnd);
// 存储嵌入的子窗口句柄
OtherWindowHandle = otherWindow;
// 注册主窗口关闭事件
MainWindowClosedHandle = FCoreDelegates::OnPreExit.AddStatic(&AMyActor::OnMainWindowClosed);
}
}
void AMyActor::OnMainWindowClosed()
{
if (OtherWindowHandle)
{
DestroyWindow(OtherWindowHandle);
}
// 取消主窗口关闭事件的注册
FCoreDelegates::OnPreExit.Remove(MainWindowClosedHandle);
}