【原創文章 轉載請註明出處】
最近有個需求,記錄在窗口切到後臺和切回前臺時的時間。找了很久,沒有具體的方法,光看到有個委託事件也不知道怎麼用。查資料+測試了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();
}
}