UE4 遊戲窗口前臺後臺監聽

【原創文章 轉載請註明出處】

最近有個需求,記錄在窗口切到後臺和切回前臺時的時間。找了很久,沒有具體的方法,光看到有個委託事件也不知道怎麼用。查資料+測試了1天,感謝各位大佬對UE 委託DELEGATE的介紹,現把我也把自己關於這部分功能的詳細代碼方上來,做個記錄吧。

由於喜歡在藍圖中實現具體邏輯,所以有些代碼可能會有些多餘。

這部分比較亂完整的代碼會在下面放出來。如果覺得有幫助請給我點個贊,哈哈

就不新建文件了,用自己的項目說了,

在CEditorGameInstance.h中

在開頭出 通過委託宏自己定義2個動態多播返回值爲viod的委託類型

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWindowActive);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWindowDeActive);

在類中聲明2個公有變量,開放給藍圖使用,之後會在藍圖中對這2個事件進行綁定。

UPROPERTY(BlueprintAssignable)
	FOnWindowActive onWindowActivatedEvent;
UPROPERTY(BlueprintAssignable)
	FOnWindowDeActive onWindowDeactivatedEvent;

之後就是獲取窗口的通知,UE自帶的窗口通知事件是由SWindow發起的,我們先參考一下有哪些類型 SWindow.h

/** Notification that a window has been activated */
DECLARE_DELEGATE( FOnWindowActivated );
DECLARE_MULTICAST_DELEGATE( FOnWindowActivatedEvent );

/** Notification that a window has been deactivated */
DECLARE_DELEGATE( FOnWindowDeactivated );
DECLARE_MULTICAST_DELEGATE( FOnWindowDeactivatedEvent );

/** Notification that a window is about to be closed */
DECLARE_DELEGATE_OneParam( FOnWindowClosed, const TSharedRef<SWindow>& );

/** Notification that a window has been moved */
DECLARE_DELEGATE_OneParam( FOnWindowMoved, const TSharedRef<SWindow>& );

/** Override delegate for RequestDestroyWindow */
DECLARE_DELEGATE_OneParam( FRequestDestroyWindowOverride, const TSharedRef<SWindow>& );

/** Called when we need to switch game worlds for a window */
DECLARE_DELEGATE_RetVal_OneParam( int32, FOnSwitchWorldHack, int32 );

我們需要用到的是這兩個:

DECLARE_DELEGATE( FOnWindowActivated );
DECLARE_DELEGATE( FOnWindowDeactivated );

回到CEditorGameInstance.h中

在聲明2個變量

FOnWindowActivated	onWindowActivedHandle;
FOnWindowDeactivated	onWindowDeactivedHandle;

這樣需要的變量就已經定義完了,如圖:

之後寫綁定函數

​​UFUNCTION(BlueprintCallable, meta = (DisplayName = "Handle Application Actived"), Category = "Application")
    void HandleOnWindowActived();//獲取窗口被激活時的信息
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Handle Application Deactived"), Category = "Application")
    void HandleOnWindowDeactived();//獲取窗口失效時的信息
    //獲得各自信息後調用委託事件(這樣藍圖中已經綁定事件的話就會收到信息)
    void OnRequestWindowActived();
    void OnRequestWindowDeactived();

 

//---------------窗口激活時的綁定------------------
void UCEditorGameInstance::HandleOnWindowActived()
{
        //爲Handle綁定函數
	onWindowActivedHandle.BindUObject(this, &UCEditorGameInstance::OnRequestWindowActived);
	if (GEngine)
	{
                //爲SWindow設置句柄
		TSharedPtr<SWindow> Application = GEngine->GameViewport->GetWindow();
		Application->SetOnWindowActivated(onWindowActivedHandle);

		UE_LOG(LogTemp, Log, TEXT("Application request Actived is handled!"));
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Can not get viewport reference, handle application Actived request failed!"));
	}
}

void UCEditorGameInstance::OnRequestWindowActived()
{
	UE_LOG(LogTemp, Log, TEXT("Application request OnRequestWindowActived is handled!---dcf"));
	if (onWindowActivatedEvent.IsBound())
	{
		onWindowActivatedEvent.Broadcast();
	}
}

 

