diff --git a/dev/Common/TerminalVelocityFeatures-StoragePickers2.h b/dev/Common/TerminalVelocityFeatures-StoragePickers2.h
new file mode 100644
index 0000000000..e44c4cfaa5
--- /dev/null
+++ b/dev/Common/TerminalVelocityFeatures-StoragePickers2.h
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft Corporation and Contributors.
+// Licensed under the MIT License.
+
+// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT IT
+
+// INPUT FILE: dev\Common\TerminalVelocityFeatures-StoragePickers2.xml
+// OPTIONS: -Channel Experimental -Language C++ -Namespace Microsoft.Windows.Storage.Pickers -Path dev\Common\TerminalVelocityFeatures-StoragePickers2.xml -Output dev\Common\TerminalVelocityFeatures-StoragePickers2.h
+
+#if defined(__midlrt)
+namespace features
+{
+ feature_name Feature_StoragePickers2 = { DisabledByDefault, FALSE };
+}
+#endif // defined(__midlrt)
+
+// Feature constants
+#define WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_STORAGE_PICKERS_FEATURE_STORAGEPICKERS2_ENABLED 1
+
+#if defined(__cplusplus)
+
+namespace Microsoft::Windows::Storage::Pickers
+{
+
+__pragma(detect_mismatch("ODR_violation_WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_STORAGE_PICKERS_FEATURE_STORAGEPICKERS2_ENABLED_mismatch", "AlwaysEnabled"))
+struct Feature_StoragePickers2
+{
+ static constexpr bool IsEnabled() { return WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_STORAGE_PICKERS_FEATURE_STORAGEPICKERS2_ENABLED == 1; }
+};
+
+} // namespace Microsoft.Windows.Storage.Pickers
+
+#endif // defined(__cplusplus)
diff --git a/dev/Common/TerminalVelocityFeatures-StoragePickers2.xml b/dev/Common/TerminalVelocityFeatures-StoragePickers2.xml
new file mode 100644
index 0000000000..b878a8128f
--- /dev/null
+++ b/dev/Common/TerminalVelocityFeatures-StoragePickers2.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+ Feature_StoragePickers2
+ New functionalities in StoragePickers for the WindowsAppRuntime: SuggestedDefaultFolder, FileTypeChoices
+ AlwaysEnabled
+
+ Preview
+ Stable
+
+
+
diff --git a/dev/Interop/StoragePickers/FileOpenPicker.cpp b/dev/Interop/StoragePickers/FileOpenPicker.cpp
index 775e6411ab..b61792f9ac 100644
--- a/dev/Interop/StoragePickers/FileOpenPicker.cpp
+++ b/dev/Interop/StoragePickers/FileOpenPicker.cpp
@@ -10,6 +10,7 @@
#include
#include
#include "TerminalVelocityFeatures-StoragePickers.h"
+#include "TerminalVelocityFeatures-StoragePickers2.h"
#include "PickerCommon.h"
#include "PickFileResult.h"
#include "PickerLocalization.h"
@@ -49,17 +50,46 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
PickerCommon::ValidateStringNoEmbeddedNulls(value);
m_commitButtonText = value;
}
- winrt::Windows::Foundation::Collections::IVector FileOpenPicker::FileTypeFilter()
+ winrt::Windows::Foundation::Collections::IMap> FileOpenPicker::FileTypeChoices()
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ return m_fileTypeChoices;
+ }
+ winrt::Windows::Foundation::Collections::IVector FileOpenPicker::FileTypeFilter()
{
return m_fileTypeFilter;
}
+ winrt::hstring FileOpenPicker::SuggestedFolder()
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ return m_suggestedFolder;
+ }
+ void FileOpenPicker::SuggestedFolder(winrt::hstring const& value)
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ PickerCommon::ValidateFolderPath(value, "SuggestedFolder");
+ m_suggestedFolder = value;
+ }
+ winrt::hstring FileOpenPicker::SuggestedStartFolder()
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ return m_suggestedStartFolder;
+ }
+ void FileOpenPicker::SuggestedStartFolder(winrt::hstring const& value)
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ PickerCommon::ValidateFolderPath(value, "SuggestedStartFolder");
+ m_suggestedStartFolder = value;
+ }
void FileOpenPicker::CaptureParameters(PickerCommon::PickerParameters& parameters)
{
parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId);
parameters.CommitButtonText = m_commitButtonText;
- parameters.PickerLocationId = m_suggestedStartLocation;
- parameters.CaptureFilterSpec(m_fileTypeFilter.GetView());
+ parameters.SuggestedFolder = m_suggestedFolder;
+ parameters.SuggestedStartLocation = m_suggestedStartLocation;
+ parameters.SuggestedStartFolder = m_suggestedStartFolder;
+ parameters.CaptureFilterSpecData(m_fileTypeFilter.GetView(), m_fileTypeChoices.GetView());
}
winrt::Windows::Foundation::IAsyncOperation FileOpenPicker::PickSingleFileAsync()
@@ -87,7 +117,6 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
auto dialog = create_instance(CLSID_FileOpenDialog, CLSCTX_INPROC_SERVER);
parameters.ConfigureDialog(dialog);
- check_hresult(dialog->SetFileTypeIndex(parameters.FileTypeFilterPara.size()));
{
auto hr = dialog->Show(parameters.HWnd);
@@ -142,7 +171,6 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
auto dialog = create_instance(CLSID_FileOpenDialog, CLSCTX_INPROC_SERVER);
parameters.ConfigureDialog(dialog);
- check_hresult(dialog->SetFileTypeIndex(parameters.FileTypeFilterPara.size()));
FILEOPENDIALOGOPTIONS dialogOptions;
check_hresult(dialog->GetOptions(&dialogOptions));
diff --git a/dev/Interop/StoragePickers/FileOpenPicker.h b/dev/Interop/StoragePickers/FileOpenPicker.h
index 47353b6310..c5ff80bc27 100644
--- a/dev/Interop/StoragePickers/FileOpenPicker.h
+++ b/dev/Interop/StoragePickers/FileOpenPicker.h
@@ -6,6 +6,7 @@
#include "PickerCommon.h"
#include "StoragePickersTelemetryHelper.h"
#include
+#include "FileTypeChoicesMap.h"
#include "FileTypeFilterVector.h"
namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
@@ -23,7 +24,14 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
winrt::hstring CommitButtonText();
void CommitButtonText(winrt::hstring const& value);
- winrt::Windows::Foundation::Collections::IVector FileTypeFilter();
+ winrt::Windows::Foundation::Collections::IVector FileTypeFilter();
+ winrt::Windows::Foundation::Collections::IMap> FileTypeChoices();
+
+ winrt::hstring SuggestedFolder();
+ void SuggestedFolder(winrt::hstring const& value);
+
+ winrt::hstring SuggestedStartFolder();
+ void SuggestedStartFolder(winrt::hstring const& value);
winrt::Windows::Foundation::IAsyncOperation PickSingleFileAsync();
winrt::Windows::Foundation::IAsyncOperation> PickMultipleFilesAsync();
@@ -34,7 +42,18 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified };
winrt::hstring m_commitButtonText{};
- winrt::Windows::Foundation::Collections::IVector m_fileTypeFilter{ make() };
+ winrt::Windows::Foundation::Collections::IVector m_fileTypeFilter{ make() };
+ winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{
+ []()
+ {
+ auto map = winrt::make_self();
+ map->ForFeature_StoragePickers2 = true;
+ return map.as>>();
+ }()
+ };
+
+ winrt::hstring m_suggestedFolder{};
+ winrt::hstring m_suggestedStartFolder{};
StoragePickersTelemetryHelper m_telemetryHelper{};
diff --git a/dev/Interop/StoragePickers/FileSavePicker.cpp b/dev/Interop/StoragePickers/FileSavePicker.cpp
index aa1f091b53..95e965be00 100644
--- a/dev/Interop/StoragePickers/FileSavePicker.cpp
+++ b/dev/Interop/StoragePickers/FileSavePicker.cpp
@@ -15,6 +15,7 @@
#include
#include
#include "TerminalVelocityFeatures-StoragePickers.h"
+#include "TerminalVelocityFeatures-StoragePickers2.h"
#include "PickerCommon.h"
#include "PickerLocalization.h"
#include "PickFileResult.h"
@@ -63,10 +64,22 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
}
void FileSavePicker::SuggestedFolder(hstring const& value)
{
- PickerCommon::ValidateSuggestedFolder(value);
+ PickerCommon::ValidateFolderPath(value, "SuggestedFolder");
m_suggestedFolder = value;
}
+ hstring FileSavePicker::SuggestedStartFolder()
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ return m_suggestedStartFolder;
+ }
+ void FileSavePicker::SuggestedStartFolder(hstring const& value)
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ PickerCommon::ValidateFolderPath(value, "SuggestedStartFolder");
+ m_suggestedStartFolder = value;
+ }
+
hstring FileSavePicker::SuggestedFileName()
{
return m_suggestedFileName;
@@ -82,10 +95,13 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
{
parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId);
parameters.CommitButtonText = m_commitButtonText;
- parameters.PickerLocationId = m_suggestedStartLocation;
parameters.SuggestedFileName = m_suggestedFileName;
parameters.SuggestedFolder = m_suggestedFolder;
- parameters.CaptureFilterSpec(m_fileTypeChoices.GetView());
+ parameters.SuggestedStartLocation = m_suggestedStartLocation;
+ parameters.SuggestedStartFolder = m_suggestedStartFolder;
+ parameters.CaptureFilterSpecData(
+ winrt::Windows::Foundation::Collections::IVectorView{},
+ m_fileTypeChoices.GetView());
}
winrt::Windows::Foundation::IAsyncOperation FileSavePicker::PickSaveFileAsync()
diff --git a/dev/Interop/StoragePickers/FileSavePicker.h b/dev/Interop/StoragePickers/FileSavePicker.h
index 59a3eb977a..849c819819 100644
--- a/dev/Interop/StoragePickers/FileSavePicker.h
+++ b/dev/Interop/StoragePickers/FileSavePicker.h
@@ -29,6 +29,9 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
hstring SuggestedFolder();
void SuggestedFolder(hstring const& value);
+ hstring SuggestedStartFolder();
+ void SuggestedStartFolder(hstring const& value);
+
hstring SuggestedFileName();
void SuggestedFileName(hstring const& value);
@@ -41,6 +44,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{ make() };
hstring m_defaultFileExtension{};
hstring m_suggestedFolder{};
+ hstring m_suggestedStartFolder{};
hstring m_suggestedFileName{};
StoragePickersTelemetryHelper m_telemetryHelper{};
diff --git a/dev/Interop/StoragePickers/FileTypeChoicesMap.cpp b/dev/Interop/StoragePickers/FileTypeChoicesMap.cpp
index 3f04a4a373..0d8571ed8b 100644
--- a/dev/Interop/StoragePickers/FileTypeChoicesMap.cpp
+++ b/dev/Interop/StoragePickers/FileTypeChoicesMap.cpp
@@ -4,6 +4,7 @@
#include "pch.h"
#include "FileTypeChoicesMap.h"
#include "FileTypeFilterVector.h"
+#include "TerminalVelocityFeatures-StoragePickers2.h"
namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
{
@@ -13,6 +14,11 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
bool FileTypeChoicesMap::Insert(hstring const& key, winrt::Windows::Foundation::Collections::IVector const& value)
{
+ if (ForFeature_StoragePickers2)
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ }
+
// Create a new FileTypeFilterVector and copy all values from the input vector
auto validatingVector = make();
diff --git a/dev/Interop/StoragePickers/FileTypeChoicesMap.h b/dev/Interop/StoragePickers/FileTypeChoicesMap.h
index 0f1e2a1a87..1dc6143667 100644
--- a/dev/Interop/StoragePickers/FileTypeChoicesMap.h
+++ b/dev/Interop/StoragePickers/FileTypeChoicesMap.h
@@ -13,6 +13,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
{
FileTypeChoicesMap();
+ bool ForFeature_StoragePickers2{ false };
+
// IMap>
winrt::Windows::Foundation::Collections::IVector Lookup(hstring const& key) const;
uint32_t Size() const;
diff --git a/dev/Interop/StoragePickers/FolderPicker.cpp b/dev/Interop/StoragePickers/FolderPicker.cpp
index c95a581607..5da7ab331e 100644
--- a/dev/Interop/StoragePickers/FolderPicker.cpp
+++ b/dev/Interop/StoragePickers/FolderPicker.cpp
@@ -9,6 +9,7 @@
#include
#include
#include "TerminalVelocityFeatures-StoragePickers.h"
+#include "TerminalVelocityFeatures-StoragePickers2.h"
#include "PickerCommon.h"
#include "PickFolderResult.h"
#include "PickerLocalization.h"
@@ -47,15 +48,38 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
PickerCommon::ValidateStringNoEmbeddedNulls(value);
m_commitButtonText = value;
}
+ hstring FolderPicker::SuggestedFolder()
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ return m_suggestedFolder;
+ }
+ void FolderPicker::SuggestedFolder(hstring const& value)
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ PickerCommon::ValidateFolderPath(value, "SuggestedFolder");
+ m_suggestedFolder = value;
+ }
+ hstring FolderPicker::SuggestedStartFolder()
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ return m_suggestedStartFolder;
+ }
+ void FolderPicker::SuggestedStartFolder(hstring const& value)
+ {
+ THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled());
+ PickerCommon::ValidateFolderPath(value, "SuggestedStartFolder");
+ m_suggestedStartFolder = value;
+ }
void FolderPicker::CaptureParameters(PickerCommon::PickerParameters& parameters)
{
parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId);
parameters.CommitButtonText = m_commitButtonText;
- parameters.PickerLocationId = m_suggestedStartLocation;
+ parameters.SuggestedFolder = m_suggestedFolder;
+ parameters.SuggestedStartLocation = m_suggestedStartLocation;
+ parameters.SuggestedStartFolder = m_suggestedStartFolder;
}
-
winrt::Windows::Foundation::IAsyncOperation FolderPicker::PickSingleFolderAsync()
{
// TODO: remove get strong reference when telementry is safe stop
diff --git a/dev/Interop/StoragePickers/FolderPicker.h b/dev/Interop/StoragePickers/FolderPicker.h
index f5e8f88136..49e7c4b1f7 100644
--- a/dev/Interop/StoragePickers/FolderPicker.h
+++ b/dev/Interop/StoragePickers/FolderPicker.h
@@ -21,6 +21,12 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
hstring CommitButtonText();
void CommitButtonText(hstring const& value);
+ hstring SuggestedFolder();
+ void SuggestedFolder(hstring const& value);
+
+ hstring SuggestedStartFolder();
+ void SuggestedStartFolder(hstring const& value);
+
winrt::Windows::Foundation::IAsyncOperation PickSingleFolderAsync();
private:
@@ -29,6 +35,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
PickerViewMode m_viewMode{ PickerViewMode::List };
PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified };
hstring m_commitButtonText{};
+ hstring m_suggestedFolder{};
+ hstring m_suggestedStartFolder{};
StoragePickersTelemetryHelper m_telemetryHelper{};
void CaptureParameters(PickerCommon::PickerParameters& parameters);
diff --git a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl
index 895fb2c621..c71d622193 100644
--- a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl
+++ b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl
@@ -1,11 +1,13 @@
// Copyright (c) Microsoft Corporation and Contributors.
// Licensed under the MIT License.
+#include
+
namespace Microsoft.Windows.Storage.Pickers
{
- [contractversion(1.8)]
+ [contractversion(2.0)]
apicontract StoragePickersContract {};
-
+
[contract(StoragePickersContract, 1.8)]
enum PickerViewMode
{
@@ -41,8 +43,21 @@ namespace Microsoft.Windows.Storage.Pickers
Microsoft.Windows.Storage.Pickers.PickerViewMode ViewMode;
Microsoft.Windows.Storage.Pickers.PickerLocationId SuggestedStartLocation;
String CommitButtonText;
+
+ [contract(StoragePickersContract, 2.0)]
+ [feature(Feature_StoragePickers2)]
+ Windows.Foundation.Collections.IMap > FileTypeChoices{ get; };
+
Windows.Foundation.Collections.IVector FileTypeFilter{ get; };
+ [contract(StoragePickersContract, 2.0)]
+ [feature(Feature_StoragePickers2)]
+ String SuggestedFolder;
+
+ [contract(StoragePickersContract, 2.0)]
+ [feature(Feature_StoragePickers2)]
+ String SuggestedStartFolder;
+
[remote_sync] Windows.Foundation.IAsyncOperation PickSingleFileAsync();
[remote_sync] Windows.Foundation.IAsyncOperation > PickMultipleFilesAsync();
}
@@ -59,6 +74,10 @@ namespace Microsoft.Windows.Storage.Pickers
String SuggestedFileName;
String SuggestedFolder;
+ [contract(StoragePickersContract, 2.0)]
+ [feature(Feature_StoragePickers2)]
+ String SuggestedStartFolder;
+
[remote_sync] Windows.Foundation.IAsyncOperation PickSaveFileAsync();
}
@@ -77,6 +96,14 @@ namespace Microsoft.Windows.Storage.Pickers
Microsoft.Windows.Storage.Pickers.PickerLocationId SuggestedStartLocation;
String CommitButtonText;
+ [contract(StoragePickersContract, 2.0)]
+ [feature(Feature_StoragePickers2)]
+ String SuggestedFolder;
+
+ [contract(StoragePickersContract, 2.0)]
+ [feature(Feature_StoragePickers2)]
+ String SuggestedStartFolder;
+
[remote_sync] Windows.Foundation.IAsyncOperation PickSingleFolderAsync();
}
}
diff --git a/dev/Interop/StoragePickers/PickerCommon.cpp b/dev/Interop/StoragePickers/PickerCommon.cpp
index dec7a50d3a..d5c003cc77 100644
--- a/dev/Interop/StoragePickers/PickerCommon.cpp
+++ b/dev/Interop/StoragePickers/PickerCommon.cpp
@@ -12,6 +12,8 @@
#include
#include
#include
+#include
+#include
namespace {
@@ -224,7 +226,7 @@ namespace PickerCommon {
ValidateStringNoEmbeddedNulls(suggestedFileName);
}
- void ValidateSuggestedFolder(winrt::hstring const& path)
+ void ValidateFolderPath(winrt::hstring const& path, std::string const& propertyName)
{
if (path.empty())
{
@@ -237,13 +239,14 @@ namespace PickerCommon {
auto pathObj = std::filesystem::path(path.c_str());
if (!pathObj.is_absolute())
{
- throw std::invalid_argument("SuggestedFolder");
+ throw std::invalid_argument(propertyName);
}
+ // The method SHSimpleIDListFromPath does syntax check on the path string.
wil::unique_cotaskmem_ptr pidl(SHSimpleIDListFromPath(path.c_str()));
if (!pidl)
{
- throw std::invalid_argument("SuggestedFolder");
+ throw std::invalid_argument(propertyName);
}
}
@@ -278,6 +281,28 @@ namespace PickerCommon {
return result;
}
+ void PickerParameters::CaptureFilterSpecData(
+ winrt::Windows::Foundation::Collections::IVectorView fileTypeFilterView,
+ winrt::Windows::Foundation::Collections::IMapView> fileTypeChoicesView)
+ {
+ // The FileTypeChoices takes precedence over FileTypeFilter if both are provided.
+ if (fileTypeChoicesView && fileTypeChoicesView.Size() > 0)
+ {
+ CaptureFilterSpec(fileTypeChoicesView);
+ return;
+ }
+
+ if (fileTypeFilterView && fileTypeFilterView.Size() > 0)
+ {
+ CaptureFilterSpec(fileTypeFilterView);
+ return;
+ }
+
+ // Even if no filters provided, we still need to set filter to All Files *.*
+ auto emptyFilters = winrt::single_threaded_vector();
+ CaptureFilterSpec(emptyFilters.GetView());
+ }
+
///
/// Capture and processing pickers filter inputs and convert them into Common Item Dialog's accepting type, for FileOpenPicker
///
@@ -330,6 +355,8 @@ namespace PickerCommon {
{
FileTypeFilterPara.push_back({ FileTypeFilterData.at(i * 2).c_str(), FileTypeFilterData.at(i * 2 + 1).c_str() });
}
+
+ FocusLastFilter = true;
}
///
@@ -372,15 +399,41 @@ namespace PickerCommon {
check_hresult(dialog->SetOkButtonLabel(CommitButtonText.c_str()));
}
- auto defaultFolder = GetKnownFolderFromId(PickerLocationId);
- if (defaultFolder != nullptr)
+ winrt::com_ptr defaultFolder{};
+
+ // The SuggestedStartFolder takes precedence over SuggestedStartLocation if both are provided.
+ if (!IsHStringNullOrEmpty(SuggestedStartFolder))
+ {
+ defaultFolder = TryParseFolderItem(SuggestedStartFolder);
+ }
+
+ if (!defaultFolder)
+ {
+ defaultFolder = GetKnownFolderFromId(SuggestedStartLocation);
+ }
+
+ if (defaultFolder)
{
check_hresult(dialog->SetDefaultFolder(defaultFolder.get()));
}
+ // SuggestedFolder takes precedence over SuggestedStartFolder/SuggestedStartLocation if both are provided.
+ if (!IsHStringNullOrEmpty(SuggestedFolder))
+ {
+ if (auto folderItem = TryParseFolderItem(SuggestedFolder))
+ {
+ check_hresult(dialog->SetFolder(folderItem.get()));
+ }
+ }
+
if (FileTypeFilterPara.size() > 0)
{
check_hresult(dialog->SetFileTypes((UINT)FileTypeFilterPara.size(), FileTypeFilterPara.data()));
+
+ if (FocusLastFilter)
+ {
+ check_hresult(dialog->SetFileTypeIndex(FileTypeFilterPara.size()));
+ }
}
}
@@ -395,13 +448,5 @@ namespace PickerCommon {
check_hresult(dialog->SetFileName(SuggestedFileName.c_str()));
}
- if (!PickerCommon::IsHStringNullOrEmpty(SuggestedFolder))
- {
- winrt::com_ptr folderItem = TryParseFolderItem(SuggestedFolder);
- if (folderItem)
- {
- check_hresult(dialog->SetFolder(folderItem.get()));
- }
- }
}
}
diff --git a/dev/Interop/StoragePickers/PickerCommon.h b/dev/Interop/StoragePickers/PickerCommon.h
index 124a9eb261..f2bc2045ab 100644
--- a/dev/Interop/StoragePickers/PickerCommon.h
+++ b/dev/Interop/StoragePickers/PickerCommon.h
@@ -26,26 +26,33 @@ namespace PickerCommon {
void ValidateSuggestedStartLocation(winrt::Microsoft::Windows::Storage::Pickers::PickerLocationId const& value);
void ValidateSingleFileTypeFilterElement(winrt::hstring const& filter);
void ValidateSuggestedFileName(winrt::hstring const& suggestedFileName);
- void ValidateSuggestedFolder(winrt::hstring const& path);
+ void ValidateFolderPath(winrt::hstring const& path, std::string const& propertyName);
struct PickerParameters {
HWND HWnd{};
winrt::hstring CommitButtonText;
- winrt::Microsoft::Windows::Storage::Pickers::PickerLocationId PickerLocationId;
+ winrt::Microsoft::Windows::Storage::Pickers::PickerLocationId SuggestedStartLocation;
std::vector FileTypeFilterData{};
std::vector FileTypeFilterPara{};
+ bool FocusLastFilter{ false };
winrt::hstring AllFilesText{ L"All Files" }; // initialize to All Files as a default value, will be updated by localization
winrt::hstring SuggestedFileName;
winrt::hstring SuggestedFolder;
+ winrt::hstring SuggestedStartFolder;
winrt::hstring FormatExtensionWithWildcard(winrt::hstring extension);
winrt::hstring JoinExtensions(winrt::Windows::Foundation::Collections::IVectorView extensions);
- void CaptureFilterSpec(winrt::Windows::Foundation::Collections::IVectorView filters);
- void CaptureFilterSpec(winrt::Windows::Foundation::Collections::IMapView> filters);
+ void CaptureFilterSpecData(
+ winrt::Windows::Foundation::Collections::IVectorView fileTypeFilterView,
+ winrt::Windows::Foundation::Collections::IMapView> fileTypeChoicesView);
void ConfigureDialog(winrt::com_ptr dialog);
void ConfigureFileSaveDialog(winrt::com_ptr dialog);
+
+ private:
+ void CaptureFilterSpec(winrt::Windows::Foundation::Collections::IVectorView filters);
+ void CaptureFilterSpec(winrt::Windows::Foundation::Collections::IMapView> filters);
};
}
diff --git a/test/StoragePickersTests/PickerCommonTests.cpp b/test/StoragePickersTests/PickerCommonTests.cpp
index 29c870c7f8..555eec06a1 100644
--- a/test/StoragePickersTests/PickerCommonTests.cpp
+++ b/test/StoragePickersTests/PickerCommonTests.cpp
@@ -99,6 +99,7 @@ namespace Test::PickerCommonTests
// Act.
auto dialog = winrt::create_instance(CLSID_FileSaveDialog, CLSCTX_INPROC_SERVER);
+ parameters.ConfigureDialog(dialog.as());
parameters.ConfigureFileSaveDialog(dialog);
// Assert.
@@ -130,6 +131,7 @@ namespace Test::PickerCommonTests
// Act.
auto dialog = winrt::create_instance(CLSID_FileSaveDialog, CLSCTX_INPROC_SERVER);
+ parameters.ConfigureDialog(dialog.as());
parameters.ConfigureFileSaveDialog(dialog);
// Assert.
@@ -150,7 +152,7 @@ namespace Test::PickerCommonTests
// Act.
PickerParameters parameters{};
- parameters.CaptureFilterSpec(picker.FileTypeFilter().GetView());
+ parameters.CaptureFilterSpecData(picker.FileTypeFilter().GetView(), nullptr);
// Assert.
VERIFY_ARE_EQUAL(parameters.FileTypeFilterPara.size(), 3);
@@ -176,7 +178,7 @@ namespace Test::PickerCommonTests
// Act.
PickerParameters parameters{};
- parameters.CaptureFilterSpec(picker.FileTypeFilter().GetView());
+ parameters.CaptureFilterSpecData(picker.FileTypeFilter().GetView(), nullptr);
// Assert.
VERIFY_ARE_EQUAL(parameters.FileTypeFilterPara.size(), 1);
@@ -196,7 +198,7 @@ namespace Test::PickerCommonTests
// Act.
PickerParameters parameters{};
- parameters.CaptureFilterSpec(picker.FileTypeFilter().GetView());
+ parameters.CaptureFilterSpecData(picker.FileTypeFilter().GetView(), nullptr);
// Assert.
VERIFY_ARE_EQUAL(parameters.FileTypeFilterPara.size(), 1);
@@ -206,6 +208,34 @@ namespace Test::PickerCommonTests
L"*");
}
+ TEST_METHOD(VerifyFilters_FileOpenPickerWhenFileTypeChoicesDefinedExpectMatchingSpec)
+ {
+ // Arrange.
+ winrt::Microsoft::UI::WindowId windowId{};
+ winrt::Microsoft::Windows::Storage::Pickers::FileOpenPicker picker(windowId);
+
+ picker.FileTypeChoices().Insert(
+ L"Documents", winrt::single_threaded_vector({ L".txt", L".doc", L".docx" }));
+ picker.FileTypeChoices().Insert(
+ L"Pictures", winrt::single_threaded_vector({ L".png", L".jpg", L".jpeg", L".bmp" }));
+
+ // Act.
+ PickerParameters parameters{};
+ parameters.CaptureFilterSpecData(
+ winrt::Windows::Foundation::Collections::IVectorView{},
+ picker.FileTypeChoices().GetView());
+
+ // Assert.
+ VERIFY_ARE_EQUAL(parameters.FileTypeFilterPara.size(), 2);
+
+ VERIFY_ARE_EQUAL(
+ std::wstring(parameters.FileTypeFilterPara[0].pszSpec),
+ L"*.txt;*.doc;*.docx");
+ VERIFY_ARE_EQUAL(
+ std::wstring(parameters.FileTypeFilterPara[1].pszSpec),
+ L"*.png;*.jpg;*.jpeg;*.bmp");
+ }
+
TEST_METHOD(VerifyFilters_FileSavePickerWhenFileTypeChoicesDefinedExpectMatchingSpec)
{
// Arrange.
@@ -219,7 +249,9 @@ namespace Test::PickerCommonTests
// Act.
PickerParameters parameters{};
- parameters.CaptureFilterSpec(picker.FileTypeChoices().GetView());
+ parameters.CaptureFilterSpecData(
+ winrt::Windows::Foundation::Collections::IVectorView{},
+ picker.FileTypeChoices().GetView());
// Assert.
VERIFY_ARE_EQUAL(parameters.FileTypeFilterPara.size(), 2);
@@ -242,7 +274,9 @@ namespace Test::PickerCommonTests
// Act.
PickerParameters parameters{};
- parameters.CaptureFilterSpec(picker.FileTypeChoices().GetView());
+ parameters.CaptureFilterSpecData(
+ winrt::Windows::Foundation::Collections::IVectorView{},
+ picker.FileTypeChoices().GetView());
// Assert.
VERIFY_ARE_EQUAL(parameters.FileTypeFilterPara.size(), 1);
@@ -250,6 +284,9 @@ namespace Test::PickerCommonTests
VERIFY_ARE_EQUAL(
std::wstring(parameters.FileTypeFilterPara[0].pszSpec),
L"*");
+ VERIFY_ARE_EQUAL(
+ std::wstring(parameters.FileTypeFilterPara[0].pszName),
+ L"All Files");
}
TEST_METHOD(VerifyFilters_FileSavePickerWhenAsteriskFileTypeChoicesDefinedExpectAsteriskSpec)
@@ -265,7 +302,9 @@ namespace Test::PickerCommonTests
// Act.
PickerParameters parameters{};
- parameters.CaptureFilterSpec(picker.FileTypeChoices().GetView());
+ parameters.CaptureFilterSpecData(
+ winrt::Windows::Foundation::Collections::IVectorView{},
+ picker.FileTypeChoices().GetView());
// Assert.
VERIFY_ARE_EQUAL(parameters.FileTypeFilterPara.size(), 1);
@@ -628,6 +667,9 @@ namespace Test::PickerCommonTests
{
picker.SuggestedFolder(suggestedFolder);
VERIFY_ARE_EQUAL(picker.SuggestedFolder(), suggestedFolder);
+
+ picker.SuggestedStartFolder(suggestedFolder);
+ VERIFY_ARE_EQUAL(picker.SuggestedStartFolder(), suggestedFolder);
}
else
{
@@ -641,6 +683,17 @@ namespace Test::PickerCommonTests
{
// Expected exception for invalid suggested folder
}
+
+ try
+ {
+ picker.SuggestedStartFolder(suggestedFolder);
+ std::wstring errorMessage = L"Expected exception for invalid suggested start folder: " + std::wstring(suggestedFolder);
+ VERIFY_FAIL(errorMessage.c_str());
+ }
+ catch (...)
+ {
+ // Expected exception for invalid suggested start folder
+ }
}
}
}
diff --git a/test/StoragePickersTests/StoragePickersTests.cpp b/test/StoragePickersTests/StoragePickersTests.cpp
index 5c63b5a2d2..97721e7c2a 100644
--- a/test/StoragePickersTests/StoragePickersTests.cpp
+++ b/test/StoragePickersTests/StoragePickersTests.cpp
@@ -153,6 +153,17 @@ namespace Test::StoragePickersTests
picker.FileTypeFilter().Append(L"*");
VERIFY_ARE_EQUAL(picker.FileTypeFilter().GetAt(0), L"*");
+
+ auto openPickerChoices = winrt::single_threaded_vector();
+ openPickerChoices.Append(L".txt");
+ picker.FileTypeChoices().Insert(L"Documents", openPickerChoices);
+ VERIFY_ARE_EQUAL(picker.FileTypeChoices().Lookup(L"Documents").GetAt(0), L".txt");
+
+ picker.SuggestedFolder(L"C:\\temp_fileopenpicker_ut_temp");
+ VERIFY_ARE_EQUAL(picker.SuggestedFolder(), L"C:\\temp_fileopenpicker_ut_temp");
+
+ picker.SuggestedStartFolder(L"C:\\temp_fileopenpicker_ut_start");
+ VERIFY_ARE_EQUAL(picker.SuggestedStartFolder(), L"C:\\temp_fileopenpicker_ut_start");
}
TEST_METHOD(VerifyFileSavePickerOptionsAreReadCorrectly)
@@ -174,6 +185,9 @@ namespace Test::StoragePickersTests
filters.Append(L"*");
picker.FileTypeChoices().Insert(L"All Files", filters);
VERIFY_ARE_EQUAL(picker.FileTypeChoices().Lookup(L"All Files").GetAt(0), L"*");
+
+ picker.SuggestedStartFolder(L"C:\\temp_filesavepicker_start");
+ VERIFY_ARE_EQUAL(picker.SuggestedStartFolder(), L"C:\\temp_filesavepicker_start");
}
TEST_METHOD(VerifyFolderPickerOptionsAreReadCorrectly)
@@ -193,6 +207,12 @@ namespace Test::StoragePickersTests
picker.CommitButtonText(L"commit");
VERIFY_ARE_EQUAL(picker.CommitButtonText(), L"commit");
+
+ picker.SuggestedFolder(L"C:\\temp_folderpicker_ut_temp");
+ VERIFY_ARE_EQUAL(picker.SuggestedFolder(), L"C:\\temp_folderpicker_ut_temp");
+
+ picker.SuggestedStartFolder(L"C:\\temp_folderpicker_ut_start");
+ VERIFY_ARE_EQUAL(picker.SuggestedStartFolder(), L"C:\\temp_folderpicker_ut_start");
}
};