Ara you OK?
我看你是思想出现了偏差
哇!你认出了错别单词!恭喜你获得一次向我支付宝充值助我重返欧洲的机会!
这个页面管关不掉了,你自己看着办吧

UE4笔记-系统对话框相关功能记录和使用方法(打开/保存文件对话框系统对话框等等...)

(当前最新版本4.24)

 

UE4其实是有实现对话框打开保存等的相关的功能的,都在‘DesktopPlatform’ Module中..

但是‘DesktopPlatform’ Module属于Developer模块,是无法打包出ship ping程序包的...

会报错:

  Error:Missing precompiled manifest for 'DesktopPlatform'

 

 

所以想在生产环境中使用该模块需要自己整改一下Module的(突然想口吐芬芳~)

 ------------------------------------------------------------------------------------------------

补全:如果仅考虑windows平台的话且没有UE风格统一强迫症的话可以直接调用Windows 的API进行封装

e.g:

#include "Engine.h"
#include "AllowWindowsPlatformTypes.h"
#include "Windows/COMPointer.h"
#include <shlobj.h>
#include "HideWindowsPlatformTypes.h"

UENUM(BlueprintType)
enum class ESystemFileDialogType : uint8
{
    Save,
    Open
};

bool UGenericExtensionMethods::OpenSystemFileDialog(FString& OutFilePath, const FString& Title, const FString& DefaultPath, ESystemFileDialogType Type, const FString& Filter)
{
    OutFilePath.Empty();
    TComPtr<IFileDialog> FileDialog;

    CLSID type_clsid;
    IID type_iid;

    switch( Type)
    {
        case ESystemFileDialogType::Open: { type_clsid = CLSID_FileOpenDialog; type_iid = IID_IFileOpenDialog; break; }
        case ESystemFileDialogType::Save: { type_clsid = CLSID_FileSaveDialog; type_iid = IID_IFileSaveDialog; break; }
    }

    //auto c = CLSID_FileSaveDialog;
    if (!SUCCEEDED(::CoCreateInstance( type_clsid,
                                       nullptr,
                                       CLSCTX_INPROC_SERVER,
                                       type_iid,
                                       IID_PPV_ARGS_Helper(&FileDialog)
                                      )))
    {
        return false;
    }
    // Set up common settings
    FileDialog->SetTitle( *Title);

    FString DefaultWindowsPath = DefaultPath;
    if (DefaultWindowsPath.IsEmpty() )
    {
        DefaultWindowsPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir());
    }

    DefaultWindowsPath.ReplaceInline(TEXT("/"), TEXT("\\"), ESearchCase::CaseSensitive);
    TComPtr<IShellItem> DefaultPathItem;
    if (SUCCEEDED(::SHCreateItemFromParsingName(*DefaultWindowsPath, nullptr, IID_PPV_ARGS(&DefaultPathItem))))
    {
        FileDialog->SetFolder(DefaultPathItem);
    }
    TArray<FString> UnformattedExtensions;
    TArray<COMDLG_FILTERSPEC> FileDialogFilters;
    {
        Filter.ParseIntoArray(UnformattedExtensions, TEXT("|"), true);
        if (UnformattedExtensions.Num() % 2 == 0)
        {
            FileDialogFilters.Reserve(UnformattedExtensions.Num() / 2);
            for (int32 ExtensionIndex = 0; ExtensionIndex < UnformattedExtensions.Num();)
            {
                COMDLG_FILTERSPEC& NewFilterSpec = FileDialogFilters[FileDialogFilters.AddDefaulted()];
                NewFilterSpec.pszName = *UnformattedExtensions[ExtensionIndex++];
                NewFilterSpec.pszSpec = *UnformattedExtensions[ExtensionIndex++];
            }
        }
    }
    FileDialog->SetFileTypes(FileDialogFilters.Num(), FileDialogFilters.GetData());
    // show
    if (!SUCCEEDED(
        FileDialog->Show(static_cast<HWND>(FSlateApplication::Get().GetActiveTopLevelWindow()->GetNativeWindow()->
            GetOSWindowHandle()))))
    {
        return false;
    }
    TComPtr<IShellItem> Result;
    if (!SUCCEEDED(FileDialog->GetResult(&Result))) { return false; }
    PWSTR pFilePath = nullptr;
    if (SUCCEEDED(Result->GetDisplayName(SIGDN_FILESYSPATH, &pFilePath)))
    {
        FString SaveFilePath = pFilePath;
        int32 FilterIndex = 0;
        if (SUCCEEDED(FileDialog->GetFileTypeIndex(reinterpret_cast<UINT*>(&FilterIndex))))
        {
            FilterIndex -= 1; // GetFileTypeIndex returns a 1-based index
        }
        if (FileDialogFilters.IsValidIndex(FilterIndex))
        {
            const FString ExtensionPattern = FileDialogFilters[FilterIndex].pszSpec;
            TArray<FString> SaveExtensions;
            ExtensionPattern.ParseIntoArray(SaveExtensions, TEXT(";"));
            FString CleanExtension = SaveExtensions[0];
            if (CleanExtension == TEXT("*.*"))
            {
                CleanExtension.Reset();
            }
            else
            {
                int32 WildCardIndex = INDEX_NONE;
                if (CleanExtension.FindChar(TEXT('*'), WildCardIndex))
                {
                    CleanExtension = CleanExtension.RightChop(WildCardIndex + 1);
                }
            }
            FString SaveFileName = FPaths::GetCleanFilename(SaveFilePath);
            SaveFilePath = FPaths::GetPath(SaveFilePath);
            if (FPaths::GetExtension(SaveFileName).IsEmpty() && !CleanExtension.IsEmpty())
            {
                SaveFileName = FPaths::SetExtension(SaveFileName, CleanExtension);
            }
            OutFilePath = FPaths::ConvertRelativePathToFull(FPaths::Combine(SaveFilePath, SaveFileName));
        }
    }
    ::CoTaskMemFree(pFilePath);

    return true;
}

 