//---------------窗口失效時的綁定------------------
void UCEditorGameInstance::HandleOnWindowDeactived()
{
	onWindowDeactivedHandle.BindUObject(this, &UCEditorGameInstance::OnRequestWindowDeactived);
	if (GEngine)
	{
		TSharedPtr<SWindow> Application = GEngine->GameViewport->GetWindow();
		Application->SetOnWindowDeactivated(onWindowDeactivedHandle);

		UE_LOG(LogTemp, Log, TEXT("Application request Deactived is handled!"));
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Can not get viewport reference, handle application Deactived request failed!"));
	}
}

void UCEditorGameInstance::OnRequestWindowDeactived()
{
	UE_LOG(LogTemp, Log, TEXT("Application request OnRequestWindowDeactived is handled!---dcf"));
	if (onWindowDeactivatedEvent.IsBound())
	{
		onWindowDeactivatedEvent.Broadcast();
	}
}

編譯啓動項目,到EditorGameInstance藍圖創建函數

 

到自己的項目的第一個Widget界面,初始化的時候調用剛纔的方法(我的是登錄界面Login_bp)

測試 啓動遊戲,點擊其他區域 在點回窗口 看到日誌已經打印出來了

 

完整的C++代碼:

.h

#include "Runtime/SlateCore/Public/Widgets/SWindow.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWindowActive);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWindowDeActive);

UCLASS()
class AJDR_API UCEditorGameInstance : public UGameInstance
{
    GENERATED_UCLASS_BODY()

public:
	UFUNCTION(BlueprintCallable, meta = (DisplayName = "Handle Application Actived"), Category = "Application")
		void HandleOnWindowActived();
	void OnRequestWindowActived();
	UFUNCTION(BlueprintCallable, meta = (DisplayName = "Handle Application Deactived"), Category = "Application")
		void HandleOnWindowDeactived();
	void OnRequestWindowDeactived();


public:
	FOnWindowActivated		onWindowActivedHandle;
	FOnWindowDeactivated	onWindowDeactivedHandle;
	UPROPERTY(BlueprintAssignable)
		FOnWindowActive onWindowActivatedEvent;
	UPROPERTY(BlueprintAssignable)
		FOnWindowDeActive onWindowDeactivatedEvent;

}

.cpp

void UCEditorGameInstance::HandleOnWindowActived()
{
	onWindowActivedHandle.BindUObject(this, &UCEditorGameInstance::OnRequestWindowActived);
	if (GEngine)
	{
		TSharedPtr<SWindow> Application = GEngine->GameViewport->GetWindow();
		Application->SetOnWindowActivated(onWindowActivedHandle);

		UE_LOG(LogTemp, Log, TEXT("Application request Actived is handled!"));
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Can not get viewport reference, handle application Actived request failed!"));
	}
}

void UCEditorGameInstance::OnRequestWindowActived()
{
	UE_LOG(LogTemp, Log, TEXT("Application request OnRequestWindowActived is handled!---dcf"));
	if (onWindowActivatedEvent.IsBound())
	{
		onWindowActivatedEvent.Broadcast();
	}
}

void UCEditorGameInstance::HandleOnWindowDeactived()
{
	onWindowDeactivedHandle.BindUObject(this, &UCEditorGameInstance::OnRequestWindowDeactived);
	if (GEngine)
	{
		TSharedPtr<SWindow> Application = GEngine->GameViewport->GetWindow();
		Application->SetOnWindowDeactivated(onWindowDeactivedHandle);

		UE_LOG(LogTemp, Log, TEXT("Application request Deactived is handled!"));
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Can not get viewport reference, handle application Deactived request failed!"));
	}
}

void UCEditorGameInstance::OnRequestWindowDeactived()
{
	UE_LOG(LogTemp, Log, TEXT("Application request OnRequestWindowDeactived is handled!---dcf"));
	if (onWindowDeactivatedEvent.IsBound())
	{
		onWindowDeactivatedEvent.Broadcast();
	}
}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章