void openBrowseDialogCore(FileDialogType type, const Path& defaultPath, const String& filterList,
		Vector<Path>& paths, AsyncOp& returnValue)
	{
		// Init COM library.
		CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

		IFileDialog* fileDialog = nullptr;

		UINT32 dialogType = ((UINT32)type & (UINT32)FileDialogType::TypeMask);
		bool isOpenDialog = dialogType == (UINT32)FileDialogType::OpenFile || dialogType == (UINT32)FileDialogType::OpenFolder;

		// Create dialog
		IID classId = isOpenDialog ? CLSID_FileOpenDialog : CLSID_FileSaveDialog;
		CoCreateInstance(classId, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&fileDialog));

		addFiltersToDialog(fileDialog, filterList);
		setDefaultPath(fileDialog, defaultPath);

		// Apply multiselect flags
		bool isMultiselect = false;
		if (isOpenDialog)
		{
			if (dialogType == (UINT32)FileDialogType::OpenFile)
			{
				if (((UINT32)type & (UINT32)FileDialogType::Multiselect) != 0)
				{
					DWORD dwFlags;
					fileDialog->GetOptions(&dwFlags);
					fileDialog->SetOptions(dwFlags | FOS_ALLOWMULTISELECT);

					isMultiselect = true;
				}
			}
			else
			{
				DWORD dwFlags;
				fileDialog->GetOptions(&dwFlags);
				fileDialog->SetOptions(dwFlags | FOS_PICKFOLDERS);
			}
		}

		// Show the dialog
		bool finalResult = false;

		// Need to enable all windows, otherwise when the browse dialog closes the active window will become some 
		// background window
		Win32Window::_enableAllWindows();

		if (SUCCEEDED(fileDialog->Show(nullptr)))
		{
			if (isMultiselect)
			{
				// Get file names
				IFileOpenDialog* fileOpenDialog;
				fileDialog->QueryInterface(IID_IFileOpenDialog, (void**)&fileOpenDialog);
				
				IShellItemArray* shellItems = nullptr;
				fileOpenDialog->GetResults(&shellItems);

				getPaths(shellItems, paths);
				shellItems->Release();
				fileOpenDialog->Release();
			}
			else
			{
				// Get the file name
				IShellItem* shellItem = nullptr;
				fileDialog->GetResult(&shellItem);

				LPWSTR filePath = nullptr;
				shellItem->GetDisplayName(SIGDN_FILESYSPATH, &filePath);

				paths.push_back((Path)UTF8::fromWide(WString(filePath)));
				CoTaskMemFree(filePath);

				shellItem->Release();
			}

			finalResult = true;
		}

		// Restore modal window state (before we enabled all windows)
		Win32Window::_restoreModalWindows();

		CoUninitialize();

		returnValue._completeOperation(finalResult);
	}
예제 #2
0
//-----------------------------------------------------------------------------
bool VistaFileSelector::runModalInternal ()
{
	fileDialog = 0;
	HRESULT hr = -1;
	if (style == kSelectSaveFile)
	{
		hr = CoCreateInstance (CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IFileDialog, &fileDialog));
		if (defaultSaveName)
		{
			fileDialog->SetFileName (UTF8StringHelper (defaultSaveName));
		}
	}
	else
	{
		hr = CoCreateInstance (CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IFileDialog, &fileDialog));
		if (SUCCEEDED (hr))
		{
			if (style == kSelectDirectory)
			{
				DWORD dwOptions = 0;
				hr = fileDialog->GetOptions (&dwOptions);
				if (SUCCEEDED (hr))
					hr = fileDialog->SetOptions (dwOptions | FOS_PICKFOLDERS);
				if (FAILED (hr))
				{
					fileDialog->Release ();
					fileDialog = 0;
					return false;
				}
			}
			if (allowMultiFileSelection)
			{
				DWORD dwOptions = 0;
				hr = fileDialog->GetOptions (&dwOptions);
				if (SUCCEEDED (hr))
					hr = fileDialog->SetOptions (dwOptions | FOS_ALLOWMULTISELECT);
				if (FAILED (hr))
				{
					fileDialog->Release ();
					fileDialog = 0;
					return false;
				}
			}
		}
	}
	if (FAILED (hr))
	{
		fileDialog = 0;
		return false;
	}

	if (title)
		hr = fileDialog->SetTitle (UTF8StringHelper (title));

	DWORD numExtensions = 0;
	DWORD defaultFileTypeIndex = 0;
	COMDLG_FILTERSPEC* filters = buildExtensionFilter (extensions, defaultExtension, numExtensions, defaultFileTypeIndex);
	if (filters)
	{
		fileDialog->SetFileTypes (numExtensions, filters);
		if (defaultFileTypeIndex)
			fileDialog->SetFileTypeIndex (defaultFileTypeIndex);
	}
	if (initialPath && _SHCreateItemFromParsingName)
	{
		IShellItem* shellItem;
		hr = _SHCreateItemFromParsingName (UTF8StringHelper (initialPath), 0, IID_PPV_ARG (IShellItem, &shellItem));
		if (SUCCEEDED (hr))
		{
			fileDialog->SetFolder (shellItem);
			shellItem->Release ();
		}
	}
	Win32Frame* win32Frame = frame->getPlatformFrame () ? dynamic_cast<Win32Frame*> (frame->getPlatformFrame ()) : 0;
	hr = fileDialog->Show (win32Frame ? win32Frame->getPlatformWindow () : 0);
	if (SUCCEEDED (hr))
	{
		if (allowMultiFileSelection)
		{
			IFileOpenDialog* openFileDialog = 0;
			hr = fileDialog->QueryInterface (IID_PPV_ARG(IFileOpenDialog, &openFileDialog));
			if (SUCCEEDED (hr))
			{
				IShellItemArray* items;
				hr = openFileDialog->GetResults (&items);
				if (SUCCEEDED (hr))
				{
					DWORD count;
					hr = items->GetCount (&count);
					for (DWORD i = 0; i < count; i++)
					{
						IShellItem* item;
						hr = items->GetItemAt (i, &item);
						if (SUCCEEDED (hr))
						{
							LPWSTR filesysPath = 0;
							hr = item->GetDisplayName (SIGDN_FILESYSPATH, &filesysPath);
							if (SUCCEEDED (hr))
							{
								UTF8StringHelper str (filesysPath);
								UTF8StringBuffer resultPath = String::newWithString (str);
								result.push_back (resultPath);
							}
							item->Release ();
						}
					}
					items->Release ();
				}
				openFileDialog->Release ();
			}
		}
		else
		{
			IShellItem *item;
			hr = fileDialog->GetResult (&item);
			if (SUCCEEDED (hr))
			{
				LPWSTR filesysPath = 0;
				hr = item->GetDisplayName (SIGDN_FILESYSPATH, &filesysPath);
				if (SUCCEEDED (hr))
				{
					UTF8StringHelper str (filesysPath);
					UTF8StringBuffer resultPath = String::newWithString (str);
					result.push_back (resultPath);
				}
				item->Release ();
			}
		}
	}
	fileDialog->Release ();
	fileDialog = 0;
	freeExtensionFilter (filters);
	return SUCCEEDED (hr);
}