Opening a file dialog from a plugin

I’m trying to make an importer plugin to help port my project from another engine, and I’m already stumped at the first step: Trying to make a dialog to let the user pick a file to import. I’m trying to use FDesktopPlatformModule::Get()->OpenFileDialog(...); in PluginButtonClicked, but I die at getting the window handle:

GEngine->GameViewport->GetWindow()->GetNativeWindow()->GetOSWindowHandle()

This crashes with an access violation.

`violation - code c0000005 (first/second chance not available)

UE4Editor_Engine!TWeakPtr::Pin() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\core\public\templates\sharedpointer.h:998]
UE4Editor_Engine!UGameViewportClient::GetWindow() [d:\buildfarm\buildmachine_++depot+ue4-releases+4.10\engine\source\runtime\engine\classes\engine\gameviewportclient.h:298]
`

Is this the right way to approach this? Are there better ways to get the user to pick a file from disk?

1 Like

I’m guessing one of the pointers in that long chain is null.

You don’t actually need to give a parent window handle to OpenFileDialog, however Windows might do some weird stuff with focus if you don’t. If your plugin has its own window, then ideally this would be the window of your plugin rather than some random viewport in the editor; if not, then I guess you could use the MainFrame window handle.

You can also get the window handle from any widget, for example, this is how SFilePathPicker gets its window handle when opening a file picker:

TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().FindWidgetWindow(AsShared());
const void* ParentWindowHandle = (ParentWindow.IsValid() && ParentWindow->GetNativeWindow().IsValid())
	? ParentWindow->GetNativeWindow()->GetOSWindowHandle()
	: nullptr;

And this is how you’d get the general “I don’t know what window to use” window handle from the MainFrame (use this as an absolute last resort):

const void* ParentWindowWindowHandle = nullptr;
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
const TSharedPtr<SWindow>& MainFrameParentWindow = MainFrameModule.GetParentWindow();
if ( MainFrameParentWindow.IsValid() && MainFrameParentWindow->GetNativeWindow().IsValid() )
{
	ParentWindowWindowHandle = MainFrameParentWindow->GetNativeWindow()->GetOSWindowHandle();
}
1 Like

Excellent, leaving the handle arg null saved my day :slight_smile: