diff --git a/WindowsAppRuntime.sln b/WindowsAppRuntime.sln
index 266ae49a34..2e644489bd 100644
--- a/WindowsAppRuntime.sln
+++ b/WindowsAppRuntime.sln
@@ -566,6 +566,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IXP", "IXP", "{7B323048-439
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IXP.TransportPackage.PackageReference", "eng\PackageReference\IXP\IXP.TransportPackage.PackageReference.csproj", "{A949149D-29CA-4AA7-B1ED-0E571B4AD9BB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Windows.Storage.Pickers.Projection", "dev\Projections\CS\Microsoft.Windows.Storage.Pickers.Projection\Microsoft.Windows.Storage.Pickers.Projection.csproj", "{8E01AA4F-A16A-4E3F-A59F-6D49422B4410}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -2002,6 +2004,22 @@ Global
{A949149D-29CA-4AA7-B1ED-0E571B4AD9BB}.Release|x64.Build.0 = Release|x64
{A949149D-29CA-4AA7-B1ED-0E571B4AD9BB}.Release|x86.ActiveCfg = Release|x86
{A949149D-29CA-4AA7-B1ED-0E571B4AD9BB}.Release|x86.Build.0 = Release|x86
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Debug|Any CPU.Build.0 = Debug|x64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Debug|ARM64.ActiveCfg = Debug|arm64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Debug|ARM64.Build.0 = Debug|arm64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Debug|x64.ActiveCfg = Debug|x64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Debug|x64.Build.0 = Debug|x64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Debug|x86.ActiveCfg = Debug|x86
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Debug|x86.Build.0 = Debug|x86
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Release|Any CPU.ActiveCfg = Release|x64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Release|Any CPU.Build.0 = Release|x64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Release|ARM64.ActiveCfg = Release|arm64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Release|ARM64.Build.0 = Release|arm64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Release|x64.ActiveCfg = Release|x64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Release|x64.Build.0 = Release|x64
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Release|x86.ActiveCfg = Release|x86
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2181,6 +2199,7 @@ Global
{D5958784-4518-44F1-A518-80514B380ED5} = {E24C263A-DE3E-4844-BA50-842DA5AD7A49}
{7B323048-439F-47E9-A3D4-7342C5ADE2A5} = {5C88AE1D-AC20-4A41-9299-1EEA15B80724}
{A949149D-29CA-4AA7-B1ED-0E571B4AD9BB} = {7B323048-439F-47E9-A3D4-7342C5ADE2A5}
+ {8E01AA4F-A16A-4E3F-A59F-6D49422B4410} = {716C26A0-E6B0-4981-8412-D14A4D410531}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77}
diff --git a/build/CopyFilesToStagingDir.ps1 b/build/CopyFilesToStagingDir.ps1
index 3c261aaac2..656d6e5e88 100644
--- a/build/CopyFilesToStagingDir.ps1
+++ b/build/CopyFilesToStagingDir.ps1
@@ -55,6 +55,7 @@ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windo
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Management.Deployment.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Media.Capture.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
+PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Storage.Pickers.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.PushNotifications.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Security.AccessControl.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Security.Authentication.OAuth.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
@@ -126,6 +127,8 @@ PublishFile $FullBuildOutput\Microsoft.Windows.Management.Deployment.Projection\
PublishFile $FullBuildOutput\Microsoft.Windows.Management.Deployment.Projection\Microsoft.Windows.Management.Deployment.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.Media.Capture.Projection\Microsoft.Windows.Media.Capture.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.Media.Capture.Projection\Microsoft.Windows.Media.Capture.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0
+PublishFile $FullBuildOutput\Microsoft.Windows.Storage.Pickers.Projection\Microsoft.Windows.Storage.Pickers.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0
+PublishFile $FullBuildOutput\Microsoft.Windows.Storage.Pickers.Projection\Microsoft.Windows.Storage.Pickers.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.PushNotifications.Projection\Microsoft.Windows.PushNotifications.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.PushNotifications.Projection\Microsoft.Windows.PushNotifications.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.Security.AccessControl.Projection\Microsoft.Windows.Security.AccessControl.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0
@@ -202,6 +205,7 @@ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windo
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Management.Deployment.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Media.Capture.winmd $NugetDir\lib\uap10.0
+PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Storage.Pickers.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.PushNotifications.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Security.AccessControl.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Security.Authentication.OAuth.winmd $NugetDir\lib\uap10.0
diff --git a/build/NuSpecs/AppxManifest.xml b/build/NuSpecs/AppxManifest.xml
index e079468216..2ee96bb190 100644
--- a/build/NuSpecs/AppxManifest.xml
+++ b/build/NuSpecs/AppxManifest.xml
@@ -111,6 +111,9 @@
+
+
+
diff --git a/build/NuSpecs/WindowsAppSDK-Nuget-Native.WinRt.props b/build/NuSpecs/WindowsAppSDK-Nuget-Native.WinRt.props
index 88fede76fd..02b59d588d 100644
--- a/build/NuSpecs/WindowsAppSDK-Nuget-Native.WinRt.props
+++ b/build/NuSpecs/WindowsAppSDK-Nuget-Native.WinRt.props
@@ -75,6 +75,12 @@
$(MSBuildThisFileDirectory)..\..\runtimes\win10-$(_WindowsAppSDKFoundationPlatform)\native\Microsoft.WindowsAppRuntime.dll
true
+
+ $(MSBuildThisFileDirectory)..\..\lib\uap10.0\Microsoft.Windows.Storage.Pickers.winmd
+ $(MSBuildThisFileDirectory)..\..\runtimes\win10-$(_WindowsAppSDKFoundationPlatform)\native\Microsoft.WindowsAppRuntime.dll
+ true
+
diff --git a/build/NuSpecs/WindowsAppSDK-Nuget-Native.targets b/build/NuSpecs/WindowsAppSDK-Nuget-Native.targets
index c18bdb650a..7057bff1ae 100644
--- a/build/NuSpecs/WindowsAppSDK-Nuget-Native.targets
+++ b/build/NuSpecs/WindowsAppSDK-Nuget-Native.targets
@@ -135,6 +135,14 @@
+
+
+ false
+ Microsoft.WindowsAppRuntime.dll
+
+
+
diff --git a/dev/Interop/StoragePicker/FileOpenPicker.cpp b/dev/Interop/StoragePicker/FileOpenPicker.cpp
new file mode 100644
index 0000000000..9684ff2f98
--- /dev/null
+++ b/dev/Interop/StoragePicker/FileOpenPicker.cpp
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+#include "pch.h"
+#include "FileOpenPicker.h"
+#include "Microsoft.Windows.Storage.Pickers.FileOpenPicker.g.cpp"
+#include "StoragePickersTelemetry.h"
+#include
+#include
+#include
+#include
+#include
+
+namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
+{
+ winrt::Windows::Foundation::IAsyncOperation FileOpenPicker::PickSingleFileAsync()
+ {
+ bool isAppPackaged = m_telemetryHelper.IsPackagedApp();
+ PCWSTR appName = m_telemetryHelper.GetAppName().c_str();
+ auto logCaptureOperation{ StoragePickersTelemetry::StoragePickersOperation::Start(isAppPackaged, appName) };
+
+ winrt::apartment_context ui_thread;
+
+ co_await winrt::resume_background();
+
+ // Handle cancellation.
+ auto cancellationToken = co_await winrt::get_cancellation_token();
+ if (cancellationToken())
+ {
+ co_return nullptr;
+ }
+
+ // TODO: should we initialize COM?
+ //wil::com_initialize_ex initializeCom{ COINIT_APARTMENTTHREADED };
+
+ wil::com_ptr fileOpenDialog;
+ THROW_IF_FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&fileOpenDialog)));
+
+ HRESULT hr = fileOpenDialog->Show(nullptr);
+ if (FAILED(hr) || cancellationToken())
+ {
+ co_return nullptr;
+ }
+
+ wil::com_ptr shellItem;
+ THROW_IF_FAILED(fileOpenDialog->GetResult(shellItem.put()));
+
+ wil::unique_cotaskmem_string filePath;
+ THROW_IF_FAILED(shellItem->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
+
+ // Convert the file path to a StorageFile.
+ auto const& file = co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(filePath.get());
+ if (cancellationToken()) {
+ co_return nullptr;
+ }
+
+ co_await ui_thread;
+ if (cancellationToken()) {
+ co_return nullptr;
+ }
+
+ co_return file;
+ }
+}
diff --git a/dev/Interop/StoragePicker/FileOpenPicker.h b/dev/Interop/StoragePicker/FileOpenPicker.h
new file mode 100644
index 0000000000..c97752674f
--- /dev/null
+++ b/dev/Interop/StoragePicker/FileOpenPicker.h
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+#pragma once
+#include "Microsoft.Windows.Storage.Pickers.FileOpenPicker.g.h"
+#include "TelemetryHelper.h"
+
+namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
+{
+ struct FileOpenPicker : FileOpenPickerT
+ {
+ FileOpenPicker() = default;
+ winrt::Windows::Foundation::IAsyncOperation PickSingleFileAsync();
+
+ private:
+ TelemetryHelper m_telemetryHelper;
+ };
+}
+
+namespace winrt::Microsoft::Windows::Storage::Pickers::factory_implementation
+{
+ struct FileOpenPicker : FileOpenPickerT
+ {
+ };
+}
diff --git a/dev/Interop/StoragePicker/FileOpenPicker.idl b/dev/Interop/StoragePicker/FileOpenPicker.idl
new file mode 100644
index 0000000000..0af9f685ef
--- /dev/null
+++ b/dev/Interop/StoragePicker/FileOpenPicker.idl
@@ -0,0 +1,13 @@
+namespace Microsoft.Windows.Storage.Pickers
+{
+ [contractversion(1)]
+ apicontract FileOpenPickerContract {};
+
+ [contract(FileOpenPickerContract, 1)]
+ runtimeclass FileOpenPicker
+ {
+ FileOpenPicker();
+
+ Windows.Foundation.IAsyncOperation PickSingleFileAsync();
+ };
+}
diff --git a/dev/Interop/StoragePicker/StoragePicker.vcxitems b/dev/Interop/StoragePicker/StoragePicker.vcxitems
new file mode 100644
index 0000000000..f49e671656
--- /dev/null
+++ b/dev/Interop/StoragePicker/StoragePicker.vcxitems
@@ -0,0 +1,25 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ {a39e7b2f-5f67-47dd-8443-531d095ca7f3}
+
+
+
+ %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dev/Interop/StoragePicker/StoragePickersTelemetry.h b/dev/Interop/StoragePicker/StoragePickersTelemetry.h
new file mode 100644
index 0000000000..beff1e2a22
--- /dev/null
+++ b/dev/Interop/StoragePicker/StoragePickersTelemetry.h
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#pragma once
+#include "..\WindowsAppRuntime_Insights\WindowsAppRuntimeInsights.h"
+#include
+
+DECLARE_TRACELOGGING_CLASS(StoragePickersTelemetryProvider,
+ "Microsoft.WindowsAppSDK.StoragePickersTelemetry",
+ // {3be0d45f-3a9d-46be-a1cf-b08465473cc4}
+ (0x3be0d45f, 0x3a9d, 0x46be, 0xa1, 0xcf, 0xb0, 0x84, 0x65, 0x47, 0x3c, 0xc4));
+
+class StoragePickersTelemetry : public wil::TraceLoggingProvider
+{
+ IMPLEMENT_TELEMETRY_CLASS(StoragePickersTelemetry, StoragePickersTelemetryProvider);
+
+public:
+ BEGIN_COMPLIANT_MEASURES_ACTIVITY_CLASS(StoragePickersOperation, PDT_ProductAndServicePerformance);
+ DEFINE_ACTIVITY_START(bool isAppPackaged, PCWSTR appName) noexcept try
+ {
+ TraceLoggingClassWriteStart(
+ StoragePickersOperation,
+ _GENERIC_PARTB_FIELDS_ENABLED,
+ TraceLoggingBool(isAppPackaged, "IsAppPackaged"),
+ TraceLoggingWideString(appName, "AppName"));
+ }
+ CATCH_LOG()
+ END_ACTIVITY_CLASS();
+};
\ No newline at end of file
diff --git a/dev/Projections/CS/Microsoft.Windows.Storage.Pickers.Projection/Microsoft.Windows.Storage.Pickers.Projection.csproj b/dev/Projections/CS/Microsoft.Windows.Storage.Pickers.Projection/Microsoft.Windows.Storage.Pickers.Projection.csproj
new file mode 100644
index 0000000000..a13846ff90
--- /dev/null
+++ b/dev/Projections/CS/Microsoft.Windows.Storage.Pickers.Projection/Microsoft.Windows.Storage.Pickers.Projection.csproj
@@ -0,0 +1,58 @@
+
+
+ net6.0-windows10.0.17763.0
+ 10.0.17763.0
+ x64;x86;arm64
+ AnyCPU
+ false
+
+
+
+ true
+ true
+
+
+
+
+ 8305
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ Microsoft.Windows.Storage.Pickers
+ 10.0.17763.0
+ false
+
+
+
+
+ pdbonly
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ $(OutDir)..\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Storage.Pickers.winmd
+ true
+
+
+
diff --git a/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj b/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj
index 62e67cef13..75db43c1f0 100644
--- a/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj
+++ b/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj
@@ -102,6 +102,7 @@
+
diff --git a/prototype-workingdir/.gitignore b/prototype-workingdir/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/prototype-workingdir/Directory.Build.props b/prototype-workingdir/Directory.Build.props
new file mode 100644
index 0000000000..6dc4195c32
--- /dev/null
+++ b/prototype-workingdir/Directory.Build.props
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/prototype-workingdir/Directory.Packages.props b/prototype-workingdir/Directory.Packages.props
new file mode 100644
index 0000000000..6dc4195c32
--- /dev/null
+++ b/prototype-workingdir/Directory.Packages.props
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/FileOpenPicker.cpp b/prototype-workingdir/Microsoft.Storage.Pickers/FileOpenPicker.cpp
new file mode 100644
index 0000000000..d3d42329d3
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/FileOpenPicker.cpp
@@ -0,0 +1,154 @@
+#include "pch.h"
+#include "FileOpenPicker.h"
+#include "FileOpenPicker.g.cpp"
+#include
+#include
+#include
+#include
+#include "PickerCommon.h"
+
+namespace winrt::Microsoft::Storage::Pickers::implementation
+{
+ FileOpenPicker::FileOpenPicker(winrt::Microsoft::UI::WindowId const& windowId)
+ : m_windowId(windowId)
+ {
+ }
+
+ winrt::Microsoft::Storage::Pickers::PickerViewMode FileOpenPicker::ViewMode()
+ {
+ return m_viewMode;
+ }
+ void FileOpenPicker::ViewMode(winrt::Microsoft::Storage::Pickers::PickerViewMode const& value)
+ {
+ m_viewMode = value;
+ }
+ hstring FileOpenPicker::SettingsIdentifier()
+ {
+ return m_settingsIdentifier;
+ }
+ void FileOpenPicker::SettingsIdentifier(hstring const& value)
+ {
+ m_settingsIdentifier = value;
+ }
+ winrt::Microsoft::Storage::Pickers::PickerLocationId FileOpenPicker::SuggestedStartLocation()
+ {
+ return m_suggestedStartLocation;
+ }
+ void FileOpenPicker::SuggestedStartLocation(winrt::Microsoft::Storage::Pickers::PickerLocationId const& value)
+ {
+ m_suggestedStartLocation = value;
+ }
+ winrt::hstring FileOpenPicker::CommitButtonText()
+ {
+ return m_commitButtonText;
+ }
+ void FileOpenPicker::CommitButtonText(winrt::hstring const& value)
+ {
+ m_commitButtonText = value;
+ }
+ winrt::Windows::Foundation::Collections::IVector FileOpenPicker::FileTypeFilter()
+ {
+ return m_fileTypeFilter;
+ }
+
+ void FileOpenPicker::CaptureParameters(PickerCommon::PickerParameters& parameters)
+ {
+ parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId);
+ parameters.CommitButtonText = m_commitButtonText;
+ parameters.SettingsIdentifierId = m_settingsIdentifier;
+ parameters.PickerLocationId = m_suggestedStartLocation;
+ parameters.FileTypeFilterPara = PickerCommon::CaptureFilterSpec(parameters.FileTypeFilterData, m_fileTypeFilter.GetView());
+ }
+
+ winrt::Windows::Foundation::IAsyncOperation FileOpenPicker::PickSingleFileAsync()
+ {
+ PickerCommon::PickerParameters parameters{};
+
+ CaptureParameters(parameters);
+
+ co_await winrt::resume_background();
+
+ auto cancellationToken = co_await winrt::get_cancellation_token();
+ if (cancellationToken())
+ {
+ co_return nullptr;
+ }
+
+ // TODO: should we initialize COM?
+ // wil::com_initialize_ex initializeCom{ COINIT_APARTMENTTHREADED };
+
+ auto dialog = create_instance(CLSID_FileOpenDialog, CONTEXT_ALL);
+
+ parameters.ConfigureDialog(dialog);
+
+ {
+ auto hr = dialog->Show(parameters.HWnd);
+ if (FAILED(hr) || cancellationToken())
+ {
+ co_return nullptr;
+ }
+ }
+
+ winrt::com_ptr shellItem{};
+ check_hresult(dialog->GetResult(shellItem.put()));
+ auto file = co_await PickerCommon::CreateStorageFileFromShellItem(shellItem);
+
+ if (cancellationToken())
+ {
+ co_return nullptr;
+ }
+ co_return file;
+ }
+
+ winrt::Windows::Foundation::IAsyncOperation> FileOpenPicker::PickMultipleFilesAsync()
+ {
+ PickerCommon::PickerParameters parameters{};
+
+ CaptureParameters(parameters);
+
+ co_await winrt::resume_background();
+
+ winrt::Windows::Foundation::Collections::IVector results{ winrt::single_threaded_vector() };
+
+ auto cancellationToken = co_await winrt::get_cancellation_token();
+ if (cancellationToken())
+ {
+ co_return results.GetView();
+ }
+
+ auto dialog = create_instance(CLSID_FileOpenDialog, CONTEXT_ALL);
+
+ parameters.ConfigureDialog(dialog);
+
+ check_hresult(dialog->SetOptions(FOS_ALLOWMULTISELECT));
+
+ {
+ auto hr = dialog->Show(parameters.HWnd);
+ if (FAILED(hr) || cancellationToken())
+ {
+ 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 file = co_await PickerCommon::CreateStorageFileFromShellItem(shellItem);
+ results.Append(file);
+ }
+
+ if (cancellationToken())
+ {
+ results.Clear();
+ co_return results.GetView();
+ }
+ co_return results.GetView();
+ }
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/FileOpenPicker.h b/prototype-workingdir/Microsoft.Storage.Pickers/FileOpenPicker.h
new file mode 100644
index 0000000000..fb68a34d2b
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/FileOpenPicker.h
@@ -0,0 +1,44 @@
+#pragma once
+#include "FileOpenPicker.g.h"
+#include "PickerCommon.h"
+
+namespace winrt::Microsoft::Storage::Pickers::implementation
+{
+ struct FileOpenPicker : FileOpenPickerT
+ {
+ FileOpenPicker(winrt::Microsoft::UI::WindowId const& windowId);
+
+ winrt::Microsoft::Storage::Pickers::PickerViewMode ViewMode();
+ void ViewMode(winrt::Microsoft::Storage::Pickers::PickerViewMode const& value);
+
+ hstring SettingsIdentifier();
+ void SettingsIdentifier(hstring const& value);
+
+ winrt::Microsoft::Storage::Pickers::PickerLocationId SuggestedStartLocation();
+ void SuggestedStartLocation(winrt::Microsoft::Storage::Pickers::PickerLocationId const& value);
+
+ winrt::hstring CommitButtonText();
+ void CommitButtonText(winrt::hstring const& value);
+
+ winrt::Windows::Foundation::Collections::IVector FileTypeFilter();
+
+ winrt::Windows::Foundation::IAsyncOperation PickSingleFileAsync();
+ winrt::Windows::Foundation::IAsyncOperation> PickMultipleFilesAsync();
+
+ private:
+ winrt::Microsoft::UI::WindowId m_windowId{};
+ PickerViewMode m_viewMode{ PickerViewMode::List };
+ winrt::hstring m_settingsIdentifier{};
+ PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified };
+ winrt::hstring m_commitButtonText{};
+ winrt::Windows::Foundation::Collections::IVector m_fileTypeFilter{ winrt::single_threaded_vector() };
+
+ void CaptureParameters(PickerCommon::PickerParameters& parameters);
+ };
+}
+namespace winrt::Microsoft::Storage::Pickers::factory_implementation
+{
+ struct FileOpenPicker : FileOpenPickerT
+ {
+ };
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/FileSavePicker.cpp b/prototype-workingdir/Microsoft.Storage.Pickers/FileSavePicker.cpp
new file mode 100644
index 0000000000..052135bf98
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/FileSavePicker.cpp
@@ -0,0 +1,138 @@
+#include "pch.h"
+#include "FileSavePicker.h"
+#include "FileSavePicker.g.cpp"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "PickerCommon.h"
+
+namespace winrt::Microsoft::Storage::Pickers::implementation
+{
+
+ FileSavePicker::FileSavePicker(winrt::Microsoft::UI::WindowId const& windowId)
+ : m_windowId(windowId)
+ {
+ }
+ hstring FileSavePicker::SettingsIdentifier()
+ {
+ return m_settingsIdentifier;
+ }
+ void FileSavePicker::SettingsIdentifier(hstring const& value)
+ {
+ m_settingsIdentifier = value;
+ }
+ winrt::Microsoft::Storage::Pickers::PickerLocationId FileSavePicker::SuggestedStartLocation()
+ {
+ return m_suggestedStartLocation;
+ }
+ void FileSavePicker::SuggestedStartLocation(winrt::Microsoft::Storage::Pickers::PickerLocationId const& value)
+ {
+ m_suggestedStartLocation = value;
+ }
+ hstring FileSavePicker::CommitButtonText()
+ {
+ return m_commitButtonText;
+ }
+ void FileSavePicker::CommitButtonText(hstring const& value)
+ {
+ m_commitButtonText = value;
+ }
+ winrt::Windows::Foundation::Collections::IMap> FileSavePicker::FileTypeChoices()
+ {
+ return m_fileTypeChoices;
+ }
+ hstring FileSavePicker::DefaultFileExtension()
+ {
+ return m_defaultFileExtension;
+ }
+ void FileSavePicker::DefaultFileExtension(hstring const& value)
+ {
+ m_defaultFileExtension = value;
+ }
+ winrt::Windows::Storage::StorageFile FileSavePicker::SuggestedSaveFile()
+ {
+ return m_suggestedSaveFile;
+ }
+ void FileSavePicker::SuggestedSaveFile(winrt::Windows::Storage::StorageFile const& value)
+ {
+ m_suggestedSaveFile = value;
+ }
+ hstring FileSavePicker::SuggestedFileName()
+ {
+ return m_suggestedFileName;
+ }
+ void FileSavePicker::SuggestedFileName(hstring const& value)
+ {
+ m_suggestedFileName = value;
+ }
+
+
+ void FileSavePicker::CaptureParameters(PickerCommon::PickerParameters& parameters)
+ {
+ parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId);
+ parameters.CommitButtonText = m_commitButtonText;
+ parameters.SettingsIdentifierId = m_settingsIdentifier;
+ parameters.PickerLocationId = m_suggestedStartLocation;
+ parameters.FileTypeFilterPara = PickerCommon::CaptureFilterSpec(parameters.FileTypeFilterData, m_fileTypeChoices.GetView());
+
+ }
+
+ winrt::Windows::Foundation::IAsyncOperation FileSavePicker::PickSaveFileAsync()
+ {
+ PickerCommon::PickerParameters parameters{};
+ CaptureParameters(parameters);
+ auto defaultFileExtension = m_defaultFileExtension;
+ auto suggestedSaveFile = m_suggestedSaveFile;
+ auto suggestedFileName = m_suggestedFileName;
+
+ co_await winrt::resume_background();
+ auto cancellationToken = co_await winrt::get_cancellation_token();
+ if (cancellationToken())
+ {
+ co_return nullptr;
+ }
+
+ auto dialog = create_instance(CLSID_FileSaveDialog, CONTEXT_ALL);
+ parameters.ConfigureDialog(dialog);
+
+ if (!PickerCommon::IsHStringNullOrEmpty(defaultFileExtension))
+ {
+ check_hresult(dialog->SetDefaultExtension(defaultFileExtension.c_str()));
+ }
+ if (!PickerCommon::IsHStringNullOrEmpty(suggestedFileName))
+ {
+ check_hresult(dialog->SetFileName(suggestedFileName.c_str()));
+ }
+ if (suggestedSaveFile != nullptr)
+ {
+ winrt::com_ptr shellItem;
+ check_hresult(SHCreateItemFromParsingName(suggestedSaveFile.Path().c_str(), nullptr, IID_PPV_ARGS(shellItem.put())));
+ check_hresult(dialog->SetSaveAsItem(shellItem.get()));
+ }
+
+ {
+ auto hr = dialog->Show(parameters.HWnd);
+ if (FAILED(hr))
+ {
+ co_return nullptr;
+ }
+ }
+
+ winrt::com_ptr shellItem{};
+ check_hresult(dialog->GetResult(shellItem.put()));
+ auto file = co_await PickerCommon::CreateStorageFileFromShellItem(shellItem);
+
+ if (cancellationToken())
+ {
+ co_return nullptr;
+ }
+ co_return file;
+ }
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/FileSavePicker.h b/prototype-workingdir/Microsoft.Storage.Pickers/FileSavePicker.h
new file mode 100644
index 0000000000..2144f51292
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/FileSavePicker.h
@@ -0,0 +1,53 @@
+#pragma once
+#include "FileSavePicker.g.h"
+#include "PickerCommon.h"
+
+namespace winrt::Microsoft::Storage::Pickers::implementation
+{
+ struct FileSavePickerParameters;
+
+ struct FileSavePicker : FileSavePickerT
+ {
+ FileSavePicker(winrt::Microsoft::UI::WindowId const& windowId);
+
+ hstring SettingsIdentifier();
+ void SettingsIdentifier(hstring const& value);
+
+ winrt::Microsoft::Storage::Pickers::PickerLocationId SuggestedStartLocation();
+ void SuggestedStartLocation(winrt::Microsoft::Storage::Pickers::PickerLocationId const& value);
+
+ hstring CommitButtonText();
+ void CommitButtonText(hstring const& value);
+
+ winrt::Windows::Foundation::Collections::IMap> FileTypeChoices();
+
+ hstring DefaultFileExtension();
+ void DefaultFileExtension(hstring const& value);
+
+ winrt::Windows::Storage::StorageFile SuggestedSaveFile();
+ void SuggestedSaveFile(winrt::Windows::Storage::StorageFile const& value);
+
+ hstring SuggestedFileName();
+ void SuggestedFileName(hstring const& value);
+
+ winrt::Windows::Foundation::IAsyncOperation PickSaveFileAsync();
+
+ private:
+ winrt::Microsoft::UI::WindowId m_windowId{};
+ hstring m_settingsIdentifier{};
+ PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified };
+ hstring m_commitButtonText{};
+ winrt::Windows::Foundation::Collections::IMap> m_fileTypeChoices{ winrt::single_threaded_map>() };
+ hstring m_defaultFileExtension{};
+ winrt::Windows::Storage::StorageFile m_suggestedSaveFile{ nullptr };
+ hstring m_suggestedFileName{};
+
+ void CaptureParameters(PickerCommon::PickerParameters& parameters);
+ };
+}
+namespace winrt::Microsoft::Storage::Pickers::factory_implementation
+{
+ struct FileSavePicker : FileSavePickerT
+ {
+ };
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/FolderPicker.cpp b/prototype-workingdir/Microsoft.Storage.Pickers/FolderPicker.cpp
new file mode 100644
index 0000000000..6e7c62d0be
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/FolderPicker.cpp
@@ -0,0 +1,98 @@
+#include "pch.h"
+#include "FolderPicker.h"
+#include "FolderPicker.g.cpp"
+#include
+#include
+#include
+#include "PickerCommon.h"
+
+namespace winrt::Microsoft::Storage::Pickers::implementation
+{
+ FolderPicker::FolderPicker(winrt::Microsoft::UI::WindowId const& windowId)
+ : m_windowId(windowId)
+ {
+ }
+ winrt::Microsoft::Storage::Pickers::PickerViewMode FolderPicker::ViewMode()
+ {
+ return m_viewMode;
+ }
+ void FolderPicker::ViewMode(winrt::Microsoft::Storage::Pickers::PickerViewMode const& value)
+ {
+ m_viewMode = value;
+ }
+ hstring FolderPicker::SettingsIdentifier()
+ {
+ return m_settingsIdentifier;
+ }
+ void FolderPicker::SettingsIdentifier(hstring const& value)
+ {
+ m_settingsIdentifier = value;
+ }
+ winrt::Microsoft::Storage::Pickers::PickerLocationId FolderPicker::SuggestedStartLocation()
+ {
+ return m_suggestedStartLocation;
+ }
+ void FolderPicker::SuggestedStartLocation(winrt::Microsoft::Storage::Pickers::PickerLocationId const& value)
+ {
+ m_suggestedStartLocation = value;
+ }
+ hstring FolderPicker::CommitButtonText()
+ {
+ return m_commitButtonText;
+ }
+ void FolderPicker::CommitButtonText(hstring const& value)
+ {
+ m_commitButtonText = value;
+ }
+ winrt::Windows::Foundation::Collections::IVector FolderPicker::FileTypeFilter()
+ {
+ return m_fileTypeFilter;
+ }
+
+ void FolderPicker::CaptureParameters(PickerCommon::PickerParameters& parameters)
+ {
+ parameters.HWnd = winrt::Microsoft::UI::GetWindowFromWindowId(m_windowId);
+ parameters.CommitButtonText = m_commitButtonText;
+ parameters.SettingsIdentifierId = m_settingsIdentifier;
+ parameters.PickerLocationId = m_suggestedStartLocation;
+ parameters.FileTypeFilterPara = PickerCommon::CaptureFilterSpec(parameters.FileTypeFilterData, m_fileTypeFilter.GetView());
+ }
+
+
+ winrt::Windows::Foundation::IAsyncOperation FolderPicker::PickSingleFolderAsync()
+ {
+ PickerCommon::PickerParameters parameters{};
+ CaptureParameters(parameters);
+
+ co_await winrt::resume_background();
+
+ auto cancellationToken = co_await winrt::get_cancellation_token();
+ if (cancellationToken())
+ {
+ co_return nullptr;
+ }
+
+ auto dialog = create_instance(CLSID_FileOpenDialog, CONTEXT_ALL);
+
+ parameters.ConfigureDialog(dialog);
+ dialog->SetOptions(FOS_PICKFOLDERS);
+
+ {
+ auto hr = dialog->Show(parameters.HWnd);
+ if (FAILED(hr) || cancellationToken())
+ {
+ co_return nullptr;
+ }
+ }
+
+ winrt::com_ptr shellItem{};
+ check_hresult(dialog->GetResult(shellItem.put()));
+ auto folder = co_await PickerCommon::CreateStorageFolderFromShellItem(shellItem);
+
+ if (cancellationToken())
+ {
+ co_return nullptr;
+ }
+ co_return folder;
+ }
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/FolderPicker.h b/prototype-workingdir/Microsoft.Storage.Pickers/FolderPicker.h
new file mode 100644
index 0000000000..56af65cb19
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/FolderPicker.h
@@ -0,0 +1,45 @@
+#pragma once
+#include "FolderPicker.g.h"
+#include "PickerCommon.h"
+
+namespace winrt::Microsoft::Storage::Pickers::implementation
+{
+ struct FolderPicker : FolderPickerT
+ {
+ FolderPicker(winrt::Microsoft::UI::WindowId const& windowId);
+
+ winrt::Microsoft::Storage::Pickers::PickerViewMode ViewMode();
+ void ViewMode(winrt::Microsoft::Storage::Pickers::PickerViewMode const& value);
+
+ hstring SettingsIdentifier();
+ void SettingsIdentifier(hstring const& value);
+
+ winrt::Microsoft::Storage::Pickers::PickerLocationId SuggestedStartLocation();
+ void SuggestedStartLocation(winrt::Microsoft::Storage::Pickers::PickerLocationId const& value);
+
+ hstring CommitButtonText();
+ void CommitButtonText(hstring const& value);
+
+ winrt::Windows::Foundation::Collections::IVector FileTypeFilter();
+
+ winrt::Windows::Foundation::IAsyncOperation PickSingleFolderAsync();
+
+ private:
+ winrt::Microsoft::UI::WindowId m_windowId{};
+
+ PickerViewMode m_viewMode{ PickerViewMode::List };
+ hstring m_settingsIdentifier{};
+ PickerLocationId m_suggestedStartLocation{ PickerLocationId::Unspecified };
+ hstring m_commitButtonText{};
+
+ winrt::Windows::Foundation::Collections::IVector m_fileTypeFilter{ winrt::single_threaded_vector() };
+
+ void CaptureParameters(PickerCommon::PickerParameters& parameters);
+ };
+}
+namespace winrt::Microsoft::Storage::Pickers::factory_implementation
+{
+ struct FolderPicker : FolderPickerT
+ {
+ };
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft.Storage.Pickers.vcxproj b/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft.Storage.Pickers.vcxproj
new file mode 100644
index 0000000000..b1b1eaf438
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft.Storage.Pickers.vcxproj
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+ true
+ true
+ true
+ {349e64cf-cb0c-4202-b1b5-7f543cc6e886}
+ Microsoft.Storage.Pickers
+ Microsoft.Storage.Pickers
+ en-US
+ 16.0
+ false
+ Windows Store
+ 10.0
+ 10.0.22621.0
+ 10.0.22000.0
+ true
+ true
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+ Release
+ ARM64
+
+
+
+ DynamicLibrary
+ v143
+ Unicode
+ false
+ true
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+
+
+ Console
+ true
+ Microsoft_Storage_Pickers.def
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+ $(CoreLibraryDependencies);%(AdditionalDependencies);shell32.lib
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ $(CoreLibraryDependencies);%(AdditionalDependencies);shell32.lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft.Storage.Pickers.vcxproj.filters b/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft.Storage.Pickers.vcxproj.filters
new file mode 100644
index 0000000000..af63f3cf8e
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft.Storage.Pickers.vcxproj.filters
@@ -0,0 +1,37 @@
+
+
+
+
+ accd3aa8-1ba0-4223-9bbe-0c431709210b
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {926ab91d-31b4-48c3-b9a4-e681349f27f0}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft_Storage_Pickers.def b/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft_Storage_Pickers.def
new file mode 100644
index 0000000000..24e7c1235c
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/Microsoft_Storage_Pickers.def
@@ -0,0 +1,3 @@
+EXPORTS
+DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
+DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/PickerCommon.cpp b/prototype-workingdir/Microsoft.Storage.Pickers/PickerCommon.cpp
new file mode 100644
index 0000000000..63e29b7ebf
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/PickerCommon.cpp
@@ -0,0 +1,200 @@
+#include "pch.h"
+#include "PickerCommon.h"
+#include
+#include "ShObjIdl.h"
+#include
+
+namespace {
+
+ GUID HashHStringToGuid(winrt::hstring const& input)
+ {
+ auto algorithmProvider = winrt::Windows::Security::Cryptography::Core::HashAlgorithmProvider::OpenAlgorithm(winrt::Windows::Security::Cryptography::Core::HashAlgorithmNames::Md5());
+
+ auto buffer = winrt::Windows::Security::Cryptography::CryptographicBuffer::ConvertStringToBinary(input, winrt::Windows::Security::Cryptography::BinaryStringEncoding::Utf16LE);
+
+ auto hash = algorithmProvider.HashData(buffer);
+
+ if (hash.Length() != 16)
+ {
+ throw winrt::hresult_error(E_FAIL, L"Invalid hash length");
+ }
+
+ winrt::com_array resultBuffer{};
+ winrt::Windows::Security::Cryptography::CryptographicBuffer::CopyToByteArray(hash, resultBuffer);
+ GUID guid = *(reinterpret_cast(resultBuffer.data()));
+
+ // TODO: verify bit pattern code from copilot is correct to fit spec
+ // Adjust the GUID to conform to version 3 UUID (MD5-based)
+ guid.Data3 = (guid.Data3 & 0x0FFF) | 0x3000; // Set the version to 3
+ guid.Data4[0] = (guid.Data4[0] & 0x3F) | 0x80; // Set variant to RFC 4122
+
+ return guid;
+ }
+
+ // TODO: use better winrt implementations?
+ // Challenge: currently winrt based Storage.KnownFolder APIs does not provide all location id we need
+ winrt::com_ptr GetKnownFolderFromId(winrt::Microsoft::Storage::Pickers::PickerLocationId pickerLocationId)
+ {
+ KNOWNFOLDERID knownFolderId;
+ switch (pickerLocationId)
+ {
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::DocumentsLibrary:
+ knownFolderId = FOLDERID_Documents;
+ break;
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::ComputerFolder:
+ knownFolderId = FOLDERID_ComputerFolder;
+ break;
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::Desktop:
+ knownFolderId = FOLDERID_Desktop;
+ break;
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::Downloads:
+ knownFolderId = FOLDERID_Downloads;
+ break;
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::HomeGroup:
+ knownFolderId = FOLDERID_HomeGroup;
+ break;
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::MusicLibrary:
+ knownFolderId = FOLDERID_MusicLibrary;
+ break;
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::PicturesLibrary:
+ knownFolderId = FOLDERID_PicturesLibrary;
+ break;
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::VideosLibrary:
+ knownFolderId = FOLDERID_VideosLibrary;
+ break;
+ case winrt::Microsoft::Storage::Pickers::PickerLocationId::Objects3D:
+ knownFolderId = FOLDERID_Objects3D;
+ break;
+ default:
+ return nullptr;
+ }
+
+ auto knownFolderManager = winrt::create_instance(CLSID_KnownFolderManager);
+ winrt::com_ptr knownFolder{};
+ winrt::check_hresult(knownFolderManager->GetFolder(knownFolderId, knownFolder.put()));
+ winrt::com_ptr defaultFolder{};
+ winrt::check_hresult(knownFolder->GetShellItem(0, IID_PPV_ARGS(defaultFolder.put())));
+ return defaultFolder;
+ }
+
+
+ winrt::hstring FormatExtensionWithWildcard(winrt::hstring extension)
+ {
+ if (!extension.empty() && extension[0] == L'*')
+ {
+ return extension;
+ }
+ else
+ {
+ return L"*" + extension;
+ }
+ }
+
+ winrt::hstring JoinExtensions(winrt::Windows::Foundation::Collections::IVectorView extensions)
+ {
+ winrt::hstring result;
+ bool first = true;
+ for (const auto& ext : extensions)
+ {
+ if (first)
+ {
+ result = FormatExtensionWithWildcard(ext);
+ first = false;
+ }
+ else
+ {
+ result = result + L";" + FormatExtensionWithWildcard(ext);
+ }
+ }
+ return result;
+ }
+
+}
+
+
+namespace PickerCommon {
+
+ using namespace winrt;
+
+ bool IsHStringNullOrEmpty(winrt::hstring value)
+ {
+ // TODO: proper handling of null string reference?
+ return value.empty();
+ }
+
+
+ // TODO: better way to convert ShellItem a StorageFile without relying on path?.
+ winrt::Windows::Foundation::IAsyncOperation CreateStorageFileFromShellItem(winrt::com_ptr shellItem)
+ {
+ wil::unique_cotaskmem_string filePath;
+ check_hresult(shellItem->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
+ co_return co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(filePath.get());
+ }
+
+ winrt::Windows::Foundation::IAsyncOperation CreateStorageFolderFromShellItem(winrt::com_ptr shellItem)
+ {
+ wil::unique_cotaskmem_string filePath;
+ check_hresult(shellItem->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
+ co_return co_await winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(filePath.get());
+ }
+
+ std::vector CaptureFilterSpec(std::vector& buffer, winrt::Windows::Foundation::Collections::IVectorView filters)
+ {
+ std::vector result(filters.Size());
+ buffer.clear();
+ buffer.reserve(filters.Size() * (size_t)2);
+ for (auto filter : filters)
+ {
+ auto ext = FormatExtensionWithWildcard(filter);
+ buffer.push_back(filter);
+ buffer.push_back(ext);
+ }
+ for (size_t i = 0; i < filters.Size(); i++)
+ {
+ result.at(i) = { buffer.at(i * 2).c_str(), buffer.at(i * 2 + 1).c_str() };
+ }
+ return result;
+ }
+
+ std::vector CaptureFilterSpec(std::vector& buffer, winrt::Windows::Foundation::Collections::IMapView> filters)
+ {
+ std::vector result(filters.Size());
+ buffer.clear();
+ buffer.reserve(filters.Size() * (size_t)2);
+
+ for (const auto& filter : filters)
+ {
+ buffer.push_back(filter.Key());
+ auto extensionList = JoinExtensions(filter.Value().GetView());
+ buffer.push_back(extensionList);
+ }
+ for (size_t i = 0; i < filters.Size(); i++)
+ {
+ result.at(i) = { buffer.at(i * 2).c_str(), buffer.at(i * 2 + 1).c_str() };
+ }
+ return result;
+ }
+
+ void PickerParameters::ConfigureDialog(winrt::com_ptr dialog)
+ {
+ if (!IsHStringNullOrEmpty(CommitButtonText))
+ {
+ check_hresult(dialog->SetOkButtonLabel(CommitButtonText.c_str()));
+ }
+
+ if (!IsHStringNullOrEmpty(SettingsIdentifierId))
+ {
+ auto guid = HashHStringToGuid(SettingsIdentifierId);
+ check_hresult(dialog->SetClientGuid(guid));
+ }
+
+ auto defaultFolder = GetKnownFolderFromId(PickerLocationId);
+ if (defaultFolder != nullptr)
+ {
+ check_hresult(dialog->SetFolder(defaultFolder.get()));
+ check_hresult(dialog->SetDefaultFolder(defaultFolder.get()));
+ }
+
+ check_hresult(dialog->SetFileTypes(FileTypeFilterPara.size(), FileTypeFilterPara.data()));
+ }
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/PickerCommon.h b/prototype-workingdir/Microsoft.Storage.Pickers/PickerCommon.h
new file mode 100644
index 0000000000..de7db7ac54
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/PickerCommon.h
@@ -0,0 +1,27 @@
+// TODO: use better namespace, maybe anonymous namespace?
+#pragma once
+#include "pch.h"
+#include "ShObjIdl.h"
+#include "winrt/Microsoft.Storage.Pickers.h"
+
+namespace PickerCommon {
+ winrt::Windows::Foundation::IAsyncOperation CreateStorageFileFromShellItem(winrt::com_ptr shellItem);
+ winrt::Windows::Foundation::IAsyncOperation CreateStorageFolderFromShellItem(winrt::com_ptr shellItem);
+
+ std::vector CaptureFilterSpec(std::vector& buffer, winrt::Windows::Foundation::Collections::IVectorView filters);
+ std::vector CaptureFilterSpec(std::vector& buffer, winrt::Windows::Foundation::Collections::IMapView> filters);
+
+ // TODO: remove this if we know proper and null safe empty test for string
+ bool IsHStringNullOrEmpty(winrt::hstring value);
+
+ struct PickerParameters {
+ HWND HWnd;
+ winrt::hstring CommitButtonText;
+ winrt::hstring SettingsIdentifierId;
+ winrt::Microsoft::Storage::Pickers::PickerLocationId PickerLocationId;
+ std::vector FileTypeFilterData{};
+ std::vector FileTypeFilterPara{};
+
+ void ConfigureDialog(winrt::com_ptr dialog);
+ };
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/Pickers.idl b/prototype-workingdir/Microsoft.Storage.Pickers/Pickers.idl
new file mode 100644
index 0000000000..31c4c6c7ea
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/Pickers.idl
@@ -0,0 +1,68 @@
+namespace Microsoft.Storage.Pickers
+{
+ enum PickerViewMode
+ {
+ List,
+ Thumbnail,
+ };
+
+ enum PickerLocationId
+ {
+ DocumentsLibrary,
+ ComputerFolder,
+ Desktop,
+ Downloads,
+ HomeGroup,
+ MusicLibrary,
+ PicturesLibrary,
+ VideosLibrary,
+ Objects3D,
+ Unspecified,
+ };
+
+
+ [default_interface]
+ runtimeclass FileOpenPicker
+ {
+ FileOpenPicker(Microsoft.UI.WindowId windowId);
+
+ Microsoft.Storage.Pickers.PickerViewMode ViewMode;
+ String SettingsIdentifier;
+ Microsoft.Storage.Pickers.PickerLocationId SuggestedStartLocation;
+ String CommitButtonText;
+ Windows.Foundation.Collections.IVector FileTypeFilter{ get; };
+
+ [remote_sync] Windows.Foundation.IAsyncOperation PickSingleFileAsync();
+ [remote_sync] Windows.Foundation.IAsyncOperation > PickMultipleFilesAsync();
+ }
+
+ [default_interface]
+ runtimeclass FileSavePicker
+ {
+ FileSavePicker(Microsoft.UI.WindowId windowId);
+
+ String SettingsIdentifier;
+ Microsoft.Storage.Pickers.PickerLocationId SuggestedStartLocation;
+ String CommitButtonText;
+ Windows.Foundation.Collections.IMap > FileTypeChoices{ get; };
+ String DefaultFileExtension;
+ Windows.Storage.StorageFile SuggestedSaveFile;
+ String SuggestedFileName;
+
+ [remote_sync] Windows.Foundation.IAsyncOperation PickSaveFileAsync();
+ }
+
+ [default_interface]
+ runtimeclass FolderPicker
+ {
+ FolderPicker(Microsoft.UI.WindowId windowId);
+
+ Microsoft.Storage.Pickers.PickerViewMode ViewMode;
+ String SettingsIdentifier;
+ Microsoft.Storage.Pickers.PickerLocationId SuggestedStartLocation;
+ String CommitButtonText;
+ Windows.Foundation.Collections.IVector FileTypeFilter{ get; };
+
+ [remote_sync] Windows.Foundation.IAsyncOperation PickSingleFolderAsync();
+ }
+}
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/packages.config b/prototype-workingdir/Microsoft.Storage.Pickers/packages.config
new file mode 100644
index 0000000000..6e553cc88c
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/pch.cpp b/prototype-workingdir/Microsoft.Storage.Pickers/pch.cpp
new file mode 100644
index 0000000000..1d9f38c57d
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/pch.h b/prototype-workingdir/Microsoft.Storage.Pickers/pch.h
new file mode 100644
index 0000000000..21563b73b3
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/pch.h
@@ -0,0 +1,33 @@
+#pragma once
+#include
+#include
+#include
+#include
+
+// Undefine GetCurrentTime macro to prevent
+// conflict with Storyboard::GetCurrentTime
+#undef GetCurrentTime
+
+
+#include "winrt/Microsoft.Storage.Pickers.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
diff --git a/prototype-workingdir/Microsoft.Storage.Pickers/readme.txt b/prototype-workingdir/Microsoft.Storage.Pickers/readme.txt
new file mode 100644
index 0000000000..6b46510cd0
--- /dev/null
+++ b/prototype-workingdir/Microsoft.Storage.Pickers/readme.txt
@@ -0,0 +1,27 @@
+========================================================================
+ Microsoft.Storage.Pickers Project Overview
+========================================================================
+
+This project demonstrates how to get started authoring Windows Runtime
+classes directly with standard C++, using the Windows App SDK and
+C++/WinRT packages to generate implementation headers from interface
+(IDL) files. The generated Windows Runtime component binary and WinMD
+files should then be bundled with the app consuming them.
+
+Steps:
+1. Create an interface (IDL) file to define your Windows Runtime class,
+ its default interface, and any other interfaces it implements.
+2. Build the project once to generate module.g.cpp, module.h.cpp, and
+ implementation templates under the "Generated Files" folder, as
+ well as skeleton class definitions under "Generated Files\sources".
+3. Use the skeleton class definitions for reference to implement your
+ Windows Runtime classes.
+
+========================================================================
+Learn more about Windows App SDK here:
+https://docs.microsoft.com/windows/apps/windows-app-sdk/
+Learn more about WinUI3 here:
+https://docs.microsoft.com/windows/apps/winui/winui3/
+Learn more about C++/WinRT here:
+http://aka.ms/cppwinrt/
+========================================================================
diff --git a/prototype-workingdir/NuGet.config b/prototype-workingdir/NuGet.config
new file mode 100644
index 0000000000..8e8d51bd44
--- /dev/null
+++ b/prototype-workingdir/NuGet.config
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/prototype-workingdir/PickerUsageApp/App.xaml b/prototype-workingdir/PickerUsageApp/App.xaml
new file mode 100644
index 0000000000..01e1e1c35d
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/App.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/prototype-workingdir/PickerUsageApp/App.xaml.cpp b/prototype-workingdir/PickerUsageApp/App.xaml.cpp
new file mode 100644
index 0000000000..fb607703e2
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/App.xaml.cpp
@@ -0,0 +1,43 @@
+#include "pch.h"
+#include "App.xaml.h"
+#include "MainWindow.xaml.h"
+
+using namespace winrt;
+using namespace Microsoft::UI::Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace winrt::PickerUsageApp::implementation
+{
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ App::App()
+ {
+ // Xaml objects should not call InitializeComponent during construction.
+ // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent
+
+#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
+ UnhandledException([](IInspectable const&, UnhandledExceptionEventArgs const& e)
+ {
+ if (IsDebuggerPresent())
+ {
+ auto errorMessage = e.Message();
+ __debugbreak();
+ }
+ });
+#endif
+ }
+
+ ///
+ /// Invoked when the application is launched.
+ ///
+ /// Details about the launch request and process.
+ void App::OnLaunched([[maybe_unused]] LaunchActivatedEventArgs const& e)
+ {
+ window = make();
+ window.Activate();
+ }
+}
diff --git a/prototype-workingdir/PickerUsageApp/App.xaml.h b/prototype-workingdir/PickerUsageApp/App.xaml.h
new file mode 100644
index 0000000000..fb5f632552
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/App.xaml.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "App.xaml.g.h"
+
+namespace winrt::PickerUsageApp::implementation
+{
+ struct App : AppT
+ {
+ App();
+
+ void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&);
+
+ private:
+ winrt::Microsoft::UI::Xaml::Window window{ nullptr };
+ };
+}
diff --git a/prototype-workingdir/PickerUsageApp/Assets/LockScreenLogo.scale-200.png b/prototype-workingdir/PickerUsageApp/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 0000000000..7440f0d4bf
Binary files /dev/null and b/prototype-workingdir/PickerUsageApp/Assets/LockScreenLogo.scale-200.png differ
diff --git a/prototype-workingdir/PickerUsageApp/Assets/SplashScreen.scale-200.png b/prototype-workingdir/PickerUsageApp/Assets/SplashScreen.scale-200.png
new file mode 100644
index 0000000000..32f486a867
Binary files /dev/null and b/prototype-workingdir/PickerUsageApp/Assets/SplashScreen.scale-200.png differ
diff --git a/prototype-workingdir/PickerUsageApp/Assets/Square150x150Logo.scale-200.png b/prototype-workingdir/PickerUsageApp/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 0000000000..53ee3777ea
Binary files /dev/null and b/prototype-workingdir/PickerUsageApp/Assets/Square150x150Logo.scale-200.png differ
diff --git a/prototype-workingdir/PickerUsageApp/Assets/Square44x44Logo.scale-200.png b/prototype-workingdir/PickerUsageApp/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 0000000000..f713bba67f
Binary files /dev/null and b/prototype-workingdir/PickerUsageApp/Assets/Square44x44Logo.scale-200.png differ
diff --git a/prototype-workingdir/PickerUsageApp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/prototype-workingdir/PickerUsageApp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 0000000000..dc9f5bea0c
Binary files /dev/null and b/prototype-workingdir/PickerUsageApp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/prototype-workingdir/PickerUsageApp/Assets/StoreLogo.png b/prototype-workingdir/PickerUsageApp/Assets/StoreLogo.png
new file mode 100644
index 0000000000..a4586f26bd
Binary files /dev/null and b/prototype-workingdir/PickerUsageApp/Assets/StoreLogo.png differ
diff --git a/prototype-workingdir/PickerUsageApp/Assets/Wide310x150Logo.scale-200.png b/prototype-workingdir/PickerUsageApp/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 0000000000..8b4a5d0dd5
Binary files /dev/null and b/prototype-workingdir/PickerUsageApp/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/prototype-workingdir/PickerUsageApp/MainWindow.idl b/prototype-workingdir/PickerUsageApp/MainWindow.idl
new file mode 100644
index 0000000000..90986b5614
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/MainWindow.idl
@@ -0,0 +1,8 @@
+namespace PickerUsageApp
+{
+ [default_interface]
+ runtimeclass MainWindow : Microsoft.UI.Xaml.Window
+ {
+ MainWindow();
+ }
+}
diff --git a/prototype-workingdir/PickerUsageApp/MainWindow.xaml b/prototype-workingdir/PickerUsageApp/MainWindow.xaml
new file mode 100644
index 0000000000..d1d606df21
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/MainWindow.xaml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+ Multi Selection
+
+
+
+ CommitButtonText
+ Enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/prototype-workingdir/PickerUsageApp/MainWindow.xaml.cpp b/prototype-workingdir/PickerUsageApp/MainWindow.xaml.cpp
new file mode 100644
index 0000000000..054d68e36b
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/MainWindow.xaml.cpp
@@ -0,0 +1,322 @@
+#include "pch.h"
+#include "MainWindow.xaml.h"
+#if __has_include("MainWindow.g.cpp")
+#include "MainWindow.g.cpp"
+#endif
+#include
+#include
+#include
+#include
+
+using namespace winrt;
+using namespace Microsoft::UI::Xaml;
+//using namespace Windows::Foundation;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace winrt::PickerUsageApp::implementation
+{
+ Windows::Storage::Pickers::PickerViewMode Convert(Microsoft::Storage::Pickers::PickerViewMode viewMode)
+ {
+ switch (viewMode)
+ {
+ case winrt::Microsoft::Storage::Pickers::PickerViewMode::List:
+ return Windows::Storage::Pickers::PickerViewMode::List;
+ case winrt::Microsoft::Storage::Pickers::PickerViewMode::Thumbnail:
+ return Windows::Storage::Pickers::PickerViewMode::Thumbnail;
+ default:
+ return Windows::Storage::Pickers::PickerViewMode::List;
+ }
+ }
+
+ winrt::Windows::Foundation::IAsyncAction MainWindow::SDKClick(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args)
+ {
+ labelBlock().Text(L"");
+ hstring message{};
+ try
+ {
+ switch (m_PickerTypeIndex)
+ {
+ case 0:
+ message = co_await OpenFileSDKClick(sender, args);
+ break;
+ case 1:
+ message = co_await SaveFileSDKClick();
+ break;
+ case 2:
+ message = co_await OpenFolderSDKClick();
+ break;
+ default:
+ message = L"Unsupported Picker Type";
+ break;
+ }
+ }
+ catch (winrt::hresult_error const& ex_)
+ {
+ message = ex_.message();
+ }
+ labelBlock().Text(message);
+ }
+
+ winrt::Windows::Foundation::IAsyncAction MainWindow::UWPClick(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args)
+ {
+ labelBlock().Text(L"");
+ hstring message{};
+ try
+ {
+ switch (m_PickerTypeIndex)
+ {
+ case 0:
+ message = co_await OpenFileUWPClick(sender, args);
+ break;
+ case 1:
+ message = co_await SaveFileUWPClick();
+ break;
+ case 2:
+ message = co_await OpenFolderUWPClick();
+ break;
+
+ default:
+ message = L"Unsupported Picker Type";
+ break;
+ }
+ }
+ catch (winrt::hresult_error const& ex_)
+ {
+ message = ex_.message();
+ }
+ labelBlock().Text(message);
+ }
+
+
+ Windows::Foundation::IAsyncOperation MainWindow::OpenFileUWPClick(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto windowNative = this->m_inner.as();
+ HWND hWnd = nullptr;
+ check_hresult(windowNative->get_WindowHandle(&hWnd));
+
+ winrt::Windows::Storage::Pickers::FileOpenPicker picker{};
+
+ picker.as<::IInitializeWithWindow>()->Initialize(hWnd);
+ SetOpenPickerOptions(picker);
+ picker.ViewMode(Convert(m_ViewMode));
+
+ if (!m_MultipleSelect)
+ {
+ auto& file = co_await picker.PickSingleFileAsync();
+ if (file != nullptr)
+ {
+ co_return file.Path();
+ }
+ }
+ else
+ {
+ auto& files = co_await picker.PickMultipleFilesAsync();
+ winrt::hstring names = L"";
+ for (auto& file : files)
+ {
+ names = names + file.Path() + L"\n";
+ }
+ co_return names;
+ }
+ co_return L"no selection";
+ }
+
+ Windows::Foundation::IAsyncOperation MainWindow::SaveFileUWPClick()
+ {
+ auto windowNative = this->m_inner.as();
+ HWND hWnd = nullptr;
+ check_hresult(windowNative->get_WindowHandle(&hWnd));
+
+ winrt::Windows::Storage::Pickers::FileSavePicker picker{};
+
+ picker.as<::IInitializeWithWindow>()->Initialize(hWnd);
+ SetSavePickerOptions(picker);
+
+ if (!m_MultipleSelect)
+ {
+ auto& file = co_await picker.PickSaveFileAsync();
+ if (file != nullptr)
+ {
+ co_return file.Path();
+ }
+ }
+ else
+ {
+ co_return L"File Save Picker does not support multi selection";
+ }
+ co_return L"no selection";
+ }
+
+ winrt::Windows::Foundation::IAsyncOperation MainWindow::OpenFolderUWPClick()
+ {
+ auto windowNative = this->m_inner.as();
+ HWND hWnd = nullptr;
+ check_hresult(windowNative->get_WindowHandle(&hWnd));
+
+ winrt::Windows::Storage::Pickers::FolderPicker picker{};
+
+ picker.as<::IInitializeWithWindow>()->Initialize(hWnd);
+ SetOpenPickerOptions(picker);
+ picker.ViewMode(Convert(m_ViewMode));
+
+ if (!m_MultipleSelect)
+ {
+ auto& folder = co_await picker.PickSingleFolderAsync();
+ if (folder != nullptr)
+ {
+ co_return folder.Path();
+ }
+ }
+ else
+ {
+ co_return L"Folder Picker does not support multi selection";
+ }
+ co_return L"no selection";
+ }
+
+ Windows::Foundation::IAsyncOperation MainWindow::OpenFileSDKClick(IInspectable const&, RoutedEventArgs const&)
+ {
+ auto id = AppWindow().Id();
+ winrt::Microsoft::Storage::Pickers::FileOpenPicker picker{ id };
+
+ SetOpenPickerOptions(picker);
+ picker.ViewMode(m_ViewMode);
+ if (!m_MultipleSelect)
+ {
+ auto& file = co_await picker.PickSingleFileAsync();
+ if (file != nullptr)
+ {
+ co_return file.Path();
+ }
+ }
+ else
+ {
+ auto& files = co_await picker.PickMultipleFilesAsync();
+ winrt::hstring names = L"";
+ for (auto& file : files)
+ {
+ names = names + file.Path() + L"\n";
+ }
+ co_return names;
+ }
+ co_return L"no selection";
+ }
+
+ Windows::Foundation::IAsyncOperation MainWindow::SaveFileSDKClick()
+ {
+ auto id = AppWindow().Id();
+ winrt::Microsoft::Storage::Pickers::FileSavePicker picker{ id };
+
+ SetSavePickerOptions(picker);
+ if (!m_MultipleSelect)
+ {
+ auto& file = co_await picker.PickSaveFileAsync();
+ if (file != nullptr)
+ {
+ co_return file.Path();
+ }
+ }
+ else
+ {
+ co_return L"FileSavePicker does not support multi selection";
+ }
+ co_return L"no selection";
+ }
+
+ winrt::Windows::Foundation::IAsyncOperation MainWindow::OpenFolderSDKClick()
+ {
+ auto id = AppWindow().Id();
+ winrt::Microsoft::Storage::Pickers::FolderPicker picker{ id };
+
+ SetOpenPickerOptions(picker);
+ picker.ViewMode(m_ViewMode);
+ if (!m_MultipleSelect)
+ {
+ auto& folder = co_await picker.PickSingleFolderAsync();
+ if (folder != nullptr)
+ {
+ co_return folder.Path();
+ }
+ }
+ else
+ {
+ co_return L"Folder multiple selection is not supported";
+ }
+ co_return L"no selection";
+ }
+}
+
+
+void winrt::PickerUsageApp::implementation::MainWindow::UIFronzenTestClick(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
+{
+ counterBlock().Text(std::to_wstring(count));
+ count++;
+}
+
+
+void winrt::PickerUsageApp::implementation::MainWindow::toggleCustomLableClick(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
+{
+ m_isUseCustomLabel = !m_isUseCustomLabel;
+ if (m_isUseCustomLabel)
+ {
+ useCustomLabelToggle().Content(box_value(L"Disable"));
+ customLabelBox().Visibility(Visibility::Visible);
+ }
+ else
+ {
+ useCustomLabelToggle().Content(box_value(L"Enable"));
+ customLabelBox().Visibility(Visibility::Collapsed);
+ }
+}
+
+
+void winrt::PickerUsageApp::implementation::MainWindow::ViewModeSelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e)
+{
+ auto radioButtons = sender.as();
+ auto selectedIndex = radioButtons.SelectedIndex();
+ switch (selectedIndex)
+ {
+ case 0:
+ m_ViewMode = Microsoft::Storage::Pickers::PickerViewMode::List;
+ break;
+ case 1:
+ m_ViewMode = Microsoft::Storage::Pickers::PickerViewMode::Thumbnail;
+ break;
+ default:
+ break;
+ }
+}
+
+
+void winrt::PickerUsageApp::implementation::MainWindow::FilterTypeSelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e)
+{
+ auto radioButtons = sender.as();
+
+ m_FilterTypeIndex = radioButtons.SelectedIndex();
+}
+
+
+void winrt::PickerUsageApp::implementation::MainWindow::SettingsIdentifierChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e)
+{
+ auto radioButtons = sender.as();
+ m_SettingsIdentifierIndex = radioButtons.SelectedIndex();
+}
+
+void winrt::PickerUsageApp::implementation::MainWindow::PickerLocationIdChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e)
+{
+ auto radioButtons = sender.as();
+ m_PickerLocationIdIndex = radioButtons.SelectedIndex();
+}
+
+
+void winrt::PickerUsageApp::implementation::MainWindow::MultiSelectToggled(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
+{
+ m_MultipleSelect = sender.as().IsOn();
+}
+
+void winrt::PickerUsageApp::implementation::MainWindow::PickerTypeChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
+{
+ m_PickerTypeIndex = sender.as().SelectedIndex();
+}
diff --git a/prototype-workingdir/PickerUsageApp/MainWindow.xaml.h b/prototype-workingdir/PickerUsageApp/MainWindow.xaml.h
new file mode 100644
index 0000000000..53dee22f4f
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/MainWindow.xaml.h
@@ -0,0 +1,115 @@
+#pragma once
+
+#include "MainWindow.g.h"
+#include
+
+namespace winrt::PickerUsageApp::implementation
+{
+ struct MainWindow : MainWindowT
+ {
+ int count{ 0 };
+
+ MainWindow()
+ {
+ // Xaml objects should not call InitializeComponent during construction.
+ // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent
+ }
+
+ winrt::Windows::Foundation::IAsyncOperation OpenFileSDKClick(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
+ winrt::Windows::Foundation::IAsyncOperation OpenFileUWPClick(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
+
+ winrt::Windows::Foundation::IAsyncOperation SaveFileUWPClick();
+ winrt::Windows::Foundation::IAsyncOperation SaveFileSDKClick();
+
+ winrt::Windows::Foundation::IAsyncOperation OpenFolderSDKClick();
+ winrt::Windows::Foundation::IAsyncOperation OpenFolderUWPClick();
+
+
+ winrt::Windows::Foundation::IAsyncAction SDKClick(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
+ winrt::Windows::Foundation::IAsyncAction UWPClick(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
+
+ void UIFronzenTestClick(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void toggleCustomLableClick(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void ViewModeSelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
+ void FilterTypeSelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
+ void SettingsIdentifierChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
+ void PickerLocationIdChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
+ void MultiSelectToggled(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void PickerTypeChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ bool m_isUseCustomLabel{ false };
+ winrt::Microsoft::Storage::Pickers::PickerViewMode m_ViewMode{ Microsoft::Storage::Pickers::PickerViewMode::List };
+ int m_FilterTypeIndex{ 0 };
+ int m_SettingsIdentifierIndex{ 0 };
+ int m_PickerLocationIdIndex{ 0 };
+ int m_PickerTypeIndex{ 0 };
+ bool m_MultipleSelect{ false };
+
+
+ // using this template approach helps us ensure use same logic on compatible user facing API
+ template void SetCommonPickerOptions(TPicker picker)
+ {
+ if (m_isUseCustomLabel)
+ {
+ picker.CommitButtonText(customLabelBox().Text());
+ }
+ switch (m_SettingsIdentifierIndex)
+ {
+ case 1:
+ picker.SettingsIdentifier(L"Identifier1");
+ break;
+ case 2:
+ picker.SettingsIdentifier(L"Identifier2");
+ break;
+ default:
+ picker.SettingsIdentifier({});
+ break;
+ }
+ switch (m_PickerLocationIdIndex)
+ {
+ case 1:
+ picker.SuggestedStartLocation(TPickerLocationId::DocumentsLibrary);
+ break;
+ case 2:
+ picker.SuggestedStartLocation(TPickerLocationId::Desktop);
+ break;
+ default:
+ break;
+ }
+ }
+
+ template void SetOpenPickerOptions(TPicker picker)
+ {
+ SetCommonPickerOptions(picker);
+ switch (m_FilterTypeIndex)
+ {
+ case 1:
+ picker.FileTypeFilter().Append(L".jpg");
+ picker.FileTypeFilter().Append(L".png");
+ break;
+ case 2:
+ picker.FileTypeFilter().Append(L".jpg");
+ picker.FileTypeFilter().Append(L".png");
+ picker.FileTypeFilter().Append(L".json");
+ break;
+ default:
+ picker.FileTypeFilter().Append(L"*");
+ break;
+ }
+ }
+
+ template void SetSavePickerOptions(TPicker picker)
+ {
+ SetCommonPickerOptions(picker);
+ picker.FileTypeChoices().Insert(L"Plain Text", winrt::single_threaded_vector({ L".txt" }));
+ }
+ };
+}
+
+namespace winrt::PickerUsageApp::factory_implementation
+{
+ struct MainWindow : MainWindowT
+ {
+ };
+}
diff --git a/prototype-workingdir/PickerUsageApp/Package.appxmanifest b/prototype-workingdir/PickerUsageApp/Package.appxmanifest
new file mode 100644
index 0000000000..a9df97a30d
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/Package.appxmanifest
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ PickerUsageApp
+ xianghong
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/prototype-workingdir/PickerUsageApp/PickerUsageApp.vcxproj b/prototype-workingdir/PickerUsageApp/PickerUsageApp.vcxproj
new file mode 100644
index 0000000000..705335bb5e
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/PickerUsageApp.vcxproj
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+ true
+ true
+ true
+ {c0c88f67-8c6c-49f8-827e-86c0e1669f09}
+ PickerUsageApp
+ PickerUsageApp
+
+ $(RootNamespace)
+ en-US
+ 16.0
+ false
+ true
+ Windows Store
+ 10.0
+ 10.0
+ 10.0.17763.0
+ true
+ true
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+ Release
+ ARM64
+
+
+
+ Application
+ v143
+ Unicode
+ true
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+ App.xaml
+
+
+ MainWindow.xaml
+
+
+
+
+
+
+
+
+ Create
+
+
+ App.xaml
+
+
+ MainWindow.xaml
+
+
+
+
+
+ Code
+ MainWindow.xaml
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {349e64cf-cb0c-4202-b1b5-7f543cc6e886}
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype-workingdir/PickerUsageApp/PickerUsageApp.vcxproj.filters b/prototype-workingdir/PickerUsageApp/PickerUsageApp.vcxproj.filters
new file mode 100644
index 0000000000..897732b290
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/PickerUsageApp.vcxproj.filters
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+ {c0c88f67-8c6c-49f8-827e-86c0e1669f09}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype-workingdir/PickerUsageApp/app.manifest b/prototype-workingdir/PickerUsageApp/app.manifest
new file mode 100644
index 0000000000..978e572078
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/app.manifest
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+
+
+
\ No newline at end of file
diff --git a/prototype-workingdir/PickerUsageApp/packages.config b/prototype-workingdir/PickerUsageApp/packages.config
new file mode 100644
index 0000000000..6e553cc88c
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype-workingdir/PickerUsageApp/pch.cpp b/prototype-workingdir/PickerUsageApp/pch.cpp
new file mode 100644
index 0000000000..ce9b73991b
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/pch.cpp
@@ -0,0 +1,2 @@
+#include "pch.h"
+
diff --git a/prototype-workingdir/PickerUsageApp/pch.h b/prototype-workingdir/PickerUsageApp/pch.h
new file mode 100644
index 0000000000..fe1ff28578
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/pch.h
@@ -0,0 +1,32 @@
+#pragma once
+#include
+#include
+#include
+#include
+
+// Undefine GetCurrentTime macro to prevent
+// conflict with Storyboard::GetCurrentTime
+#undef GetCurrentTime
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "winrt/Microsoft.Storage.Pickers.h"
+#include "winrt/Windows.Storage.Pickers.h"
+#include "winrt/Windows.Storage.h"
+#include
+#include
+#include
+
+#include
diff --git a/prototype-workingdir/PickerUsageApp/readme.txt b/prototype-workingdir/PickerUsageApp/readme.txt
new file mode 100644
index 0000000000..0241fd41ef
--- /dev/null
+++ b/prototype-workingdir/PickerUsageApp/readme.txt
@@ -0,0 +1,27 @@
+========================================================================
+ PickerUsageApp Project Overview
+========================================================================
+
+This project demonstrates how to get started writing WinUI3 apps directly
+with standard C++, using the Windows App SDK and C++/WinRT packages and
+XAML compiler support to generate implementation headers from interface
+(IDL) files. These headers can then be used to implement the local
+Windows Runtime classes referenced in the app's XAML pages.
+
+Steps:
+1. Create an interface (IDL) file to define any local Windows Runtime
+ classes referenced in the app's XAML pages.
+2. Build the project once to generate implementation templates under
+ the "Generated Files" folder, as well as skeleton class definitions
+ under "Generated Files\sources".
+3. Use the skeleton class definitions for reference to implement your
+ Windows Runtime classes.
+
+========================================================================
+Learn more about Windows App SDK here:
+https://docs.microsoft.com/windows/apps/windows-app-sdk/
+Learn more about WinUI3 here:
+https://docs.microsoft.com/windows/apps/winui/winui3/
+Learn more about C++/WinRT here:
+http://aka.ms/cppwinrt/
+========================================================================
diff --git a/prototype-workingdir/PickersPrototype.sln b/prototype-workingdir/PickersPrototype.sln
new file mode 100644
index 0000000000..66bdb66599
--- /dev/null
+++ b/prototype-workingdir/PickersPrototype.sln
@@ -0,0 +1,57 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.11.35431.28
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Storage.Pickers", "Microsoft.Storage.Pickers\Microsoft.Storage.Pickers.vcxproj", "{349E64CF-CB0C-4202-B1B5-7F543CC6E886}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PickerUsageApp", "PickerUsageApp\PickerUsageApp.vcxproj", "{C0C88F67-8C6C-49F8-827E-86C0E1669F09}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Debug|ARM64.Build.0 = Debug|ARM64
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Debug|x64.ActiveCfg = Debug|x64
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Debug|x64.Build.0 = Debug|x64
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Debug|x86.ActiveCfg = Debug|Win32
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Debug|x86.Build.0 = Debug|Win32
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Release|ARM64.ActiveCfg = Release|ARM64
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Release|ARM64.Build.0 = Release|ARM64
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Release|x64.ActiveCfg = Release|x64
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Release|x64.Build.0 = Release|x64
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Release|x86.ActiveCfg = Release|Win32
+ {349E64CF-CB0C-4202-B1B5-7F543CC6E886}.Release|x86.Build.0 = Release|Win32
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|ARM64.Build.0 = Debug|ARM64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|x64.ActiveCfg = Debug|x64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|x64.Build.0 = Debug|x64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|x64.Deploy.0 = Debug|x64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|x86.ActiveCfg = Debug|Win32
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|x86.Build.0 = Debug|Win32
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Debug|x86.Deploy.0 = Debug|Win32
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|ARM64.ActiveCfg = Release|ARM64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|ARM64.Build.0 = Release|ARM64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|ARM64.Deploy.0 = Release|ARM64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|x64.ActiveCfg = Release|x64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|x64.Build.0 = Release|x64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|x64.Deploy.0 = Release|x64
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|x86.ActiveCfg = Release|Win32
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|x86.Build.0 = Release|Win32
+ {C0C88F67-8C6C-49F8-827E-86C0E1669F09}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4C5161F0-084E-45BA-B6B8-9A15B5EB5725}
+ EndGlobalSection
+EndGlobal
diff --git a/prototype-workingdir/README.md b/prototype-workingdir/README.md
new file mode 100644
index 0000000000..3d9d6793a6
--- /dev/null
+++ b/prototype-workingdir/README.md
@@ -0,0 +1,26 @@
+# Picker Prototypes Implementation Notes
+
+This folder contains prototype implementations for adding types in `Storage.Pickers` to the Windows App SDK. It is currently under development and **not** ready for review or production use.
+
+NOTE: a develop certificate maybe required to run the demo app, if you encounter deployment issues, please add a new certificate to the PickerUsageApp project.
+
+## Current State
+
+- Basic implementation of most core functionalities was added in `Microsoft.Storage.Pickers/`.
+- A basic demo app for testing and comparing purpose was added in `PickerUsageApp/`.
+
+### Next steps
+- Additional argument validation needs to be added.
+- More detailed error handling and exception code, with proper internationalization (localization), is required.
+- Add Unit tests
+- Need to be moved to proper folder and integrate with normal WinAppSDK pipeline
+
+## Questions
+
+- The implementation of `SettingsIdentifier` is based on `IFileDialog`'s `SetClientGuid` method, which requires converting the user-provided `SettingsIdentifier` string into a GUID to pass to `SetClientGuid`. We are using MD5 hashing for this conversion to avoid dependence on external state (static or other persistent states). Is this an acceptable approach?
+- The implementation uses Win32 interop APIs, which require linking to `Shell32.lib`. Is this the correct way to implement pickers?
+- Should we check for COM initialization?
+- How can we obtain resources (i18n) for proper error reporting for hardcoded labels like `"All"` for `*` file type filters?
+
+
+
diff --git a/prototype-workingdir/environment.props b/prototype-workingdir/environment.props
new file mode 100644
index 0000000000..6dc4195c32
--- /dev/null
+++ b/prototype-workingdir/environment.props
@@ -0,0 +1 @@
+
\ No newline at end of file