Hello,
I have question if it’s possible to drag and drop file/files to shipped UE4 project and gives the engine an array of path strings of files which were dropped. (C:\MyFile.txt,C:\MySecondFile.png…)
I have found exactly what I was looking for here: Google Translate (Google translated)
Unfortunately it’s not working for me at some point. Or if you know a better solution how to do it, I would be really grateful!
Here is the code:
WindowsDragFileBorder.h
#include "CoreMinimal.h"
#include "Components/ContentWidget.h"
#include "Widgets/SBoxPanel.h"
#include "Widgets/Layout/SBorder.h"
#include "WindowsDragFileBorder.generated.h"
/**
*
*/
//接收SDragBorder拖拽信号
DECLARE_DELEGATE(FOnDragEnterHandle);
DECLARE_DELEGATE(FOnDragLeaveHandle);
DECLARE_DELEGATE(FOnDragOverHandle);
DECLARE_DELEGATE_OneParam(FOnDropHandle, const TArray<FString>&);
//传给UMG
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDragEnterEvent);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDragLeaveEvent);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDragOverEvent);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDropEvent, const TArray<FString>&, FilesPath);
class AGAMID_API SDragBorder : public SBorder
{
public:
SLATE_BEGIN_ARGS(SDragBorder)
{}
SLATE_EVENT(FOnDragEnterHandle, OnDragEnter)
SLATE_EVENT(FOnDragLeaveHandle, OnDragLeave)
SLATE_EVENT(FOnDragOverHandle, OnDragOver)
SLATE_EVENT(FOnDropHandle, OnDrop)
SLATE_END_ARGS()
public:
// SWidget interface
// End of SWidget interface
void Construct(const FArguments& InArgs);
virtual void SetContent(TSharedRef< SWidget > InContent) override;
public:
// SWidget interface
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;
// End of SWidget interface
protected:
// Begin SWidget overrides.
virtual FVector2D ComputeDesiredSize(float) const override;
// End SWidget overrides.
private:
bool isFileDrag(const FDragDropEvent& DragDropEvent);
public:
/** Drag detection and handling */
//virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual void OnDragEnter(FGeometry const& MyGeometry, FDragDropEvent const& DragDropEvent) override;
virtual void OnDragLeave(FDragDropEvent const& DragDropEvent) override;
virtual FReply OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
virtual FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
private:
/** Delegate triggered when a user's drag enters the bounds of this slot item */
FOnDragEnterHandle OnDragEnter_Handler;
/** Delegate triggered when a user's drag leaves the bounds of this slot item */
FOnDragLeaveHandle OnDragLeave_Handler;
/** Delegate triggered when a user's drag is dropped in the bounds of this slot item */
FOnDropHandle OnDrop_Handler;
FOnDragOverHandle OnDragOver_Handler;
};
UCLASS()
class AGAMID_API UWindowsDragFileBorder : public UContentWidget
{
GENERATED_BODY()
public:
void OnDragEnter();
void OnDragLeave();
void OnDragOver();
void OnDragDrop(const TArray<FString>& FilesPath);
//FReply OnDragOver(FDragDropEvent const& DragDropEvent);
/** Called when the button is released */
UPROPERTY(BlueprintAssignable, Category = "WindowsDragFile|Event")
FOnDragEnterEvent OnDragEnterEvent;
UPROPERTY(BlueprintAssignable, Category = "WindowsDragFile|Event")
FOnDragLeaveEvent OnDragLeaveEvent;
UPROPERTY(BlueprintAssignable, Category = "WindowsDragFile|Event")
FOnDragOverEvent OnDragOverEvent;
UPROPERTY(BlueprintAssignable, Category = "WindowsDragFile|Event")
FOnDropEvent OnDragDropEvent;
protected:
virtual TSharedRef<SWidget> RebuildWidget() override;
protected:
TSharedPtr<SDragBorder> MyBorder;
};
WindowsDragFileBorder.cpp
#include "WindowsDragFileBorder.h"
#include "Widgets/SWidget.h"
#include "Widgets/Layout/SBorder.h"
#include "Components/BorderSlot.h"
void SDragBorder::Construct(const FArguments& InArgs)
{
SBorder::SBorder();
SBorder::Construct(SBorder::FArguments());
OnDragEnter_Handler = InArgs._OnDragEnter;
OnDragLeave_Handler = InArgs._OnDragLeave;
OnDrop_Handler = InArgs._OnDrop;
OnDragOver_Handler = InArgs._OnDragOver;
}
void UWindowsDragFileBorder::OnDragEnter()
{
if (OnDragEnterEvent.IsBound())
{
OnDragEnterEvent.Broadcast();
}
}
void UWindowsDragFileBorder::OnDragLeave()
{
if (OnDragLeaveEvent.IsBound())
{
OnDragLeaveEvent.Broadcast();
}
}
void UWindowsDragFileBorder::OnDragOver()
{
if (OnDragOverEvent.IsBound())
{
OnDragOverEvent.Broadcast();
}
}
void UWindowsDragFileBorder::OnDragDrop(const TArray<FString>& FilesPath)
{
if (OnDragDropEvent.IsBound())
{
OnDragDropEvent.Broadcast(FilesPath);
}
}
TSharedRef<SWidget> UWindowsDragFileBorder::RebuildWidget()
{
MyBorder = SNew(SDragBorder)
.OnDragEnter_UObject(this, &UWindowsDragFileBorder::OnDragEnter)
.OnDragLeave_UObject(this, &UWindowsDragFileBorder::OnDragLeave)
.OnDragOver_UObject(this, &UWindowsDragFileBorder::OnDragOver)
.OnDrop_UObject(this, &UWindowsDragFileBorder::OnDragDrop)
;
if (GetChildrenCount() > 0)
{
//Cast<UBorderSlot>(GetContentSlot())->BuildSlot(MyBorder.ToSharedRef());
MyBorder->SetContent(GetContent() ? GetContent()->TakeWidget() : SNullWidget::NullWidget);
}
// ;
// ;
//MyBorder = SNew(SDragBorder);
return MyBorder.ToSharedRef();
}
void SDragBorder::OnDragEnter(FGeometry const& MyGeometry, FDragDropEvent const& DragDropEvent)
{
if (isFileDrag(DragDropEvent) && OnDragEnter_Handler.IsBound())
{
OnDragEnter_Handler.Execute();
}
}
void SDragBorder::OnDragLeave(FDragDropEvent const& DragDropEvent)
{
if (OnDragLeave_Handler.IsBound())
{
OnDragLeave_Handler.Execute();
}
}
FReply SDragBorder::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
bool bisFileDrag = isFileDrag(DragDropEvent);
if (bisFileDrag)
{
if (OnDragOver_Handler.IsBound())
{
OnDragOver_Handler.Execute();
}
return FReply::Handled();
}
return FReply::Handled();
}
FReply SDragBorder::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
FExternalDragOperation* DragDropOperation = (FExternalDragOperation*)(DragDropEvent.GetOperation().Get());
if (DragDropOperation)
{
OnDrop_Handler.Execute(DragDropOperation->GetFiles());
}
return FReply::Handled();
}
void SDragBorder::SetContent(TSharedRef<SWidget> InContent)
{
SBorder::SetContent(InContent);
}
int32 SDragBorder::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
return SBorder::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
}
FVector2D SDragBorder::ComputeDesiredSize(float LayoutScaleMultiplier) const
{
return DesiredSizeScale.Get() * SCompoundWidget::ComputeDesiredSize(LayoutScaleMultiplier);
}
bool SDragBorder::isFileDrag(const FDragDropEvent& DragDropEvent)
{
FExternalDragOperation* DragDropOperation = (FExternalDragOperation*)(DragDropEvent.GetOperation().Get());
if (!DragDropOperation)
{
return false;
}
if (!DragDropOperation->HasFiles())
{
return false;
}
return true;
}
FReply SDragBorder::OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
return FReply::Handled();
}