From 5044a9ffb6b23d37e7ab1b6ebf9185e51e945785 Mon Sep 17 00:00:00 2001 From: DinahK-2SO <116714259+DinahK-2SO@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:05:27 +0800 Subject: [PATCH 1/6] settings identifier --- dev/Interop/StoragePickers/FileOpenPicker.cpp | 10 ++++++++ dev/Interop/StoragePickers/FileOpenPicker.h | 4 +++ dev/Interop/StoragePickers/FileSavePicker.cpp | 10 ++++++++ dev/Interop/StoragePickers/FileSavePicker.h | 4 +++ dev/Interop/StoragePickers/FolderPicker.cpp | 10 ++++++++ dev/Interop/StoragePickers/FolderPicker.h | 4 +++ .../Microsoft.Windows.Storage.Pickers.idl | 4 +++ dev/Interop/StoragePickers/PickerCommon.cpp | 25 +++++++++++++++++++ dev/Interop/StoragePickers/PickerCommon.h | 4 +++ 9 files changed, 75 insertions(+) diff --git a/dev/Interop/StoragePickers/FileOpenPicker.cpp b/dev/Interop/StoragePickers/FileOpenPicker.cpp index b61792f9ac..950a3bf32a 100644 --- a/dev/Interop/StoragePickers/FileOpenPicker.cpp +++ b/dev/Interop/StoragePickers/FileOpenPicker.cpp @@ -50,6 +50,15 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerCommon::ValidateStringNoEmbeddedNulls(value); m_commitButtonText = value; } + winrt::hstring FileOpenPicker::SettingsIdentifier() + { + return m_settingsIdentifier; + } + void FileOpenPicker::SettingsIdentifier(winrt::hstring const& value) + { + PickerCommon::ValidateStringNoEmbeddedNulls(value); + m_settingsIdentifier = value; + } winrt::Windows::Foundation::Collections::IMap> FileOpenPicker::FileTypeChoices() { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); @@ -86,6 +95,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId); parameters.CommitButtonText = m_commitButtonText; + parameters.SettingsIdentifier = m_settingsIdentifier; parameters.SuggestedFolder = m_suggestedFolder; parameters.SuggestedStartLocation = m_suggestedStartLocation; parameters.SuggestedStartFolder = m_suggestedStartFolder; diff --git a/dev/Interop/StoragePickers/FileOpenPicker.h b/dev/Interop/StoragePickers/FileOpenPicker.h index c5ff80bc27..de94d7e6b3 100644 --- a/dev/Interop/StoragePickers/FileOpenPicker.h +++ b/dev/Interop/StoragePickers/FileOpenPicker.h @@ -24,6 +24,9 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::hstring CommitButtonText(); void CommitButtonText(winrt::hstring const& value); + winrt::hstring SettingsIdentifier(); + void SettingsIdentifier(winrt::hstring const& value); + winrt::Windows::Foundation::Collections::IVector FileTypeFilter(); winrt::Windows::Foundation::Collections::IMap> FileTypeChoices(); @@ -41,6 +44,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerViewMode m_viewMode{ PickerViewMode::List }; PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified }; winrt::hstring m_commitButtonText{}; + winrt::hstring m_settingsIdentifier{}; winrt::Windows::Foundation::Collections::IVector m_fileTypeFilter{ make() }; winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{ diff --git a/dev/Interop/StoragePickers/FileSavePicker.cpp b/dev/Interop/StoragePickers/FileSavePicker.cpp index 7ffe72f818..4c2b2e3ef6 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.cpp +++ b/dev/Interop/StoragePickers/FileSavePicker.cpp @@ -46,6 +46,15 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerCommon::ValidateStringNoEmbeddedNulls(value); m_commitButtonText = value; } + winrt::hstring FileSavePicker::SettingsIdentifier() + { + return m_settingsIdentifier; + } + void FileSavePicker::SettingsIdentifier(winrt::hstring const& value) + { + PickerCommon::ValidateStringNoEmbeddedNulls(value); + m_settingsIdentifier = value; + } winrt::Windows::Foundation::Collections::IMap> FileSavePicker::FileTypeChoices() { return m_fileTypeChoices; @@ -95,6 +104,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId); parameters.CommitButtonText = m_commitButtonText; + parameters.SettingsIdentifier = m_settingsIdentifier; parameters.SuggestedFileName = m_suggestedFileName; parameters.SuggestedFolder = m_suggestedFolder; parameters.SuggestedStartLocation = m_suggestedStartLocation; diff --git a/dev/Interop/StoragePickers/FileSavePicker.h b/dev/Interop/StoragePickers/FileSavePicker.h index 849c819819..b0dc7a7d1b 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.h +++ b/dev/Interop/StoragePickers/FileSavePicker.h @@ -21,6 +21,9 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation hstring CommitButtonText(); void CommitButtonText(hstring const& value); + winrt::hstring SettingsIdentifier(); + void SettingsIdentifier(winrt::hstring const& value); + winrt::Windows::Foundation::Collections::IMap> FileTypeChoices(); hstring DefaultFileExtension(); @@ -41,6 +44,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::Microsoft::UI::WindowId m_windowId{}; PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified }; hstring m_commitButtonText{}; + winrt::hstring m_settingsIdentifier{}; winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{ make() }; hstring m_defaultFileExtension{}; hstring m_suggestedFolder{}; diff --git a/dev/Interop/StoragePickers/FolderPicker.cpp b/dev/Interop/StoragePickers/FolderPicker.cpp index 5da7ab331e..4d4b0c4be9 100644 --- a/dev/Interop/StoragePickers/FolderPicker.cpp +++ b/dev/Interop/StoragePickers/FolderPicker.cpp @@ -48,6 +48,15 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerCommon::ValidateStringNoEmbeddedNulls(value); m_commitButtonText = value; } + winrt::hstring FolderPicker::SettingsIdentifier() + { + return m_settingsIdentifier; + } + void FolderPicker::SettingsIdentifier(winrt::hstring const& value) + { + PickerCommon::ValidateStringNoEmbeddedNulls(value); + m_settingsIdentifier = value; + } hstring FolderPicker::SuggestedFolder() { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); @@ -75,6 +84,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId); parameters.CommitButtonText = m_commitButtonText; + parameters.SettingsIdentifier = m_settingsIdentifier; parameters.SuggestedFolder = m_suggestedFolder; parameters.SuggestedStartLocation = m_suggestedStartLocation; parameters.SuggestedStartFolder = m_suggestedStartFolder; diff --git a/dev/Interop/StoragePickers/FolderPicker.h b/dev/Interop/StoragePickers/FolderPicker.h index 49e7c4b1f7..c26aba8bfb 100644 --- a/dev/Interop/StoragePickers/FolderPicker.h +++ b/dev/Interop/StoragePickers/FolderPicker.h @@ -21,6 +21,9 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation hstring CommitButtonText(); void CommitButtonText(hstring const& value); + winrt::hstring SettingsIdentifier(); + void SettingsIdentifier(winrt::hstring const& value); + hstring SuggestedFolder(); void SuggestedFolder(hstring const& value); @@ -35,6 +38,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerViewMode m_viewMode{ PickerViewMode::List }; PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified }; hstring m_commitButtonText{}; + hstring m_settingsIdentifier{}; hstring m_suggestedFolder{}; hstring m_suggestedStartFolder{}; StoragePickersTelemetryHelper m_telemetryHelper{}; diff --git a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl index c71d622193..ab8a46dbfe 100644 --- a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl +++ b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl @@ -43,6 +43,7 @@ namespace Microsoft.Windows.Storage.Pickers Microsoft.Windows.Storage.Pickers.PickerViewMode ViewMode; Microsoft.Windows.Storage.Pickers.PickerLocationId SuggestedStartLocation; String CommitButtonText; + String SettingsIdentifier; [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] @@ -69,6 +70,8 @@ namespace Microsoft.Windows.Storage.Pickers Microsoft.Windows.Storage.Pickers.PickerLocationId SuggestedStartLocation; String CommitButtonText; + String SettingsIdentifier; + Windows.Foundation.Collections.IMap > FileTypeChoices{ get; }; String DefaultFileExtension; String SuggestedFileName; @@ -95,6 +98,7 @@ namespace Microsoft.Windows.Storage.Pickers Microsoft.Windows.Storage.Pickers.PickerViewMode ViewMode; Microsoft.Windows.Storage.Pickers.PickerLocationId SuggestedStartLocation; String CommitButtonText; + String SettingsIdentifier; [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] diff --git a/dev/Interop/StoragePickers/PickerCommon.cpp b/dev/Interop/StoragePickers/PickerCommon.cpp index 3ba9effe05..784aa3e915 100644 --- a/dev/Interop/StoragePickers/PickerCommon.cpp +++ b/dev/Interop/StoragePickers/PickerCommon.cpp @@ -392,6 +392,16 @@ namespace PickerCommon { } } + winrt::hstring PickerParameters::TryGetAppUserModelId() + { + return winrt::hstring(); + } + + winrt::hstring PickerParameters::TryGetProcessFullPath() + { + return winrt::hstring(); + } + void PickerParameters::ConfigureDialog(winrt::com_ptr dialog) { if (!IsHStringNullOrEmpty(CommitButtonText)) @@ -435,6 +445,21 @@ namespace PickerCommon { check_hresult(dialog->SetFileTypeIndex(FileTypeFilterPara.size())); } } + + if (!IsHStringNullOrEmpty(SettingsIdentifier)) + { + auto appDistinctString = TryGetAppUserModelId(); + if (appDistinctString.empty()) + { + appDistinctString = TryGetProcessFullPath(); + } + if (!appDistinctString.empty()) + { + auto clientId = HashHStringToGuid(appDistinctString + L"|" + SettingsIdentifier); + check_hresult(dialog->SetClientGuid(clientId)); + } + } + } /// diff --git a/dev/Interop/StoragePickers/PickerCommon.h b/dev/Interop/StoragePickers/PickerCommon.h index f2bc2045ab..4845adf390 100644 --- a/dev/Interop/StoragePickers/PickerCommon.h +++ b/dev/Interop/StoragePickers/PickerCommon.h @@ -31,6 +31,7 @@ namespace PickerCommon { struct PickerParameters { HWND HWnd{}; winrt::hstring CommitButtonText; + winrt::hstring SettingsIdentifier; winrt::Microsoft::Windows::Storage::Pickers::PickerLocationId SuggestedStartLocation; std::vector FileTypeFilterData{}; std::vector FileTypeFilterPara{}; @@ -51,6 +52,9 @@ namespace PickerCommon { void ConfigureDialog(winrt::com_ptr dialog); void ConfigureFileSaveDialog(winrt::com_ptr dialog); + winrt::hstring TryGetAppUserModelId(); + winrt::hstring TryGetProcessFullPath(); + private: void CaptureFilterSpec(winrt::Windows::Foundation::Collections::IVectorView filters); void CaptureFilterSpec(winrt::Windows::Foundation::Collections::IMapView> filters); From 18d588827231908e52cd432ac41930872123b6e4 Mon Sep 17 00:00:00 2001 From: DinahK-2SO <116714259+DinahK-2SO@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:40:21 +0800 Subject: [PATCH 2/6] app id and exe path --- dev/Interop/StoragePickers/PickerCommon.cpp | 41 ++++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/dev/Interop/StoragePickers/PickerCommon.cpp b/dev/Interop/StoragePickers/PickerCommon.cpp index 784aa3e915..9658175274 100644 --- a/dev/Interop/StoragePickers/PickerCommon.cpp +++ b/dev/Interop/StoragePickers/PickerCommon.cpp @@ -3,6 +3,7 @@ #include "pch.h" #include "shellapi.h" +#include #include "PickerCommon.h" #include "PickerLocalization.h" #include @@ -14,7 +15,7 @@ #include #include #include - +#include namespace { @@ -394,11 +395,47 @@ namespace PickerCommon { winrt::hstring PickerParameters::TryGetAppUserModelId() { - return winrt::hstring(); + UINT32 length = 0; + LONG rc = GetCurrentApplicationUserModelId(&length, nullptr); + if (rc != ERROR_INSUFFICIENT_BUFFER) + { + return winrt::hstring(); + } + + std::wstring aumid; + aumid.resize(length); + rc = GetCurrentApplicationUserModelId(&length, aumid.data()); + if (rc != ERROR_SUCCESS) + { + return winrt::hstring(); + } + + // Remove null terminator + if (!aumid.empty() && aumid.back() == L'\0') + { + aumid.pop_back(); + } + + return winrt::hstring(aumid); } winrt::hstring PickerParameters::TryGetProcessFullPath() { + wchar_t buffer[MAX_PATH]; + DWORD length = GetModuleFileNameW(nullptr, buffer, ARRAYSIZE(buffer)); + if (length > 0 && length < ARRAYSIZE(buffer)) + { + return winrt::hstring(buffer); + } + + // Handle long paths + std::vector longBuffer(32768); + length = GetModuleFileNameW(nullptr, longBuffer.data(), static_cast(longBuffer.size())); + if (length > 0) + { + return winrt::hstring(longBuffer.data()); + } + return winrt::hstring(); } From f66ab7434c9a95bb6eb0a7e531ff4eb99de0ca71 Mon Sep 17 00:00:00 2001 From: DinahK-2SO <116714259+DinahK-2SO@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:29:35 +0800 Subject: [PATCH 3/6] Title; FileTypeIndex; PickeMultipleFoldersAsync; Containment and Telemetries --- dev/Interop/StoragePickers/FileOpenPicker.cpp | 28 ++++++ dev/Interop/StoragePickers/FileOpenPicker.h | 9 ++ dev/Interop/StoragePickers/FileSavePicker.cpp | 26 ++++++ dev/Interop/StoragePickers/FileSavePicker.h | 14 ++- dev/Interop/StoragePickers/FolderPicker.cpp | 87 ++++++++++++++++++- dev/Interop/StoragePickers/FolderPicker.h | 9 +- .../Microsoft.Windows.Storage.Pickers.idl | 34 ++++++++ dev/Interop/StoragePickers/PickerCommon.cpp | 59 ++++++------- dev/Interop/StoragePickers/PickerCommon.h | 3 +- .../StoragePickers/StoragePickersTelemetry.h | 28 ++++++ 10 files changed, 255 insertions(+), 42 deletions(-) diff --git a/dev/Interop/StoragePickers/FileOpenPicker.cpp b/dev/Interop/StoragePickers/FileOpenPicker.cpp index 950a3bf32a..06147a36a4 100644 --- a/dev/Interop/StoragePickers/FileOpenPicker.cpp +++ b/dev/Interop/StoragePickers/FileOpenPicker.cpp @@ -50,12 +50,25 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerCommon::ValidateStringNoEmbeddedNulls(value); m_commitButtonText = value; } + winrt::hstring FileOpenPicker::Title() + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + return m_title; + } + void FileOpenPicker::Title(winrt::hstring const& value) + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + PickerCommon::ValidateStringNoEmbeddedNulls(value); + m_title = value; + } winrt::hstring FileOpenPicker::SettingsIdentifier() { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); return m_settingsIdentifier; } void FileOpenPicker::SettingsIdentifier(winrt::hstring const& value) { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); PickerCommon::ValidateStringNoEmbeddedNulls(value); m_settingsIdentifier = value; } @@ -68,6 +81,16 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { return m_fileTypeFilter; } + int FileOpenPicker::FileTypeIndex() + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + return m_fileTypeIndex; + } + void FileOpenPicker::FileTypeIndex(int value) + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + m_fileTypeIndex = value; + } winrt::hstring FileOpenPicker::SuggestedFolder() { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); @@ -95,10 +118,15 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId); parameters.CommitButtonText = m_commitButtonText; + parameters.Title = m_title; parameters.SettingsIdentifier = m_settingsIdentifier; parameters.SuggestedFolder = m_suggestedFolder; parameters.SuggestedStartLocation = m_suggestedStartLocation; parameters.SuggestedStartFolder = m_suggestedStartFolder; + + // Note: the user-defined index must be written in parameters before capturing filter spec for the open picker. + // for the fileTypeFilter may override FileTypeIndex to select "All Files" if the index is not specified by the user. + parameters.FileTypeIndex = m_fileTypeIndex; parameters.CaptureFilterSpecData(m_fileTypeFilter.GetView(), m_fileTypeChoices.GetView()); } diff --git a/dev/Interop/StoragePickers/FileOpenPicker.h b/dev/Interop/StoragePickers/FileOpenPicker.h index de94d7e6b3..a5afc1e3ab 100644 --- a/dev/Interop/StoragePickers/FileOpenPicker.h +++ b/dev/Interop/StoragePickers/FileOpenPicker.h @@ -24,12 +24,18 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::hstring CommitButtonText(); void CommitButtonText(winrt::hstring const& value); + winrt::hstring Title(); + void Title(winrt::hstring const& value); + winrt::hstring SettingsIdentifier(); void SettingsIdentifier(winrt::hstring const& value); winrt::Windows::Foundation::Collections::IVector FileTypeFilter(); winrt::Windows::Foundation::Collections::IMap> FileTypeChoices(); + int FileTypeIndex(); + void FileTypeIndex(int value); + winrt::hstring SuggestedFolder(); void SuggestedFolder(winrt::hstring const& value); @@ -44,6 +50,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerViewMode m_viewMode{ PickerViewMode::List }; PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified }; winrt::hstring m_commitButtonText{}; + winrt::hstring m_title{}; winrt::hstring m_settingsIdentifier{}; winrt::Windows::Foundation::Collections::IVector m_fileTypeFilter{ make() }; @@ -56,6 +63,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation }() }; + int m_fileTypeIndex{ 0 }; + winrt::hstring m_suggestedFolder{}; winrt::hstring m_suggestedStartFolder{}; diff --git a/dev/Interop/StoragePickers/FileSavePicker.cpp b/dev/Interop/StoragePickers/FileSavePicker.cpp index 4c2b2e3ef6..316015f105 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.cpp +++ b/dev/Interop/StoragePickers/FileSavePicker.cpp @@ -46,12 +46,25 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerCommon::ValidateStringNoEmbeddedNulls(value); m_commitButtonText = value; } + winrt::hstring FileSavePicker::Title() + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + return m_title; + } + void FileSavePicker::Title(winrt::hstring const& value) + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + PickerCommon::ValidateStringNoEmbeddedNulls(value); + m_title = value; + } winrt::hstring FileSavePicker::SettingsIdentifier() { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); return m_settingsIdentifier; } void FileSavePicker::SettingsIdentifier(winrt::hstring const& value) { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); PickerCommon::ValidateStringNoEmbeddedNulls(value); m_settingsIdentifier = value; } @@ -59,6 +72,16 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { return m_fileTypeChoices; } + int FileSavePicker::FileTypeIndex() + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + return m_fileTypeIndex; + } + void FileSavePicker::FileTypeIndex(int value) + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + m_fileTypeIndex = value; + } hstring FileSavePicker::DefaultFileExtension() { return m_defaultFileExtension; @@ -104,11 +127,14 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId); parameters.CommitButtonText = m_commitButtonText; + parameters.Title = m_title; parameters.SettingsIdentifier = m_settingsIdentifier; parameters.SuggestedFileName = m_suggestedFileName; parameters.SuggestedFolder = m_suggestedFolder; parameters.SuggestedStartLocation = m_suggestedStartLocation; parameters.SuggestedStartFolder = m_suggestedStartFolder; + + parameters.FileTypeIndex = m_fileTypeIndex; parameters.CaptureFilterSpecData( winrt::Windows::Foundation::Collections::IVectorView{}, m_fileTypeChoices.GetView()); diff --git a/dev/Interop/StoragePickers/FileSavePicker.h b/dev/Interop/StoragePickers/FileSavePicker.h index b0dc7a7d1b..85eea85a2a 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.h +++ b/dev/Interop/StoragePickers/FileSavePicker.h @@ -21,11 +21,17 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation hstring CommitButtonText(); void CommitButtonText(hstring const& value); - winrt::hstring SettingsIdentifier(); - void SettingsIdentifier(winrt::hstring const& value); + hstring Title(); + void Title(hstring const& value); + + hstring SettingsIdentifier(); + void SettingsIdentifier(hstring const& value); winrt::Windows::Foundation::Collections::IMap> FileTypeChoices(); + int FileTypeIndex(); + void FileTypeIndex(int value); + hstring DefaultFileExtension(); void DefaultFileExtension(hstring const& value); @@ -44,8 +50,10 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::Microsoft::UI::WindowId m_windowId{}; PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified }; hstring m_commitButtonText{}; - winrt::hstring m_settingsIdentifier{}; + hstring m_title{}; + hstring m_settingsIdentifier{}; winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{ make() }; + int m_fileTypeIndex{ 0 }; hstring m_defaultFileExtension{}; hstring m_suggestedFolder{}; hstring m_suggestedStartFolder{}; diff --git a/dev/Interop/StoragePickers/FolderPicker.cpp b/dev/Interop/StoragePickers/FolderPicker.cpp index 4d4b0c4be9..c53a3b79de 100644 --- a/dev/Interop/StoragePickers/FolderPicker.cpp +++ b/dev/Interop/StoragePickers/FolderPicker.cpp @@ -48,12 +48,25 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerCommon::ValidateStringNoEmbeddedNulls(value); m_commitButtonText = value; } + winrt::hstring FolderPicker::Title() + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + return m_title; + } + void FolderPicker::Title(winrt::hstring const& value) + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + PickerCommon::ValidateStringNoEmbeddedNulls(value); + m_title = value; + } winrt::hstring FolderPicker::SettingsIdentifier() { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); return m_settingsIdentifier; } void FolderPicker::SettingsIdentifier(winrt::hstring const& value) { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); PickerCommon::ValidateStringNoEmbeddedNulls(value); m_settingsIdentifier = value; } @@ -84,6 +97,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId); parameters.CommitButtonText = m_commitButtonText; + parameters.Title = m_title; parameters.SettingsIdentifier = m_settingsIdentifier; parameters.SuggestedFolder = m_suggestedFolder; parameters.SuggestedStartLocation = m_suggestedStartLocation; @@ -98,8 +112,6 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation auto logTelemetry{ StoragePickersTelemetry::FolderPickerPickSingleFolder::Start(m_telemetryHelper) }; PickerCommon::PickerParameters parameters{}; - parameters.AllFilesText = PickerLocalization::GetStoragePickersLocalizationText(PickerCommon::AllFilesLocalizationKey); - CaptureParameters(parameters); auto cancellationToken = co_await winrt::get_cancellation_token(); @@ -141,4 +153,75 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation logTelemetry.Stop(m_telemetryHelper, true); co_return result; } + + winrt::Windows::Foundation::IAsyncOperation> FolderPicker::PickMultipleFoldersAsync() + { + // TODO: remove get strong reference when telementry is safe stop + auto lifetime{ get_strong() }; + + auto logTelemetry{ StoragePickersTelemetry::FolderPickerPickMultipleFolder::Start(m_telemetryHelper) }; + + // capture parameters to avoid using get strong referece of picker + PickerCommon::PickerParameters parameters{}; + CaptureParameters(parameters); + + auto cancellationToken = co_await winrt::get_cancellation_token(); + cancellationToken.enable_propagation(true); + co_await winrt::resume_background(); + + winrt::Windows::Foundation::Collections::IVector results{ winrt::single_threaded_vector() }; + if (cancellationToken()) + { + logTelemetry.Stop(m_telemetryHelper, true, false); + co_return results.GetView(); + } + + auto dialog = create_instance(CLSID_FileOpenDialog, CLSCTX_INPROC_SERVER); + + FILEOPENDIALOGOPTIONS dialogOptions; + check_hresult(dialog->GetOptions(&dialogOptions)); + check_hresult(dialog->SetOptions(dialogOptions | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM | FOS_ALLOWMULTISELECT)); + + { + auto hr = dialog->Show(parameters.HWnd); + if (FAILED(hr) || cancellationToken()) + { + logTelemetry.Stop(m_telemetryHelper, true, false); + co_return results.GetView(); + } + } + + winrt::com_ptr shellItems{}; + check_hresult(dialog->GetResults(shellItems.put())); + + DWORD itemCount = 0; + check_hresult(shellItems->GetCount(&itemCount)); + + winrt::com_ptr shellItem{}; + for (DWORD i = 0; i < itemCount; i++) + { + check_hresult(shellItems->GetItemAt(i, shellItem.put())); + auto path = PickerCommon::GetPathFromShellItem(shellItem); + auto result{ make(path) }; + results.Append(result); + } + + bool isCancelled = false; + if (cancellationToken()) + { + results.Clear(); + isCancelled = true; + } + auto resultView = results.GetView(); + + if (results.Size() > 0) + { + logTelemetry.Stop(m_telemetryHelper, isCancelled, true); + } + else + { + logTelemetry.Stop(m_telemetryHelper, isCancelled, false); + } + co_return resultView; + } } diff --git a/dev/Interop/StoragePickers/FolderPicker.h b/dev/Interop/StoragePickers/FolderPicker.h index c26aba8bfb..abc82e51f1 100644 --- a/dev/Interop/StoragePickers/FolderPicker.h +++ b/dev/Interop/StoragePickers/FolderPicker.h @@ -21,8 +21,11 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation hstring CommitButtonText(); void CommitButtonText(hstring const& value); - winrt::hstring SettingsIdentifier(); - void SettingsIdentifier(winrt::hstring const& value); + hstring Title(); + void Title(hstring const& value); + + hstring SettingsIdentifier(); + void SettingsIdentifier(hstring const& value); hstring SuggestedFolder(); void SuggestedFolder(hstring const& value); @@ -31,6 +34,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation void SuggestedStartFolder(hstring const& value); winrt::Windows::Foundation::IAsyncOperation PickSingleFolderAsync(); + winrt::Windows::Foundation::IAsyncOperation> PickMultipleFoldersAsync(); private: winrt::Microsoft::UI::WindowId m_windowId{}; @@ -38,6 +42,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation PickerViewMode m_viewMode{ PickerViewMode::List }; PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified }; hstring m_commitButtonText{}; + hstring m_title{}; hstring m_settingsIdentifier{}; hstring m_suggestedFolder{}; hstring m_suggestedStartFolder{}; diff --git a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl index ab8a46dbfe..b4af1514b0 100644 --- a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl +++ b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl @@ -43,6 +43,13 @@ 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)] + String Title; + + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] String SettingsIdentifier; [contract(StoragePickersContract, 2.0)] @@ -51,6 +58,10 @@ namespace Microsoft.Windows.Storage.Pickers Windows.Foundation.Collections.IVector FileTypeFilter{ get; }; + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] + UInt32 FileTypeIndex; + [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] String SuggestedFolder; @@ -70,9 +81,21 @@ namespace Microsoft.Windows.Storage.Pickers Microsoft.Windows.Storage.Pickers.PickerLocationId SuggestedStartLocation; String CommitButtonText; + + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] + String Title; + + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] String SettingsIdentifier; Windows.Foundation.Collections.IMap > FileTypeChoices{ get; }; + + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] + UInt32 FileTypeIndex; + String DefaultFileExtension; String SuggestedFileName; String SuggestedFolder; @@ -98,6 +121,13 @@ 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)] + String Title; + + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] String SettingsIdentifier; [contract(StoragePickersContract, 2.0)] @@ -109,5 +139,9 @@ namespace Microsoft.Windows.Storage.Pickers String SuggestedStartFolder; [remote_sync] Windows.Foundation.IAsyncOperation PickSingleFolderAsync(); + + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] + [remote_sync] Windows.Foundation.IAsyncOperation > PickMultipleFoldersAsync(); } } diff --git a/dev/Interop/StoragePickers/PickerCommon.cpp b/dev/Interop/StoragePickers/PickerCommon.cpp index 9658175274..0a9ec98b7d 100644 --- a/dev/Interop/StoragePickers/PickerCommon.cpp +++ b/dev/Interop/StoragePickers/PickerCommon.cpp @@ -357,7 +357,11 @@ namespace PickerCommon { FileTypeFilterPara.push_back({ FileTypeFilterData.at(i * 2).c_str(), FileTypeFilterData.at(i * 2 + 1).c_str() }); } - FocusLastFilter = true; + if (FileTypeIndex == 0) + { + // If the FileTypeIndex is not specified by the user, set to focuse the last one ("All Files") + FileTypeIndex = static_cast(resultSize); + } } /// @@ -395,48 +399,30 @@ namespace PickerCommon { winrt::hstring PickerParameters::TryGetAppUserModelId() { - UINT32 length = 0; - LONG rc = GetCurrentApplicationUserModelId(&length, nullptr); - if (rc != ERROR_INSUFFICIENT_BUFFER) - { - return winrt::hstring(); - } + wchar_t appUserModelId[APPLICATION_USER_MODEL_ID_MAX_LENGTH] = {}; + UINT32 appUserModelIdSize{ APPLICATION_USER_MODEL_ID_MAX_LENGTH }; - std::wstring aumid; - aumid.resize(length); - rc = GetCurrentApplicationUserModelId(&length, aumid.data()); - if (rc != ERROR_SUCCESS) - { - return winrt::hstring(); - } - - // Remove null terminator - if (!aumid.empty() && aumid.back() == L'\0') + auto hr{GetCurrentApplicationUserModelId(&appUserModelIdSize, appUserModelId) }; + if (SUCCEEDED(hr)) { - aumid.pop_back(); + return winrt::hstring{ appUserModelId }; } - return winrt::hstring(aumid); + return winrt::hstring{}; } winrt::hstring PickerParameters::TryGetProcessFullPath() { - wchar_t buffer[MAX_PATH]; - DWORD length = GetModuleFileNameW(nullptr, buffer, ARRAYSIZE(buffer)); - if (length > 0 && length < ARRAYSIZE(buffer)) - { - return winrt::hstring(buffer); - } - - // Handle long paths - std::vector longBuffer(32768); - length = GetModuleFileNameW(nullptr, longBuffer.data(), static_cast(longBuffer.size())); - if (length > 0) + PCWSTR exeFullPath{}; + wil::unique_cotaskmem_string module; + auto hr{ LOG_IF_FAILED(wil::GetModuleFileNameW(nullptr, module)) }; + if (SUCCEEDED(hr)) { - return winrt::hstring(longBuffer.data()); + exeFullPath = module.get(); + return winrt::hstring{ exeFullPath }; } - return winrt::hstring(); + return winrt::hstring{}; } void PickerParameters::ConfigureDialog(winrt::com_ptr dialog) @@ -446,6 +432,11 @@ namespace PickerCommon { check_hresult(dialog->SetOkButtonLabel(CommitButtonText.c_str())); } + if (!IsHStringNullOrEmpty(Title)) + { + check_hresult(dialog->SetTitle(Title.c_str())); + } + winrt::com_ptr defaultFolder{}; // The SuggestedStartFolder takes precedence over SuggestedStartLocation if both are provided. @@ -477,9 +468,9 @@ namespace PickerCommon { { check_hresult(dialog->SetFileTypes((UINT)FileTypeFilterPara.size(), FileTypeFilterPara.data())); - if (FocusLastFilter) + if (FileTypeIndex > 0 && FileTypeIndex <= static_cast(FileTypeFilterPara.size())) { - check_hresult(dialog->SetFileTypeIndex(FileTypeFilterPara.size())); + check_hresult(dialog->SetFileTypeIndex(FileTypeIndex)); } } diff --git a/dev/Interop/StoragePickers/PickerCommon.h b/dev/Interop/StoragePickers/PickerCommon.h index 4845adf390..e7ef47c5da 100644 --- a/dev/Interop/StoragePickers/PickerCommon.h +++ b/dev/Interop/StoragePickers/PickerCommon.h @@ -31,11 +31,12 @@ namespace PickerCommon { struct PickerParameters { HWND HWnd{}; winrt::hstring CommitButtonText; + winrt::hstring Title; winrt::hstring SettingsIdentifier; winrt::Microsoft::Windows::Storage::Pickers::PickerLocationId SuggestedStartLocation; std::vector FileTypeFilterData{}; std::vector FileTypeFilterPara{}; - bool FocusLastFilter{ false }; + int FileTypeIndex{ 0 }; winrt::hstring AllFilesText{ L"All Files" }; // initialize to All Files as a default value, will be updated by localization winrt::hstring SuggestedFileName; diff --git a/dev/Interop/StoragePickers/StoragePickersTelemetry.h b/dev/Interop/StoragePickers/StoragePickersTelemetry.h index cf116c778f..2bb72d6cd8 100644 --- a/dev/Interop/StoragePickers/StoragePickersTelemetry.h +++ b/dev/Interop/StoragePickers/StoragePickersTelemetry.h @@ -124,4 +124,32 @@ class StoragePickersTelemetry : public wil::TraceLoggingProvider } CATCH_LOG() END_ACTIVITY_CLASS(); + + BEGIN_COMPLIANT_CRITICAL_DATA_ACTIVITY_CLASS(FolderPickerPickMultipleFolder, PDT_ProductAndServicePerformance); + DEFINE_ACTIVITY_START(StoragePickersTelemetryHelper& telemetryHelper) noexcept try + { + TraceLoggingClassWriteStart( + FolderPickerPickMultipleFolder, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingBool(telemetryHelper.IsPackagedApp(), "IsAppPackaged"), + TraceLoggingBool(telemetryHelper.IsRunningAsAdmin(), "IsRunningAsAdmin"), + TraceLoggingBool(telemetryHelper.IsRunningInContainer(), "IsRunningInContainer"), + TraceLoggingWideString(telemetryHelper.GetAppName().c_str(), "AppName")); + } + CATCH_LOG() + + DEFINE_ACTIVITY_STOP(StoragePickersTelemetryHelper& telemetryHelper, bool const resultCancelled, bool const resultNotEmpty) noexcept try + { + TraceLoggingClassWriteStop( + FolderPickerPickMultipleFolder, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingBool(resultCancelled, "resultCancelled"), + TraceLoggingBool(resultNotEmpty, "resultNotEmpty"), + TraceLoggingBool(telemetryHelper.IsPackagedApp(), "IsAppPackaged"), + TraceLoggingBool(telemetryHelper.IsRunningAsAdmin(), "IsRunningAsAdmin"), + TraceLoggingBool(telemetryHelper.IsRunningInContainer(), "IsRunningInContainer"), + TraceLoggingWideString(telemetryHelper.GetAppName().c_str(), "AppName")); + } + CATCH_LOG() + END_ACTIVITY_CLASS(); }; From 3ec20e15f469c5e03e2d28157b8e2f56aa845002 Mon Sep 17 00:00:00 2001 From: DinahK-2SO <116714259+DinahK-2SO@users.noreply.github.com> Date: Thu, 4 Dec 2025 16:11:38 +0800 Subject: [PATCH 4/6] adding FileSavePicker.ShowOverwritePrompt and FileSavePicker.CreateNewFileIfNotExists --- dev/Interop/StoragePickers/FileSavePicker.cpp | 31 +++++++++++++++++-- dev/Interop/StoragePickers/FileSavePicker.h | 8 +++++ .../Microsoft.Windows.Storage.Pickers.idl | 8 +++++ dev/Interop/StoragePickers/PickerCommon.cpp | 8 +++++ dev/Interop/StoragePickers/PickerCommon.h | 2 ++ 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/dev/Interop/StoragePickers/FileSavePicker.cpp b/dev/Interop/StoragePickers/FileSavePicker.cpp index 316015f105..b8194cdb2e 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.cpp +++ b/dev/Interop/StoragePickers/FileSavePicker.cpp @@ -86,6 +86,26 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { return m_defaultFileExtension; } + bool FileSavePicker::ShowOverwritePrompt() + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + return m_showOverwritePrompt; + } + void FileSavePicker::ShowOverwritePrompt(bool value) + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + m_showOverwritePrompt = value; + } + bool FileSavePicker::CreateNewFileIfNotExists() + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + return m_createNewFileIfNotExists; + } + void FileSavePicker::CreateNewFileIfNotExists(bool value) + { + THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); + m_createNewFileIfNotExists = value; + } void FileSavePicker::DefaultFileExtension(hstring const& value) { m_defaultFileExtension = value; @@ -138,6 +158,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation parameters.CaptureFilterSpecData( winrt::Windows::Foundation::Collections::IVectorView{}, m_fileTypeChoices.GetView()); + parameters.ShowOverwritePrompt = m_showOverwritePrompt; } winrt::Windows::Foundation::IAsyncOperation FileSavePicker::PickSaveFileAsync() @@ -207,9 +228,13 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation check_hresult(shellItem->GetDisplayName(SIGDN_NORMALDISPLAY, fileName.put())); std::wstring fileNameStr(fileName.get()); - // Create an empty file if the file doesn't exist, - // If the file already exists, do nothing. - auto [handle, _] = wil::try_open_or_create_file(pathStr.c_str(), GENERIC_WRITE); + // Feature_StoragePickers2 gives the option to skip creating the picked file when it doesn't exist. + if (m_createNewFileIfNotExists || !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()) + { + // Create an empty file if the file doesn't exist, + // If the file already exists, do nothing. + auto [handle, _] = wil::try_open_or_create_file(pathStr.c_str(), GENERIC_WRITE); + } if (cancellationToken()) { diff --git a/dev/Interop/StoragePickers/FileSavePicker.h b/dev/Interop/StoragePickers/FileSavePicker.h index 85eea85a2a..e6a517af61 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.h +++ b/dev/Interop/StoragePickers/FileSavePicker.h @@ -35,6 +35,12 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation hstring DefaultFileExtension(); void DefaultFileExtension(hstring const& value); + bool ShowOverwritePrompt(); + void ShowOverwritePrompt(bool value); + + bool CreateNewFileIfNotExists(); + void CreateNewFileIfNotExists(bool value); + hstring SuggestedFolder(); void SuggestedFolder(hstring const& value); @@ -55,6 +61,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{ make() }; int m_fileTypeIndex{ 0 }; hstring m_defaultFileExtension{}; + bool m_showOverwritePrompt{ true }; + bool m_createNewFileIfNotExists{ true }; hstring m_suggestedFolder{}; hstring m_suggestedStartFolder{}; hstring m_suggestedFileName{}; diff --git a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl index b4af1514b0..aad1adae97 100644 --- a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl +++ b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl @@ -104,6 +104,14 @@ namespace Microsoft.Windows.Storage.Pickers [feature(Feature_StoragePickers2)] String SuggestedStartFolder; + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] + Boolean ShowOverwritePrompt; + + [contract(StoragePickersContract, 2.0)] + [feature(Feature_StoragePickers2)] + Boolean CreateNewFileIfNotExists; + [remote_sync] Windows.Foundation.IAsyncOperation PickSaveFileAsync(); } diff --git a/dev/Interop/StoragePickers/PickerCommon.cpp b/dev/Interop/StoragePickers/PickerCommon.cpp index 0a9ec98b7d..2883200a9c 100644 --- a/dev/Interop/StoragePickers/PickerCommon.cpp +++ b/dev/Interop/StoragePickers/PickerCommon.cpp @@ -501,5 +501,13 @@ namespace PickerCommon { check_hresult(dialog->SetFileName(SuggestedFileName.c_str())); } + if (!ShowOverwritePrompt) + { + FILEOPENDIALOGOPTIONS options{}; + check_hresult(dialog->GetOptions(&options)); + options = static_cast(options & ~FOS_OVERWRITEPROMPT); + check_hresult(dialog->SetOptions(options)); + } + } } diff --git a/dev/Interop/StoragePickers/PickerCommon.h b/dev/Interop/StoragePickers/PickerCommon.h index e7ef47c5da..cf53210662 100644 --- a/dev/Interop/StoragePickers/PickerCommon.h +++ b/dev/Interop/StoragePickers/PickerCommon.h @@ -56,6 +56,8 @@ namespace PickerCommon { winrt::hstring TryGetAppUserModelId(); winrt::hstring TryGetProcessFullPath(); + bool ShowOverwritePrompt; + private: void CaptureFilterSpec(winrt::Windows::Foundation::Collections::IVectorView filters); void CaptureFilterSpec(winrt::Windows::Foundation::Collections::IMapView> filters); From 8b758b12772bef29867c972184edbb744cbee58f Mon Sep 17 00:00:00 2001 From: DinahK-2SO <116714259+DinahK-2SO@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:40:44 +0800 Subject: [PATCH 5/6] rename to DefaultFileTypeIndex; 0-based --- dev/Interop/StoragePickers/FileOpenPicker.cpp | 12 ++++++------ dev/Interop/StoragePickers/FileOpenPicker.h | 6 +++--- dev/Interop/StoragePickers/FileSavePicker.cpp | 10 +++++----- dev/Interop/StoragePickers/FileSavePicker.h | 6 +++--- .../Microsoft.Windows.Storage.Pickers.idl | 4 ++-- dev/Interop/StoragePickers/PickerCommon.cpp | 10 +++++----- dev/Interop/StoragePickers/PickerCommon.h | 2 +- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/dev/Interop/StoragePickers/FileOpenPicker.cpp b/dev/Interop/StoragePickers/FileOpenPicker.cpp index 06147a36a4..0fb8c36232 100644 --- a/dev/Interop/StoragePickers/FileOpenPicker.cpp +++ b/dev/Interop/StoragePickers/FileOpenPicker.cpp @@ -81,15 +81,15 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { return m_fileTypeFilter; } - int FileOpenPicker::FileTypeIndex() + int FileOpenPicker::DefaultFileTypeIndex() { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); - return m_fileTypeIndex; + return m_defaultFileTypeIndex; } - void FileOpenPicker::FileTypeIndex(int value) + void FileOpenPicker::DefaultFileTypeIndex(int value) { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); - m_fileTypeIndex = value; + m_defaultFileTypeIndex = value; } winrt::hstring FileOpenPicker::SuggestedFolder() { @@ -125,8 +125,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation parameters.SuggestedStartFolder = m_suggestedStartFolder; // Note: the user-defined index must be written in parameters before capturing filter spec for the open picker. - // for the fileTypeFilter may override FileTypeIndex to select "All Files" if the index is not specified by the user. - parameters.FileTypeIndex = m_fileTypeIndex; + // for the fileTypeFilter may override DefaultFileTypeIndex to select "All Files" if the index is not specified by the user. + parameters.DefaultFileTypeIndex = m_defaultFileTypeIndex; parameters.CaptureFilterSpecData(m_fileTypeFilter.GetView(), m_fileTypeChoices.GetView()); } diff --git a/dev/Interop/StoragePickers/FileOpenPicker.h b/dev/Interop/StoragePickers/FileOpenPicker.h index a5afc1e3ab..ae9b2198d9 100644 --- a/dev/Interop/StoragePickers/FileOpenPicker.h +++ b/dev/Interop/StoragePickers/FileOpenPicker.h @@ -33,8 +33,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::Windows::Foundation::Collections::IVector FileTypeFilter(); winrt::Windows::Foundation::Collections::IMap> FileTypeChoices(); - int FileTypeIndex(); - void FileTypeIndex(int value); + int DefaultFileTypeIndex(); + void DefaultFileTypeIndex(int value); winrt::hstring SuggestedFolder(); void SuggestedFolder(winrt::hstring const& value); @@ -63,7 +63,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation }() }; - int m_fileTypeIndex{ 0 }; + int m_defaultFileTypeIndex{ -1 }; winrt::hstring m_suggestedFolder{}; winrt::hstring m_suggestedStartFolder{}; diff --git a/dev/Interop/StoragePickers/FileSavePicker.cpp b/dev/Interop/StoragePickers/FileSavePicker.cpp index b8194cdb2e..48be5a96c5 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.cpp +++ b/dev/Interop/StoragePickers/FileSavePicker.cpp @@ -72,15 +72,15 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { return m_fileTypeChoices; } - int FileSavePicker::FileTypeIndex() + int FileSavePicker::DefaultFileTypeIndex() { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); - return m_fileTypeIndex; + return m_defaultFileTypeIndex; } - void FileSavePicker::FileTypeIndex(int value) + void FileSavePicker::DefaultFileTypeIndex(int value) { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); - m_fileTypeIndex = value; + m_defaultFileTypeIndex = value; } hstring FileSavePicker::DefaultFileExtension() { @@ -154,7 +154,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation parameters.SuggestedStartLocation = m_suggestedStartLocation; parameters.SuggestedStartFolder = m_suggestedStartFolder; - parameters.FileTypeIndex = m_fileTypeIndex; + parameters.DefaultFileTypeIndex = m_defaultFileTypeIndex; parameters.CaptureFilterSpecData( winrt::Windows::Foundation::Collections::IVectorView{}, m_fileTypeChoices.GetView()); diff --git a/dev/Interop/StoragePickers/FileSavePicker.h b/dev/Interop/StoragePickers/FileSavePicker.h index e6a517af61..4507048baf 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.h +++ b/dev/Interop/StoragePickers/FileSavePicker.h @@ -29,8 +29,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::Windows::Foundation::Collections::IMap> FileTypeChoices(); - int FileTypeIndex(); - void FileTypeIndex(int value); + int DefaultFileTypeIndex(); + void DefaultFileTypeIndex(int value); hstring DefaultFileExtension(); void DefaultFileExtension(hstring const& value); @@ -59,7 +59,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation hstring m_title{}; hstring m_settingsIdentifier{}; winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{ make() }; - int m_fileTypeIndex{ 0 }; + int m_defaultFileTypeIndex{ -1 }; hstring m_defaultFileExtension{}; bool m_showOverwritePrompt{ true }; bool m_createNewFileIfNotExists{ true }; diff --git a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl index aad1adae97..1f03ad58e6 100644 --- a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl +++ b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl @@ -60,7 +60,7 @@ namespace Microsoft.Windows.Storage.Pickers [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] - UInt32 FileTypeIndex; + Int32 DefaultFileTypeIndex; [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] @@ -94,7 +94,7 @@ namespace Microsoft.Windows.Storage.Pickers [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] - UInt32 FileTypeIndex; + Int32 DefaultFileTypeIndex; String DefaultFileExtension; String SuggestedFileName; diff --git a/dev/Interop/StoragePickers/PickerCommon.cpp b/dev/Interop/StoragePickers/PickerCommon.cpp index 2883200a9c..88301c4e64 100644 --- a/dev/Interop/StoragePickers/PickerCommon.cpp +++ b/dev/Interop/StoragePickers/PickerCommon.cpp @@ -357,10 +357,10 @@ namespace PickerCommon { FileTypeFilterPara.push_back({ FileTypeFilterData.at(i * 2).c_str(), FileTypeFilterData.at(i * 2 + 1).c_str() }); } - if (FileTypeIndex == 0) + if (DefaultFileTypeIndex == -1) { - // If the FileTypeIndex is not specified by the user, set to focuse the last one ("All Files") - FileTypeIndex = static_cast(resultSize); + // If the DefaultFileTypeIndex is not specified by the user, set to focuse the last one ("All Files") + DefaultFileTypeIndex = static_cast(resultSize) - 1; } } @@ -468,9 +468,9 @@ namespace PickerCommon { { check_hresult(dialog->SetFileTypes((UINT)FileTypeFilterPara.size(), FileTypeFilterPara.data())); - if (FileTypeIndex > 0 && FileTypeIndex <= static_cast(FileTypeFilterPara.size())) + if (DefaultFileTypeIndex != -1 && DefaultFileTypeIndex < static_cast(FileTypeFilterPara.size())) { - check_hresult(dialog->SetFileTypeIndex(FileTypeIndex)); + check_hresult(dialog->SetFileTypeIndex(DefaultFileTypeIndex + 1)); // COMDLG file type index is 1-based } } diff --git a/dev/Interop/StoragePickers/PickerCommon.h b/dev/Interop/StoragePickers/PickerCommon.h index cf53210662..a112323a69 100644 --- a/dev/Interop/StoragePickers/PickerCommon.h +++ b/dev/Interop/StoragePickers/PickerCommon.h @@ -36,7 +36,7 @@ namespace PickerCommon { winrt::Microsoft::Windows::Storage::Pickers::PickerLocationId SuggestedStartLocation; std::vector FileTypeFilterData{}; std::vector FileTypeFilterPara{}; - int FileTypeIndex{ 0 }; + int DefaultFileTypeIndex{ -1 }; winrt::hstring AllFilesText{ L"All Files" }; // initialize to All Files as a default value, will be updated by localization winrt::hstring SuggestedFileName; From 852aa73312202c81a36ae085867738fbd0fd293e Mon Sep 17 00:00:00 2001 From: DinahK-2SO <116714259+DinahK-2SO@users.noreply.github.com> Date: Wed, 10 Dec 2025 16:28:36 +0800 Subject: [PATCH 6/6] nullable (IReference) DefaultFileTypeIndex --- dev/Interop/StoragePickers/FileOpenPicker.cpp | 20 +++++++++++++++---- dev/Interop/StoragePickers/FileOpenPicker.h | 7 ++++--- dev/Interop/StoragePickers/FileSavePicker.cpp | 20 +++++++++++++++---- dev/Interop/StoragePickers/FileSavePicker.h | 7 ++++--- .../Microsoft.Windows.Storage.Pickers.idl | 4 ++-- dev/Interop/StoragePickers/PickerCommon.cpp | 8 ++++---- dev/Interop/StoragePickers/PickerCommon.h | 3 ++- 7 files changed, 48 insertions(+), 21 deletions(-) diff --git a/dev/Interop/StoragePickers/FileOpenPicker.cpp b/dev/Interop/StoragePickers/FileOpenPicker.cpp index 0fb8c36232..809aedd2ef 100644 --- a/dev/Interop/StoragePickers/FileOpenPicker.cpp +++ b/dev/Interop/StoragePickers/FileOpenPicker.cpp @@ -81,15 +81,27 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { return m_fileTypeFilter; } - int FileOpenPicker::DefaultFileTypeIndex() + winrt::Windows::Foundation::IReference FileOpenPicker::DefaultFileTypeIndex() { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); - return m_defaultFileTypeIndex; + if (!m_defaultFileTypeIndex.has_value()) + { + return nullptr; + } + + return winrt::box_value(*m_defaultFileTypeIndex).as>(); } - void FileOpenPicker::DefaultFileTypeIndex(int value) + void FileOpenPicker::DefaultFileTypeIndex(winrt::Windows::Foundation::IReference const& value) { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); - m_defaultFileTypeIndex = value; + if (value) + { + m_defaultFileTypeIndex = value.Value(); + } + else + { + m_defaultFileTypeIndex.reset(); + } } winrt::hstring FileOpenPicker::SuggestedFolder() { diff --git a/dev/Interop/StoragePickers/FileOpenPicker.h b/dev/Interop/StoragePickers/FileOpenPicker.h index ae9b2198d9..556498b867 100644 --- a/dev/Interop/StoragePickers/FileOpenPicker.h +++ b/dev/Interop/StoragePickers/FileOpenPicker.h @@ -8,6 +8,7 @@ #include #include "FileTypeChoicesMap.h" #include "FileTypeFilterVector.h" +#include namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { @@ -33,8 +34,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::Windows::Foundation::Collections::IVector FileTypeFilter(); winrt::Windows::Foundation::Collections::IMap> FileTypeChoices(); - int DefaultFileTypeIndex(); - void DefaultFileTypeIndex(int value); + winrt::Windows::Foundation::IReference DefaultFileTypeIndex(); + void DefaultFileTypeIndex(winrt::Windows::Foundation::IReference const& value); winrt::hstring SuggestedFolder(); void SuggestedFolder(winrt::hstring const& value); @@ -63,7 +64,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation }() }; - int m_defaultFileTypeIndex{ -1 }; + std::optional m_defaultFileTypeIndex{}; winrt::hstring m_suggestedFolder{}; winrt::hstring m_suggestedStartFolder{}; diff --git a/dev/Interop/StoragePickers/FileSavePicker.cpp b/dev/Interop/StoragePickers/FileSavePicker.cpp index 48be5a96c5..a9b4f922aa 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.cpp +++ b/dev/Interop/StoragePickers/FileSavePicker.cpp @@ -72,15 +72,27 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { return m_fileTypeChoices; } - int FileSavePicker::DefaultFileTypeIndex() + winrt::Windows::Foundation::IReference FileSavePicker::DefaultFileTypeIndex() { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); - return m_defaultFileTypeIndex; + if (!m_defaultFileTypeIndex.has_value()) + { + return nullptr; + } + + return winrt::box_value(*m_defaultFileTypeIndex).as>(); } - void FileSavePicker::DefaultFileTypeIndex(int value) + void FileSavePicker::DefaultFileTypeIndex(winrt::Windows::Foundation::IReference const& value) { THROW_HR_IF(E_NOTIMPL, !::Microsoft::Windows::Storage::Pickers::Feature_StoragePickers2::IsEnabled()); - m_defaultFileTypeIndex = value; + if (value) + { + m_defaultFileTypeIndex = value.Value(); + } + else + { + m_defaultFileTypeIndex.reset(); + } } hstring FileSavePicker::DefaultFileExtension() { diff --git a/dev/Interop/StoragePickers/FileSavePicker.h b/dev/Interop/StoragePickers/FileSavePicker.h index 4507048baf..77a5b2d878 100644 --- a/dev/Interop/StoragePickers/FileSavePicker.h +++ b/dev/Interop/StoragePickers/FileSavePicker.h @@ -6,6 +6,7 @@ #include "PickerCommon.h" #include "StoragePickersTelemetryHelper.h" #include "FileTypeChoicesMap.h" +#include namespace winrt::Microsoft::Windows::Storage::Pickers::implementation { @@ -29,8 +30,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation winrt::Windows::Foundation::Collections::IMap> FileTypeChoices(); - int DefaultFileTypeIndex(); - void DefaultFileTypeIndex(int value); + winrt::Windows::Foundation::IReference DefaultFileTypeIndex(); + void DefaultFileTypeIndex(winrt::Windows::Foundation::IReference const& value); hstring DefaultFileExtension(); void DefaultFileExtension(hstring const& value); @@ -59,7 +60,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation hstring m_title{}; hstring m_settingsIdentifier{}; winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{ make() }; - int m_defaultFileTypeIndex{ -1 }; + std::optional m_defaultFileTypeIndex{}; hstring m_defaultFileExtension{}; bool m_showOverwritePrompt{ true }; bool m_createNewFileIfNotExists{ true }; diff --git a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl index 1f03ad58e6..542ee3da23 100644 --- a/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl +++ b/dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl @@ -60,7 +60,7 @@ namespace Microsoft.Windows.Storage.Pickers [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] - Int32 DefaultFileTypeIndex; + Windows.Foundation.IReference DefaultFileTypeIndex; [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] @@ -94,7 +94,7 @@ namespace Microsoft.Windows.Storage.Pickers [contract(StoragePickersContract, 2.0)] [feature(Feature_StoragePickers2)] - Int32 DefaultFileTypeIndex; + Windows.Foundation.IReference DefaultFileTypeIndex; String DefaultFileExtension; String SuggestedFileName; diff --git a/dev/Interop/StoragePickers/PickerCommon.cpp b/dev/Interop/StoragePickers/PickerCommon.cpp index 88301c4e64..0874861808 100644 --- a/dev/Interop/StoragePickers/PickerCommon.cpp +++ b/dev/Interop/StoragePickers/PickerCommon.cpp @@ -357,10 +357,10 @@ namespace PickerCommon { FileTypeFilterPara.push_back({ FileTypeFilterData.at(i * 2).c_str(), FileTypeFilterData.at(i * 2 + 1).c_str() }); } - if (DefaultFileTypeIndex == -1) + if (!DefaultFileTypeIndex.has_value()) { // If the DefaultFileTypeIndex is not specified by the user, set to focuse the last one ("All Files") - DefaultFileTypeIndex = static_cast(resultSize) - 1; + DefaultFileTypeIndex = static_cast(resultSize - 1); } } @@ -468,9 +468,9 @@ namespace PickerCommon { { check_hresult(dialog->SetFileTypes((UINT)FileTypeFilterPara.size(), FileTypeFilterPara.data())); - if (DefaultFileTypeIndex != -1 && DefaultFileTypeIndex < static_cast(FileTypeFilterPara.size())) + if (DefaultFileTypeIndex.has_value() && *DefaultFileTypeIndex < static_cast(FileTypeFilterPara.size())) { - check_hresult(dialog->SetFileTypeIndex(DefaultFileTypeIndex + 1)); // COMDLG file type index is 1-based + check_hresult(dialog->SetFileTypeIndex(static_cast(*DefaultFileTypeIndex + 1))); // COMDLG file type index is 1-based } } diff --git a/dev/Interop/StoragePickers/PickerCommon.h b/dev/Interop/StoragePickers/PickerCommon.h index a112323a69..a682017af2 100644 --- a/dev/Interop/StoragePickers/PickerCommon.h +++ b/dev/Interop/StoragePickers/PickerCommon.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace PickerCommon { winrt::hstring GetPathFromShellItem(winrt::com_ptr shellItem); @@ -36,7 +37,7 @@ namespace PickerCommon { winrt::Microsoft::Windows::Storage::Pickers::PickerLocationId SuggestedStartLocation; std::vector FileTypeFilterData{}; std::vector FileTypeFilterPara{}; - int DefaultFileTypeIndex{ -1 }; + std::optional DefaultFileTypeIndex{}; winrt::hstring AllFilesText{ L"All Files" }; // initialize to All Files as a default value, will be updated by localization winrt::hstring SuggestedFileName;