------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------

 

整理步骤记录:

在Engine\Source\Developer 找到DesktopPlatform和SlateFileDialogs(DesktopPlatform的依赖,也是属于Developer)文件夹..

然后将其复制粘贴到自己Project(插件里也可以)的Source中..

再修改掉DesktopPlatform和SlateFileDialogs的Module名称并builds装载即可(防止模块重名,不好区分),例如改成DesktopPlatformEx和SlateFileDialogsEx

 需要注意一下Build.cs 的PrivateIncludePaths路径

------------------------------------------------------------------------------------------------

 

DesktopPlatform模块的简单使用示例(打开文件对话框):

FString UCommonBPLibrary::OpenFileDialog()
{
    void* ParentWindowPtr = FSlateApplication::Get().GetActiveTopLevelWindow()->GetNativeWindow()->GetOSWindowHandle();
    IDesktopPlatform* DesktopPlatform = FDesktopPlatformModuleEx::Get();

    FJsonSerializableArray OutFileNames;

    if (DesktopPlatform)
    {

        EFileDialogFlags::Type SelectionFlag = EFileDialogFlags::None; 
        //A value of 0 represents single file selection while a value of 1 represents multiple file selection
        DesktopPlatform->OpenFileDialog( ParentWindowPtr, 
                                         TEXT( "选取一张图片" ), 
                                         TEXT( "/" ), 
                                         TEXT( "" ), 
                                         TEXT( "(Image Files)|*.BMP;*.JPG;*.PNG;*.JPEG;)" ), 
                                         SelectionFlag ,
                                         OutFileNames );

    }


    if (OutFileNames.Num() > 0)
    {
        return FString (OutFileNames[0]);
    }
    else 
    {
        return TEXT("");
    }  
}

TArray<FString> UCommonBPLibrary::OpenFileDialogMultiple()
{
    TArray<FString> ret_arr;

    void* ParentWindowPtr = FSlateApplication::Get().GetActiveTopLevelWindow()->GetNativeWindow()->GetOSWindowHandle();
    IDesktopPlatform* DesktopPlatform = FDesktopPlatformModuleEx::Get();

    FJsonSerializableArray OutFileNames;

    if (DesktopPlatform)
    {
        EFileDialogFlags::Type SelectionFlag = EFileDialogFlags::Multiple;
        //A value of 0 represents single file selection while a value of 1 represents multiple file selection
        DesktopPlatform->OpenFileDialog(ParentWindowPtr,
            TEXT("选取图片"),
            TEXT("/"),
            TEXT(""),
            TEXT("(Image Files)|*.BMP;*.JPG;*.PNG;*.JPEG;)"),
            SelectionFlag,
            OutFileNames);
    }

    for (int i = 0; i < OutFileNames.Num(); i++) 
    {
        ret_arr.Add(FString(OutFileNames[i]));
    }

    return ret_arr;
}

 

posted @ 2020-04-07 18:13  林清  阅读(3232)  评论(4编辑  收藏  举报