diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 95a0a9c9b..9d9e9025d 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -37,15 +37,15 @@ Nuget Package(s): Package Version(s): Windows 10 Build Number: -- [ ] Anniversary Update (14393) - [ ] Creators Update (15063) - [ ] Fall Creators Update (16299) +- [ ] April 2018 Update (17134) - [ ] Insider Build (build number: ) App min and target version: -- [ ] Anniversary Update (14393) - [ ] Creators Update (15063) - [ ] Fall Creators Update (16299) +- [ ] April 2018 Update (17134) - [ ] Insider Build (xxxxx) Device form factor: diff --git a/.vsts-ci.yml b/.vsts-ci.yml index b7b5a73d5..64c7a19df 100644 --- a/.vsts-ci.yml +++ b/.vsts-ci.yml @@ -1,3 +1,7 @@ +trigger: +- master +- rel/* + variables: BuildConfiguration: Release @@ -14,8 +18,14 @@ steps: inputs: versionSpec: 4.6.2 -- powershell: | - .\build\build.ps1 -target=SignNuGet +- task: DotNetCoreCLI@2 + inputs: + command: build + projects: build/setversion.csproj + arguments: -c $(BuildConfiguration) + displayName: Set Version + +- powershell: .\build\build.ps1 -target=SignNuGet displayName: Build env: SignClientSecret: $(SignClientSecret) diff --git a/.vsts-pr.yml b/.vsts-pr.yml new file mode 100644 index 000000000..f46a6126c --- /dev/null +++ b/.vsts-pr.yml @@ -0,0 +1,27 @@ +trigger: none +variables: + BuildConfiguration: Release + +steps: +- task: BatchScript@1 + inputs: + filename: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Common7\\Tools\\VsDevCmd.bat" + arguments: -no_logo + modifyEnvironment: true + displayName: Setup Environment Variables + +- task: NuGetToolInstaller@0 + displayName: Use NuGet 4.6.2 + inputs: + versionSpec: 4.6.2 + +- powershell: .\build\build.ps1 -target=Package + displayName: Build + +- task: PublishBuildArtifacts@1 + displayName: Publish Package Artifacts + inputs: + pathToPublish: .\bin\nupkg + artifactType: container + artifactName: Packages + condition: eq(variables['system.pullrequest.isfork'], false) \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 81a6e30b7..d659b1148 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,16 +1,14 @@ - Microsoft + Microsoft.Toolkit true true - https://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/master/build/nuget.png - https://github.com/Microsoft/UWPCommunityToolkit - https://github.com/Microsoft/UWPCommunityToolkit/blob/master/license.md - v2.0: https://github.com/Microsoft/UWPCommunityToolkit/releases/tag/v2.0.0 - © Microsoft Corporation. All rights reserved. - - + https://raw.githubusercontent.com/Microsoft/WindowsCommunityToolkit/master/build/nuget.png + https://github.com/Microsoft/WindowsCommunityToolkit + https://github.com/Microsoft/WindowsCommunityToolkit/blob/master/license.md + v3.0 release https://github.com/Microsoft/WindowsCommunityToolkit/releases + (c) .NET Foundation and Contributors. All rights reserved. $(MSBuildThisFileDirectory)Toolkit.ruleset @@ -19,16 +17,50 @@ $(MSBuildProjectName.Contains('.Design')) $(MSBuildProjectName.Contains('Test')) $(MSBuildProjectName.Contains('Uwp')) + $(MSBuildProjectName.Contains('Win32')) $(MSBuildProjectName.Contains('Sample')) - - 5.4.1 - 16299 - 14393 - + 17134 + 15063 $(MSBuildThisFileDirectory)bin\nupkg + + + + Debug + AnyCPU + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + 512 + true + prompt + 4 + + true + 1591 + Off + bin\$(Platform)\$(Configuration) + + true + + + true + full + $(DefineConstants);DEBUG;TRACE + false + + + true + pdbonly + true + $(DefineConstants);TRACE + + + + @@ -38,21 +70,26 @@ - + true - - - - - - + + + true + + true + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + + + + @@ -79,7 +116,7 @@ - + stylecop.json diff --git a/Directory.Build.targets b/Directory.Build.targets index faf1b365d..8a96b9092 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -10,7 +10,6 @@ - Windows Desktop Extensions for the UWP @@ -23,4 +22,27 @@ + + + + 10.0.$(DefaultTargetPlatformVersion).0 + 10.0.$(DefaultTargetPlatformMinVersion).0 + + + + $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\$(TargetPlatformMinVersion)\Windows.winmd + $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\$(TargetPlatformVersion)\Windows.winmd + False + + + + + + + + <_Parameter1>CommitHash + <_Parameter2>$(SourceRevisionId) + + + \ No newline at end of file diff --git a/GazeInputTest/App.xaml b/GazeInputTest/App.xaml new file mode 100644 index 000000000..760dafe33 --- /dev/null +++ b/GazeInputTest/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/GazeInputTest/App.xaml.cs b/GazeInputTest/App.xaml.cs new file mode 100644 index 000000000..8628a0a8e --- /dev/null +++ b/GazeInputTest/App.xaml.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Uwp.Input.GazeInteraction; +using System; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; + +namespace GazeInputTest +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App : Application + { + /// + /// 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(). + /// + public App() + { + this.InitializeComponent(); + this.Suspending += OnSuspending; + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs e) + { + Frame rootFrame = Window.Current.Content as Frame; + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == null) + { + // Create a Frame to act as the navigation context and navigate to the first page + rootFrame = new Frame(); + + rootFrame.NavigationFailed += OnNavigationFailed; + + if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) + { + //TODO: Load state from previously suspended application + } + + // Place the frame in the current Window + Window.Current.Content = rootFrame; + } + + if (e.PrelaunchActivated == false) + { + if (rootFrame.Content == null) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame.Navigate(typeof(MainPage), e.Arguments); + } + // Ensure the current window is active + Window.Current.Activate(); + } + + GazeInput.Interaction = Interaction.Enabled; + } + + /// + /// Invoked when Navigation to a certain page fails + /// + /// The Frame which failed navigation + /// Details about the navigation failure + void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new Exception("Failed to load Page " + e.SourcePageType.FullName); + } + + /// + /// Invoked when application execution is being suspended. Application state is saved + /// without knowing whether the application will be terminated or resumed with the contents + /// of memory still intact. + /// + /// The source of the suspend request. + /// Details about the suspend request. + private void OnSuspending(object sender, SuspendingEventArgs e) + { + var deferral = e.SuspendingOperation.GetDeferral(); + //TODO: Save application state and stop any background activity + deferral.Complete(); + } + } +} diff --git a/GazeInputTest/Assets/LockScreenLogo.scale-200.png b/GazeInputTest/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 000000000..735f57adb Binary files /dev/null and b/GazeInputTest/Assets/LockScreenLogo.scale-200.png differ diff --git a/GazeInputTest/Assets/SplashScreen.scale-200.png b/GazeInputTest/Assets/SplashScreen.scale-200.png new file mode 100644 index 000000000..023e7f1fe Binary files /dev/null and b/GazeInputTest/Assets/SplashScreen.scale-200.png differ diff --git a/GazeInputTest/Assets/Square150x150Logo.scale-200.png b/GazeInputTest/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 000000000..af49fec1a Binary files /dev/null and b/GazeInputTest/Assets/Square150x150Logo.scale-200.png differ diff --git a/GazeInputTest/Assets/Square44x44Logo.scale-200.png b/GazeInputTest/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 000000000..ce342a2ec Binary files /dev/null and b/GazeInputTest/Assets/Square44x44Logo.scale-200.png differ diff --git a/GazeInputTest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/GazeInputTest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 000000000..f6c02ce97 Binary files /dev/null and b/GazeInputTest/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/GazeInputTest/Assets/StoreLogo.png b/GazeInputTest/Assets/StoreLogo.png new file mode 100644 index 000000000..7385b56c0 Binary files /dev/null and b/GazeInputTest/Assets/StoreLogo.png differ diff --git a/GazeInputTest/Assets/Wide310x150Logo.scale-200.png b/GazeInputTest/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 000000000..288995b39 Binary files /dev/null and b/GazeInputTest/Assets/Wide310x150Logo.scale-200.png differ diff --git a/GazeInputTest/GazeInputTest.csproj b/GazeInputTest/GazeInputTest.csproj new file mode 100644 index 000000000..8e9a70dce --- /dev/null +++ b/GazeInputTest/GazeInputTest.csproj @@ -0,0 +1,151 @@ + + + + + Debug + x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6} + AppContainerExe + Properties + GazeInputTest + GazeInputTest + en-US + UAP + 10.0.17134.0 + 10.0.17134.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + GazeInputTest_TemporaryKey.pfx + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x86 + false + prompt + true + true + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM + false + prompt + true + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x64 + false + prompt + true + true + + + PackageReference + + + + App.xaml + + + MainPage.xaml + + + + + + Designer + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + + + 6.0.8 + + + + + {a5e98964-45b1-442d-a07a-298a3221d81e} + Microsoft.Toolkit.Uwp.Input.GazeInteraction + + + + 14.0 + + + + \ No newline at end of file diff --git a/GazeInputTest/MainPage.xaml b/GazeInputTest/MainPage.xaml new file mode 100644 index 000000000..7e15659b0 --- /dev/null +++ b/GazeInputTest/MainPage.xaml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + TabIndex="2"> @@ -839,38 +890,47 @@ - + - + - + ShadowOpacity="0.6" + Color="Black"> @@ -901,14 +961,14 @@ - + - + HorizontalAlignment="Left" + Background="{StaticResource Brush-Blue-01}" + Opacity="1" + Visibility="{Binding BadgeUpdateVersionRequired, Converter={StaticResource EmptyStringToObject}}"> - + - - + + - - + + - - + + - - + + @@ -972,7 +1055,7 @@ - + @@ -995,7 +1078,8 @@ - - diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BladeView/BladePage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BladeView/BladePage.xaml.cs index 323488ee1..302543fd4 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BladeView/BladePage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BladeView/BladePage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.UI.Controls; using Microsoft.Toolkit.Uwp.UI.Extensions; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BluetoothLEHelper/BluetoothLEHelperPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BluetoothLEHelper/BluetoothLEHelperPage.xaml.cs index a43cd246c..5a8433982 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BluetoothLEHelper/BluetoothLEHelperPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BluetoothLEHelper/BluetoothLEHelperPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using Microsoft.Toolkit.Uwp.Connectivity; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml.cs index afb6afe2f..050934f89 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.SampleApp.Models; using Microsoft.Toolkit.Uwp.UI.Animations; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorXaml.bind index d9249ba37..82eb49376 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorXaml.bind +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Blur/BlurBehaviorXaml.bind @@ -18,6 +18,7 @@ Duration="@[Duration:DoubleSlider:3000.0:0.0-10000.0]" Delay="@[Delay:DoubleSlider:0.0:0.0-5000.0]" EasingType="@[EasingType:Enum:EasingType.Linear]" + EasingMode="@[EasingMode:Enum:EasingMode.EaseOut]" AutomaticallyStart="@[AutomaticallyStart:Bool:True]"/> diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelper.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelper.png new file mode 100644 index 000000000..a5e17a426 Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelper.png differ diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperCode.bind new file mode 100644 index 000000000..f827ff419 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperCode.bind @@ -0,0 +1,50 @@ +// Creates a Camera Helper and subscribes to frames from an available frame source. +// Make sure you have the capability webcam enabled for your app to access the device's camera. + +using Microsoft.Toolkit.Uwp.Helpers; + +CameraHelper cameraHelper = new CameraHelper(); +var result = await _cameraHelper.InitializeAndStartCaptureAsync(); + +if(result == CameraHelperResult.Success) +{ + // Subscribe to get frames as they arrive + cameraHelper.FrameArrived += CameraHelper_FrameArrived; +} +else +{ + // Get error information + var errorMessage = result.ToString(); +} + +private void CameraHelper_FrameArrived(object sender, FrameEventArgs e) +{ + // Gets the current video frame + VideoFrame currentVideoFrame = e.VideoFrame; + + // Gets the software bitmap image + SoftwareBitmap softwareBitmap = currentVideoFrame.SoftwareBitmap; +} + +private async void Application_Suspending(object sender, SuspendingEventArgs e) +{ + if (Frame.CurrentSourcePageType == typeof(CameraHelperPage)) + { + var deferral = e.SuspendingOperation.GetDeferral(); + await CleanUpAsync(); + deferral.Complete(); + } +} + +private async Task CleanUpAsync() +{ + // You may want to unsubscribe from any events and call CameraHelper CleanUpAsync() method + // to free up camera helper resources on App suspending, Page OnNavigatedFrom events when appropriate. + // Note: You would need to re-initialize the CameraHelper and rehook events on App resuming, OnNavigatedTo events. + if (_cameraHelper != null) + { + _cameraHelper.FrameArrived -= CameraHelper_FrameArrived; + await _cameraHelper.CleanUpAsync(); + _cameraHelper = null; + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperPage.xaml new file mode 100644 index 000000000..bd125052f --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperPage.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperPage.xaml.cs new file mode 100644 index 000000000..4b59133f0 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper/CameraHelperPage.xaml.cs @@ -0,0 +1,148 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Threading.Tasks; +using Microsoft.Toolkit.Uwp.Helpers; +using Windows.ApplicationModel; +using Windows.Graphics.Imaging; +using Windows.Media; +using Windows.Media.Capture.Frames; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media.Imaging; +using Windows.UI.Xaml.Navigation; + +namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages +{ + /// + /// Sample page for Camera Helper + /// + public sealed partial class CameraHelperPage : Page + { + private CameraHelper _cameraHelper; + private VideoFrame _currentVideoFrame; + private SoftwareBitmapSource _softwareBitmapSource; + + public CameraHelperPage() + { + this.InitializeComponent(); + } + + protected override async void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + _softwareBitmapSource = new SoftwareBitmapSource(); + CurrentFrameImage.Source = _softwareBitmapSource; + + Application.Current.Suspending += Application_Suspending; + Application.Current.Resuming += Application_Resuming; + + await InitializeAsync(); + } + + protected async override void OnNavigatedFrom(NavigationEventArgs e) + { + Application.Current.Suspending -= Application_Suspending; + Application.Current.Resuming -= Application_Resuming; + await CleanUpAsync(); + } + + private async void Application_Suspending(object sender, SuspendingEventArgs e) + { + if (Frame.CurrentSourcePageType == typeof(CameraHelperPage)) + { + var deferral = e.SuspendingOperation.GetDeferral(); + await CleanUpAsync(); + deferral.Complete(); + } + } + + private async void Application_Resuming(object sender, object e) + { + await InitializeAsync(); + } + + private void CameraHelper_FrameArrived(object sender, FrameEventArgs e) + { + _currentVideoFrame = e.VideoFrame; + } + + private async Task InitializeAsync() + { + var frameSourceGroups = await CameraHelper.GetFrameSourceGroupsAsync(); + if (_cameraHelper == null) + { + _cameraHelper = new CameraHelper(); + } + + var result = await _cameraHelper.InitializeAndStartCaptureAsync(); + if (result == CameraHelperResult.Success) + { + // Subscribe to the video frame as they arrive + _cameraHelper.FrameArrived += CameraHelper_FrameArrived; + FrameSourceGroupCombo.ItemsSource = frameSourceGroups; + FrameSourceGroupCombo.SelectionChanged += FrameSourceGroupCombo_SelectionChanged; + FrameSourceGroupCombo.SelectedIndex = 0; + } + + SetUIControls(result); + } + + private async void FrameSourceGroupCombo_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (FrameSourceGroupCombo.SelectedItem is MediaFrameSourceGroup selectedGroup) + { + _cameraHelper.FrameSourceGroup = selectedGroup; + var result = await _cameraHelper.InitializeAndStartCaptureAsync(); + SetUIControls(result); + } + } + + private void SetUIControls(CameraHelperResult result) + { + var success = result == CameraHelperResult.Success; + if (!success) + { + _currentVideoFrame = null; + } + + CameraErrorTextBlock.Text = result.ToString(); + CameraErrorTextBlock.Visibility = success ? Visibility.Collapsed : Visibility.Visible; + + CaptureButton.IsEnabled = success; + CurrentFrameImage.Opacity = success ? 1 : 0.5; + } + + private async void CaptureButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e) + { + var softwareBitmap = _currentVideoFrame?.SoftwareBitmap; + + if (softwareBitmap != null) + { + if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight) + { + softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied); + } + + await _softwareBitmapSource.SetBitmapAsync(softwareBitmap); + } + } + + private async Task CleanUpAsync() + { + if (FrameSourceGroupCombo != null) + { + FrameSourceGroupCombo.SelectionChanged -= FrameSourceGroupCombo_SelectionChanged; + } + + if (_cameraHelper != null) + { + _cameraHelper.FrameArrived -= CameraHelper_FrameArrived; + await _cameraHelper.CleanUpAsync(); + _cameraHelper = null; + } + } + } +} diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreview.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreview.png new file mode 100644 index 000000000..85ed9a6bc Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreview.png differ diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewCode.bind new file mode 100644 index 000000000..6334c654c --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewCode.bind @@ -0,0 +1,48 @@ +// Make sure you have the capability webcam enabled for your app to access the device's camera. + + + + + + + + + + +// Initialize the CameraPreview control and subscribe to the events +CameraPreviewControl.PreviewFailed += CameraPreviewControl_PreviewFailed; +await CameraPreviewControl.StartAsync(); +CameraPreviewControl.CameraHelper.FrameArrived += CameraPreviewControl_FrameArrived; + +// Create a software bitmap source and set it to the Xaml Image control source. +var softwareBitmapSource = new SoftwareBitmapSource(); +CurrentFrameImage.Source = softwareBitmapSource; + +// Register for FrameArrived to get real time video frames, software bitmaps. +private void CameraPreviewControl_FrameArrived(object sender, FrameEventArgs e) +{ + var videoFrame = e.VideoFrame; + var softwareBitmap = e.VideoFrame.SoftwareBitmap; + var targetSoftwareBitmap = softwareBitmap; + + if (softwareBitmap != null) + { + if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight) + { + targetSoftwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied); + } + + await softwareBitmapSource.SetBitmapAsync(targetSoftwareBitmap); + } +} + +// Register for PreviewFailed to get failure error information. +private void CameraPreviewControl_PreviewFailed(object sender, PreviewFailedEventArgs e) +{ + ErrorMessage.Text = e.Error; +} diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewPage.xaml new file mode 100644 index 000000000..2751f9f91 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewPage.xaml @@ -0,0 +1,10 @@ + + diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewPage.xaml.cs new file mode 100644 index 000000000..6af549ba4 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewPage.xaml.cs @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Toolkit.Uwp.Helpers; +using Microsoft.Toolkit.Uwp.UI.Controls; +using Microsoft.Toolkit.Uwp.UI.Extensions; +using Windows.ApplicationModel; +using Windows.Graphics.Imaging; +using Windows.Media; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media.Imaging; +using Windows.UI.Xaml.Navigation; + +namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages +{ + /// + /// CameraPreviewPage + /// + public sealed partial class CameraPreviewPage : Page, IXamlRenderListener + { + private static SemaphoreSlim semaphoreSlim; + private VideoFrame _currentVideoFrame; + private SoftwareBitmapSource _softwareBitmapSource; + private CameraPreview _cameraPreviewControl; + private Image _imageControl; + private TextBlock _errorMessageText; + + public CameraPreviewPage() + { + this.InitializeComponent(); + semaphoreSlim = new SemaphoreSlim(1); + } + + public async void OnXamlRendered(FrameworkElement control) + { + // Using a semaphore lock for synchronocity. + // This method gets called multiple times when accessing the page from Latest Pages + // and creates unused duplicate references to Camera and memory leaks. + await semaphoreSlim.WaitAsync(); + + var cameraHelper = _cameraPreviewControl?.CameraHelper; + UnsubscribeFromEvents(); + + _cameraPreviewControl = control.FindChild(); + if (_cameraPreviewControl != null) + { + _cameraPreviewControl.PreviewFailed += CameraPreviewControl_PreviewFailed; + await _cameraPreviewControl.StartAsync(cameraHelper); + _cameraPreviewControl.CameraHelper.FrameArrived += CameraPreviewControl_FrameArrived; + } + + _imageControl = control.FindDescendantByName("CurrentFrameImage") as Image; + if (_imageControl != null) + { + _softwareBitmapSource = new SoftwareBitmapSource(); + _imageControl.Source = _softwareBitmapSource; + } + + _errorMessageText = control.FindDescendantByName("ErrorMessage") as TextBlock; + + semaphoreSlim.Release(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + Shell.Current.RegisterNewCommand("Capture Current Frame", CaptureButton_Click); + Application.Current.Suspending += Application_Suspending; + Application.Current.Resuming += Application_Resuming; + } + + protected async override void OnNavigatedFrom(NavigationEventArgs e) + { + Application.Current.Suspending -= Application_Suspending; + Application.Current.Resuming -= Application_Resuming; + await CleanUpAsync(); + } + + private async void Application_Suspending(object sender, SuspendingEventArgs e) + { + if (Frame.CurrentSourcePageType == typeof(CameraPreviewPage)) + { + var deferral = e.SuspendingOperation.GetDeferral(); + await CleanUpAsync(); + deferral.Complete(); + } + } + + private async void Application_Resuming(object sender, object e) + { + if (_cameraPreviewControl != null) + { + var cameraHelper = _cameraPreviewControl.CameraHelper; + _cameraPreviewControl.PreviewFailed += CameraPreviewControl_PreviewFailed; + await _cameraPreviewControl.StartAsync(cameraHelper); + _cameraPreviewControl.CameraHelper.FrameArrived += CameraPreviewControl_FrameArrived; + } + } + + private void CameraPreviewControl_FrameArrived(object sender, FrameEventArgs e) + { + _currentVideoFrame = e.VideoFrame; + } + + private void CameraPreviewControl_PreviewFailed(object sender, PreviewFailedEventArgs e) + { + if (_errorMessageText != null) + { + _errorMessageText.Text = e.Error; + } + } + + private async void CaptureButton_Click(object sender, RoutedEventArgs e) + { + var softwareBitmap = _currentVideoFrame?.SoftwareBitmap; + + if (softwareBitmap != null) + { + if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight) + { + softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied); + } + + await _softwareBitmapSource.SetBitmapAsync(softwareBitmap); + } + } + + private void UnsubscribeFromEvents() + { + if (_cameraPreviewControl != null) + { + if (_cameraPreviewControl.CameraHelper != null) + { + _cameraPreviewControl.CameraHelper.FrameArrived -= CameraPreviewControl_FrameArrived; + } + + _cameraPreviewControl.PreviewFailed -= CameraPreviewControl_PreviewFailed; + } + } + + private async Task CleanUpAsync() + { + UnsubscribeFromEvents(); + + if (_cameraPreviewControl != null) + { + _cameraPreviewControl.Stop(); + await _cameraPreviewControl.CameraHelper?.CleanUpAsync(); + } + } + } +} diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewXaml.bind new file mode 100644 index 000000000..d3dada3ca --- /dev/null +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraPreview/CameraPreviewXaml.bind @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Carousel/CarouselPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Carousel/CarouselPage.xaml.cs index b94f76ea5..99b590387 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Carousel/CarouselPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Carousel/CarouselPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using Microsoft.Toolkit.Uwp.SampleApp.Models; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/ConnectedAnimationsPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/ConnectedAnimationsPage.xaml.cs index 21cebe4fa..ddbe9b01f 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/ConnectedAnimationsPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/ConnectedAnimationsPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.SampleApp.SamplePages.ConnectedAnimations.Pages; using Microsoft.Toolkit.Uwp.UI.Animations; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/FirstPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/FirstPage.xaml.cs index 4f0b9c98c..949026add 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/FirstPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/FirstPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/SecondPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/SecondPage.xaml.cs index c413930c3..1b7831977 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/SecondPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/SecondPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System.Collections.Generic; using Microsoft.Toolkit.Uwp.SampleApp.Models; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/ThirdPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/ThirdPage.xaml.cs index f2a43eff3..dc0e03c7c 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/ThirdPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Connected Animations/Pages/ThirdPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.SampleApp.Models; using Windows.UI.Xaml.Controls; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DataGrid/DataGridPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DataGrid/DataGridPage.xaml.cs index 79b50e9fb..a912afd29 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DataGrid/DataGridPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DataGrid/DataGridPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.SampleApp.Data; using Microsoft.Toolkit.Uwp.UI.Controls; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DispatcherHelper/DispatcherHelperPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DispatcherHelper/DispatcherHelperPage.xaml.cs index 808b51b3c..b2cf59877 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DispatcherHelper/DispatcherHelperPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DispatcherHelper/DispatcherHelperPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System.Threading.Tasks; using Microsoft.Toolkit.Uwp.Helpers; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DockPanel/DockPanelPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DockPanel/DockPanelPage.xaml.cs index 8c9cd9190..9b352524a 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DockPanel/DockPanelPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DockPanel/DockPanelPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using Microsoft.Toolkit.Uwp.UI.Controls; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DropShadowPanel/DropShadowPanelPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DropShadowPanel/DropShadowPanelPage.xaml.cs index cc045e253..f8592fc35 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DropShadowPanel/DropShadowPanelPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DropShadowPanel/DropShadowPanelPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.SampleApp.Models; using Microsoft.Toolkit.Uwp.UI.Controls; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml index 70d49ffe9..53acb344b 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml @@ -7,49 +7,6 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> - - - - - - - + - - - - - - - - - - - - - - - diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml.cs index a91e0afef..13b9b7a35 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml.cs +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderPage.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderXaml.bind index 4f38e8837..6043bb39e 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderXaml.bind +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Expander/ExpanderXaml.bind @@ -6,46 +6,46 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> + + + + + Header="This is the header - expander 1" + HorizontalContentAlignment="Stretch" + IsExpanded="@[IsExpanded1:Bool:False]@" + ExpandDirection="@[ExpandDirection1:Enum:ExpandDirection.Down]"> + TextWrapping="Wrap" + Text="This is the expanded content" + VerticalAlignment="Center" /> - + + HorizontalAlignment="Center" + VerticalAlignment="Center" /> - + Header="This is the header - expander 2" + HorizontalContentAlignment="Stretch" + IsExpanded="@[IsExpanded2:Bool:True]@" + ExpandDirection="@[ExpandDirection2:Enum:ExpandDirection.Right]"> + + TextWrapping="Wrap" + Text="This is the expanded content without a content overlay" + VerticalAlignment="Center" + Foreground="{ThemeResource SystemControlForegroundChromeLowBrush}" /> diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Facebook Service/FacebookPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Facebook Service/FacebookPage.xaml index aa15f83a2..7479e811f 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Facebook Service/FacebookPage.xaml +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Facebook Service/FacebookPage.xaml @@ -224,7 +224,7 @@ + Text="https://github.com/Microsoft/WindowsCommunityToolkit" /> + + + @@ -182,7 +315,7 @@ - + HorizontalContentAlignment="Stretch" + VerticalAlignment="{TemplateBinding VerticalContentAlignment}" + VerticalContentAlignment="Center" + TextWrapping="WrapWholeWords" /> + + + + + + + + diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/MainWindow.xaml.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/MainWindow.xaml.cs new file mode 100644 index 000000000..568b0b478 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/MainWindow.xaml.cs @@ -0,0 +1,169 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Windows; +using System.Windows.Input; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.WinForms; + +namespace Microsoft.Toolkit.Win32.Samples.WPF.WebView +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + private bool _isFullScreen; + + private bool _processExitedAttached; + + public MainWindow() + { + InitializeComponent(); + } + + private void BrowseBack_OnCanExecute(object sender, CanExecuteRoutedEventArgs e) + { + e.CanExecute = WebView1 != null && WebView1.CanGoBack; + } + + private void BrowseBack_OnExecuted(object sender, ExecutedRoutedEventArgs e) + { + WebView1?.GoBack(); + } + + private void BrowseForward_CanExecute(object sender, CanExecuteRoutedEventArgs e) + { + e.CanExecute = WebView1 != null && WebView1.CanGoForward; + } + + private void BrowseForward_OnExecuted(object sender, ExecutedRoutedEventArgs e) + { + WebView1?.GoForward(); + } + + private void GoToPage_CanExecute(object sender, CanExecuteRoutedEventArgs e) + { + e.CanExecute = true; + } + + private void GoToPage_OnExecuted(object sender, ExecutedRoutedEventArgs e) + { + var result = (Uri)new WebBrowserUriTypeConverter().ConvertFromString(Url.Text); + WebView1.Source = result; + } + private void OnWindowLoaded(object sender, RoutedEventArgs e) + { + TryAttachProcessExitedEventHandler(); + } + + private void TryAttachProcessExitedEventHandler() + { + if (!_processExitedAttached && WebView1?.Process != null) + { + WebView1.Process.ProcessExited += (o, a) => + { + //WebView has encountered and error and was terminated + Close(); + }; + + _processExitedAttached = true; + } + } + + private void Url_OnKeyUp(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter && WebView1 != null) + { + var result = + (Uri)new WebBrowserUriTypeConverter().ConvertFromString( + Url.Text); + WebView1.Source = result; + } + } + + private void WebView1_OnContainsFullScreenElementChanged(object sender, object e) + { + void EnterFullScreen() + { + WindowState = WindowState.Normal; + ResizeMode = ResizeMode.NoResize; + WindowState = WindowState.Maximized; + } + + void LeaveFullScreen() + { + ResizeMode = ResizeMode.CanResize; + WindowState = WindowState.Normal; + } + + // Toggle + _isFullScreen = !_isFullScreen; + + if (_isFullScreen) + { + EnterFullScreen(); + } + else + { + LeaveFullScreen(); + } + } + + private void WebView1_OnNavigationCompleted(object sender, WebViewControlNavigationCompletedEventArgs e) + { + TryAttachProcessExitedEventHandler(); + Url.Text = e.Uri?.ToString() ?? string.Empty; + Title = WebView1.DocumentTitle; + if (!e.IsSuccess) + { + MessageBox.Show($"Could not navigate to {e.Uri?.ToString() ?? "NULL"}", $"Error: {e.WebErrorStatus}", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + + private void WebView1_OnNavigationStarting(object sender, WebViewControlNavigationStartingEventArgs e) + { + Title = $"Navigating {e.Uri?.ToString() ?? string.Empty}"; + Url.Text = e.Uri?.ToString() ?? string.Empty; + } + + private void WebView1_OnPermissionRequested(object sender, WebViewControlPermissionRequestedEventArgs e) + { + if (e.PermissionRequest.State == WebViewControlPermissionState.Allow) return; + + var msg = $"Allow {e.PermissionRequest.Uri.Host} to access {e.PermissionRequest.PermissionType}?"; + + var response = MessageBox.Show(msg, "Permission Request", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes); + + if (response == MessageBoxResult.Yes) + { + if (e.PermissionRequest.State == WebViewControlPermissionState.Defer) + { + WebView1.GetDeferredPermissionRequestById(e.PermissionRequest.Id)?.Allow(); + } + else + { + e.PermissionRequest.Allow(); + } + } + else + { + if (e.PermissionRequest.State == WebViewControlPermissionState.Defer) + { + WebView1.GetDeferredPermissionRequestById(e.PermissionRequest.Id)?.Deny(); + } + else + { + e.PermissionRequest.Deny(); + } + } + } + + private void WebView1_OnScriptNotify(object sender, WebViewControlScriptNotifyEventArgs e) + { + MessageBox.Show(e.Value, e.Uri?.ToString() ?? string.Empty); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Microsoft.Toolkit.Win32.Samples.WPF.WebView.csproj b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Microsoft.Toolkit.Win32.Samples.WPF.WebView.csproj new file mode 100644 index 000000000..b0415d2ca --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Microsoft.Toolkit.Win32.Samples.WPF.WebView.csproj @@ -0,0 +1,80 @@ + + + + + {2FE9AA6A-BD27-438F-9941-221033E4A1DD} + WinExe + Microsoft.Toolkit.Win32.Samples.WPF.WebView + Microsoft.Toolkit.Win32.Samples.WPF.WebView + v4.6.2 + app.manifest + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + + + + + 4.0 + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + {78d8b77b-2a55-4037-bcc9-b47806039d23} + Microsoft.Toolkit.Win32.UI.Controls + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/AssemblyInfo.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..6048bdc7d --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Microsoft.Toolkit.Win32.Samples.WPF.WebView.exe")] +[assembly: AssemblyDescription("Microsoft.Toolkit.Win32.Samples.WPF.WebView.exe")] + + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Resources.Designer.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Resources.Designer.cs new file mode 100644 index 000000000..c3c01479c --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Toolkit.Win32.Samples.WPF.WebView.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Toolkit.Win32.Samples.WPF.WebView.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Resources.resx b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Settings.Designer.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Settings.Designer.cs new file mode 100644 index 000000000..38080ff83 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Toolkit.Win32.Samples.WPF.WebView.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.6.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Settings.settings b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/app.manifest b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/app.manifest new file mode 100644 index 000000000..826a45a44 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WPF.WebView/app.manifest @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PerMonitor + true/PM + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/App.config b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/App.config new file mode 100644 index 000000000..f492da186 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/App.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.Designer.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.Designer.cs new file mode 100644 index 000000000..8500bc241 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.Designer.cs @@ -0,0 +1,165 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Windows.Forms; + +namespace Microsoft.Toolkit.Win32.Samples.WinForms.WebView +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.webView1 = new Microsoft.Toolkit.Win32.UI.Controls.WinForms.WebView(); + this.button2 = new System.Windows.Forms.Button(); + this.url = new System.Windows.Forms.TextBox(); + this.Go = new System.Windows.Forms.Button(); + this.tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.webView1)).BeginInit(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Dock = System.Windows.Forms.DockStyle.Fill; + this.button1.Location = new System.Drawing.Point(0, 0); + this.button1.Margin = new System.Windows.Forms.Padding(0); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(30, 30); + this.button1.TabIndex = 2; + this.button1.Text = "<"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 4; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30F)); + this.tableLayoutPanel1.Controls.Add(this.button1, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.webView1, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.button2, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.url, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.Go, 3, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(761, 576); + this.tableLayoutPanel1.TabIndex = 4; + // + // webView1 + // + this.webView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel1.SetColumnSpan(this.webView1, 4); + this.webView1.IsPrivateNetworkClientServerCapabilityEnabled = true; + this.webView1.IsScriptNotifyAllowed = true; + this.webView1.Location = new System.Drawing.Point(3, 33); + this.webView1.MinimumSize = new System.Drawing.Size(20, 20); + this.webView1.Name = "webView1"; + this.webView1.Size = new System.Drawing.Size(755, 540); + this.webView1.Source = new System.Uri("https://www.bing.com", System.UriKind.Absolute); + this.webView1.TabIndex = 3; + this.webView1.ContainsFullScreenElementChanged += new System.EventHandler(this.webView1_ContainsFullScreenElementChanged); + this.webView1.NavigationCompleted += new System.EventHandler(this.webView1_NavigationCompleted); + this.webView1.NavigationStarting += new System.EventHandler(this.webView1_NavigationStarting); + this.webView1.PermissionRequested += new System.EventHandler(this.webView1_PermissionRequested); + this.webView1.ScriptNotify += new System.EventHandler(this.webView1_ScriptNotify); + // + // button2 + // + this.button2.Dock = System.Windows.Forms.DockStyle.Fill; + this.button2.Location = new System.Drawing.Point(30, 0); + this.button2.Margin = new System.Windows.Forms.Padding(0); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(30, 30); + this.button2.TabIndex = 4; + this.button2.Text = ">"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // url + // + this.url.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + this.url.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.AllUrl; + this.url.Dock = System.Windows.Forms.DockStyle.Fill; + this.url.Font = new System.Drawing.Font("Microsoft Sans Serif", 16F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.url.Location = new System.Drawing.Point(60, 0); + this.url.Margin = new System.Windows.Forms.Padding(0); + this.url.Name = "url"; + this.url.Size = new System.Drawing.Size(671, 32); + this.url.TabIndex = 5; + this.url.KeyUp += new System.Windows.Forms.KeyEventHandler(this.url_KeyUp); + // + // Go + // + this.Go.Dock = System.Windows.Forms.DockStyle.Fill; + this.Go.Location = new System.Drawing.Point(731, 0); + this.Go.Margin = new System.Windows.Forms.Padding(0); + this.Go.Name = "Go"; + this.Go.Size = new System.Drawing.Size(30, 30); + this.Go.TabIndex = 6; + this.Go.Text = "Go"; + this.Go.UseVisualStyleBackColor = true; + this.Go.Click += new System.EventHandler(this.Go_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(761, 576); + this.Controls.Add(this.tableLayoutPanel1); + this.Margin = new System.Windows.Forms.Padding(2); + this.Name = "Form1"; + this.Text = "WinForms WebView"; + this.Load += new System.EventHandler(this.OnFormLoaded); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.webView1)).EndInit(); + this.ResumeLayout(false); + + } + + + #endregion + + private Button button1; + private TableLayoutPanel tableLayoutPanel1; + private UI.Controls.WinForms.WebView webView1; + private Button button2; + private TextBox url; + private Button Go; + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.cs new file mode 100644 index 000000000..f5e257212 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Windows.Forms; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.WinForms; + +namespace Microsoft.Toolkit.Win32.Samples.WinForms.WebView +{ + public partial class Form1 : Form + { + private bool _isFullScreen; + + private bool _processExitedAttached; + + public Form1() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + webView1?.GoBack(); + } + + private void button2_Click(object sender, EventArgs e) + { + webView1?.GoForward(); + } + + private void Go_Click(object sender, EventArgs e) + { + var result = (Uri)new WebBrowserUriTypeConverter().ConvertFromString(url.Text); + webView1.Source = result; + } + + private void OnFormLoaded(object sender, EventArgs e) + { + TryAttachProcessExitedEventHandler(); + } + + private void TryAttachProcessExitedEventHandler() + { + if (!_processExitedAttached && webView1?.Process != null) + { + webView1.Process.ProcessExited += (o, a) => + { + //WebView has encountered and error and was terminated + Close(); + }; + + _processExitedAttached = true; + } + } + + private void url_KeyUp(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter && webView1 != null) + { + var result = (Uri)new WebBrowserUriTypeConverter().ConvertFromString(url.Text); + webView1.Source = result; + } + } + + private void webView1_ContainsFullScreenElementChanged(object sender, object e) + { + void EnterFullScreen() + { + WindowState = FormWindowState.Normal; + FormBorderStyle = FormBorderStyle.None; + WindowState = FormWindowState.Maximized; + } + + void LeaveFullScreen() + { + FormBorderStyle = FormBorderStyle.Sizable; + WindowState = FormWindowState.Normal; + } + + // Toggle + _isFullScreen = !_isFullScreen; + + if (_isFullScreen) + { + EnterFullScreen(); + } + else + { + LeaveFullScreen(); + } + } + + private void webView1_NavigationCompleted(object sender, WebViewControlNavigationCompletedEventArgs e) + { + TryAttachProcessExitedEventHandler(); + url.Text = e.Uri?.ToString() ?? string.Empty; + Text = webView1.DocumentTitle; + if (!e.IsSuccess) + { + MessageBox.Show($"Could not navigate to {e.Uri}", $"Error: {e.WebErrorStatus}", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void webView1_NavigationStarting(object sender, WebViewControlNavigationStartingEventArgs e) + { + Text = "Navigating " + e.Uri?.ToString() ?? string.Empty; + url.Text = e.Uri?.ToString() ?? string.Empty; + } + + private void webView1_PermissionRequested(object sender, WebViewControlPermissionRequestedEventArgs e) + { + if (e.PermissionRequest.State == WebViewControlPermissionState.Allow) return; + + var msg = $"Allow {e.PermissionRequest.Uri.Host} to access {e.PermissionRequest.PermissionType}?"; + + var response = MessageBox.Show(msg, "Permission Request", MessageBoxButtons.YesNo, MessageBoxIcon.Question, + MessageBoxDefaultButton.Button1); + + if (response == DialogResult.Yes) + { + if (e.PermissionRequest.State == WebViewControlPermissionState.Defer) + { + webView1.GetDeferredPermissionRequestById(e.PermissionRequest.Id)?.Allow(); + } + else + { + e.PermissionRequest.Allow(); + } + } + else + { + if (e.PermissionRequest.State == WebViewControlPermissionState.Defer) + { + webView1.GetDeferredPermissionRequestById(e.PermissionRequest.Id)?.Deny(); + } + else + { + e.PermissionRequest.Deny(); + } + } + } + + private void webView1_ScriptNotify(object sender, WebViewControlScriptNotifyEventArgs e) + { + MessageBox.Show(e.Value, e.Uri?.ToString() ?? string.Empty); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.resx b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Microsoft.Toolkit.Win32.Samples.WinForms.WebView.csproj b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Microsoft.Toolkit.Win32.Samples.WinForms.WebView.csproj new file mode 100644 index 000000000..d72e2bc28 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Microsoft.Toolkit.Win32.Samples.WinForms.WebView.csproj @@ -0,0 +1,67 @@ + + + + + {D103E448-64B1-407C-B09E-7C61AF9F2740} + WinExe + Microsoft.Toolkit.Win32.Samples.WinForms.WebView + Microsoft.Toolkit.Win32.Samples.WinForms.WebView + v4.6.2 + app.manifest + + + + + + + + + + + Form + + + Form1.cs + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + Designer + + + + + {78d8b77b-2a55-4037-bcc9-b47806039d23} + Microsoft.Toolkit.Win32.UI.Controls + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Program.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Program.cs new file mode 100644 index 000000000..74653f990 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Program.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Windows.Forms; + +namespace Microsoft.Toolkit.Win32.Samples.WinForms.WebView +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/AssemblyInfo.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ce2783477 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Microsoft.Toolkit.Win32.Samples.WinForms.WebView")] +[assembly: AssemblyDescription("Microsoft.Toolkit.Win32.Samples.WinForms.WebView.exe")] + diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Resources.Designer.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Resources.Designer.cs new file mode 100644 index 000000000..c7fb41b8c --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Toolkit.Win32.Samples.WinForms.WebView.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Toolkit.Win32.Samples.WinForms.WebView.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Resources.resx b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Settings.Designer.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Settings.Designer.cs new file mode 100644 index 000000000..60bd6e060 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Toolkit.Win32.Samples.WinForms.WebView.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.6.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Settings.settings b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/app.manifest b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/app.manifest new file mode 100644 index 000000000..92b50ba95 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.Samples.WinForms.WebView/app.manifest @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/PM + + + + + + + + + + + + + + diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/ClientUtilities.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/ClientUtilities.cs new file mode 100644 index 000000000..f2c5fcfd8 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/ClientUtilities.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; +using System.Threading; + +namespace Microsoft.Toolkit.Win32.UI.Controls +{ + internal static class ClientUtilities + { + internal static bool IsCriticalException(this Exception ex) + { + return ex is NullReferenceException + || ex is StackOverflowException + || ex is OutOfMemoryException + || ex is ThreadAbortException + || ex is IndexOutOfRangeException + || ex is AccessViolationException; + } + + internal static bool IsSecurityOrCriticalException(this Exception exception) + { + return exception is SecurityException || IsCriticalException(exception); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/DesignerUI.Designer.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/DesignerUI.Designer.cs new file mode 100644 index 000000000..56a0108ea --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/DesignerUI.Designer.cs @@ -0,0 +1,468 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Toolkit.Win32.UI.Controls { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class DesignerUI { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal DesignerUI() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Toolkit.Win32.UI.Controls.DesignerUI", typeof(DesignerUI).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Accessibility. + /// + internal static string CatAccessibility { + get { + return ResourceManager.GetString("CatAccessibility", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Action. + /// + internal static string CatAction { + get { + return ResourceManager.GetString("CatAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Appearance. + /// + internal static string CatAppearance { + get { + return ResourceManager.GetString("CatAppearance", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Behavior. + /// + internal static string CatBehavior { + get { + return ResourceManager.GetString("CatBehavior", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Data. + /// + internal static string CatData { + get { + return ResourceManager.GetString("CatData", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Display. + /// + internal static string CatDisplay { + get { + return ResourceManager.GetString("CatDisplay", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Drag Drop. + /// + internal static string CatDragDrop { + get { + return ResourceManager.GetString("CatDragDrop", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Focus. + /// + internal static string CatFocus { + get { + return ResourceManager.GetString("CatFocus", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Items. + /// + internal static string CatItems { + get { + return ResourceManager.GetString("CatItems", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Layout. + /// + internal static string CatLayout { + get { + return ResourceManager.GetString("CatLayout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Settings. + /// + internal static string CatSettings { + get { + return ResourceManager.GetString("CatSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The code in your application is attempting to set a property of the WebView control that is read-only because the control has already begun initializing. Your code can modify this property before it calls the ISupportInitialize.BeginInit method, but not after.. + /// + internal static string E_CANNOT_CHANGE_AFTER_INIT { + get { + return ResourceManager.GetString("E_CANNOT_CHANGE_AFTER_INIT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to initialize a WebView control in a ClickOnce application. See Release notes: https://go.microsoft.com/fwlink/?linkid=872619. + /// + internal static string E_CLICKONCE_PARTIAL_TRUST { + get { + return ResourceManager.GetString("E_CLICKONCE_PARTIAL_TRUST", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to initialize the WebView control because the system is running a version of Windows that doesn’t support this control. The WebView control runs only on Windows 10 April 2018 Update or later.. + /// + internal static string E_NOTSUPPORTED_OS_RS4 { + get { + return ResourceManager.GetString("E_NOTSUPPORTED_OS_RS4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The system is running a version of Windows that doesn't support this control.. + /// + internal static string E_UNRECOGNIZED_OS { + get { + return ResourceManager.GetString("E_UNRECOGNIZED_OS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to initialize the WebView control because the Microsoft Edge web browser has been disabled by the group or location admin policy of your system.. + /// + internal static string E_WEB_BROWSER_DISABLED { + get { + return ResourceManager.GetString("E_WEB_BROWSER_DISABLED", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to initialize a WebView control in a ClickOnce application or from an application that is opened in certain types of Web browsers. See Release notes: https://go.microsoft.com/fwlink/?linkid=872619. + /// + internal static string E_WEB_PERMISSION_RESTRICTED { + get { + return ResourceManager.GetString("E_WEB_PERMISSION_RESTRICTED", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The code in your application is attempting to initialize a WebView control that is already initialized.. + /// + internal static string E_WEBVIEW_ALREADY_INITIALIZED { + get { + return ResourceManager.GetString("E_WEBVIEW_ALREADY_INITIALIZED", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The code in your application is attempting to initialize a WebView control that is already in the process of being initialized by a previous call to the ISupportInitialize.BeginInit() method.. + /// + internal static string E_WEBVIEW_ALREADY_INITIALIZING { + get { + return ResourceManager.GetString("E_WEBVIEW_ALREADY_INITIALIZING", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The code in your application is attempting to use a member of the WebView control before the control is completely initialized.. + /// + internal static string E_WEBVIEW_CANNOT_INVOKE_BEFORE_INIT { + get { + return ResourceManager.GetString("E_WEBVIEW_CANNOT_INVOKE_BEFORE_INIT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The code in your application sets the Source property or calls the Navigate method by using an invalid URI.. + /// + internal static string E_WEBVIEW_INVALID_URI { + get { + return ResourceManager.GetString("E_WEBVIEW_INVALID_URI", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The code in your application sets the Source property or calls the Navigate method by using a URI that doesn’t have the format of an absolute URI.. + /// + internal static string E_WEBVIEW_NOT_ABSOLUTE_URI { + get { + return ResourceManager.GetString("E_WEBVIEW_NOT_ABSOLUTE_URI", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The WebView control is not initialized.. + /// + internal static string E_WEBVIEW_NOT_INITIALIZED { + get { + return ResourceManager.GetString("E_WEBVIEW_NOT_INITIALIZED", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to initialize the WebView control because the code in your application calls the IsSupportInitialize.EndInit() method without first calling the ISupportInitialize.BeginInit() method. + /// + internal static string E_WEBVIEW_NOT_INITIALIZING { + get { + return ResourceManager.GetString("E_WEBVIEW_NOT_INITIALIZING", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when the status of WebView contains a full screen element.. + /// + internal static string WebViewContainsFullScreenElementChangedDesc { + get { + return ResourceManager.GetString("WebViewContainsFullScreenElementChangedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when WebView started loading new content.. + /// + internal static string WebViewContentLoadingDesc { + get { + return ResourceManager.GetString("WebViewContentLoadingDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Embeds a view into your application that renders web content using the Microsoft Edge rendering engine.. + /// + internal static string WebViewDesc { + get { + return ResourceManager.GetString("WebViewDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when WebView finished parsing the current content.. + /// + internal static string WebViewDomContentLoadedDesc { + get { + return ResourceManager.GetString("WebViewDomContentLoadedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gets or sets the enterprise ID of this process.. + /// + internal static string WebViewEnterpriseIdDesc { + get { + return ResourceManager.GetString("WebViewEnterpriseIdDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when a frame in WebView has started loading new content.. + /// + internal static string WebViewFrameContentLoadingDesc { + get { + return ResourceManager.GetString("WebViewFrameContentLoadingDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when a frame in WebView finished parsing the current content.. + /// + internal static string WebViewFrameDomContentLoadedDesc { + get { + return ResourceManager.GetString("WebViewFrameDomContentLoadedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when a frame in WebView finished navigating to new content.. + /// + internal static string WebViewFrameNavigationCompletedDesc { + get { + return ResourceManager.GetString("WebViewFrameNavigationCompletedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs before a frame in WebView navigates to new content.. + /// + internal static string WebViewFrameNavigationStartingDesc { + get { + return ResourceManager.GetString("WebViewFrameNavigationStartingDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs periodically while WebView executes JavaScript, letting you halt the script.. + /// + internal static string WebViewLongRunningScriptDetectedDesc { + get { + return ResourceManager.GetString("WebViewLongRunningScriptDetectedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when a focus move is requested.. + /// + internal static string WebViewMoveFocusRequestedDesc { + get { + return ResourceManager.GetString("WebViewMoveFocusRequestedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when WebView finished navigating to new content.. + /// + internal static string WebViewNavigationCompletedDesc { + get { + return ResourceManager.GetString("WebViewNavigationCompletedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs before WebView navigates to new content.. + /// + internal static string WebViewNavigationStartingDesc { + get { + return ResourceManager.GetString("WebViewNavigationStartingDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when an action is performed that causes content to be opened in a new window.. + /// + internal static string WebViewNewWindowRequestedDesc { + get { + return ResourceManager.GetString("WebViewNewWindowRequestedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when WebView requires a permission.. + /// + internal static string WebViewPermissionRequestedDesc { + get { + return ResourceManager.GetString("WebViewPermissionRequestedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when content in WebView passes a string from JavaScript.. + /// + internal static string WebViewScriptNotifyDesc { + get { + return ResourceManager.GetString("WebViewScriptNotifyDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gets or sets the Uniform Resource Identifier (URI) source of the content to display.. + /// + internal static string WebViewSourceDesc { + get { + return ResourceManager.GetString("WebViewSourceDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when WebView shows a warning page for content that was reported as unsafe by SmartScreen filter.. + /// + internal static string WebViewUnsafeContentWarningDisplayingDesc { + get { + return ResourceManager.GetString("WebViewUnsafeContentWarningDisplayingDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when an attempt is made to navigate to a Source using a scheme that WebView does not support.. + /// + internal static string WebViewUnsupportedUriSchemeIdentifiedDesc { + get { + return ResourceManager.GetString("WebViewUnsupportedUriSchemeIdentifiedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when WebView attempts to download an unsupported file.. + /// + internal static string WebViewUnviewableContentIdentifiedDesc { + get { + return ResourceManager.GetString("WebViewUnviewableContentIdentifiedDesc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Occurs when WebView requests a HTTP resource.. + /// + internal static string WebViewWebResourceRequestedDesc { + get { + return ResourceManager.GetString("WebViewWebResourceRequestedDesc", resourceCulture); + } + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/DesignerUI.resx b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/DesignerUI.resx new file mode 100644 index 000000000..a70787ba4 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/DesignerUI.resx @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Accessibility + + + Action + + + Appearance + + + Behavior + + + Data + + + Display + + + Drag Drop + + + Focus + + + Items + + + Layout + + + Settings + + + The code in your application is attempting to set a property of the WebView control that is read-only because the control has already begun initializing. Your code can modify this property before it calls the ISupportInitialize.BeginInit method, but not after. + A member has been invoked after the control is already initialized + + + Unable to initialize a WebView control in a ClickOnce application. See Release notes: https://go.microsoft.com/fwlink/?linkid=872619 + ClickOnce uses AppLaunch.exe to host partial-trust applications (and we don't support partial trust) + + + Unable to initialize the WebView control because the system is running a version of Windows that doesn’t support this control. The WebView control runs only on Windows 10 April 2018 Update or later. + WebView requires RS4 or later + + + The system is running a version of Windows that doesn't support this control. + OS version check received an OS combination it did not understand + + + The code in your application is attempting to initialize a WebView control that is already initialized. + Caller attempted to call BeginInit after calling EndInit + + + The code in your application is attempting to initialize a WebView control that is already in the process of being initialized by a previous call to the ISupportInitialize.BeginInit() method. + Caller attempted to call BeginInit after calling BeginInit + + + The code in your application is attempting to use a member of the WebView control before the control is completely initialized. + A WebView member has been invoked before the control has been initialized + + + The code in your application sets the Source property or calls the Navigate method by using an invalid URI. + Navigate called with a value that cannot be converted to Uri + + + The code in your application sets the Source property or calls the Navigate method by using a URI that doesn’t have the format of an absolute URI. + Source property or Navigate target invoked with a value that is not a proper absolute Uri + + + The WebView control is not initialized. + + + Unable to initialize the WebView control because the code in your application calls the IsSupportInitialize.EndInit() method without first calling the ISupportInitialize.BeginInit() method + Caller attempted to finalize initialization of the control with EndInit with out requesting it be initialized with BeginInit + + + Unable to initialize the WebView control because the Microsoft Edge web browser has been disabled by the group or location admin policy of your system. + Browser disabled by admin local or group policy object + + + Unable to initialize a WebView control in a ClickOnce application or from an application that is opened in certain types of Web browsers. See Release notes: https://go.microsoft.com/fwlink/?linkid=872619 + Could be hosted in browser, as an internet zone XBAP, or standalone ClickOnce + + + Occurs when the status of WebView contains a full screen element. + + + Occurs when WebView started loading new content. + + + Embeds a view into your application that renders web content using the Microsoft Edge rendering engine. + Used for AutoPop in toolbox + + + Occurs when WebView finished parsing the current content. + + + Gets or sets the enterprise ID of this process. + + + Occurs when a frame in WebView has started loading new content. + + + Occurs when a frame in WebView finished parsing the current content. + + + Occurs when a frame in WebView finished navigating to new content. + + + Occurs before a frame in WebView navigates to new content. + + + Occurs periodically while WebView executes JavaScript, letting you halt the script. + + + Occurs when a focus move is requested. + + + Occurs when WebView finished navigating to new content. + + + Occurs before WebView navigates to new content. + + + Occurs when an action is performed that causes content to be opened in a new window. + + + Occurs when WebView requires a permission. + + + Occurs when content in WebView passes a string from JavaScript. + + + Gets or sets the Uniform Resource Identifier (URI) source of the content to display. + + + Occurs when WebView shows a warning page for content that was reported as unsafe by SmartScreen filter. + + + Occurs when an attempt is made to navigate to a Source using a scheme that WebView does not support. + + + Occurs when WebView attempts to download an unsupported file. + + + Occurs when WebView requests a HTTP resource. + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/GlobalSuppressions.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/GlobalSuppressions.cs new file mode 100644 index 000000000..f5a03b225 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/GlobalSuppressions.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. +// +// To add a suppression to this file, right-click the message in the +// Code Analysis results, point to "Suppress Message", and click +// "In Suppression File". +// You do not need to add suppressions to this file manually. +#pragma warning disable SA1404 // Code analysis suppression must have justification +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "A", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#A")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "B", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#B")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "C", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#C")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "D", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#D")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "E", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#E")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "F", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#F")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "G", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#G")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "H", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#H")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "I", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#I")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "J", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#J")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "K", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#K")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "L", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#L")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "M", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#M")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "N", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#N")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "O", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#O")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "P", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#P")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Q", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#Q")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "R", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#R")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "S", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#S")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "T", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#T")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#U")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#V")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "W", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#W")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#X")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#Y")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Z", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#Z")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadLeftThumbstickButton")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadRightThumbstickButton")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadLeftThumbstickUp")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadLeftThumbstickDown")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadLeftThumbstickRight")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadLeftThumbstickLeft")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadRightThumbstickUp")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadRightThumbstickDown")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadRightThumbstickRight")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#GamepadRightThumbstickLeft")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Junja", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.VirtualKey.#Junja")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Geolocation", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.WebViewControlPermissionType.#Geolocation")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unviewable", Scope = "type", Target = "Microsoft.Windows10.Web.Wrappers.WebViewControlUnviewableContentIdentifiedEventArgs")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Satisfiable", Scope = "member", Target = "Microsoft.Windows10.Web.Wrappers.WebErrorStatus.#RequestedRangeNotSatisfiable")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields must begin with upper-case letter", Scope = "member", Target = "~F:Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32.RECT.bottom")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields must begin with upper-case letter", Scope = "member", Target = "~F:Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32.RECT.left")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields must begin with upper-case letter", Scope = "member", Target = "~F:Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32.RECT.right")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields must begin with upper-case letter", Scope = "member", Target = "~F:Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32.RECT.top")] + + + +#pragma warning restore SA1404 // Code analysis suppression must have justification \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/IWebView.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/IWebView.cs new file mode 100644 index 000000000..d03ab67df --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/IWebView.cs @@ -0,0 +1,373 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; + +namespace Microsoft.Toolkit.Win32.UI.Controls +{ + /// + /// + /// Provides a control that hosts HTML content in an app. + /// + /// + /// + /// Subset of functionality from + /// + public interface IWebView : IDisposable + { + /// + /// An event that is triggered when the accelerator key is pressed. + /// + event EventHandler AcceleratorKeyPressed; + + /// + /// Occurs when the status of whether the currently contains a full screen element or not changes. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Justification = "Matches IWebViewControl interface")] + event EventHandler ContainsFullScreenElementChanged; + + /// + /// Occurs when the has started loading new content. + /// + event EventHandler ContentLoading; + + /// + /// Occurs when the finished parsing the current content. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "DOM", Justification = "Name from WinRT type")] + event EventHandler DOMContentLoaded; + + /// + /// Occurs when a frame in the has started loading new content. + /// + event EventHandler FrameContentLoading; + + /// + /// Occurs when a frame in the finished parsing its current content. + /// + event EventHandler FrameDOMContentLoaded; + + /// + /// Occurs when a frame in the finished navigating to new content. + /// + event EventHandler FrameNavigationCompleted; + + /// + /// Occurs when a frame in the navigates to new content. + /// + event EventHandler FrameNavigationStarting; + + /// + /// Occurs periodically while the executes JavaScript, letting you halt the script. + /// + /// + /// Your app might appear unresponsive while scripts are running. This event provides an opportunity to interrupt a long-running + /// script. To determine how long the script has been running, check the + /// property of the object. To halt the script, set the event args + /// property to true. The halted script will + /// not execute again unless it is reloaded during a subsequent navigation. + /// + /// + /// + /// + event EventHandler LongRunningScriptDetected; + + /// + /// Occurs when a focus move is requested. + /// + event EventHandler MoveFocusRequested; + + /// + /// Occurs when the control finished navigating to new content. + /// + event EventHandler NavigationCompleted; + + /// + /// Occurs before the navigates to new content. + /// + event EventHandler NavigationStarting; + + /// + /// Occurs when an action is performed that causes content to be opened in a new window. + /// + event EventHandler NewWindowRequested; + + /// + /// Occurs when an action in a requires that permission be granted. + /// + /// + /// The types of permission that can be requested are defined in the enumeration. + /// + /// If you don't handle the event, the denies permission by default. + /// + /// When you handle a permission request in , you get a object as + /// the value of the property. You can call Allow to grant the request, + /// Deny to deny the request, or Defer to defer the request until a later time. + /// + event EventHandler PermissionRequested; + + /// + /// Occurs when the content contained in the control passes a string to the application by using JavaScript. + /// + event EventHandler ScriptNotify; + + /// + /// Occurs when shows a warning page for content that was reported as unsafe by SmartScreen filter. + /// + event EventHandler UnsafeContentWarningDisplaying; + + /// + /// Occurs when an attempt is made to navigate to a using a scheme that does not support. + /// + event EventHandler UnsupportedUriSchemeIdentified; + + /// + /// Occurs when attempts to navigate to a content type it cannot render. Like other navigation events, it is only triggered by top level navigations. + /// + /// + /// Event is triggered as soon as the content that can be identified is unsupported. For HTTP(s) content, this is right after the headers have been received. + /// + event EventHandler UnviewableContentIdentified; + + /// + /// Gets a value indicating whether there is at least one page in the backward navigation history. + /// + /// true if the can navigate backward; otherwise, false. + bool CanGoBack { get; } + + /// + /// Gets a value indicating whether there is at least one page in the forward navigation history. + /// + /// true if the can navigate forward; otherwise, false. + bool CanGoForward { get; } + + /// + /// Gets a value indicating whether contains an element that supports full screen. + /// + /// if the contains an element that supports full screen; otherwise, . + bool ContainsFullScreenElement { get; } + + /// + /// Gets the title of the page currently displayed in the . + /// + /// The page title. + string DocumentTitle { get; } + + /// + /// Gets or sets an enterprise ID for this process. + /// + /// The enterprise ID of this process. + /// Value can be set prior to the component being initialized. + /// + string EnterpriseId { get; set; } + + /// + /// Gets or sets a value indicating whether the use of IndexedDB is allowed. + /// + /// true if IndexedDB is allowed; otherwise, false. The default is true. + /// + bool IsIndexedDBEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether the use of JavaScript is allowed. + /// + /// true if JavaScript is allowed in the ; otherwise, false. The default is true. + /// + bool IsJavaScriptEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether the + /// + /// if this instance is private network client server capability enabled; otherwise, . + /// Value can be set prior to the component being initialized. + /// + bool IsPrivateNetworkClientServerCapabilityEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether is allowed. + /// + /// Whether is allowed. + /// + bool IsScriptNotifyAllowed { get; set; } + + /// + /// Gets the that the control is hosted in. + /// + /// The that the control is hosted in. + WebViewControlProcess Process { get; } + + /// + /// Gets a object that contains properties to enable or disable features. + /// + /// A object that contains properties to enable or disable features. + /// + /// + /// + /// Use the object to enable or disable the use of JavaScript, ScriptNotify, and IndexedDB in the . + WebViewControlSettings Settings { get; } + + /// + /// Gets or sets the Uniform Resource Identifier (URI) source of the HTML content to display in the . + /// + /// + /// The Uniform Resource Identifier (URI) source of the HTML content to display in the . + /// + Uri Source { get; set; } + + /// + /// Gets the version of EDGEHTML.DLL used by . + /// + /// The version of EDGEHTML.DLL used by . + Version Version { get; } + + /// + /// Closes this instance. + /// + /// Equivalent to calling . + void Close(); + + /// + /// Gets the deferred permission request with the specified . + /// + /// The of the deferred permission request. + /// The deferred permission request with the specified , or null if no permission request with the specified was found. + WebViewControlDeferredPermissionRequest GetDeferredPermissionRequestById(uint id); + + /// + /// Navigates the to the previous page in the navigation history. + /// + /// true if the navigation to the previous page in the navigation history is successful; otherwise, false. + bool GoBack(); + + /// + /// Navigates the to the next page in the navigation history. + /// + /// true if the navigation to the next page in the navigation history is successful; otherwise, false. + bool GoForward(); + + /// + /// Executes the specified script function from the currently loaded HTML, with no arguments, as a synchronous action. + /// + /// Name of the script function to invoke. + /// When this method returns, the result of the script invocation. + /// To prevent malicious code from exploiting your app, be sure to call this method to invoke only scripts that you trust. + string InvokeScript(string scriptName); + + /// + /// Executes the specified script function from the currently loaded HTML, with no arguments, as a synchronous action. + /// + /// Name of the script function to invoke. + /// A string array that packages arguments to the script function. + /// When this method returns, the result of the script invocation. + /// + /// To prevent malicious code from exploiting your app, be sure to call this method to invoke only scripts that you trust. + /// + string InvokeScript(string scriptName, params string[] arguments); + + /// + /// Executes the specified script function from the currently loaded HTML, with no arguments, as a synchronous action. + /// + /// Name of the script function to invoke. + /// A string array that packages arguments to the script function. + /// When this method returns, the result of the script invocation. + /// + /// To prevent malicious code from exploiting your app, be sure to call this method to invoke only scripts that you trust. + /// + string InvokeScript(string scriptName, IEnumerable arguments); + + /// + /// Executes the specified script function from the currently loaded HTML, with no arguments, as an asynchronous action. + /// + /// Name of the script function to invoke. + /// When this method returns, the result of the script invocation. + /// + /// To prevent malicious code from exploiting your app, be sure to call this method to invoke only scripts that you trust. + /// The invoked script can only return string values. + /// + Task InvokeScriptAsync(string scriptName); + + /// + /// Executes the specified script function from the currently loaded HTML, with no arguments, as an asynchronous action. + /// + /// Name of the script function to invoke. + /// A string array that packages arguments to the script function. + /// When this method returns, the result of the script invocation. + /// + /// To prevent malicious code from exploiting your app, be sure to call this method to invoke only scripts that you trust. + /// The invoked script can only return string values. + /// + Task InvokeScriptAsync(string scriptName, params string[] arguments); + + /// + /// Executes the specified script function from the currently loaded HTML, with no arguments, as an asynchronous action. + /// + /// Name of the script function to invoke. + /// A string array that packages arguments to the script function. + /// When this method returns, the result of the script invocation. + /// + /// To prevent malicious code from exploiting your app, be sure to call this method to invoke only scripts that you trust. + /// The invoked script can only return string values. + /// + Task InvokeScriptAsync(string scriptName, IEnumerable arguments); + + /// + /// Moves the focus. + /// + /// The reason. + void MoveFocus(WebViewControlMoveFocusReason reason); + + /// + /// Loads the HTML content at the specified Uniform Resource Identifier (URI). + /// + /// The Uniform Resource Identifier (URI) to load. + /// + /// is asynchronous. Use the event to detect when + /// navigation has completed. + void Navigate(Uri source); + + /// + /// Loads the HTML content at the specified Uniform Resource Identifier (URI). + /// + /// The Uniform Resource Identifier (URI) to load. + /// is asynchronous. Use the event to detect when + /// navigation has completed. + void Navigate(string source); + + /// + /// Loads the specified HTML content relative to the location of the current executable. + /// + /// The relative path. + /// is asynchronous. Use the event to detect when + /// navigation has completed. + void NavigateToLocal(string relativePath); + + /// + /// Loads the specified HTML content as a new document. + /// + /// The HTML content to display in the . + /// + /// is asynchronous. Use the event to detect when + /// navigation has completed. + /// + /// supports content with references to external files such as CSS, scripts, images, + /// and fonts. However, it does not provide a way to generate or provide these resources programmatically. + /// + void NavigateToString(string text); + + /// + /// Reloads the current in the . + /// + /// If the current source was loaded via , this method reloads the file without forced cache validation by sending a Pragma:no-cache header to the server. + void Refresh(); + + /// + /// Halts the current navigation or download. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Stop", Justification = "Method exposed in WinRT type")] + void Stop(); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/OSVersionHelper.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/OSVersionHelper.cs new file mode 100644 index 000000000..a0d39dac6 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/OSVersionHelper.cs @@ -0,0 +1,178 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Security; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32; +using Windows.Foundation.Metadata; +using Windows.Security.EnterpriseData; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop +{ + internal static class OSVersionHelper + { + private const string ContractName = "Windows.Foundation.UniversalApiContract"; + + [SecurityCritical] + static OSVersionHelper() + { + if (IsSince(WindowsVersions.Win10)) + { + if (IsApiContractPresent(6)) + { + Windows10Release = Windows10Release.April2018; + } + else if (IsApiContractPresent(5)) + { + Windows10Release = Windows10Release.FallCreators; + } + else if (IsApiContractPresent(4)) + { + Windows10Release = Windows10Release.Creators; + } + else if (IsApiContractPresent(3)) + { + Windows10Release = Windows10Release.Anniversary; + } + else if (IsApiContractPresent(2)) + { + Windows10Release = Windows10Release.Threshold2; + } + else if (IsApiContractPresent(1)) + { + Windows10Release = Windows10Release.Threshold1; + } + else + { + Windows10Release = Windows10Release.Unknown; + } + } + } + + internal static bool IsWindowsNt { get; } = Environment.OSVersion.Platform == PlatformID.Win32NT; + + internal static bool EdgeExists { get; } = File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), ExternDll.EdgeHtml)); + + internal static bool IsWindows10 { get; } = IsWindowsNt && IsSince(WindowsVersions.Win10); + + /// + /// Gets a value indicating whether the current OS is Windows 10 April 2018 Update (Redstone 4) or greater + /// + internal static bool IsWindows10April2018OrGreater => IsWindows10 && Windows10Release >= Windows10Release.April2018; + + /// + /// Gets a value indicating whether the current OS is Windows 10 Fall Creators Update (Redstone 3) or greater + /// + internal static bool IsWindows10FallCreatorsOrGreater => IsWindows10 && Windows10Release >= Windows10Release.FallCreators; + + /// + /// Gets a value indicating whether the current OS is Windows 10 Creators Update (Redstone 2) or greater + /// + internal static bool IsWindows10CreatorsOrGreater => IsWindows10 && Windows10Release >= Windows10Release.Creators; + + /// + /// Gets a value indicating whether the current OS is Windows 10 Anniversary Update (Redstone 1) or greater + /// + internal static bool IsWindows10AnniversaryOrGreater => IsWindows10 && Windows10Release >= Windows10Release.Anniversary; + + /// + /// Gets a value indicating whether the current OS is Windows 10 Threshold 2 or greater + /// + internal static bool IsWindows10Threshold2OrGreater => IsWindows10 && Windows10Release >= Windows10Release.Threshold2; + + /// + /// Gets a value indicating whether the current OS is Windows 10 Threshold 1 or greater + /// + internal static bool IsWindows10Threshold1OrGreater => IsWindows10 && Windows10Release >= Windows10Release.Threshold1; + + internal static bool IsWorkstation { get; } = !IsServer(); + + internal static bool UseWindowsInformationProtectionApi + { + [SecurityCritical] + get => Windows10Release >= Windows10Release.Anniversary && ProtectionPolicyManager.IsProtectionEnabled; + } + + internal static Windows10Release Windows10Release { get; } + + /// + /// Checks if OS is Windows 10 April 2018 or later, is a workstation, and Microsoft Edge exists. + /// + /// Not running correct OS or OS Version, or Microsoft Edge does not exist. + internal static void ThrowIfBeforeWindows10April2018() + { + if (IsWindows10April2018OrGreater && IsWorkstation && EdgeExists) + { + return; + } + + throw new NotSupportedException(DesignerUI.E_NOTSUPPORTED_OS_RS4); + } + + [SecurityCritical] + private static bool IsApiContractPresent(ushort majorVersion) => ApiInformation.IsApiContractPresent(ContractName, majorVersion); + + [SecurityCritical] + private static bool IsServer() + { + var versionInfo = NativeMethods.RtlGetVersion(); + return versionInfo.ProductType == ProductType.VER_NT_DOMAIN_CONTROLLER + || versionInfo.ProductType == ProductType.VER_NT_SERVER; + } + + [SecurityCritical] + internal static bool IsSince(WindowsVersions version) + { + int major; + int minor; + + switch (version) + { + case WindowsVersions.Win7: + case WindowsVersions.Server2008R2: + major = 6; + minor = 1; + break; + + case WindowsVersions.Win8: + case WindowsVersions.Server2012: + major = 6; + minor = 2; + break; + + case WindowsVersions.Win81: + case WindowsVersions.Server2012R2: + major = 6; + minor = 3; + break; + + case WindowsVersions.Win10: + case WindowsVersions.Server2016: + major = 10; + minor = 0; + break; + + default: + throw new ArgumentException(DesignerUI.E_UNRECOGNIZED_OS, nameof(version)); + } + + // After 8.1 apps without manifest or are not manifested for 8.1/10 return 6.2 when using GetVersionEx. + // Need to use RtlGetVersion to get correct major/minor/build + var os = NativeMethods.RtlGetVersion(); + + if (os.MajorVersion > major) + { + return true; + } + + if (os.MajorVersion == major) + { + return os.MinorVersion >= minor; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/DpiHelper.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/DpiHelper.cs new file mode 100644 index 000000000..b67c937f5 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/DpiHelper.cs @@ -0,0 +1,173 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop +{ + /// + /// Class for scaling coordinates according to current DPI scaling set in Windows + /// + internal static class DpiHelper + { + internal const double LogicalDpi = 96d; + + // The primary screen's (device) current DPI + private static double _deviceDpi = LogicalDpi; + + private static bool _enableHighDpi; + private static bool _isInitialized; + private static bool _enableDpiChangedMessageHandling; + private static double _logicalToDeviceUnitsScalingFactor; + + internal static int DeviceDpi + { + get + { + Initialize(); + return (int)_deviceDpi; + } + } + + /// + /// Gets a value indicating whether to enable processing of WM_DPICHANGED and related messages + /// + internal static bool EnableDpiChangedMessageHandling + { + get + { + Initialize(); + if (_enableDpiChangedMessageHandling) + { + // We can't cache this because different top level windows can have different DPI awareness contexts + var dpiAwareness = NativeMethods.GetThreadDpiAwarenessContext(); + return NativeMethods.AreDpiAwarenessContextsEqual( + dpiAwareness, + NativeMethods.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); + } + + return false; + } + } + + internal static bool IsPerMonitorDpiAware + { + get + { + Initialize(); + if (_enableHighDpi) + { + var result = UnsafeNativeMethods.GetProcessDpiAwareness( + IntPtr.Zero, // Current process + out PROCESS_DPI_AWARENESS value); + + if (result != 0) + { + // Some sort of error + return false; + } + + return value == PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE; + } + + return false; + } + } + + /// + /// Gets a value indicating whether scaling is required when converting between logical-device units, if the application opted in the automatic scaling + /// + /// if scaling is required; otherwise, . + internal static bool IsScalingRequired + { + get + { + Initialize(); +#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator + return _deviceDpi != LogicalDpi; +#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator + } + } + + private static double LogicalToDeviceUnitsScalingFactor + { + get + { +#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator + if (_logicalToDeviceUnitsScalingFactor == 0d) +#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator + { + Initialize(); + _logicalToDeviceUnitsScalingFactor = _deviceDpi / LogicalDpi; + } + + return _logicalToDeviceUnitsScalingFactor; + } + } + + public static int Scale(double value, double scalingFactor) => (int)Math.Round(scalingFactor * value); + + // Sets DPI awareness for the process. Returns true if DPI awareness is successfully set; otherwise, false. + public static bool SetPerMonitorDpiAwareness() + { + // Only works if we're on RS2 or later and have ComCtl v6 + if (OSVersionHelper.IsWindows10CreatorsOrGreater) + { + const int rs2AndAboveDpiFlag = NativeMethods.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2; + return NativeMethods.SetProcessDpiAwarenessContext(rs2AndAboveDpiFlag); + } + + return false; + } + + internal static void Initialize() + { + if (!_isInitialized) + { + if (OSVersionHelper.IsWindows10AnniversaryOrGreater) + { + // Primary screen DPI might be 96, but other screens may not be + _enableDpiChangedMessageHandling = true; + _enableHighDpi = true; + } + + if (_enableHighDpi) + { + _deviceDpi = GetSystemDpi(); + } + + _isInitialized = true; + } + } + + // Transforms a horizontal or vertical integer coordinate from logical to device units + // by scaling it up for current DPI and rounding to nearest integer value + internal static int LogicalToDeviceUnits(double value, int devicePixels = 0) + { + if (devicePixels == 0) + { + return (int)Math.Round(LogicalToDeviceUnitsScalingFactor * value); + } + + double scalingFactor = devicePixels / LogicalDpi; + return Scale(value, scalingFactor); + } + + // Returns the system DPI + private static double GetSystemDpi() + { + var newDpiX = 0; + var hDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef); + if (hDC != IntPtr.Zero) + { + newDpiX = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, hDC), NativeMethods.LOGPIXELSX); + UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, hDC)); + } + + return newDpiX; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/ExternDll.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/ExternDll.cs new file mode 100644 index 000000000..f6e28ef66 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/ExternDll.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + internal static class ExternDll + { + internal const string Kernel32 = "kernel32.dll"; + internal const string User32 = "user32.dll"; + internal const string Ntdll = "ntdll.dll"; + internal const string Gdi32 = "gdi32.dll"; + internal const string EdgeHtml = "edgehtml.dll"; + internal const string ShCore = "shcore.dll"; + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Facility.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Facility.cs new file mode 100644 index 000000000..b099193f3 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Facility.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + internal enum Facility + { + /// FACILITY_NULL + Null = 0, + + /// FACILITY_RPC + Rpc = 1, + + /// FACILITY_DISPATCH + Dispatch = 2, + + /// FACILITY_STORAGE + Storage = 3, + + /// FACILITY_ITF + Itf = 4, + + /// FACILITY_WIN32 + Win32 = 7, + + /// FACILITY_WINDOWS + Windows = 8, + + /// FACILITY_CONTROL + Control = 10, + + /// MSDN doced facility code for ESE errors. + Ese = 0xE5E, + + /// FACILITY_WINCODEC (WIC) + WinCodec = 0x898, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/HRESULT.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/HRESULT.cs new file mode 100644 index 000000000..b355601bb --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/HRESULT.cs @@ -0,0 +1,359 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + /// Wrapper for HRESULT status codes. + [StructLayout(LayoutKind.Explicit)] + internal struct HRESULT + { + [FieldOffset(0)] + private readonly uint _value; + + // NOTE: These public static field declarations are automatically + // picked up by ToString through reflection. + + /// S_OK + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT S_OK = new HRESULT(0x00000000); + + /// S_FALSE + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT S_FALSE = new HRESULT(0x00000001); + + /// E_PENDING + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_PENDING = new HRESULT(0x8000000A); + + /// E_NOTIMPL + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_NOTIMPL = new HRESULT(0x80004001); + + /// E_NOINTERFACE + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_NOINTERFACE = new HRESULT(0x80004002); + + /// E_POINTER + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_POINTER = new HRESULT(0x80004003); + + /// E_ABORT + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_ABORT = new HRESULT(0x80004004); + + /// E_FAIL + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_FAIL = new HRESULT(0x80004005); + + /// E_UNEXPECTED + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_UNEXPECTED = new HRESULT(0x8000FFFF); + + /// STG_E_INVALIDFUNCTION + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT STG_E_INVALIDFUNCTION = new HRESULT(0x80030001); + + /// REGDB_E_CLASSNOTREG + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT REGDB_E_CLASSNOTREG = new HRESULT(0x80040154); + + /// DESTS_E_NO_MATCHING_ASSOC_HANDLER. Win7 internal error code for Jump Lists. + /// There is no Assoc Handler for the given item registered by the specified application. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT DESTS_E_NO_MATCHING_ASSOC_HANDLER = new HRESULT(0x80040F03); + + /// DESTS_E_NORECDOCS. Win7 internal error code for Jump Lists. + /// The given item is excluded from the recent docs folder by the NoRecDocs bit on its registration. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT DESTS_E_NORECDOCS = new HRESULT(0x80040F04); + + /// DESTS_E_NOTALLCLEARED. Win7 internal error code for Jump Lists. + /// Not all of the items were successfully cleared + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT DESTS_E_NOTALLCLEARED = new HRESULT(0x80040F05); + + /// E_ACCESSDENIED + /// Win32Error ERROR_ACCESS_DENIED. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_ACCESSDENIED = new HRESULT(0x80070005); + + /// E_OUTOFMEMORY + /// Win32Error ERROR_OUTOFMEMORY. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_OUTOFMEMORY = new HRESULT(0x8007000E); + + /// E_INVALIDARG + /// Win32Error ERROR_INVALID_PARAMETER. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT E_INVALIDARG = new HRESULT(0x80070057); + + /// INTSAFE_E_ARITHMETIC_OVERFLOW + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT INTSAFE_E_ARITHMETIC_OVERFLOW = new HRESULT(0x80070216); + + /// COR_E_OBJECTDISPOSED + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT COR_E_OBJECTDISPOSED = new HRESULT(0x80131622); + + /// WC_E_GREATERTHAN + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT WC_E_GREATERTHAN = new HRESULT(0xC00CEE23); + + /// WC_E_SYNTAX + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May only be used in DEBUG builds")] + public static readonly HRESULT WC_E_SYNTAX = new HRESULT(0xC00CEE2D); + + /// + /// Initializes a new instance of the struct. + /// + /// containing HRESULT. + public HRESULT(uint i) + { + _value = i; + } + + public static HRESULT Make(bool severe, Facility facility, int code) + { + // #define MAKE_HRESULT(sev,fac,code) \ + // ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + + // Severity has 1 bit reserved. + // bitness is enforced by the boolean parameter. + + // Facility has 11 bits reserved (different than SCODES, which have 4 bits reserved) + // MSDN documentation incorrectly uses 12 bits for the ESE facility (e5e), so go ahead and let that one slide. + // And WIC also ignores it the documented size... + Verify.Implies((int)facility != (int)((int)facility & 0x1FF), facility == Facility.Ese || facility == Facility.WinCodec); + + // Code has 4 bits reserved. + Verify.AreEqual(code, code & 0xFFFF); + + return new HRESULT((uint)((severe ? 1 << 31 : 0) | ((int)facility << 16) | code)); + } + + /// + /// Gets HRESULT_FACILITY + /// + public Facility Facility + { + get + { + return GetFacility((int)_value); + } + } + + public static Facility GetFacility(int errorCode) + { + // #define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) + return (Facility)((errorCode >> 16) & 0x1fff); + } + + /// + /// Gets HRESULT_CODE + /// + public int Code + { + get + { + return GetCode((int)_value); + } + } + + public static int GetCode(int error) + { + // #define HRESULT_CODE(hr) ((hr) & 0xFFFF) + return (int)(error & 0xFFFF); + } + + /// + /// Get a string representation of this HRESULT. + /// + /// Name of HRESULT + public override string ToString() + { + // Use reflection to try to name this HRESULT. + // This is expensive, but if someone's ever printing HRESULT strings then + // I think it's a fair guess that they're not in a performance critical area + // (e.g. printing exception strings). + // This is less error prone than trying to keep the list in the function. + // To properly add an HRESULT's name to the ToString table, just add the HRESULT + // like all the others above. + // + // CONSIDER: This data is static. It could be cached + // after first usage for fast lookup since the keys are unique. + foreach (var publicStaticField in typeof(HRESULT).GetFields(BindingFlags.Static | BindingFlags.Public)) + { + if (publicStaticField.FieldType == typeof(HRESULT)) + { + var hr = (HRESULT)publicStaticField.GetValue(null); + if (hr == this) + { + return publicStaticField.Name; + } + } + } + + // Try Win32 error codes also + if (Facility == Facility.Win32) + { + foreach (var publicStaticField in typeof(Win32Error).GetFields(BindingFlags.Static | BindingFlags.Public)) + { + if (publicStaticField.FieldType == typeof(Win32Error)) + { + var error = (Win32Error)publicStaticField.GetValue(null); + if ((HRESULT)error == this) + { + return "HRESULT_FROM_WIN32(" + publicStaticField.Name + ")"; + } + } + } + } + + // If there's no good name for this HRESULT, + // return the string as readable hex (0x########) format. + return string.Format(CultureInfo.InvariantCulture, "0x{0:X8}", _value); + } + + public override bool Equals(object obj) + { + try + { + return ((HRESULT)obj)._value == _value; + } + catch (InvalidCastException) + { + return false; + } + } + + public override int GetHashCode() + { + return _value.GetHashCode(); + } + + public static bool operator ==(HRESULT hrLeft, HRESULT hrRight) + { + return hrLeft._value == hrRight._value; + } + + public static bool operator !=(HRESULT hrLeft, HRESULT hrRight) + { + return !(hrLeft == hrRight); + } + + public bool Succeeded + { + get { return (int)_value >= 0; } + } + + public bool Failed + { + get { return (int)_value < 0; } + } + + /// + /// Convert the result of Win32 GetLastError() into a raised exception. + /// + [SecurityCritical] + public static void ThrowLastError() + { + ((HRESULT)Win32Error.GetLastError()).ThrowIfFailed(); + + // Only expecting to call this when we're expecting a failed GetLastError() + Verify.Fail(); + } + + // Critical: P-Invoke + [SecurityCritical] + [SuppressMessage( + "Microsoft.Usage", + "CA2201:DoNotRaiseReservedExceptionTypes", + Justification = "Only recreating Exceptions that were already raised.")] + [SuppressMessage( + "Microsoft.Globalization", + "CA1303:DoNotPassLiteralsAsLocalizedParameters", + Justification ="For DEBUG only")] + public void ThrowIfFailed(string message = null) + { + if (Failed) + { + if (string.IsNullOrEmpty(message)) + { + message = ToString(); + } +#if DEBUG + else + { + message += " (" + ToString() + ")"; + } +#endif + + // Wow. Reflection in a throw call. Later on this may turn out to have been a bad idea. + // If you're throwing an exception I assume it's OK for me to take some time to give it back. + // I want to convert the HRESULT to a more appropriate exception type than COMException. + // Marshal.ThrowExceptionForHR does this for me, but the general call uses GetErrorInfo + // if it's set, and then ignores the HRESULT that I've provided. This makes it so this + // call works the first time but you get burned on the second. To avoid this, I use + // the overload that explicitly ignores the IErrorInfo. + // In addition, the function doesn't allow me to set the Message unless I go through + // the process of implementing an IErrorInfo and then use that. There's no stock + // implementations of IErrorInfo available and I don't think it's worth the maintenance + // overhead of doing it, nor would it have significant value over this approach. + var e = NativeMethods.GetExceptionForHR((int)_value); + Verify.IsNotNull(e); + + // ArgumentNullException doesn't have the right constructor parameters, + // (nor does Win32Exception...) + // but E_POINTER gets mapped to NullReferenceException, + // so I don't think it will ever matter. + Verify.IsFalse(e is ArgumentNullException); + + // If we're not getting anything better than a COMException from Marshal, + // then at least check the facility and attempt to do better ourselves. + if (e.GetType() == typeof(COMException)) + { + switch (Facility) + { + case Facility.Win32: + e = CreateWin32Exception(Code, message); + break; + + default: + e = new COMException(message, (int)_value); + break; + } + } + else + { + var cons = e.GetType().GetConstructor(new[] { typeof(string) }); + if (cons != null) + { + e = cons.Invoke(new object[] { message }) as Exception; + Verify.IsNotNull(e); + } + } + + throw e; + } + } + + [SecuritySafeCritical] + [SuppressMessage( + "Microsoft.Security", + "CA2136:TransparencyAnnotationsShouldNotConflict", + Justification = "Calls safe overload of Win32Exception ctor that explicitly sets the error code and message.")] + private static Exception CreateWin32Exception(int code, string message) + { + return new Win32Exception(code, message); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/NativeMethods.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/NativeMethods.cs new file mode 100644 index 000000000..567a37ee9 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/NativeMethods.cs @@ -0,0 +1,226 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using System.Security; +using System.Text; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + // Some native methods are shimmed through public versions that handle converting failures into thrown exceptions. + internal static class NativeMethods + { + public const int LOGPIXELSX = 88; + public const int LOGPIXELSY = 90; + + public const int DPI_AWARENESS_CONTEXT_UNAWARE = -1; + public const int DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = -2; + public const int DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = -3; + public const int DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = -4; + +#pragma warning disable SA1401 // Fields must be private + public static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero); +#pragma warning restore SA1401 // Fields must be private + + // Critical: P-Invoke + // Available in Windows 10 version RS1 and above. + [SecurityCritical] + [DllImport(ExternDll.User32)] + [ResourceExposure(ResourceScope.None)] + public static extern bool AreDpiAwarenessContextsEqual(int dpiContextA, int dpiContextB); + + // Critical: P-Invoke + // Available in Windows 10 version RS1 and above. + [SecurityCritical] + [DllImport(ExternDll.User32)] + [ResourceExposure(ResourceScope.None)] + public static extern int GetThreadDpiAwarenessContext(); + + // Critical: P-Invoke + // for Windows 10 version RS2 and above + [SecurityCritical] + [DllImport(ExternDll.User32, SetLastError = true)] + [ResourceExposure(ResourceScope.None)] + public static extern bool SetProcessDpiAwarenessContext(int dpiFlag); + + [SecurityCritical] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern bool IsChild(HandleRef parent, HandleRef child); + + [SecurityCritical] + [DllImport(ExternDll.Ntdll, SetLastError = true, EntryPoint = "RtlGetVersion")] + private static extern bool _RtlGetVersion(ref OSVERSIONINFOEX versionInfo); + + [SecurityCritical] + public static OSVERSIONINFOEX RtlGetVersion() + { + var osVersionInfo = new OSVERSIONINFOEX { OSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX)) }; + _RtlGetVersion(ref osVersionInfo); + var err = Win32Error.GetLastError(); + if (!err.Equals(Win32Error.ERROR_SUCCESS)) + { + if (osVersionInfo.MajorVersion == 0) + { + err.ToHRESULT().ThrowIfFailed(); + } + } + + return osVersionInfo; + } + + // Enables the mouse to act as a pointer input device and send WM_POINTER messages. + [SecurityCritical] // P-Invokes + [DllImport(ExternDll.User32, SetLastError = true, EntryPoint = "EnableMouseInPointer")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool _EnableMouseInPointer(bool fEnable); + + [SecurityCritical] + public static bool EnableMouseInPointer(bool enable) + { + // NOTE: This is available on Windows 8 or later only + var ret = _EnableMouseInPointer(enable); + if (!ret) + { + HRESULT.ThrowLastError(); + } + + return ret; + } + + // Critical: This calls into Marshal.GetExceptionForHR which is critical + // it populates the exception object from data stored in a per thread IErrorInfo + // the IErrorInfo may have security sensitive information like file paths stored in it + // TreatAsSafe: Uses overload of GetExceptionForHR that omits IErrorInfo information from exception message + [SecuritySafeCritical] + internal static Exception GetExceptionForHR(int hr) + { + return Marshal.GetExceptionForHR(hr, new IntPtr(-1)); + } + + // Critical : P-Invokes + [SecurityCritical] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateWindowExW")] + private static extern IntPtr _CreateWindowEx( + WS_EX dwExStyle, + [MarshalAs(UnmanagedType.LPWStr)] string lpClassName, + [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, + WS dwStyle, + int x, + int y, + int nWidth, + int nHeight, + IntPtr hWndParent, + IntPtr hMenu, + IntPtr hInstance, + IntPtr lpParam); + + // Critical : Calls critical method + [SecurityCritical] + public static IntPtr CreateWindowEx( + WS_EX dwExStyle, + string lpClassName, + string lpWindowName, + WS dwStyle, + int x, + int y, + int nWidth, + int nHeight, + IntPtr hWndParent, + IntPtr hMenu, + IntPtr hInstance, + IntPtr lpParam) + { + var ret = _CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + if (ret == IntPtr.Zero) + { + HRESULT.ThrowLastError(); + } + + return ret; + } + + // Critical : Calls critical method + [SecurityCritical] + public static IntPtr CreateWindow(string className, WS styles, int x, int y, int width, int height, IntPtr parentWindow) + { + return CreateWindowEx( + 0, + className, + string.Empty, + styles, + x, + y, + width, + height, + parentWindow, + IntPtr.Zero, + Marshal.GetHINSTANCE(typeof(NativeMethods).Module), + IntPtr.Zero); + } + + // Critical : P-Invokes + [SecurityCritical] + [DllImport(ExternDll.User32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DestroyWindow(IntPtr hwnd); + + // Critical : P-Invokes + [SecurityCritical] + [DllImport(ExternDll.User32)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsWindow(IntPtr hwnd); + + // Critical : P-Invokes + [SecurityCritical] + [DllImport(ExternDll.Kernel32, EntryPoint = "GetModuleFileName", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern int _GetModuleFileName(IntPtr hModule, StringBuilder lpFilename, int nSize); + + // Critical : Calls critical method + [SecurityCritical] + public static string GetModuleFileName(IntPtr hModule) + { + var buffer = new StringBuilder((int)Win32Value.MAX_PATH); + while (true) + { + var size = _GetModuleFileName(hModule, buffer, buffer.Capacity); + if (size == 0) + { + HRESULT.ThrowLastError(); + } + + // GetModuleFileName returns nSize when it's truncated but does NOT set the last error. + // MSDN documentation says this has changed in Windows 2000+. + if (size == buffer.Capacity) + { + // Enlarge the buffer and try again. + buffer.EnsureCapacity(buffer.Capacity * 2); + continue; + } + + return buffer.ToString(); + } + } + + // Critical : P-Invokes + [SecurityCritical] + [DllImport(ExternDll.Kernel32, EntryPoint = "GetModuleHandleW", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern IntPtr _GetModuleHandle([MarshalAs(UnmanagedType.LPWStr)] string lpModuleName); + + // Critical : Calls critical method + [SecurityCritical] + public static IntPtr GetModuleHandle(string lpModuleName) + { + var retPtr = _GetModuleHandle(lpModuleName); + if (retPtr == IntPtr.Zero) + { + HRESULT.ThrowLastError(); + } + + return retPtr; + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/OSVERSIONINFOEX.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/OSVERSIONINFOEX.cs new file mode 100644 index 000000000..d91516028 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/OSVERSIONINFOEX.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct OSVERSIONINFOEX + { + // The OSVersionInfoSize field must be set to Marshal.SizeOf(typeof(OSVERSIONINFOEX)) + internal int OSVersionInfoSize; + internal int MajorVersion; + internal int MinorVersion; + internal int BuildNumber; + internal int PlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + internal string CSDVersion; + internal ushort ServicePackMajor; + internal ushort ServicePackMinor; + internal short SuiteMask; + internal ProductType ProductType; + internal byte Reserved; + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/PROCESS_DPI_AWARENESS.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/PROCESS_DPI_AWARENESS.cs new file mode 100644 index 000000000..e983d36a5 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/PROCESS_DPI_AWARENESS.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + /// + /// Identifies dots per inch (dpi) awareness values. + /// + internal enum PROCESS_DPI_AWARENESS + { + PROCESS_DPI_UNINITIALIZED = -1, + + /// + /// DPI unaware. This app does not scale for DPI changes and is always assumed to have a scale factor of 100% (96 DPI). It will be automatically scaled by the system on any other DPI setting. + /// + PROCESS_DPI_UNAWARE = 0, + + /// + /// System DPI aware. This app does not scale for DPI changes. It will query for the DPI once and use that value for the lifetime of the app. If the DPI changes, the app will not adjust to the new DPI value. It will be automatically scaled up or down by the system when the DPI changes from the system value. + /// + PROCESS_SYSTEM_DPI_AWARE = 1, + + /// + /// Per monitor DPI aware. This app checks for the DPI when it is created and adjusts the scale factor whenever the DPI changes. These applications are not automatically scaled by the system. + /// + PROCESS_PER_MONITOR_DPI_AWARE = 2 + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/ProductType.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/ProductType.cs new file mode 100644 index 000000000..24740f363 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/ProductType.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + internal enum ProductType : byte + { + /// + /// The operating system is Windows 10, Windows 8, Windows 7, Windows Vista, Windows XP Professional, Windows XP Home Edition, or Windows 2000 Professional + /// + VER_NT_WORKSTATION = 0x0000001, + + /// + /// The system is a domain controller and the operating system is Windows Server 2016, Windows Server 2012, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, or Windows 2000 Server + /// + VER_NT_DOMAIN_CONTROLLER = 0x0000002, + + /// + /// The operating system is Windows Server 2016, Windows Server 2012, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, or Windows 2000 Server. + /// + /// + /// Note that a server that is also a domain controller is reported as , not + /// + VER_NT_SERVER = 0x0000003 + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/RECT.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/RECT.cs new file mode 100644 index 000000000..2fae05ed9 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/RECT.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + internal struct RECT + { + public int bottom; + public int left; + public int right; + public int top; + + public RECT(int left, int top, int right, int bottom) + { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + public RECT(Rectangle r) + { + this.left = r.Left; + this.top = r.Top; + this.right = r.Right; + this.bottom = r.Bottom; + } + + public Size Size + { + get + { + return new Size(this.right - this.left, this.bottom - this.top); + } + } + + public static RECT FromXYWH(int x, int y, int width, int height) + { + return new RECT(x, y, x + width, y + height); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/UnsafeNativeMethods.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/UnsafeNativeMethods.cs new file mode 100644 index 000000000..077649824 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/UnsafeNativeMethods.cs @@ -0,0 +1,112 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using System.Security; +using System.Text; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + internal static class UnsafeNativeMethods + { + // Critical: P-Invokes + [SecurityCritical] + [DllImport(ExternDll.ShCore, SetLastError = true)] + public static extern int GetProcessDpiAwareness( + IntPtr hprocess, + out PROCESS_DPI_AWARENESS value); + + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "GetDC", CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.Process)] + private static extern IntPtr IntGetDC(HandleRef hWnd); + + [ResourceExposure(ResourceScope.Process)] + [ResourceConsumption(ResourceScope.Process)] + public static IntPtr GetDC(HandleRef hWnd) + { + // REVIEW: We can leak this handle unless ReleaseDC is called + return IntGetDC(hWnd); + } + + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "ReleaseDC", CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + private static extern int IntReleaseDC(HandleRef hWnd, HandleRef hDC); + + public static int ReleaseDC(HandleRef hWnd, HandleRef hDC) + { + return IntReleaseDC(hWnd, hDC); + } + + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)] + [ResourceExposure(ResourceScope.None)] + public static extern int GetDeviceCaps(HandleRef hDC, int nIndex); + + // Critical: P-Invokes + [SecurityCritical] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + internal static extern bool GetClientRect(HandleRef hWnd, [In, Out] ref RECT rect); + + // Critical: P-Invokes + [SecurityCritical] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + internal static extern IntPtr GetParent(HandleRef hWnd); + + // Critical: This code elevates to unmanaged code permission + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, EntryPoint = "GetModuleFileName", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern int IntGetModuleFileName(HandleRef hModule, StringBuilder buffer, int length); + + // Critical: This code elevates to unmanaged code permission by calling into IntGetModuleFileName + [SecurityCritical] + internal static string GetModuleFileName(HandleRef hModule) + { + // .Net is currently far behind Windows with regard to supporting paths longer than MAX_PATH. + // At one point it was tested trying to load UNC paths longer than MAX_PATH and mscorlib threw + // FileIOExceptions before WPF was even on the stack. + // All the same, we still want to have this grow-and-retry logic because the CLR can be hosted + // in a native application. Callers bothering to use this rather than Assembly based reflection + // are likely doing so because of (at least the potential for) the returned name referring to a + // native module. + var buffer = new StringBuilder((int)Win32Value.MAX_PATH); + while (true) + { + var size = IntGetModuleFileName(hModule, buffer, buffer.Capacity); + if (size == 0) + { + throw new Win32Exception(); + } + + // GetModuleFileName returns nSize when it's truncated but does NOT set the last error. + // MSDN documentation says this has changed in Windows 2000+. + if (size == buffer.Capacity) + { + // Enlarge the buffer and try again. + buffer.EnsureCapacity(buffer.Capacity * 2); + continue; + } + + return buffer.ToString(); + } + } + + // Critical: P-Invokes + [SecurityCritical] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr GetFocus(); + + // Critical: P-Invokes + [SecurityCritical] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + public static extern int MapWindowPoints(HandleRef hWndFrom, HandleRef hWndTo, [In, Out] ref RECT rect, int cPoints); + + // Critical: P-Invokes + [SecurityCritical] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + public static extern bool GetWindowRect(HandleRef hWnd, [In, Out] ref RECT rect); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WM.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WM.cs new file mode 100644 index 000000000..eb710730a --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WM.cs @@ -0,0 +1,162 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + /// + /// Window message values, WM_* + /// + internal enum WM + { + NULL = 0x0000, + CREATE = 0x0001, + DESTROY = 0x0002, + MOVE = 0x0003, + SIZE = 0x0005, + ACTIVATE = 0x0006, + SETFOCUS = 0x0007, + KILLFOCUS = 0x0008, + ENABLE = 0x000A, + SETREDRAW = 0x000B, + SETTEXT = 0x000C, + GETTEXT = 0x000D, + GETTEXTLENGTH = 0x000E, + PAINT = 0x000F, + CLOSE = 0x0010, + QUERYENDSESSION = 0x0011, + QUIT = 0x0012, + QUERYOPEN = 0x0013, + ERASEBKGND = 0x0014, + SYSCOLORCHANGE = 0x0015, + SHOWWINDOW = 0x0018, + CTLCOLOR = 0x0019, + WININICHANGE = 0x001A, + SETTINGCHANGE = 0x001A, + ACTIVATEAPP = 0x001C, + SETCURSOR = 0x0020, + MOUSEACTIVATE = 0x0021, + CHILDACTIVATE = 0x0022, + QUEUESYNC = 0x0023, + GETMINMAXINFO = 0x0024, + + WINDOWPOSCHANGING = 0x0046, + WINDOWPOSCHANGED = 0x0047, + + CONTEXTMENU = 0x007B, + STYLECHANGING = 0x007C, + STYLECHANGED = 0x007D, + DISPLAYCHANGE = 0x007E, + GETICON = 0x007F, + SETICON = 0x0080, + NCCREATE = 0x0081, + NCDESTROY = 0x0082, + NCCALCSIZE = 0x0083, + NCHITTEST = 0x0084, + NCPAINT = 0x0085, + NCACTIVATE = 0x0086, + GETDLGCODE = 0x0087, + SYNCPAINT = 0x0088, + NCMOUSEMOVE = 0x00A0, + NCLBUTTONDOWN = 0x00A1, + NCLBUTTONUP = 0x00A2, + NCLBUTTONDBLCLK = 0x00A3, + NCRBUTTONDOWN = 0x00A4, + NCRBUTTONUP = 0x00A5, + NCRBUTTONDBLCLK = 0x00A6, + NCMBUTTONDOWN = 0x00A7, + NCMBUTTONUP = 0x00A8, + NCMBUTTONDBLCLK = 0x00A9, + + SYSKEYDOWN = 0x0104, + SYSKEYUP = 0x0105, + SYSCHAR = 0x0106, + SYSDEADCHAR = 0x0107, + COMMAND = 0x0111, + SYSCOMMAND = 0x0112, + + MOUSEMOVE = 0x0200, + LBUTTONDOWN = 0x0201, + LBUTTONUP = 0x0202, + LBUTTONDBLCLK = 0x0203, + RBUTTONDOWN = 0x0204, + RBUTTONUP = 0x0205, + RBUTTONDBLCLK = 0x0206, + MBUTTONDOWN = 0x0207, + MBUTTONUP = 0x0208, + MBUTTONDBLCLK = 0x0209, + MOUSEWHEEL = 0x020A, + XBUTTONDOWN = 0x020B, + XBUTTONUP = 0x020C, + XBUTTONDBLCLK = 0x020D, + MOUSEHWHEEL = 0x020E, + PARENTNOTIFY = 0x0210, + + CAPTURECHANGED = 0x0215, + POWERBROADCAST = 0x0218, + DEVICECHANGE = 0x0219, + + ENTERSIZEMOVE = 0x0231, + EXITSIZEMOVE = 0x0232, + + IME_SETCONTEXT = 0x0281, + IME_NOTIFY = 0x0282, + IME_CONTROL = 0x0283, + IME_COMPOSITIONFULL = 0x0284, + IME_SELECT = 0x0285, + IME_CHAR = 0x0286, + IME_REQUEST = 0x0288, + IME_KEYDOWN = 0x0290, + IME_KEYUP = 0x0291, + + NCMOUSELEAVE = 0x02A2, + + TABLET_DEFBASE = 0x02C0, + + // WM_TABLET_MAXOFFSET = 0x20, + TABLET_ADDED = TABLET_DEFBASE + 8, + TABLET_DELETED = TABLET_DEFBASE + 9, + TABLET_FLICK = TABLET_DEFBASE + 11, + TABLET_QUERYSYSTEMGESTURESTATUS = TABLET_DEFBASE + 12, + + CUT = 0x0300, + COPY = 0x0301, + PASTE = 0x0302, + CLEAR = 0x0303, + UNDO = 0x0304, + RENDERFORMAT = 0x0305, + RENDERALLFORMATS = 0x0306, + DESTROYCLIPBOARD = 0x0307, + DRAWCLIPBOARD = 0x0308, + PAINTCLIPBOARD = 0x0309, + VSCROLLCLIPBOARD = 0x030A, + SIZECLIPBOARD = 0x030B, + ASKCBFORMATNAME = 0x030C, + CHANGECBCHAIN = 0x030D, + HSCROLLCLIPBOARD = 0x030E, + QUERYNEWPALETTE = 0x030F, + PALETTEISCHANGING = 0x0310, + PALETTECHANGED = 0x0311, + HOTKEY = 0x0312, + PRINT = 0x0317, + PRINTCLIENT = 0x0318, + APPCOMMAND = 0x0319, + THEMECHANGED = 0x031A, + + DWMCOMPOSITIONCHANGED = 0x031E, + DWMNCRENDERINGCHANGED = 0x031F, + DWMCOLORIZATIONCOLORCHANGED = 0x0320, + DWMWINDOWMAXIMIZEDCHANGE = 0x0321, + + GETTITLEBARINFOEX = 0x033F, + DWMSENDICONICTHUMBNAIL = 0x0323, + DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326, + + USER = 0x0400, + + // This is the hard-coded message value used by WinForms for Shell_NotifyIcon. + // It's relatively safe to reuse. + TRAYMOUSEMESSAGE = 0x800, // WM_USER + 1024 + APP = 0x8000, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WS.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WS.cs new file mode 100644 index 000000000..a4842a657 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WS.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + /// + /// WindowStyle values, WS_* + /// + [Flags] + internal enum WS : uint + { + OVERLAPPED = 0x00000000, + POPUP = 0x80000000, + CHILD = 0x40000000, + MINIMIZE = 0x20000000, + VISIBLE = 0x10000000, + DISABLED = 0x08000000, + CLIPSIBLINGS = 0x04000000, + CLIPCHILDREN = 0x02000000, + MAXIMIZE = 0x01000000, + BORDER = 0x00800000, + DLGFRAME = 0x00400000, + VSCROLL = 0x00200000, + HSCROLL = 0x00100000, + SYSMENU = 0x00080000, + THICKFRAME = 0x00040000, + GROUP = 0x00020000, + TABSTOP = 0x00010000, + + MINIMIZEBOX = 0x00020000, + MAXIMIZEBOX = 0x00010000, + + CAPTION = BORDER | DLGFRAME, + TILED = OVERLAPPED, + ICONIC = MINIMIZE, + SIZEBOX = THICKFRAME, + TILEDWINDOW = OVERLAPPEDWINDOW, + + OVERLAPPEDWINDOW = OVERLAPPED | CAPTION | SYSMENU | THICKFRAME | MINIMIZEBOX | MAXIMIZEBOX, + POPUPWINDOW = POPUP | BORDER | SYSMENU, + CHILDWINDOW = CHILD, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WS_EX.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WS_EX.cs new file mode 100644 index 000000000..6bcdb55e8 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/WS_EX.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + /// + /// Window style extended values, WS_EX_* + /// + [Flags] + internal enum WS_EX : uint + { + None = 0, + DLGMODALFRAME = 0x00000001, + NOPARENTNOTIFY = 0x00000004, + TOPMOST = 0x00000008, + ACCEPTFILES = 0x00000010, + TRANSPARENT = 0x00000020, + MDICHILD = 0x00000040, + TOOLWINDOW = 0x00000080, + WINDOWEDGE = 0x00000100, + CLIENTEDGE = 0x00000200, + CONTEXTHELP = 0x00000400, + RIGHT = 0x00001000, + LEFT = 0x00000000, + RTLREADING = 0x00002000, + LTRREADING = 0x00000000, + LEFTSCROLLBAR = 0x00004000, + RIGHTSCROLLBAR = 0x00000000, + CONTROLPARENT = 0x00010000, + STATICEDGE = 0x00020000, + APPWINDOW = 0x00040000, + LAYERED = 0x00080000, + NOINHERITLAYOUT = 0x00100000, // Disable inheritance of mirroring by children + LAYOUTRTL = 0x00400000, // Right to left mirroring + COMPOSITED = 0x02000000, + NOACTIVATE = 0x08000000, + OVERLAPPEDWINDOW = WINDOWEDGE | CLIENTEDGE, + PALETTEWINDOW = WINDOWEDGE | TOOLWINDOW | TOPMOST, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Win32Error.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Win32Error.cs new file mode 100644 index 000000000..6e75a6384 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Win32Error.cs @@ -0,0 +1,188 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + /// + /// Wrapper for common Win32 status codes. + /// + [StructLayout(LayoutKind.Explicit)] + internal struct Win32Error + { + [FieldOffset(0)] + private readonly int _value; + + // NOTE: These public static field declarations are automatically + // picked up by (HRESULT's) ToString through reflection. + + /// The operation completed successfully. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_SUCCESS = new Win32Error(0); + + /// Incorrect function. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_INVALID_FUNCTION = new Win32Error(1); + + /// The system cannot find the file specified. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_FILE_NOT_FOUND = new Win32Error(2); + + /// The system cannot find the path specified. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_PATH_NOT_FOUND = new Win32Error(3); + + /// The system cannot open the file. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_TOO_MANY_OPEN_FILES = new Win32Error(4); + + /// Access is denied. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_ACCESS_DENIED = new Win32Error(5); + + /// The handle is invalid. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_INVALID_HANDLE = new Win32Error(6); + + /// Not enough storage is available to complete this operation. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_OUTOFMEMORY = new Win32Error(14); + + /// There are no more files. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_NO_MORE_FILES = new Win32Error(18); + + /// The process cannot access the file because it is being used by another process. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_SHARING_VIOLATION = new Win32Error(32); + + /// The parameter is incorrect. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_INVALID_PARAMETER = new Win32Error(87); + + /// The data area passed to a system call is too small. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_INSUFFICIENT_BUFFER = new Win32Error(122); + + /// Cannot nest calls to LoadModule. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_NESTING_NOT_ALLOWED = new Win32Error(215); + + /// Illegal operation attempted on a registry key that has been marked for deletion. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_KEY_DELETED = new Win32Error(1018); + + /// Element not found. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_NOT_FOUND = new Win32Error(1168); + + /// There was no match for the specified key in the index. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_NO_MATCH = new Win32Error(1169); + + /// An invalid device was specified. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_BAD_DEVICE = new Win32Error(1200); + + /// The operation was canceled by the user. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_CANCELLED = new Win32Error(1223); + + /// Not all privileges or groups references are assigned to the caller + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_NOT_ALL_ASSIGNED = new Win32Error(1300); + + /// The window class was already registered. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_CLASS_ALREADY_EXISTS = new Win32Error(1410); + + /// The specified datatype is invalid. + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "May be used in DEBUG")] + public static readonly Win32Error ERROR_INVALID_DATATYPE = new Win32Error(1804); + + /// + /// Initializes a new instance of the struct. + /// + /// The integer value of the error. + public Win32Error(int i) + { + _value = i; + } + + /// Performs HRESULT_FROM_WIN32 conversion. + /// The Win32 error being converted to an HRESULT. + /// The equivalent HRESULT value. + public static explicit operator HRESULT(Win32Error error) + { + // #define __HRESULT_FROM_WIN32(x) + // ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) + if (error._value <= 0) + { + return new HRESULT((uint)error._value); + } + + return HRESULT.Make(true, Facility.Win32, error._value & 0x0000FFFF); + } + + /// Performs the equivalent of Win32's GetLastError() + /// A Win32Error instance with the result of the native GetLastError + [SecurityCritical] + public static Win32Error GetLastError() + { + return new Win32Error(Marshal.GetLastWin32Error()); + } + + // Method version of the cast operation + + /// Performs HRESULT_FROM_WIN32 conversion. + /// The equivalent HRESULT value. + public HRESULT ToHRESULT() + { + return (HRESULT)this; + } + + public override bool Equals(object obj) + { + try + { + return ((Win32Error)obj)._value == _value; + } + catch (InvalidCastException) + { + return false; + } + } + + public override int GetHashCode() + { + return _value.GetHashCode(); + } + + /// + /// Compare two Win32 error codes for equality. + /// + /// The first error code to compare. + /// The second error code to compare. + /// Whether the two error codes are the same. + public static bool operator ==(Win32Error errLeft, Win32Error errRight) + { + return errLeft._value == errRight._value; + } + + /// + /// Compare two Win32 error codes for inequality. + /// + /// The first error code to compare. + /// The second error code to compare. + /// Whether the two error codes are not the same. + public static bool operator !=(Win32Error errLeft, Win32Error errRight) + { + return !(errLeft == errRight); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Win32Value.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Win32Value.cs new file mode 100644 index 000000000..c8eaa6a93 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Win32/Win32Value.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32 +{ + internal static class Win32Value + { + public const uint MAX_PATH = 260; + public const uint INFOTIPSIZE = 1024; + public const uint TRUE = 1; + public const uint FALSE = 0; + public const uint Sizeof_WCHAR = 2; + public const uint SizeofChar = 1; + public const uint SizeofBool = 4; + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/CoreAcceleratorKeyEventType.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/CoreAcceleratorKeyEventType.cs new file mode 100644 index 000000000..5eca99963 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/CoreAcceleratorKeyEventType.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// Specifies the set of possible accelerator key events that can invoke a callback. + /// Copy from to avoid requirement to link Windows.winmd + /// +#pragma warning disable 1591 + public enum CoreAcceleratorKeyEventType + { + KeyDown, + KeyUp, + Character, + DeadCharacter, + SystemKeyDown, + SystemKeyUp, + SystemCharacter, + SystemDeadCharacter, + UnicodeCharacter, + } +#pragma warning restore 1591 +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/UriToLocalStreamResolver.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/UriToLocalStreamResolver.cs new file mode 100644 index 000000000..619a277a9 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/UriToLocalStreamResolver.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32; +using Windows.Foundation; +using Windows.Storage.Streams; +using Windows.Web; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + internal sealed class UriToLocalStreamResolver : IUriToStreamResolver + { + public IAsyncOperation UriToStreamAsync(Uri uri) + { + if (uri == null) + { + throw new ArgumentNullException(nameof(uri)); + } + + var path = uri.AbsolutePath; + return GetContentAsync(path).AsAsyncOperation(); + } + + private bool IsRelative(string path) + { + return path != null && path[0] == '/'; + } + + private static readonly Lazy BasePath = new Lazy(() => +#pragma warning disable SA1129 // Do not use default value type constructor + Path.GetDirectoryName(UnsafeNativeMethods.GetModuleFileName(new HandleRef()))); +#pragma warning restore SA1129 // Do not use default value type constructor + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + private async Task GetContentAsync(string path) +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + { + if (IsRelative(path)) + { + // Clean up path + while (path[0] == '/') + { + path = path.TrimStart('/'); + } + + // Translate forward slash into backslash for use in file paths + path = path.Replace(@"/", @"\"); + + var fullPath = Path.Combine(BasePath.Value, path); + + // TODO: Make this proper async all the way through + return File.Open(fullPath, FileMode.Open, FileAccess.Read).AsInputStream(); + } + + throw new NotSupportedException(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/VirtualKey.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/VirtualKey.cs new file mode 100644 index 000000000..e83d7104e --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/VirtualKey.cs @@ -0,0 +1,224 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// Specifies the values for each virtual key. + /// Copy from to avoid requirement to link Windows.winmd + /// +#pragma warning disable 1591 +#pragma warning disable SA1404 // Code analysis suppression must have justification + public enum VirtualKey + { + None = 0, + LeftButton = 1, + RightButton = 2, + Cancel = 3, + MiddleButton = 4, + XButton1 = 5, + XButton2 = 6, + Back = 8, + Tab = 9, + Clear = 12, + Enter = 13, + Shift = 16, + Control = 17, + Menu = 18, + Pause = 19, + CapitalLock = 20, + Hangul = 21, + Kana = 21, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Junja")] + Junja = 23, + Final = 24, + Hanja = 25, + Kanji = 25, + Escape = 27, + Convert = 28, + NonConvert = 29, + Accept = 30, + ModeChange = 31, + Space = 32, + PageUp = 33, + PageDown = 34, + End = 35, + Home = 36, + Left = 37, + Up = 38, + Right = 39, + Down = 40, + Select = 41, + Print = 42, + Execute = 43, + Snapshot = 44, + Insert = 45, + Delete = 46, + Help = 47, + Number0 = 48, + Number1 = 49, + Number2 = 50, + Number3 = 51, + Number4 = 52, + Number5 = 53, + Number6 = 54, + Number7 = 55, + Number8 = 56, + Number9 = 57, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "A")] + A = 65, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "B")] + B = 66, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "C")] + C = 67, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "D")] + D = 68, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "E")] + E = 69, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "F")] + F = 70, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "G")] + G = 71, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "H")] + H = 72, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "I")] + I = 73, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "J")] + J = 74, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "K")] + K = 75, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "L")] + L = 76, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "M")] + M = 77, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "N")] + N = 78, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "O")] + O = 79, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "P")] + P = 80, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Q")] + Q = 81, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "R")] + R = 82, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "S")] + S = 83, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "T")] + T = 84, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "U")] + U = 85, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "V")] + V = 86, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "W")] + W = 87, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")] + X = 88, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y")] + Y = 89, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Z")] + Z = 90, + LeftWindows = 91, + RightWindows = 92, + Application = 93, + Sleep = 95, + NumberPad0 = 96, + NumberPad1 = 97, + NumberPad2 = 98, + NumberPad3 = 99, + NumberPad4 = 100, + NumberPad5 = 101, + NumberPad6 = 102, + NumberPad7 = 103, + NumberPad8 = 104, + NumberPad9 = 105, + Multiply = 106, + Add = 107, + Separator = 108, + Subtract = 109, + Decimal = 110, + Divide = 111, + F1 = 112, + F2 = 113, + F3 = 114, + F4 = 115, + F5 = 116, + F6 = 117, + F7 = 118, + F8 = 119, + F9 = 120, + F10 = 121, + F11 = 122, + F12 = 123, + F13 = 124, + F14 = 125, + F15 = 126, + F16 = 127, + F17 = 128, + F18 = 129, + F19 = 130, + F20 = 131, + F21 = 132, + F22 = 133, + F23 = 134, + F24 = 135, + NavigationView = 136, + NavigationMenu = 137, + NavigationUp = 138, + NavigationDown = 139, + NavigationLeft = 140, + NavigationRight = 141, + NavigationAccept = 142, + NavigationCancel = 143, + NumberKeyLock = 144, + Scroll = 145, + LeftShift = 160, + RightShift = 161, + LeftControl = 162, + RightControl = 163, + LeftMenu = 164, + RightMenu = 165, + GoBack = 166, + GoForward = 167, + Refresh = 168, + Stop = 169, + Search = 170, + Favorites = 171, + GoHome = 172, + GamepadA = 195, + GamepadB = 196, + GamepadX = 197, + GamepadY = 198, + GamepadRightShoulder = 199, + GamepadLeftShoulder = 200, + GamepadLeftTrigger = 201, + GamepadRightTrigger = 202, + GamepadDPadUp = 203, + GamepadDPadDown = 204, + GamepadDPadLeft = 205, + GamepadDPadRight = 206, + GamepadMenu = 207, + GamepadView = 208, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadLeftThumbstickButton = 209, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadRightThumbstickButton = 210, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadLeftThumbstickUp = 211, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadLeftThumbstickDown = 212, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadLeftThumbstickRight = 213, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadLeftThumbstickLeft = 214, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadRightThumbstickUp = 215, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadRightThumbstickDown = 216, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadRightThumbstickRight = 217, + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Thumbstick")] + GamepadRightThumbstickLeft = 218, + } +#pragma warning restore SA1404 // Code analysis suppression must have justification +#pragma warning restore 1591 +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebErrorStatus.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebErrorStatus.cs new file mode 100644 index 000000000..4737b7d85 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebErrorStatus.cs @@ -0,0 +1,290 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Defines errors encountered during operations involving web services, such as authentication, proxy configuration, and destination URIs. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + public enum WebErrorStatus + { + /// + /// An unknown error has occurred. + /// + Unknown = 0, + + /// + /// The SSL certificate common name does not match the web address. + /// + CertificateCommonNameIsIncorrect = 1, + + /// + /// The SSL certificate has expired. + /// + CertificateExpired = 2, + + /// + /// The SSL certificate contains errors. + /// + CertificateContainsErrors = 3, + + /// + /// The SSL certificate has been revoked. + /// + CertificateRevoked = 4, + + /// + /// The SSL certificate is invalid. + /// + CertificateIsInvalid = 5, + + /// + /// The server is not responding. + /// + ServerUnreachable = 6, + + /// + /// The connection has timed out. + /// + Timeout = 7, + + /// + /// The server returned an invalid or unrecognized response. + /// + ErrorHttpInvalidServerResponse = 8, + + /// + /// The connection was aborted. + /// + ConnectionAborted = 9, + + /// + /// The connection was reset. + /// + ConnectionReset = 10, + + /// + /// The connection was ended. + /// + Disconnected = 11, + + /// + /// Redirected from a location to a secure location. + /// + HttpToHttpsOnRedirection = 12, + + /// + /// Redirected from a secure location to an unsecure location. + /// + HttpsToHttpOnRedirection = 13, + + /// + /// Cannot connect to destination. + /// + CannotConnect = 14, + + /// + /// Could not resolve provided host name. + /// + HostNameNotResolved = 15, + + /// + /// The operation was canceled. + /// + OperationCanceled = 16, + + /// + /// The request redirect failed. + /// + RedirectFailed = 17, + + /// + /// An unexpected status code indicating a failure was received. + /// + UnexpectedStatusCode = 18, + + /// + /// A request was unexpectedly redirected. + /// + UnexpectedRedirection = 19, + + /// + /// An unexpected client-side error has occurred. + /// + UnexpectedClientError = 20, + + /// + /// An unexpected server-side error has occurred. + /// + UnexpectedServerError = 21, + + /// + /// The request does not support the range. + /// + InsufficientRangeSupport = 22, + + /// + /// The request is mising the file size. + /// + MissingContentLengthSupport = 23, + + /// + /// The requested URL represents a high level grouping of which lower level selections need to be made. + /// + MultipleChoices = 300, + + /// + /// This and all future requests should be directed to the given URI. + /// + MovedPermanently = 301, + + /// + /// The resource was found but is available in a location different from the one included in the request. + /// + Found = 302, + + /// + /// The response to the request can be found under another URI using a GET method. + /// + SeeOther = 303, + + /// + /// Indicates the resource has not been modified since last requested. + /// + NotModified = 304, + + /// + /// The requested resource must be accessed through the proxy given by the Location field. + /// + UseProxy = 305, + + /// + /// The requested resource resides temporarily under a different URI. + /// + TemporaryRedirect = 307, + + /// + /// The request cannot be fulfilled due to bad syntax. + /// + BadRequest = 400, + + /// + /// Authentication has failed or credentials have not yet been provided. + /// + Unauthorized = 401, + + /// + /// Reserved. + /// + PaymentRequired = 402, + + /// + /// The server has refused the request. + /// + Forbidden = 403, + + /// + /// The requested resource could not be found but may be available again in the future. + /// + NotFound = 404, + + /// + /// A request was made of a resource using a request method not supported by that resource. + /// + MethodNotAllowed = 405, + + /// + /// The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request. + /// + NotAcceptable = 406, + + /// + /// The client must first authenticate itself with the proxy. + /// + ProxyAuthenticationRequired = 407, + + /// + /// The server timed out waiting for the request. + /// + RequestTimeout = 408, + + /// + /// Indicates that the request could not be processed because of conflict in the request. + /// + Conflict = 409, + + /// + /// Indicates that the resource requested is no longer available and will not be available again. + /// + Gone = 410, + + /// + /// The request did not specify the length of its content, which is required by the requested resource. + /// + LengthRequired = 411, + + /// + /// The server does not meet one of the preconditions that the requester put on the request. + /// + PreconditionFailed = 412, + + /// + /// The request is larger than the server is willing or able to process. + /// + RequestEntityTooLarge = 413, + + /// + /// Provided URI length exceeds the maximum length the server can process. + /// + RequestUriTooLong = 414, + + /// + /// The request entity has a media type which the server or resource does not support. + /// + UnsupportedMediaType = 415, + + /// + /// The client has asked for a portion of the file, but the server cannot supply that portion. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Satisfiable", Justification="Spelling of WinRT type")] + RequestedRangeNotSatisfiable = 416, + + /// + /// The server cannot meet the requirements of the Expect request-header field. + /// + ExpectationFailed = 417, + + /// + /// A generic error message, given when no more specific message is suitable. + /// + InternalServerError = 500, + + /// + /// The server either does not recognize the request method, or it lacks the ability to fulfill the request. + /// + NotImplemented = 501, + + /// + /// The server was acting as a gateway or proxy and received an invalid response from the upstream server. + /// + BadGateway = 502, + + /// + /// The server is currently unavailable. + /// + ServiceUnavailable = 503, + + /// + /// The server was acting as a gateway or proxy and did not receive a timely response from the upstream server. + /// + GatewayTimeout = 504, + + /// + /// The server does not support the HTTP protocol version used in the request. + /// + HttpVersionNotSupported = 505, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlAcceleratorKeyPressedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlAcceleratorKeyPressedEventArgs.cs new file mode 100644 index 000000000..6a4236d30 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlAcceleratorKeyPressedEventArgs.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// This class provides information for the event. + /// + public class WebViewControlAcceleratorKeyPressedEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.Interop.WebViewControlAcceleratorKeyPressedEventArgs _args; + + [SecurityCritical] + internal WebViewControlAcceleratorKeyPressedEventArgs(Windows.Web.UI.Interop.WebViewControlAcceleratorKeyPressedEventArgs args) + { + _args = args; + } + + /// + /// Gets the type of the event. + /// + /// The type of the event. + public CoreAcceleratorKeyEventType EventType + { + [SecurityCritical] + get { return (CoreAcceleratorKeyEventType)_args.EventType; } + } + + /// + /// Gets or sets a value indicating whether this is handled. + /// + /// if handled; otherwise, . + public bool Handled + { + [SecurityCritical] + get => _args.Handled; + [SecurityCritical] + set => _args.Handled = value; + } + + /// + /// Gets the routing stage. + /// + /// The routing stage. + public WebViewControlAcceleratorKeyRoutingStage RoutingStage + { + [SecurityCritical] + get { return (WebViewControlAcceleratorKeyRoutingStage)_args.RoutingStage; } + } + + /// + /// Gets the virtual key. + /// + /// The virtual key. + public VirtualKey VirtualKey + { + [SecurityCritical] + get { return (VirtualKey)_args.VirtualKey; } + } + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + [SecurityCritical] + public static implicit operator WebViewControlAcceleratorKeyPressedEventArgs( + Windows.Web.UI.Interop.WebViewControlAcceleratorKeyPressedEventArgs args) + { + return new WebViewControlAcceleratorKeyPressedEventArgs(args); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlAcceleratorKeyRoutingStage.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlAcceleratorKeyRoutingStage.cs new file mode 100644 index 000000000..9d6599297 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlAcceleratorKeyRoutingStage.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// An enumeration that describes the accelerator key routing stage. + /// Copy from to avoid requirement to link Windows.winmd + /// + public enum WebViewControlAcceleratorKeyRoutingStage + { +#pragma warning disable 1591 + Tunneling, + Bubbling, +#pragma warning restore 1591 + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlContentLoadingEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlContentLoadingEventArgs.cs new file mode 100644 index 000000000..4ae06aece --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlContentLoadingEventArgs.cs @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the and events. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + public sealed class WebViewControlContentLoadingEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlContentLoadingEventArgs _args; + + [SecurityCritical] + internal WebViewControlContentLoadingEventArgs(Windows.Web.UI.WebViewControlContentLoadingEventArgs args) + { + _args = args; + } + + /// + /// Gets the Uniform Resource Identifier (URI) of the content the is loading. + /// + public Uri Uri + { + [SecurityCritical] + get { return _args.Uri; } + } + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + [SecurityCritical] + public static implicit operator WebViewControlContentLoadingEventArgs( + Windows.Web.UI.WebViewControlContentLoadingEventArgs args) + { + return FromWebViewControlContentLoadingEventArgs(args); + } + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// + public static WebViewControlContentLoadingEventArgs FromWebViewControlContentLoadingEventArgs(Windows.Web.UI.WebViewControlContentLoadingEventArgs args) + { + return new WebViewControlContentLoadingEventArgs(args); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlDeferredPermissionRequest.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlDeferredPermissionRequest.cs new file mode 100644 index 000000000..988b1bcb1 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlDeferredPermissionRequest.cs @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Represents a deferred request for permissions in an . This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + public sealed class WebViewControlDeferredPermissionRequest + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlDeferredPermissionRequest _webViewControlDeferredPermissionRequest; + + internal WebViewControlDeferredPermissionRequest(Windows.Web.UI.WebViewControlDeferredPermissionRequest webViewControlDeferredPermissionRequest) + { + _webViewControlDeferredPermissionRequest = webViewControlDeferredPermissionRequest; + } + + /// + /// Gets the identifier for the permission request. + /// + public uint Id => _webViewControlDeferredPermissionRequest.Id; + + /// + /// Gets a value that indicates the type of permission that's requested. + /// + public WebViewControlPermissionType PermissionType => (WebViewControlPermissionType)_webViewControlDeferredPermissionRequest.PermissionType; + + /// + /// Gets the Uniform Resource Identifier (URI) of the content where the permission request originated. + /// + public Uri Uri => _webViewControlDeferredPermissionRequest.Uri; + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlDeferredPermissionRequest(Windows.Web.UI.WebViewControlDeferredPermissionRequest args) => ToWebViewControlDeferredPermissionRequest(args); + + /// + /// Creates a from . + /// + /// The instance containing the deferred permission request. + /// . + public static WebViewControlDeferredPermissionRequest ToWebViewControlDeferredPermissionRequest(Windows.Web.UI.WebViewControlDeferredPermissionRequest args) => new WebViewControlDeferredPermissionRequest(args); + + /// + /// Grants the requested permission. + /// + [SecurityCritical] + public void Allow() => _webViewControlDeferredPermissionRequest.Allow(); + + /// + /// Denies the requested permission. + /// + [SecurityCritical] + public void Deny() => _webViewControlDeferredPermissionRequest.Deny(); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlDomContentLoadedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlDomContentLoadedEventArgs.cs new file mode 100644 index 000000000..160e6f745 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlDomContentLoadedEventArgs.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the and events. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Microsoft.Naming", + "CA1709:IdentifiersShouldBeCasedCorrectly", + MessageId = "DOM", + Justification = "Maintain consistency with WinRT type name")] + public sealed class WebViewControlDOMContentLoadedEventArgs : EventArgs + { + [SecurityCritical] + internal WebViewControlDOMContentLoadedEventArgs(Windows.Web.UI.WebViewControlDOMContentLoadedEventArgs args) + { + Uri = args.Uri; + } + + internal WebViewControlDOMContentLoadedEventArgs(Uri uri) + { + Uri = uri; + } + + /// + /// Gets the Uniform Resource Identifier (URI) of the content the is loading. + /// + /// The Uniform Resource Identifier (URI) of the content the is loading. + public Uri Uri { get; } + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlDOMContentLoadedEventArgs(Windows.Web.UI.WebViewControlDOMContentLoadedEventArgs args) => FromWebViewControlDOMContentLoadedEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// . + public static WebViewControlDOMContentLoadedEventArgs FromWebViewControlDOMContentLoadedEventArgs( + Windows.Web.UI.WebViewControlDOMContentLoadedEventArgs args) => + new WebViewControlDOMContentLoadedEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlHost.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlHost.cs new file mode 100644 index 000000000..79a73e921 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlHost.cs @@ -0,0 +1,973 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Security; +using System.Threading.Tasks; + +using Windows.Web; +using Windows.Web.UI; +using Windows.Web.UI.Interop; + +using Rect = Windows.Foundation.Rect; + +// Suppress document warnings as the items are internal and are used to propagate exception info up to consuming classes +#pragma warning disable SA1604 // Element documentation must have summary +#pragma warning disable SA1615 // Element return value must be documented + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides a control that hosts HTML content in an app. + /// + /// + /// navigation events occur in the following order: + /// + /// + /// + /// + /// + /// + /// Similar events occur in the same order for each iframe in the content: + /// + /// + /// + /// + /// + /// + /// + internal sealed class WebViewControlHost : IDisposable + { + [SecurityCritical] + private WebViewControl _webViewControl; + + private bool _webViewControlClosed; + + internal WebViewControlHost(WebViewControl webViewControl) + { + Verify.IsNotNull(webViewControl); + + _webViewControl = webViewControl ?? throw new ArgumentNullException(nameof(webViewControl)); + Process = _webViewControl.Process; + SubscribeEvents(); + SubscribeProcessExited(); + } + + ~WebViewControlHost() + { + Dispose(false); + } + + internal event EventHandler AcceleratorKeyPressed = (sender, args) => { }; + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Justification = "This is the declaration from WinRT")] + internal event EventHandler ContainsFullScreenElementChanged = (sender, args) => { }; + + internal event EventHandler ContentLoading = (sender, args) => { }; + + internal event EventHandler DOMContentLoaded = (sender, args) => { }; + + internal event EventHandler FrameContentLoading = (sender, args) => { }; + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "DOM", Justification = "This is the name from WinRT")] + internal event EventHandler FrameDOMContentLoaded = (sender, args) => { }; + + internal event EventHandler FrameNavigationCompleted = (sender, args) => { }; + + internal event EventHandler FrameNavigationStarting = (sender, args) => { }; + + internal event EventHandler LongRunningScriptDetected = (sender, args) => { }; + + internal event EventHandler MoveFocusRequested = (sender, args) => { }; + + internal event EventHandler NavigationCompleted = (sender, args) => { }; + + internal event EventHandler NavigationStarting = (sender, args) => { }; + + internal event EventHandler NewWindowRequested = (sender, args) => { }; + + internal event EventHandler PermissionRequested = (sender, args) => { }; + + internal event EventHandler ScriptNotify = (sender, args) => { }; + + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Microsoft.Design", + "CA1009:DeclareEventHandlersCorrectly", + Justification = "WinRT type does not derive from EventArgs. Signature kept to maintain compatibility")] + internal event EventHandler UnsafeContentWarningDisplaying = (sender, args) => { }; + + internal event EventHandler UnsupportedUriSchemeIdentified = (sender, args) => { }; + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unviewable", Justification ="This is the name from WinRT")] + internal event EventHandler UnviewableContentIdentified = (sender, args) => { }; + + internal static bool IsSupported => OSVersionHelper.IsWindows10April2018OrGreater + && OSVersionHelper.IsWorkstation + && OSVersionHelper.EdgeExists; + + internal bool CanGoBack + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + if (!IsDisposed && _webViewControl != null) + { + return _webViewControl.CanGoBack; + } + + return false; + } + } + + internal bool CanGoForward + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + if (!IsDisposed && _webViewControl != null) + { + return _webViewControl.CanGoForward; + } + + return false; + } + } + + internal bool ContainsFullScreenElement + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + if (!IsDisposed && _webViewControl != null) + { + return _webViewControl.ContainsFullScreenElement; + } + + return false; + } + } + + internal string DocumentTitle + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + return _webViewControl?.DocumentTitle; + } + } + + private bool IsDisposed { get; set; } + + private bool IsDisposing { get; set; } + + internal bool IsVisible + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + return _webViewControl?.IsVisible ?? false; + } + + set + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + _webViewControl.IsVisible = value; + } + } + + internal Windows.Web.UI.Interop.WebViewControlProcess Process { get; private set; } + + internal Windows.Web.UI.WebViewControlSettings Settings + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.Settings; + } + } + + internal Uri Source + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + Uri url = null; + + if (_webViewControl != null) + { + // Current url + url = _webViewControl.Source; + + // When Source set to null or navigating to stream/string, we navigate to "about:blank" + // internally. Make sure we return null in those cases. + // Note that the current Source may not be "about:blank" yet + // Also, we'll (inconsistently) return "about:blank" in some cases + if (NavigatingToAboutBlank) + { + url = null; + } + } + + return url; + } + + set + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + if (_webViewControl != null) + { + Navigate(value); + } + } + } + + /// + /// Gets the version of EDGEHTML.DLL used by the control. + /// + /// The version of EDGEHTML.DLL used by the control. + internal Version Version + { + get + { + if (OSVersionHelper.EdgeExists) + { + var versionInfo = FileVersionInfo.GetVersionInfo( + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "edgehtml.dll")); + return new Version( + versionInfo.FileMajorPart, + versionInfo.FileMinorPart, + versionInfo.FileBuildPart, + versionInfo.FilePrivatePart); + } + + // Reuse the message, close enough + throw new InvalidOperationException(DesignerUI.E_NOTSUPPORTED_OS_RS4); + } + } + + private Guid LastNavigation + { + get; + [SecurityCritical] + set; + } + + // Indicates whether we are navigating to "about:blank" internally because Source is set to null or navigating to string + // Set is SecurityCritical because it is involved in making security decisions + private bool NavigatingToAboutBlank + { + get; + [SecurityCritical] + set; + } + + internal Uri BuildStream(string contentIdentifier, string relativePath) + { + return _webViewControl?.BuildLocalStreamUri(contentIdentifier, relativePath); + } + + internal void Close() + { + var webViewControlAlreadyClosed = _webViewControlClosed; + _webViewControlClosed = true; + + // Unsubscribe all events: + UnsubscribeEvents(); + UnsubscribeProcessExited(); + + if (!webViewControlAlreadyClosed) + { + Verify.IsNotNull(_webViewControl); + + _webViewControl?.Close(); + } + + _webViewControl = null; + Process = null; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + internal WebViewControlDeferredPermissionRequest GetDeferredPermissionRequestById(uint id) + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + if (_webViewControl == null) + { + return null; + } + + _webViewControl.GetDeferredPermissionRequestById(id, out var retval); + return retval; + } + + internal bool GoBack() + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + var retval = _webViewControl != null; + try + { + _webViewControl?.GoBack(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) + { + throw; + } + + retval = false; + } + + return retval; + } + + internal bool GoForward() + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + + var retval = _webViewControl != null; + try + { + _webViewControl?.GoForward(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) + { + throw; + } + + retval = false; + } + + return retval; + } + + /// When the underlying is not yet initialized. + internal string InvokeScript(string scriptName) => InvokeScript(scriptName, null); + + /// When the underlying is not yet initialized. + internal string InvokeScript(string scriptName, params string[] arguments) => InvokeScript(scriptName, (IEnumerable)arguments); + + /// When the underlying is not yet initialized. + internal string InvokeScript(string scriptName, IEnumerable arguments) => InvokeScriptAsync(scriptName, arguments).GetAwaiter().GetResult(); + + /// When the underlying is not yet initialized. + internal Task InvokeScriptAsync(string scriptName) => InvokeScriptAsync(scriptName, null); + + /// When the underlying is not yet initialized. + internal Task InvokeScriptAsync(string scriptName, params string[] arguments) => InvokeScriptAsync(scriptName, (IEnumerable)arguments); + + /// When the underlying is not yet initialized. + /// is + internal Task InvokeScriptAsync(string scriptName, IEnumerable arguments) + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + Verify.IsNeitherNullNorEmpty(scriptName); + + if (string.IsNullOrEmpty(scriptName)) + { + throw new ArgumentNullException(nameof(scriptName)); + } + + // Cannot invoke script + if (_webViewControl == null) + { + throw new InvalidOperationException(DesignerUI.E_WEBVIEW_CANNOT_INVOKE_BEFORE_INIT); + } + + // Protect against the cross domain scripting attacks + // If it is our internal navigation to about:blank for navigating to null or load string or before navigation has happened, Source will be null + var currentSource = Source; + if (currentSource != null) + { + Security.DemandWebPermission(currentSource); + } + + return _webViewControl + .InvokeScriptAsync(scriptName, arguments) + .AsTask(); + } + + internal void MoveFocus(WebViewControlMoveFocusReason reason) + { + _webViewControl?.MoveFocus((Windows.Web.UI.Interop.WebViewControlMoveFocusReason)reason); + } + + /// The provided is a relative URI. + internal void Navigate(Uri source) + { + Verify.IsNotNull(_webViewControl); + + if (_webViewControl != null) + { + // Cancel any outstanding navigation + // TODO: Does this show a cancel page? Can we suppress that? + _webViewControl.Stop(); + + LastNavigation = Guid.NewGuid(); + + if (source == null) + { + NavigatingToAboutBlank = true; + source = WebViewDefaults.AboutBlankUri; + } + else + { + CleanInternalState(); + } + + // Absolute URI only. Not sure what the host would be if using relative + if (!source.IsAbsoluteUri) + { + throw new ArgumentException(DesignerUI.E_WEBVIEW_NOT_ABSOLUTE_URI, nameof(source)); + } + + // TODO: Handle POPUP window + // TODO: Handle navigation for frame + + // TODO: Security for partial trust (e.g. about:blank is not allowed) + // If we are navigating to "about:blank" internally as a result of setting source to null + // or navigating to string, do not demand WebPermission + if (!NavigatingToAboutBlank) + { + Security.DemandWebPermission(source); + } + + // TODO: Sanitize URI containing invalid UTF-8 sequences + try + { + _webViewControl.Navigate(source); + } + catch (Exception) + { + // Clear internal state if navigation fails + CleanInternalState(); + + throw; + } + } + } + + /// + /// In the .NET for Windows Store apps or the Portable Class Library, catch the base class exception, , instead. + /// is empty.-or- The scheme specified in is not correctly formed. See .-or- + /// contains too many slashes.-or- The password specified in is not valid.-or- The host name specified in is not valid.-or- The file name specified in is not valid. -or- The user name specified in is not valid.-or- The host or authority name specified in cannot be terminated by backslashes.-or- The port number specified in is not valid or cannot be parsed.-or- The length of exceeds 65519 characters.-or- The length of the scheme specified in exceeds 1023 characters.-or- There is an invalid character sequence in .-or- The MS-DOS path specified in must start with c:\\. + internal void Navigate(string source) + { + Navigate(UriHelper.StringToUri(source)); + } + + internal void NavigateToLocal(string relativePath) + { + var uri = BuildStream("LocalContent", relativePath); + var resolver = new UriToLocalStreamResolver(); + NavigateToLocalStreamUri(uri, resolver); + } + + internal void NavigateToLocalStreamUri(Uri source, IUriToStreamResolver streamResolver) + { + _webViewControl?.NavigateToLocalStreamUri(source, streamResolver); + } + + /// is + internal void NavigateToString(string text) + { + if (string.IsNullOrEmpty(text)) + { + throw new ArgumentNullException(nameof(text)); + } + + _webViewControl?.NavigateToString(text); + } + + internal void Refresh() + { + try + { + _webViewControl?.Refresh(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) + { + throw; + } + } + } + + internal void Stop() + { + try + { + _webViewControl?.Stop(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) + { + throw; + } + } + } + + // We don't expose the Bounds property because of issues with placement of Core window + internal void UpdateBounds(Rect bounds) + { + if (_webViewControl != null) + { + _webViewControl.Bounds = bounds; + } + } + + [SecurityCritical] // Resets NavigatingToAboutBlank which is used in security decisions + private void CleanInternalState() + { + NavigatingToAboutBlank = false; + } + + private void Dispose(bool disposing) + { + IsDisposing = true; + try + { + if (disposing) + { + Close(); + } + } + finally + { + IsDisposing = false; + IsDisposed = true; + } + } + + private void OnAcceleratorKeyPressed(WebViewControlAcceleratorKeyPressedEventArgs args) + { + var handler = AcceleratorKeyPressed; + if (handler != null) + { + handler(this, args); + } + } + + private void OnAcceleratorKeyPressed(WebViewControl sender, Windows.Web.UI.Interop.WebViewControlAcceleratorKeyPressedEventArgs args) => OnAcceleratorKeyPressed(args); + + private void OnContainsFullScreenElementChanged(object args) + { + var handler = ContainsFullScreenElementChanged; + if (handler != null) + { + handler(this, args); + } + } + + private void OnContainsFullScreenElementChanged(IWebViewControl sender, object args) => OnContainsFullScreenElementChanged(args); + + private void OnContentLoading(WebViewControlContentLoadingEventArgs args) + { + var handler = ContentLoading; + if (handler != null) + { + handler(this, args); + } + } + + private void OnContentLoading(IWebViewControl sender, Windows.Web.UI.WebViewControlContentLoadingEventArgs args) => OnContentLoading(args); + + private void OnDOMContentLoaded(WebViewControlDOMContentLoadedEventArgs args) + { + var handler = DOMContentLoaded; + if (handler != null) + { + handler(this, args); + } + } + + private void OnDOMContentLoaded(IWebViewControl sender, Windows.Web.UI.WebViewControlDOMContentLoadedEventArgs args) + { + // When Source set to null or navigating to stream/string, we navigate to "about:blank" internally. + if (NavigatingToAboutBlank) + { + Verify.Implies(NavigatingToAboutBlank, Source == null || Source == WebViewDefaults.AboutBlankUri); + + // Make sure we pass null in the event args + var a = new WebViewControlDOMContentLoadedEventArgs((Uri)null); + OnDOMContentLoaded(a); + } + else + { + OnDOMContentLoaded(args); + } + } + + private void OnFrameContentLoading(WebViewControlContentLoadingEventArgs args) + { + var handler = FrameContentLoading; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameContentLoading(IWebViewControl sender, Windows.Web.UI.WebViewControlContentLoadingEventArgs args) => OnFrameContentLoading(args); + + private void OnFrameDOMContentLoaded(WebViewControlDOMContentLoadedEventArgs args) + { + var handler = FrameDOMContentLoaded; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameDOMContentLoaded(IWebViewControl sender, Windows.Web.UI.WebViewControlDOMContentLoadedEventArgs args) => OnFrameDOMContentLoaded(args); + + private void OnFrameNavigationCompleted(WebViewControlNavigationCompletedEventArgs args) + { + var handler = FrameNavigationCompleted; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameNavigationCompleted(IWebViewControl sender, Windows.Web.UI.WebViewControlNavigationCompletedEventArgs args) + { + // TODO: Need to handle frame navigation like NavigationCompleted? + OnFrameNavigationCompleted(args); + } + + private void OnFrameNavigationStarting(WebViewControlNavigationStartingEventArgs args) + { + var handler = FrameNavigationStarting; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameNavigationStarting(IWebViewControl sender, Windows.Web.UI.WebViewControlNavigationStartingEventArgs args) => OnFrameNavigationStarting(args); + + private void OnLongRunningScriptDetected(WebViewControlLongRunningScriptDetectedEventArgs args) + { + var handler = LongRunningScriptDetected; + if (handler != null) + { + handler(this, args); + } + } + + private void OnLongRunningScriptDetected(IWebViewControl sender, Windows.Web.UI.WebViewControlLongRunningScriptDetectedEventArgs args) => OnLongRunningScriptDetected(args); + + private void OnMoveFocusRequested(WebViewControlMoveFocusRequestedEventArgs args) + { + var handler = MoveFocusRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnMoveFocusRequested(WebViewControl sender, Windows.Web.UI.Interop.WebViewControlMoveFocusRequestedEventArgs args) => OnMoveFocusRequested(args); + + private void OnNavigationCompleted(WebViewControlNavigationCompletedEventArgs args) + { + // We could have used + // if (NavigationCompleted != null) NavigationCompleted(this, args); + // However, if there is a subscriber and the moment the null check and the call to + // the event handler by the method is invoked, the subscriber may unsubscribe + // (e.g. on a different thread) and cause a NullReferenceException. + // To work around this create a temporarily local variable to store the reference and check that + var handler = NavigationCompleted; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNavigationCompleted(IWebViewControl sender, Windows.Web.UI.WebViewControlNavigationCompletedEventArgs args) + { + // When Source set to null or navigating to stream/string, we navigate to "about:blank" internally. + if (NavigatingToAboutBlank) + { + Verify.Implies(NavigatingToAboutBlank, Source == null || Source == WebViewDefaults.AboutBlankUri); + + // Make sure we pass null in the event args + var a = new WebViewControlNavigationCompletedEventArgs(args, null); + OnNavigationCompleted(a); + } + else + { + OnNavigationCompleted(args); + } + } + + private void OnNavigationStarting(WebViewControlNavigationStartingEventArgs args) + { + var handler = NavigationStarting; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNavigationStarting(IWebViewControl sender, Windows.Web.UI.WebViewControlNavigationStartingEventArgs args) + { + var newNavigationRequested = false; + var cancelRequested = false; + + try + { + var url = args.Uri; + + // The NavigatingToAboutBlank property indicates whether we are navigating to "about:blank" as a result of navigating + // to a null source, or stream/string navigation. + // We set the NavigatingToAboutBlank bit to true in the void Navigate(Uri) method. When the above conditions are true, + // the NavigatingToAboutBlank is true and the source must be "about:blank" + if (NavigatingToAboutBlank && url != null && url != new Uri("about:blank")) + { + NavigatingToAboutBlank = false; + } + + if (!NavigatingToAboutBlank && !Security.CallerHasWebPermission(url)) + { + cancelRequested = true; + } + else + { + // When Source is set to null or navigating to stream/string, we navigate to "about:blank" internally. + // Make sure we pass null in the event args + if (NavigatingToAboutBlank) + { + url = null; + } + + var a = new WebViewControlNavigationStartingEventArgs(args, url); + + // Launching a navigation from the NavigationStarting event handler causes re-entrancy + var lastNavigation = LastNavigation; + + // Fire navigating event + OnNavigationStarting(a); + + if (LastNavigation != lastNavigation) + { + newNavigationRequested = true; + } + + cancelRequested = a.Cancel; + } + } + + // Disable to suppress FXCop warning since we really do want to catch all exceptions +#pragma warning disable 6502 + catch + { + cancelRequested = true; + } +#pragma warning restore 6502 + finally + { + if (cancelRequested && !newNavigationRequested) + { + CleanInternalState(); + } + + if (cancelRequested || newNavigationRequested) + { + args.Cancel = true; + } + } + } + + private void OnNewWindowRequested(WebViewControlNewWindowRequestedEventArgs args) + { + var handler = NewWindowRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNewWindowRequested(IWebViewControl sender, Windows.Web.UI.WebViewControlNewWindowRequestedEventArgs args) => OnNewWindowRequested(args); + + private void OnOnScriptNotify(IWebViewControl sender, Windows.Web.UI.WebViewControlScriptNotifyEventArgs args) => OnScriptNotify(args); + + private void OnPermissionRequested(WebViewControlPermissionRequestedEventArgs args) + { + var handler = PermissionRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnPermissionRequested(IWebViewControl sender, Windows.Web.UI.WebViewControlPermissionRequestedEventArgs args) => OnPermissionRequested(args); + + private void OnProcessExited(object sender, object e) + { + _webViewControlClosed = true; + Close(); + } + + private void OnScriptNotify(WebViewControlScriptNotifyEventArgs args) + { + var handler = ScriptNotify; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnsafeContentWarningDisplaying(object args) + { + var handler = UnsafeContentWarningDisplaying; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnsafeContentWarningDisplaying(IWebViewControl sender, object args) => OnUnsafeContentWarningDisplaying(args); + + private void OnUnsupportedUriSchemeIdentified(WebViewControlUnsupportedUriSchemeIdentifiedEventArgs args) + { + var handler = UnsupportedUriSchemeIdentified; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnsupportedUriSchemeIdentified(IWebViewControl sender, Windows.Web.UI.WebViewControlUnsupportedUriSchemeIdentifiedEventArgs args) => OnUnsupportedUriSchemeIdentified(args); + + private void OnUnviewableContentIdentified(WebViewControlUnviewableContentIdentifiedEventArgs args) + { + var handler = UnviewableContentIdentified; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnviewableContentIdentified(IWebViewControl sender, Windows.Web.UI.WebViewControlUnviewableContentIdentifiedEventArgs args) => OnUnviewableContentIdentified(args); + + [SecurityCritical] + private void SubscribeEvents() + { + if (_webViewControl == null) + { + return; + } + + _webViewControl.AcceleratorKeyPressed += OnAcceleratorKeyPressed; + _webViewControl.ContainsFullScreenElementChanged += OnContainsFullScreenElementChanged; + _webViewControl.ContentLoading += OnContentLoading; + _webViewControl.DOMContentLoaded += OnDOMContentLoaded; + _webViewControl.FrameContentLoading += OnFrameContentLoading; + _webViewControl.FrameDOMContentLoaded += OnFrameDOMContentLoaded; + _webViewControl.FrameNavigationCompleted += OnFrameNavigationCompleted; + _webViewControl.FrameNavigationStarting += OnFrameNavigationStarting; + _webViewControl.LongRunningScriptDetected += OnLongRunningScriptDetected; + _webViewControl.MoveFocusRequested += OnMoveFocusRequested; + _webViewControl.NavigationCompleted += OnNavigationCompleted; + _webViewControl.NavigationStarting += OnNavigationStarting; + _webViewControl.NewWindowRequested += OnNewWindowRequested; + _webViewControl.PermissionRequested += OnPermissionRequested; + _webViewControl.ScriptNotify += OnOnScriptNotify; + _webViewControl.UnsafeContentWarningDisplaying += OnUnsafeContentWarningDisplaying; + _webViewControl.UnsupportedUriSchemeIdentified += OnUnsupportedUriSchemeIdentified; + _webViewControl.UnviewableContentIdentified += OnUnviewableContentIdentified; + } + + [SecurityCritical] + private void SubscribeProcessExited() + { + if (Process == null) + { + return; + } + + Process.ProcessExited += OnProcessExited; + } + + private void UnsubscribeEvents() + { + if (_webViewControl == null) + { + return; + } + + _webViewControl.AcceleratorKeyPressed -= OnAcceleratorKeyPressed; + _webViewControl.ContainsFullScreenElementChanged -= OnContainsFullScreenElementChanged; + _webViewControl.ContentLoading -= OnContentLoading; + _webViewControl.DOMContentLoaded -= OnDOMContentLoaded; + _webViewControl.FrameContentLoading -= OnFrameContentLoading; + _webViewControl.FrameDOMContentLoaded -= OnFrameDOMContentLoaded; + _webViewControl.FrameNavigationCompleted -= OnFrameNavigationCompleted; + _webViewControl.FrameNavigationStarting -= OnFrameNavigationStarting; + _webViewControl.LongRunningScriptDetected -= OnLongRunningScriptDetected; + _webViewControl.MoveFocusRequested -= OnMoveFocusRequested; + _webViewControl.NavigationCompleted -= OnNavigationCompleted; + _webViewControl.NavigationStarting -= OnNavigationStarting; + _webViewControl.NewWindowRequested -= OnNewWindowRequested; + _webViewControl.PermissionRequested -= OnPermissionRequested; + _webViewControl.ScriptNotify -= OnOnScriptNotify; + _webViewControl.UnsafeContentWarningDisplaying -= OnUnsafeContentWarningDisplaying; + _webViewControl.UnsupportedUriSchemeIdentified -= OnUnsupportedUriSchemeIdentified; + _webViewControl.UnviewableContentIdentified -= OnUnviewableContentIdentified; + } + + private void UnsubscribeProcessExited() + { + if (Process == null) + { + return; + } + + try + { + Process.ProcessExited -= OnProcessExited; + } + catch (Exception) + { + // Yes, really catch all + // 'The process terminated unexpectedly. (Exception from HRESULT: 0x8007042B)' + } + } + + // TODO: Expose Bounds + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlLongRunningScriptDetectedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlLongRunningScriptDetectedEventArgs.cs new file mode 100644 index 000000000..1efc95f8f --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlLongRunningScriptDetectedEventArgs.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the event. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + public sealed class WebViewControlLongRunningScriptDetectedEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlLongRunningScriptDetectedEventArgs _args; + + internal WebViewControlLongRunningScriptDetectedEventArgs(Windows.Web.UI.WebViewControlLongRunningScriptDetectedEventArgs args) + { + _args = args ?? throw new ArgumentNullException(nameof(args)); + } + + /// + /// Gets the amount of time that the has been executing a long-running script. + /// + /// The execution time of a long-running script. + public TimeSpan ExecutionTime => _args.ExecutionTime; + + /// + /// Gets or sets a value indicating whether a long-running script executing in a should halt. + /// + /// if the long-running script should halt; otherwise, . + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "StopPage", Justification = "Name from WinRT type")] + public bool StopPageScriptExecution + { + get => _args.StopPageScriptExecution; + set => _args.StopPageScriptExecution = value; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlLongRunningScriptDetectedEventArgs(Windows.Web.UI.WebViewControlLongRunningScriptDetectedEventArgs args) => ToWebViewControlLongRunningScriptDetectedEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// WebViewControlLongRunningScriptDetectedEventArgs. + public static WebViewControlLongRunningScriptDetectedEventArgs + ToWebViewControlLongRunningScriptDetectedEventArgs( + Windows.Web.UI.WebViewControlLongRunningScriptDetectedEventArgs args) => + new WebViewControlLongRunningScriptDetectedEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlMoveFocusReason.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlMoveFocusReason.cs new file mode 100644 index 000000000..1ccbca5bc --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlMoveFocusReason.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// An enum that describes the reason for moving the focus. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + public enum WebViewControlMoveFocusReason + { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + Programmatic, + Next, + Previous, +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlMoveFocusRequestedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlMoveFocusRequestedEventArgs.cs new file mode 100644 index 000000000..3ed1299c1 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlMoveFocusRequestedEventArgs.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the event. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + public sealed class WebViewControlMoveFocusRequestedEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.Interop.WebViewControlMoveFocusRequestedEventArgs _args; + + internal WebViewControlMoveFocusRequestedEventArgs(Windows.Web.UI.Interop.WebViewControlMoveFocusRequestedEventArgs args) + { + _args = args ?? throw new ArgumentNullException(nameof(args)); + } + + /// + /// Gets the move focus reason. + /// + /// The move focus reason + public WebViewControlMoveFocusReason Reason => (WebViewControlMoveFocusReason)_args.Reason; + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlMoveFocusRequestedEventArgs(Windows.Web.UI.Interop.WebViewControlMoveFocusRequestedEventArgs args) => ToWebViewControlMoveFocusRequestedEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// + public static WebViewControlMoveFocusRequestedEventArgs ToWebViewControlMoveFocusRequestedEventArgs( + Windows.Web.UI.Interop.WebViewControlMoveFocusRequestedEventArgs args) => + new WebViewControlMoveFocusRequestedEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNavigationCompletedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNavigationCompletedEventArgs.cs new file mode 100644 index 000000000..1602de338 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNavigationCompletedEventArgs.cs @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the and events. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + public sealed class WebViewControlNavigationCompletedEventArgs : EventArgs + { + internal WebViewControlNavigationCompletedEventArgs(Windows.Web.UI.WebViewControlNavigationCompletedEventArgs args) + { + IsSuccess = args.IsSuccess; + Uri = args.Uri; + WebErrorStatus = (WebErrorStatus)args.WebErrorStatus; + } + + internal WebViewControlNavigationCompletedEventArgs(Windows.Web.UI.WebViewControlNavigationCompletedEventArgs args, Uri uri) + : this(args) + { + Uri = uri; + } + + /// + /// Gets a value indicating whether the navigation completed successfully. + /// + /// if the navigation completed successfully; otherwise, . + public bool IsSuccess { get; } + + /// + /// Gets the Uniform Resource Identifier (URI) of the navigated content. + /// + /// The URI. + public Uri Uri { get; } + + /// + /// Gets the reason the navigation was successful. + /// + /// The web error status. + /// + public WebErrorStatus WebErrorStatus { get; } + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlNavigationCompletedEventArgs(Windows.Web.UI.WebViewControlNavigationCompletedEventArgs args) => ToWebViewControlNavigationCompletedEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// + public static WebViewControlNavigationCompletedEventArgs ToWebViewControlNavigationCompletedEventArgs( + Windows.Web.UI.WebViewControlNavigationCompletedEventArgs args) => + new WebViewControlNavigationCompletedEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNavigationStartingEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNavigationStartingEventArgs.cs new file mode 100644 index 000000000..1e4f35d5b --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNavigationStartingEventArgs.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the and events. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + public sealed class WebViewControlNavigationStartingEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlNavigationStartingEventArgs _args; + + [SecurityCritical] + internal WebViewControlNavigationStartingEventArgs(Windows.Web.UI.WebViewControlNavigationStartingEventArgs args) + { + _args = args; + Uri = args.Uri; + } + + [SecurityCritical] + internal WebViewControlNavigationStartingEventArgs(Windows.Web.UI.WebViewControlNavigationStartingEventArgs args, Uri uri) + : this(args) + { + Uri = uri; + } + + /// + /// Gets or sets a value indicating whether to cancel the navigation. + /// + /// if cancel; otherwise, . + public bool Cancel + { + [SecurityCritical] + get => _args.Cancel; + [SecurityCritical] + set => _args.Cancel = value; + } + + /// + /// Gets the Uniform Resource Identifier (URI) of the content the is loading. + /// + /// The Uniform Resource Identifier (URI) of the content the is loading. + public Uri Uri { get; } + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlNavigationStartingEventArgs(Windows.Web.UI.WebViewControlNavigationStartingEventArgs args) => ToWebViewControlNavigationStartingEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// . + public static WebViewControlNavigationStartingEventArgs ToWebViewControlNavigationStartingEventArgs( + Windows.Web.UI.WebViewControlNavigationStartingEventArgs args) => + new WebViewControlNavigationStartingEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNewWindowRequestedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNewWindowRequestedEventArgs.cs new file mode 100644 index 000000000..4446e173e --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlNewWindowRequestedEventArgs.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the event. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + public sealed class WebViewControlNewWindowRequestedEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlNewWindowRequestedEventArgs _args; + + internal WebViewControlNewWindowRequestedEventArgs(Windows.Web.UI.WebViewControlNewWindowRequestedEventArgs args) + { + _args = args ?? throw new ArgumentNullException(nameof(args)); + } + + /// + /// Gets the Uniform Resource Identifier (URI) of the content the is attempting to navigate to. + /// + /// The Uniform Resource Identifier (URI) of the content the is attempting to navigate to. + public Uri Uri => _args.Uri; + + /// + /// Gets the Uniform Resource Identifier (URI) of the content where the navigation was initiated. + /// + /// The the Uniform Resource Identifier (URI) of the content where the navigation was initiated. + public Uri Referrer => _args.Referrer; + + /// + /// Gets or sets a value indicating whether the routed event is handled. + /// + /// if handled; otherwise, . + public bool Handled + { + get => _args.Handled; + set => _args.Handled = value; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlNewWindowRequestedEventArgs(Windows.Web.UI.WebViewControlNewWindowRequestedEventArgs args) => ToWebViewControlNewWindowRequestedEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// + public static WebViewControlNewWindowRequestedEventArgs ToWebViewControlNewWindowRequestedEventArgs( + Windows.Web.UI.WebViewControlNewWindowRequestedEventArgs args) => + new WebViewControlNewWindowRequestedEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionRequest.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionRequest.cs new file mode 100644 index 000000000..8eb49220a --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionRequest.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Represents a request for permissions in an . This class cannot be inherited. + /// + /// + ///

Copy from to avoid requirement to link Windows.winmd.

+ ///

For more info, see the event.

+ ///
+ /// + public sealed class WebViewControlPermissionRequest + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlPermissionRequest _permissionRequest; + + internal WebViewControlPermissionRequest(Windows.Web.UI.WebViewControlPermissionRequest permissionRequest) + { + _permissionRequest = permissionRequest ?? throw new ArgumentNullException(nameof(permissionRequest)); + } + + /// + /// Gets the identifier for the permission request. + /// + /// The permission request identifier. + public uint Id => _permissionRequest?.Id ?? 0U; + + /// + /// Gets the type of the permission that's requested. + /// + /// The type of the permission that's requested. + public WebViewControlPermissionType PermissionType => (WebViewControlPermissionType)_permissionRequest.PermissionType; + + /// + /// Gets the current state of the permission request. + /// + /// The current state of the permission request. + public WebViewControlPermissionState State => (WebViewControlPermissionState)_permissionRequest.State; + + /// + /// Gets the Uniform Resource Identifier (URI) of the content where the permission request originated. + /// + /// The Uniform Resource Identifier (URI) of the content where the permission request originated. + public Uri Uri => _permissionRequest.Uri; + + /// + /// Performs an implicit conversion from to . + /// + /// The permission request. + /// The result of the conversion. + public static implicit operator WebViewControlPermissionRequest(Windows.Web.UI.WebViewControlPermissionRequest args) => ToWebViewControlPermissionRequest(args); + + /// + /// Creates a from . + /// + /// The . + /// + public static WebViewControlPermissionRequest ToWebViewControlPermissionRequest( + Windows.Web.UI.WebViewControlPermissionRequest args) => new WebViewControlPermissionRequest(args); + + /// + /// Grants the requested permission. + /// + public void Allow() + { + _permissionRequest?.Allow(); + } + + /// + /// Defers the permission request to be allowed or denied at a later time. + /// + /// + public void Defer() + { + _permissionRequest?.Defer(); + } + + /// + /// Denies the requested permission. + /// + public void Deny() + { + _permissionRequest?.Deny(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionRequestedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionRequestedEventArgs.cs new file mode 100644 index 000000000..68bcf3765 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionRequestedEventArgs.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the event. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + public sealed class WebViewControlPermissionRequestedEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlPermissionRequestedEventArgs _args; + + internal WebViewControlPermissionRequestedEventArgs(Windows.Web.UI.WebViewControlPermissionRequestedEventArgs args) + { + _args = args; + } + + /// + /// Gets the object that contains information about the request. + /// + /// The permission request. + public WebViewControlPermissionRequest PermissionRequest => _args.PermissionRequest; + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlPermissionRequestedEventArgs(Windows.Web.UI.WebViewControlPermissionRequestedEventArgs args) => ToWebViewControlPermissionRequestedEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// + public static WebViewControlPermissionRequestedEventArgs ToWebViewControlPermissionRequestedEventArgs( + Windows.Web.UI.WebViewControlPermissionRequestedEventArgs args) => + new WebViewControlPermissionRequestedEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionState.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionState.cs new file mode 100644 index 000000000..b288feb32 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionState.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + // Type is a copy. Information regarding the origination of the type is in summary comments +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + /// + /// Defines constants that specify the state of a event. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + public enum WebViewControlPermissionState + { + Unknown, + Defer, + Allow, + Deny, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionType.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionType.cs new file mode 100644 index 000000000..e59d68b45 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlPermissionType.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Defines constants that specify the state of a event. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + public enum WebViewControlPermissionType + { + /// + /// Permission is for geolocation. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Geolocation", Justification = "Value from WinRT type")] + Geolocation, + + /// + /// Permission is for unlimited IndexedDB data storage. + /// + UnlimitedIndexedDBQuota, + + /// + /// Permission is for media. + /// + Media, + + /// + /// Permission is for pointer lock. + /// + PointerLock, + + /// + /// Permission is for web notifications. + /// + WebNotifications, + + /// + /// Permission is for screen. + /// + Screen, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcess.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcess.cs new file mode 100644 index 000000000..efe78d1ca --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcess.cs @@ -0,0 +1,142 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; +using System.Threading.Tasks; + +using Windows.Foundation; +using Windows.Web.UI.Interop; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// A proxy for . + /// + public class WebViewControlProcess + { + [SecurityCritical] + private readonly Windows.Web.UI.Interop.WebViewControlProcess _process; + + /// + /// Initializes a new instance of the class. + /// + public WebViewControlProcess() + : this(new WebViewControlProcessOptions()) + { + } + + /// + /// Initializes a new instance of the class with the specified . + /// + /// The process options. + public WebViewControlProcess(WebViewControlProcessOptions processOptions) + : this(new Windows.Web.UI.Interop.WebViewControlProcess(processOptions.ToWinRtWebViewControlProcessOptions())) + { + } + + private WebViewControlProcess(Windows.Web.UI.Interop.WebViewControlProcess process) + { + _process = process ?? throw new ArgumentNullException(nameof(process)); + SubscribeEvents(); + } + + /// + /// Occurs when the underlying WWAHost process exits. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Justification ="This is the declaration from WinRT")] + public event EventHandler ProcessExited = (sender, args) => { }; + + /// + /// Gets the enterprise identifier. + /// + /// The enterprise identifier. + public string EnterpriseId => _process.EnterpriseId; + + /// + /// Gets a value indicating whether this instance is private network client server capability enabled. + /// + /// true if this instance can access the private network; otherwise, false. + public bool IsPrivateNetworkClientServerCapabilityEnabled => _process.IsPrivateNetworkClientServerCapabilityEnabled; + + /// + /// Gets the process identifier (PID) of the underlying WWAHost. + /// + /// The process identifier (PID). + public uint ProcessId => _process.ProcessId; + + /// + /// Performs an implicit conversion from to . + /// + /// The process. + /// The result of the conversion. + public static implicit operator WebViewControlProcess(Windows.Web.UI.Interop.WebViewControlProcess process) => ToWebViewControlProcess(process); + + /// + /// Creates a from . + /// + /// The instance. + /// + public static WebViewControlProcess ToWebViewControlProcess( + Windows.Web.UI.Interop.WebViewControlProcess process) => new WebViewControlProcess(process); + + /// + /// Terminates the underlying WWAHost process. + /// + public void Terminate() => _process.Terminate(); + + internal async Task CreateWebViewControlHostAsync(IntPtr hostWindowHandle, Rect bounds) + { + if (hostWindowHandle == IntPtr.Zero) + { + throw new ArgumentNullException(nameof(hostWindowHandle)); + } + + var wvc = await await Task.Run(() => CreateWebViewControlAsync(hostWindowHandle, bounds)).ConfigureAwait(false); + + return new WebViewControlHost(wvc); + } + + private IAsyncOperation CreateWebViewControlAsync( + IntPtr hostWindowHandle, + Rect bounds) + { + var hwh = hostWindowHandle.ToInt64(); + return CreateWebViewControlAsync(hwh, bounds); + } + + [SecurityCritical] + private IAsyncOperation CreateWebViewControlAsync( + long hostWindowHandle, + Rect bounds) + { + Security.DemandUnmanagedCode(); + if (hostWindowHandle == 0) + { + throw new ArgumentNullException(nameof(hostWindowHandle)); + } + + return _process.CreateWebViewControlAsync(hostWindowHandle, bounds); + } + + private void OnWebViewControlProcessExited(Windows.Web.UI.Interop.WebViewControlProcess sender, object args) + { + var handler = ProcessExited; + if (handler != null) + { + handler(this, args); + } + } + + private void SubscribeEvents() + { + _process.ProcessExited += OnWebViewControlProcessExited; + } + + private void UnsubscribeEvents() + { + _process.ProcessExited -= OnWebViewControlProcessExited; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcessCapabilityState.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcessCapabilityState.cs new file mode 100644 index 000000000..3d66f68cd --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcessCapabilityState.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Represents the state of the . + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + public enum WebViewControlProcessCapabilityState + { + /// + /// The process is in an unknown state. + /// + Default, + + /// + /// The process is disabled. + /// + Disabled, + + /// + /// The process is enabled. + /// + Enabled, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcessOptions.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcessOptions.cs new file mode 100644 index 000000000..6a7ccddf4 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlProcessOptions.cs @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// This class contains options that can be set when creating a instance. + /// + /// + /// Copy from to avoid requirement to link Windows.winmd. + /// + /// + public class WebViewControlProcessOptions + { + /// + /// Gets or sets the enterprise identifier for apps that are WIP-enabled. + /// + /// The enterprise identifier. + public string EnterpriseId { get; set; } + + /// + /// Gets or sets the private network client server capability. + /// + /// The private network client server capability. + public WebViewControlProcessCapabilityState PrivateNetworkClientServerCapability { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public WebViewControlProcessOptions() + { + EnterpriseId = string.Empty; + PrivateNetworkClientServerCapability = WebViewControlProcessCapabilityState.Default; + } + + /// + /// Converts this instance to a instance. + /// + /// A instance. + internal Windows.Web.UI.Interop.WebViewControlProcessOptions ToWinRtWebViewControlProcessOptions() + { + var retval = new Windows.Web.UI.Interop.WebViewControlProcessOptions(); + + if (!string.IsNullOrEmpty(EnterpriseId) && !StringComparer.InvariantCulture.Equals(retval.EnterpriseId, EnterpriseId)) + { + retval.EnterpriseId = EnterpriseId; + } + + retval.PrivateNetworkClientServerCapability = (Windows.Web.UI.Interop.WebViewControlProcessCapabilityState)PrivateNetworkClientServerCapability; + + return retval; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlScriptNotifyEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlScriptNotifyEventArgs.cs new file mode 100644 index 000000000..4228941da --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlScriptNotifyEventArgs.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the event. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + public sealed class WebViewControlScriptNotifyEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlScriptNotifyEventArgs _args; + + internal WebViewControlScriptNotifyEventArgs(Windows.Web.UI.WebViewControlScriptNotifyEventArgs args) + { + _args = args; + } + + /// + /// Gets the Uniform Resource Identifier (URI) that originated the event. + /// + /// The Uniform Resource Identifier (URI). + public Uri Uri => _args.Uri; + + /// + /// Gets the string value passed to the app. + /// + /// The string value passed to the app. + public string Value => _args.Value; + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlScriptNotifyEventArgs(Windows.Web.UI.WebViewControlScriptNotifyEventArgs args) => ToWebViewControlScriptNotifyEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// + public static WebViewControlScriptNotifyEventArgs ToWebViewControlScriptNotifyEventArgs( + Windows.Web.UI.WebViewControlScriptNotifyEventArgs args) => new WebViewControlScriptNotifyEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlSettings.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlSettings.cs new file mode 100644 index 000000000..caf965dd2 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlSettings.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// A proxy for . This class cannot be inherited. + /// + /// + public sealed class WebViewControlSettings + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlSettings _settings; + + internal WebViewControlSettings(Windows.Web.UI.WebViewControlSettings settings) + { + _settings = settings ?? throw new ArgumentNullException(nameof(settings)); + } + + /// + /// Gets or sets a value indicating whether the use of IndexedDB is allowed. + /// + /// true if IndexedDB is allowed; otherwise, false. The default is true. + public bool IsIndexedDBEnabled + { + get => _settings.IsIndexedDBEnabled; + set => _settings.IsIndexedDBEnabled = value; + } + + /// + /// Gets or sets a value indicating whether the use of JavaScript is allowed. + /// + /// true if JavaScript is allowed in the ; otherwise, false. The default is true. + public bool IsJavaScriptEnabled + { + get => _settings.IsJavaScriptEnabled; + set => _settings.IsJavaScriptEnabled = value; + } + + /// + /// Gets or sets a value indicating whether is allowed. + /// + /// Whether is allowed. + public bool IsScriptNotifyAllowed + { + get => _settings.IsScriptNotifyAllowed; + set => _settings.IsScriptNotifyAllowed = value; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The settings. + /// The result of the conversion. + public static implicit operator WebViewControlSettings(Windows.Web.UI.WebViewControlSettings settings) => ToWebViewControlSettings(settings); + + /// + /// Creates a from . + /// + /// The settings. + /// + public static WebViewControlSettings ToWebViewControlSettings(Windows.Web.UI.WebViewControlSettings settings) => + new WebViewControlSettings(settings); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlUnsupportedUriSchemeIdentifiedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlUnsupportedUriSchemeIdentifiedEventArgs.cs new file mode 100644 index 000000000..d1f60fc25 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlUnsupportedUriSchemeIdentifiedEventArgs.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// Provides data for the event. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + public sealed class WebViewControlUnsupportedUriSchemeIdentifiedEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlUnsupportedUriSchemeIdentifiedEventArgs _args; + + internal WebViewControlUnsupportedUriSchemeIdentifiedEventArgs(Windows.Web.UI.WebViewControlUnsupportedUriSchemeIdentifiedEventArgs args) + { + _args = args ?? throw new ArgumentNullException(nameof(args)); + } + + /// + /// Gets or sets a value indicating whether the routed event is handled. A value for Handled prevents other handlers along the event route from handling the same event again. + /// + /// to mark the routed event handled. to leave the routed event unhandled, which permits the event to potentially route further and be acted on by other handlers. The default is . + public bool Handled + { + get => _args.Handled; + set => _args.Handled = value; + } + + /// + /// Gets the Uniform Resource Identifier (URI) of the content the attempted to navigate to. + /// + /// The Uniform Resource Identifier (URI) of the content. + public Uri Uri => _args.Uri; + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlUnsupportedUriSchemeIdentifiedEventArgs(Windows.Web.UI.WebViewControlUnsupportedUriSchemeIdentifiedEventArgs args) => ToWebViewControlUnsupportedUriSchemeIdentifiedEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// + public static WebViewControlUnsupportedUriSchemeIdentifiedEventArgs ToWebViewControlUnsupportedUriSchemeIdentifiedEventArgs( + Windows.Web.UI.WebViewControlUnsupportedUriSchemeIdentifiedEventArgs args) => + new WebViewControlUnsupportedUriSchemeIdentifiedEventArgs(args); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlUnviewableContentIdentifiedEventArgs.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlUnviewableContentIdentifiedEventArgs.cs new file mode 100644 index 000000000..ff97f04de --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewControlUnviewableContentIdentifiedEventArgs.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + /// + /// CProvides data for the event. This class cannot be inherited. + /// + /// Copy from to avoid requirement to link Windows.winmd + /// + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unviewable", Justification = "Same as WinRT type")] + public sealed class WebViewControlUnviewableContentIdentifiedEventArgs : EventArgs + { + [SecurityCritical] + private readonly Windows.Web.UI.WebViewControlUnviewableContentIdentifiedEventArgs _args; + + internal WebViewControlUnviewableContentIdentifiedEventArgs(Windows.Web.UI.WebViewControlUnviewableContentIdentifiedEventArgs args) + { + _args = args ?? throw new ArgumentNullException(nameof(args)); + } + + /// + /// Gets the Uniform Resource Identifier (URI) of the content the attempted to load. + /// + /// The URI. + public Uri Uri => _args.Uri; + + /// + /// Gets the Uniform Resource Identifier (URI) of the page that contains the link to the unviewable content. + /// + /// The referrer. + public Uri Referrer => _args.Referrer; + + /// + /// Gets the media type of the content that cannot be viewed. + /// + /// The type of the media. + public string MediaType => _args.MediaType; + + /// + /// Performs an implicit conversion from to . + /// + /// The instance containing the event data. + /// The result of the conversion. + public static implicit operator WebViewControlUnviewableContentIdentifiedEventArgs(Windows.Web.UI.WebViewControlUnviewableContentIdentifiedEventArgs args) => ToWebViewControlUnviewableContentIdentifiedEventArgs(args); + + /// + /// Creates a from . + /// + /// The instance containing the event data. + /// + public static WebViewControlUnviewableContentIdentifiedEventArgs + ToWebViewControlUnviewableContentIdentifiedEventArgs( + Windows.Web.UI.WebViewControlUnviewableContentIdentifiedEventArgs args) => + new WebViewControlUnviewableContentIdentifiedEventArgs(args); + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewDefaults.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewDefaults.cs new file mode 100644 index 000000000..60a29f29a --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WinRT/WebViewDefaults.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT +{ + internal static class WebViewDefaults + { + public const string AboutBlank = "about:blank"; + public const string EnterpriseId = ""; + public const bool IsIndexedDBEnabled = true; + public const bool IsJavaScriptEnabled = true; + public const bool IsPrivateNetworkEnabled = false; + public const bool IsScriptNotifyEnabled = false; + public static readonly Uri AboutBlankUri = new Uri(AboutBlank); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Windows10Release.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Windows10Release.cs new file mode 100644 index 000000000..a8c4ba611 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/Windows10Release.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop +{ + /// + /// Identifies Windows 10 release IDs + /// + internal enum Windows10Release + { + /// + /// Unknown + /// + Unknown = 0, + + /// + /// 10.0.10240.0 + /// + Threshold1 = 1507, + + /// + /// 10.0.10586 + /// + Threshold2 = 1511, + + /// + /// 10.0.14393.0 (Redstone 1) + /// + Anniversary = 1607, + + /// + /// 10.0.15063.0 (Redstone 2) + /// + Creators = 1703, + + /// + /// 10.0.16299.0 (Redstone 3) + /// + FallCreators = 1709, + + /// + /// 10.0.17134.0 (Redstone 4) + /// + April2018 = 1803, + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WindowsVersions.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WindowsVersions.cs new file mode 100644 index 000000000..7c6653d82 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Interop/WindowsVersions.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Interop +{ + internal enum WindowsVersions + { + Win7, + Server2008R2, // 6.1 + Win8, + Server2012, // 6.2 + Win81, + Server2012R2, // 6.3 + Win10, + Server2016, // 10.0 + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Microsoft.Toolkit.Win32.UI.Controls.csproj b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Microsoft.Toolkit.Win32.UI.Controls.csproj new file mode 100644 index 000000000..608bde06a --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Microsoft.Toolkit.Win32.UI.Controls.csproj @@ -0,0 +1,77 @@ + + + + net462 + Microsoft.Toolkit.Win32.UI.Controls + Microsoft.Toolkit.Win32.UI.Controls + false + true + + Windows Community Toolkit Win32 Controls + This library provides XAML user controls for Win32. It is part of the Windows Community Toolkit. + WebView Win32 WPF WindowsForms + + + + 10.0.17110.0 + + 10.0.17134.0 + + + + TRACE;DEBUG;CODE_ANALYSIS;NET47;DEV_DEBUG;DEBUG_LAYOUT + + + + + + + + + + + + + + 4.0.0 + + + + + + DesignerUI.resx + True + True + + + Component + WebView.cs + + + Component + + + Component + WebView.cs + + + Component + WebView.cs + + + Component + WebView.cs + + + + + + DesignerUI.Designer.cs + ResXFileCodeGenerator + + + + + + + diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Properties/AssemblyInfo.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..2708b152d --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Properties/AssemblyInfo.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Windows Community Toolkit Controls for Windows Forms and WPF")] +[assembly: AssemblyDescription("Wndows Forms and WPF controls for Windows Community Toolkit")] + +// Make sure this is the same in the VisualToolsManifest.xml file +[assembly: AssemblyProduct("Windows Community Toolkit")] +[assembly: AssemblyCopyright("\x00a9 Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyCompany("Microsoft Corporation")] + +[assembly: ComVisible(false)] +[assembly: NeutralResourcesLanguage("en-US")] +#if DEBUG +[assembly: AssemblyConfiguration("Debug")] +#else +[assembly: AssemblyConfiguration("Release")] +#endif + +// Dependencies + +// Common +[assembly: Dependency("System", LoadHint.Always)] +[assembly: Dependency("System.Core", LoadHint.Always)] +[assembly: Dependency("System.Xml", LoadHint.Always)] + +// WinForms +[assembly: Dependency("System.Windows.Forms", LoadHint.Sometimes)] + +[assembly: Dependency("System.Drawing", LoadHint.Sometimes)] +[assembly: Dependency("System.Configuration", LoadHint.Sometimes)] + +[assembly: Dependency("Windows.Web.winmd", LoadHint.Sometimes)] +[assembly: Dependency("System.Runtime.InteropServices.WindowsRuntime", LoadHint.Sometimes)] +[assembly: Dependency("Windows.Foundation.winmd", LoadHint.Sometimes)] +[assembly: Dependency("System.Runtime.WindowsRuntime", LoadHint.Sometimes)] +[assembly: Dependency("System.Runtime", LoadHint.Sometimes)] + +// WPF +[assembly: Dependency("PresentationFramework", LoadHint.Sometimes)] +[assembly: Dependency("PresentationCore", LoadHint.Sometimes)] +[assembly: Dependency("WindowsBase", LoadHint.Sometimes)] +[assembly: Dependency("System.Xaml", LoadHint.Sometimes)] +[assembly: Dependency("System.Configuration", LoadHint.Sometimes)] +[assembly: Dependency("PresentationFramework.Aero2", LoadHint.Sometimes)] +[assembly: Dependency("Windows.Foundation.winmd", LoadHint.Sometimes)] +[assembly: Dependency("Windows.Web.winmd", LoadHint.Sometimes)] +[assembly: Dependency("System.Runtime.InteropServices.WindowsRuntime", LoadHint.Sometimes)] +[assembly: Dependency("System.Runtime.Serialization", LoadHint.Sometimes)] +[assembly: Dependency("SMDiagnostics", LoadHint.Sometimes)] +[assembly: Dependency("System.ServiceModel.Internals", LoadHint.Sometimes)] +[assembly: Dependency("System.Runtime.WindowsRuntime", LoadHint.Sometimes)] +[assembly: Dependency("UIAutomationProvider", LoadHint.Sometimes)] +[assembly: Dependency("System.Windows.Forms", LoadHint.Sometimes)] +[assembly: Dependency("System.Drawing", LoadHint.Sometimes)] +[assembly: Dependency("System.Runtime", LoadHint.Sometimes)] +[assembly: Dependency("Windows.Globalization.winmd", LoadHint.Sometimes)] +[assembly: Dependency("Windows.Storage.winmd", LoadHint.Sometimes)] + +// InternalsVisableTo +[assembly: InternalsVisibleTo("Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView")] +[assembly: InternalsVisibleTo("Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared")] + +[assembly: SecurityRules(SecurityRuleSet.Level2)] +#if ALLOW_PARTIALLY_TRUSTED_CALLERS +[assembly: System.Security.AllowPartiallyTrustedCallers] +#endif diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Properties/launchSettings.json b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Properties/launchSettings.json new file mode 100644 index 000000000..e7afb3574 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Microsoft.Toolkit.Win32.UI.Controls": { + "commandName": "Executable", + "executablePath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\Common7\\IDE\\devenv.exe" + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Security.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Security.cs new file mode 100644 index 000000000..d2dc846db --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Security.cs @@ -0,0 +1,115 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Net; +using System.Security; +using System.Security.Permissions; + +namespace Microsoft.Toolkit.Win32.UI.Controls +{ + internal static class Security + { + private static SecurityPermission _unmanagedCodePermission; + + private static WebBrowserPermission _webBrowserPermission; + + internal static WebBrowserPermission CachedWebBrowserPermission + { + [SecurityCritical] + get + { + return _webBrowserPermission ?? (_webBrowserPermission = new WebBrowserPermission(PermissionState.Unrestricted)); + } + } + + [SecuritySafeCritical] + internal static bool AppDomainHasPermission(IPermission permissionToCheck) + { + var psToCheck = new PermissionSet(PermissionState.None); + psToCheck.AddPermission(permissionToCheck); + return psToCheck.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet); + } + + [SecuritySafeCritical] + internal static bool CallerAndAppDomainHaveUnrestrictedWebBrowserPermission() + { + if (!AppDomainHasPermission(CachedWebBrowserPermission)) + { + return false; + } + + try + { + DemandWebBrowserPermission(); + } + catch (SecurityException) + { + return false; + } + + return true; + } + + [SecurityCritical] + internal static bool CallerHasWebPermission(Uri uri) + { + try + { + DemandWebPermission(uri); + return true; + } + catch (SecurityException) + { + return false; + } + } + + // Critical: Exception raised by a demand may contain security sensitive information + + /// + /// Demands for + /// + /// A caller higher in the call stack does not have the permission specified by the current instance.-or- A caller higher in the call stack has called on the current permission object. + [SecurityCritical] + internal static void DemandUnmanagedCode() + { + if (_unmanagedCodePermission == null) + { + _unmanagedCodePermission = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); + } + + _unmanagedCodePermission.Demand(); + } + + [SecurityCritical] + internal static void DemandWebBrowserPermission() + { + CachedWebBrowserPermission.Demand(); + } + + // Critical: Exceptions raised by a demand may contain security sensitive information + [SecurityCritical] + internal static void DemandWebPermission(Uri uri) + { + if (uri == null) + { + return; + } + + if (uri.IsFile) + { + new FileIOPermission(FileIOPermissionAccess.Read, uri.LocalPath).Demand(); + } + else + { + // As a security measure, since the code below uses a string anyway, + // sanitize the input + var finalUri = UriHelper.UriToString(uri); + + new WebPermission(NetworkAccess.Connect, finalUri).Demand(); + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResource.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResource.cs new file mode 100644 index 000000000..384cf5b74 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResource.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Globalization; +using System.Resources; +using System.Threading; + +namespace Microsoft.Toolkit.Win32.UI.Controls +{ + internal sealed class StringResource + { + private static StringResource _loader; + private readonly ResourceManager _resources; + + static StringResource() + { + } + + internal StringResource() + { + _resources = DesignerUI.ResourceManager; + } + + public static ResourceManager Resources => GetLoader()?._resources; + + private static CultureInfo Culture => null; + + public static object GetObject(string name) => Resources?.GetObject(name, Culture); + + public static string GetString(string name) => Resources?.GetString(name, Culture); + + private static StringResource GetLoader() + { + if (_loader == null) + { + var r = new StringResource(); + Interlocked.CompareExchange(ref _loader, r, null); + } + + return _loader; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResourceCategoryAttribute.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResourceCategoryAttribute.cs new file mode 100644 index 000000000..9bdb371e1 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResourceCategoryAttribute.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; + +namespace Microsoft.Toolkit.Win32.UI.Controls +{ + [AttributeUsage(AttributeTargets.All)] + internal sealed class StringResourceCategoryAttribute : CategoryAttribute + { + public StringResourceCategoryAttribute(string category) + : base(category) + { + } + + protected override string GetLocalizedString(string value) => StringResource.GetString(value); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResourceDescriptionAttribute.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResourceDescriptionAttribute.cs new file mode 100644 index 000000000..d07d8e6d8 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/StringResourceDescriptionAttribute.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; + +namespace Microsoft.Toolkit.Win32.UI.Controls +{ + [AttributeUsage(AttributeTargets.All)] + internal sealed class StringResourceDescriptionAttribute : DescriptionAttribute + { + private bool _replaced; + + public StringResourceDescriptionAttribute(string description) + : base(description) + { + } + + public override string Description + { + get + { + if (!_replaced) + { + _replaced = true; + DescriptionValue = StringResource.GetString(Description); + } + + return base.Description; + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/UriHelper.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/UriHelper.cs new file mode 100644 index 000000000..70cf31918 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/UriHelper.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; + +namespace Microsoft.Toolkit.Win32.UI.Controls +{ + // TODO: Place within WebBrowserUriTypeConverter + internal static class UriHelper + { + private const int MAX_PATH_LENGTH = 2048; + private const int MAX_SCHEME_LENGTH = 32; + private const int MAX_URL_LENGTH = MAX_PATH_LENGTH + MAX_SCHEME_LENGTH + 3; /*=sizeof("://")*/ + + /// + /// Converts a Uniform Resource Identifier (URI) to string. + /// + /// The Uniform Resource Identifier (URI). + /// System.String. + /// is + /// If the length of the URI exceeds 2048 characters, the first 2048 are returned. + internal static string UriToString(Uri uri) + { + if (uri == null) + { + throw new ArgumentNullException(nameof(uri)); + } + + return new StringBuilder( + uri.GetComponents( + uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString, + UriFormat.SafeUnescaped), + MAX_URL_LENGTH).ToString(); + } + + internal static Uri StringToUri(string source) + { + if (string.IsNullOrEmpty(source)) + { + source = WebViewDefaults.AboutBlank; + } + + if (Uri.TryCreate(source, UriKind.Absolute, out Uri result)) + { + return result; + } + + // Unrecognized URI + throw new ArgumentException(DesignerUI.E_WEBVIEW_INVALID_URI); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Verify.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Verify.cs new file mode 100644 index 000000000..2ed04d100 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/Verify.cs @@ -0,0 +1,309 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Threading; + +namespace Microsoft.Toolkit.Win32.UI.Controls +{ + [DebuggerStepThrough] + [DebuggerNonUserCode] + internal static class Verify + { + // Conditional to use more aggressive fail-fast behaviors when debugging +#if DEV_DEBUG + private const bool AggressiveFailFast = true; +#else + private const bool AggressiveFailFast = false; +#endif + + /// + /// Verifies that two generic type data are equal. The assertion fails if they are not. + /// + /// The generic type to compare for equality. + /// The first generic type data to compare. This is is the expected value. + /// The second generic type data to compare. This is the actual value. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void AreEqual(T expected, T actual) + { +#pragma warning disable RECS0017 // Possible compare of value type with 'null' + if (expected == null) +#pragma warning restore RECS0017 // Possible compare of value type with 'null' + { + // Two nulls are considered equal, regardless of type semantics. +#pragma warning disable RECS0017 // Possible compare of value type with 'null' + if (actual != null && !actual.Equals(expected)) +#pragma warning restore RECS0017 // Possible compare of value type with 'null' + { + Break(); + } + } + else if (!expected.Equals(actual)) + { + Break(); + } + } + + /// + /// This line should never be executed. The assertion always fails. + /// + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void Fail() => Fail(null); + + /// + /// This line should never be executed. The assertion always fails. + /// + /// The message to display if this function is executed. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void Fail(string message) => Break(message); + + /// + /// Verifies that if the specified condition is true, then so is the result. + /// The assertion fails if the condition is true but the result is false. + /// + /// if set to true [condition]. + /// + /// A second Boolean statement. If the first was true then so must this be. + /// If the first statement was false then the value of this is ignored. + /// + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void Implies(bool condition, bool result) + { + if (condition && !result) + { + Break(); + } + } + + /// + /// Verify the current thread's apartment state is what's expected. The assertion fails if it isn't + /// + /// + /// The expected apartment state for the current thread. + /// + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void IsApartmentState(ApartmentState expectedState) + { + if (Thread.CurrentThread.GetApartmentState() != expectedState) + { + Break(); + } + } + + /// + /// Verifies that the specified condition is false. The assertion fails if it is true. + /// + /// The expression that should be false. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void IsFalse(bool condition) + { + IsFalse(condition, null); + } + + /// + /// Verifies that the specified condition is false. The assertion fails if it is true. + /// + /// The expression that should be false. + /// The message to display if the condition is true. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void IsFalse(bool condition, string message) + { + if (condition) + { + Break(message); + } + } + + /// + /// Verifies that a string has content. I.e. it is not null and it is not empty. + /// + /// The string to verify. + [Conditional("DEBUG")] + internal static void IsNeitherNullNorEmpty(string value) => IsFalse(string.IsNullOrEmpty(value)); + + /// + /// Verifies that a string has content. I.e. it is not null and it is not purely whitespace. + /// + /// The string to verify. + [Conditional("DEBUG")] + internal static void IsNeitherNullNorWhitespace(string value) => IsFalse(string.IsNullOrWhiteSpace(value)); + + /// + /// Verifies the specified value is not null. The assertion fails if it is. + /// + /// The generic reference type. + /// The value to check for nullness. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void IsNotNull(T value) + where T : class + { + if (value == null) + { + Break(); + } + } + + [Conditional("DEBUG")] + internal static void IsNotOnMainThread() + { + if (System.Windows.Application.Current.Dispatcher.CheckAccess()) + { + Break("Is not on WPF main thread"); + } + } + + /// + /// Verifies that the specified object is null. The assertion fails if it is not. + /// + /// The type of item to verify. + /// The item to verify is null. + [Conditional("DEBUG")] + internal static void IsNull(T item) + where T : class + { + if (item != null) + { + Break(); + } + } + + /// + /// Verifies that the specified condition is true. The assertion fails if it is not. + /// + /// A condition that is expected to be true. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void IsTrue(bool condition) => IsTrue(condition, null); + + /// + /// Verifies that the specified condition is true. The assertion fails if it is not. + /// + /// A condition that is expected to be true. + /// The message to write in case the condition is false. + /// This breaks into the debugger in the case of a failed assertion. + [Conditional("DEBUG")] + internal static void IsTrue(bool condition, string message) + { + if (!condition) + { + Break(message); + } + } + + [Conditional("DEBUG")] + private static void Break(string message = null) + { + // If we're running under a unit test, do some additional checking + // Since this method can only be called in DEBUG builds, the additional + // cost of enumerating assemblies or walking the stack is forgivable + if (IsRunningInUnitTest) + { + if (Debugger.IsAttached) + { + // Since a debugger is attached use the existing behavior + _Break(message); + } + else + { + throw new InvalidOperationException(message ?? "Code encountered a BREAK condition and cannot continue. Review stack for more information."); + } + } + else + { + _Break(message); + } + } + + [Conditional("DEBUG")] +#pragma warning disable SA1300 // Element must begin with upper-case letter + private static void _Break(string message) +#pragma warning restore SA1300 // Element must begin with upper-case letter + { +#pragma warning disable RECS0110 // Condition is set by DEV_DEBUG compile constant + if (AggressiveFailFast) +#pragma warning restore RECS0110 // Condition is set by DEV_DEBUG compile constant + { +#pragma warning disable 162 + if (!string.IsNullOrEmpty(message)) + { + Debug.WriteLine(message); + } + + Debugger.Break(); +#pragma warning restore 162 + } + else +#pragma warning disable 162 + { + Debug.Assert(false, message); + } +#pragma warning restore 162 + } + + private static readonly HashSet UnitTestAttributes = new HashSet + { + "Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute" + }; + + private static readonly HashSet UnitTestFrameworks = new HashSet + { + "Microsoft.VisualStudio.QualityTools.UnitTestFramework", + "Microsoft.VisualStudio.TestPlatform.TestFramework" + }; + + private static bool IsRunningInUnitTest + { + get + { + // Check if the current AppDomain has loaded a unit test assembly + bool AppDomainHasUnitTestAssembly() + { + return AppDomain + .CurrentDomain + .GetAssemblies() + .Any(AssemblyIsUnitTestFramework); + } + + bool AssemblyIsUnitTestFramework(Assembly a) + { + foreach (var f in UnitTestFrameworks) + { + if (a.FullName.StartsWith(f, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + + // Walk the stack and determine if any type has a known attribute for unit tests + bool TypeHasUnitTestAttribute() + { + return new StackTrace() + .GetFrames() + .Any(f => f + .GetMethod() + .DeclaringType + .GetCustomAttributes(false) + .Any(x => UnitTestAttributes.Contains(x.GetType().FullName))); + } + + return AppDomainHasUnitTestAssembly() || TypeHasUnitTestAttribute(); + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/VisualStudioToolsManifest.xml b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/VisualStudioToolsManifest.xml new file mode 100644 index 000000000..2d6459ecb --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/VisualStudioToolsManifest.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/DispatcherExtensions.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/DispatcherExtensions.cs new file mode 100644 index 000000000..060a5a587 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/DispatcherExtensions.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Windows.Threading; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WPF +{ + /// + /// Provides additional functionality to the object. + /// + internal static class DispatcherExtensions + { + /// + /// Pushes an empty at . + /// + /// A instance. + /// + /// No frame is pushed if the is null, is true, or is true. + /// + internal static void DoEvents(this Dispatcher dispatcher) + { + object ExitFrame(object arg) + { + ((DispatcherFrame)arg).Continue = false; + return null; + } + + // Check if we have a valid dispatcher + if (dispatcher != null + && !dispatcher.HasShutdownStarted + && !dispatcher.HasShutdownFinished) + { + // Set the priority to ContextIdle to force the queue to flush higher priority events + var frame = new DispatcherFrame(); + dispatcher.BeginInvoke( + DispatcherPriority.ContextIdle, + new DispatcherOperationCallback(ExitFrame), + frame); + Dispatcher.PushFrame(frame); + } + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebView.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebView.cs new file mode 100644 index 000000000..ef4af135d --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebView.cs @@ -0,0 +1,1090 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.InteropServices; +using System.Security; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Threading; +using Microsoft.Toolkit.Win32.UI.Controls.Interop; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.WinForms; +using Point = Windows.Foundation.Point; +using Size = Windows.Foundation.Size; + +/* + +Overview of Keyboard Input Routing for IWebViewControl + +The window hosting IWebViewControl receives regular alphanumeric keyboard input via its WndProc, and whoever is running the message loop +calls DispatchMessage() after any preprocessing and special routing, and the message gets to the WndProc of the window with focus. "Accelerator" +keys need to be passed to the IWebViewControl via TranslateAccelerator() + +However, due to the way the window is hosted out of process, we are not able to intercept those messages. As such we have no support to handle +tabbing in or out of the IWebBrowserControl window. + +NOTE: Depending on how the control is hosted, input messages flow different + + */ + +namespace Microsoft.Toolkit.Win32.UI.Controls.WPF +{ + /// + /// This class is an implementation of for WPF. This class cannot be inherited. + /// + /// + /// + [ToolboxItem(true)] + [DesignTimeVisible(true)] + public sealed class WebView : WebViewHost, IWebView + { + private const int InitializationBlockingTime = 200; + + private static readonly DependencyProperty EnterpriseIdProperty = DependencyProperty.Register( + nameof(EnterpriseId), + typeof(string), + typeof(WebView), + new PropertyMetadata(WebViewDefaults.EnterpriseId, PropertyChangedCallback)); + + private static readonly Hashtable InvalidatorMap = new Hashtable(); + + private static readonly DependencyProperty IsIndexedDBEnabledProperty = DependencyProperty.Register( + nameof(IsIndexedDBEnabled), + typeof(bool), + typeof(WebView), + new PropertyMetadata(WebViewDefaults.IsIndexedDBEnabled, PropertyChangedCallback)); + + private static readonly DependencyProperty IsJavaScriptEnabledProperty = DependencyProperty.Register( + nameof(IsJavaScriptEnabled), + typeof(bool), + typeof(WebView), + new PropertyMetadata(WebViewDefaults.IsJavaScriptEnabled, PropertyChangedCallback)); + + private static readonly DependencyProperty IsPrivateNetworkClientServerCapabilityEnabledProperty = DependencyProperty.Register( + nameof(IsPrivateNetworkClientServerCapabilityEnabled), + typeof(bool), + typeof(WebView), + new PropertyMetadata(WebViewDefaults.IsPrivateNetworkEnabled, PropertyChangedCallback)); + + private static readonly DependencyProperty IsScriptNotifyAllowedProperty = DependencyProperty.Register( + nameof(IsScriptNotifyAllowed), + typeof(bool), + typeof(WebView), + new PropertyMetadata(WebViewDefaults.IsScriptNotifyEnabled, PropertyChangedCallback)); + + private static readonly bool IsWebPermissionRestricted = !Security.CallerAndAppDomainHaveUnrestrictedWebBrowserPermission(); + + private static readonly DependencyProperty SourceProperty = DependencyProperty.Register( + nameof(Source), + typeof(Uri), + typeof(WebView), + new PropertyMetadata(WebViewDefaults.AboutBlankUri, PropertyChangedCallback)); + + private WebViewControlProcess _process; + + private volatile WebViewControlHost _webViewControl; + + // Initialization flag for ISupportInitialize + private InitializationState _initializationState; + + private ManualResetEvent _initializationComplete; + + [SecuritySafeCritical] + [SuppressMessage("Microsoft.Design", "CA1065", Justification ="Exceptions thrown to fail as fast as possible.")] + static WebView() + { +#pragma warning disable 1065 + if (IsWebPermissionRestricted) + { + // Could be hosted in non-IE browser (e.g. Firefox) as an Internet-zone XBAP + // Could also be a standalone ClickOnce application + + // Either way, we don't currently support this + throw new NotSupportedException(DesignerUI.E_WEB_PERMISSION_RESTRICTED); + } + + // ClickOnce uses AppLaunch.exe to host partial-trust applications +#pragma warning disable SA1129 // Do not use default value type constructor + var hostProcessName = Path.GetFileName(UnsafeNativeMethods.GetModuleFileName(new HandleRef())); +#pragma warning restore SA1129 // Do not use default value type constructor + if (string.Compare(hostProcessName, "AppLaunch.exe", StringComparison.OrdinalIgnoreCase) == 0) + { + // Not currently supported + throw new NotSupportedException(DesignerUI.E_CLICKONCE_PARTIAL_TRUST); + } + + // Haven't tested with MTA + Verify.IsApartmentState(ApartmentState.STA); + + // TODO: Assign Feature Control Keys + + // We use this map to lookup which invalidator method to call when the parent's properties change + InvalidatorMap[VisibilityProperty] = new PropertyInvalidator(OnVisibilityInvalidated); + InvalidatorMap[IsEnabledProperty] = new PropertyInvalidator(OnIsEnabledInvalidated); +#pragma warning restore 1065 + } + + private bool WebViewInitialized => _initializationState == InitializationState.IsInitialized; + + private bool WebViewInitializing => _initializationState == InitializationState.IsInitializing; + + private bool WebViewControlInitialized => _webViewControl != null && WebViewInitialized; + + /// + /// Initializes a new instance of the class. + /// + [SecurityCritical] + public WebView() + { + // TODO: Check whether browser is disabled + // TODO: Handle case (OnLoad) for handling POPUP windows + _initializationComplete = new ManualResetEvent(false); + } + + internal WebView(WebViewControlHost webViewControl) + : this() + { + _webViewControl = webViewControl ?? throw new ArgumentNullException(nameof(webViewControl)); + _process = webViewControl.Process; + } + + /// + /// Starts the initialization process for this element. + /// + /// + /// May occur if the element is already initialized or is already initializing. + /// + /// + public override void BeginInit() + { + if (WebViewInitialized) + { + // Cannot initialize WebView since it is already completely initialized + throw new InvalidOperationException(DesignerUI.E_WEBVIEW_ALREADY_INITIALIZED); + } + + if (WebViewInitializing) + { + // Cannot initialize WebView since it is already being initialized + throw new InvalidOperationException(DesignerUI.E_WEBVIEW_ALREADY_INITIALIZING); + } + + _initializationState = InitializationState.IsInitializing; + + base.BeginInit(); + } + + /// + /// Indicates that the initialization process for the element is complete. + /// + /// May occur when is not previously called. + /// + public override void EndInit() + { + if (!WebViewInitializing) + { + // Cannot complete WebView initialization that is not being initialized + throw new InvalidOperationException(DesignerUI.E_WEBVIEW_NOT_INITIALIZING); + } + + base.EndInit(); + } + + // Ensures this class is initialized. Initialization involves using ISupportInitialize methods + private void EnsureInitialized() + { + // If not already initialized and not already initializing + if (!WebViewInitialized && !WebViewInitializing) + { + BeginInit(); + EndInit(); + } + } + + private delegate void PropertyInvalidator(WebView webViewHost); + + /// + public event EventHandler AcceleratorKeyPressed = (sender, args) => { }; + + /// + [SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Justification = "Event does not provide argument deriving from EventArgs")] + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewContainsFullScreenElement)] + public event EventHandler ContainsFullScreenElementChanged = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewContentLoading)] + public event EventHandler ContentLoading = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewDomContentLoaded)] + public event EventHandler DOMContentLoaded = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewFrameContentLoading)] + public event EventHandler FrameContentLoading = (sender, args) => { }; + + /// + [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "DOM", Justification = "Name is the same as the WinRT type")] + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewFrameDomContentLoaded)] + public event EventHandler FrameDOMContentLoaded = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewFrameNavigationCompleted)] + public event EventHandler FrameNavigationCompleted = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewFrameNavigationStarting)] + public event EventHandler FrameNavigationStarting = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewLongRunningScriptDetected)] + public event EventHandler LongRunningScriptDetected = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewMoveFocusRequested)] + public event EventHandler MoveFocusRequested = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewNavigationCompleted)] + public event EventHandler NavigationCompleted = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewNavigationStarting)] + public event EventHandler NavigationStarting = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewNewWindowRequested)] + public event EventHandler NewWindowRequested = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewPermissionRequested)] + public event EventHandler PermissionRequested = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewScriptNotify)] + public event EventHandler ScriptNotify = (sender, args) => { }; + + /// + [SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Justification = "WinRT type signature does not have argument that inherits from EventArgs")] + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewUnsafeContentWarningDisplaying)] + public event EventHandler UnsafeContentWarningDisplaying = (sender, args) => { }; + + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewUnsupportedUriSchemeIdentified)] + public event EventHandler UnsupportedUriSchemeIdentified = (sender, args) => { }; + + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unviewable", Justification = "Unviewable is in WinRT type")] + public event EventHandler UnviewableContentIdentified = (sender, args) => { }; + + /// + /// Gets a value indicating whether is supported in this environment. + /// + /// if this instance is supported; otherwise, . + public static bool IsSupported => WebViewControlHost.IsSupported; + + /// + public bool CanGoBack + { + get + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.CanGoBack ?? false; + } + } + + /// + public bool CanGoForward + { + get + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.CanGoForward ?? false; + } + } + + /// + public bool ContainsFullScreenElement + { + get + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.ContainsFullScreenElement ?? false; + } + } + + /// + public string DocumentTitle + { + get + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.DocumentTitle ?? string.Empty; + } + } + + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.EnterpriseId)] + public string EnterpriseId + { + get => (string)GetValue(EnterpriseIdProperty); + set => SetValue(EnterpriseIdProperty, value); + } + + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.IsIndexedDBEnabled)] + public bool IsIndexedDBEnabled + { + get => (bool)GetValue(IsIndexedDBEnabledProperty); + set => SetValue(IsIndexedDBEnabledProperty, value); + } + + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.IsJavaScriptEnabled)] + public bool IsJavaScriptEnabled + { + get => (bool)GetValue(IsJavaScriptEnabledProperty); + set => SetValue(IsJavaScriptEnabledProperty, value); + } + + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.IsPrivateNetworkEnabled)] + public bool IsPrivateNetworkClientServerCapabilityEnabled + { + get => (bool)GetValue(IsPrivateNetworkClientServerCapabilityEnabledProperty); + set => SetValue(IsPrivateNetworkClientServerCapabilityEnabledProperty, value); + } + + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.IsScriptNotifyEnabled)] + public bool IsScriptNotifyAllowed + { + get => (bool)GetValue(IsScriptNotifyAllowedProperty); + set => SetValue(IsScriptNotifyAllowedProperty, value); + } + + /// + /// Gets or sets a value indicating whether this instance is web view visible. + /// + /// if this instance is web view visible; otherwise, . + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool IsWebViewVisible + { + get + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl.IsVisible; + } + + set + { + Verify.IsNotNull(_webViewControl); + + if (_webViewControl != null) + { + _webViewControl.IsVisible = value; + } + } + } + + /// + [Browsable(false)] + public WebViewControlProcess Process + { + get + { + VerifyAccess(); + + // NOTE: Not really in the spirit of a Property + do + { + Dispatcher.CurrentDispatcher.DoEvents(); + } + while (!_initializationComplete.WaitOne(InitializationBlockingTime)); + + Verify.IsNotNull(_webViewControl); + return _webViewControl?.Process; + } + } + + /// + [Browsable(false)] + public WebViewControlSettings Settings + { + get + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.Settings; + } + } + + /// + public Uri Source + { + get => (Uri)GetValue(SourceProperty); + set => SetValue(SourceProperty, value); + } + + /// + [Browsable(false)] + public Version Version + { + get + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.Version; + } + } + + /// + public override void Close() + { + // TODO: Guard IsDisposed + UnsubscribeEvents(); + _webViewControl?.Close(); + _webViewControl?.Dispose(); + + _webViewControl = null; + _process = null; + } + + /// + public WebViewControlDeferredPermissionRequest GetDeferredPermissionRequestById(uint id) + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.GetDeferredPermissionRequestById(id); + } + + /// + public bool GoBack() + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.GoBack() ?? false; + } + + /// + public bool GoForward() + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.GoForward() ?? false; + } + + /// + public string InvokeScript(string scriptName) + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.InvokeScript(scriptName); + } + + /// + public string InvokeScript(string scriptName, params string[] arguments) + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.InvokeScript(scriptName, arguments); + } + + /// + public string InvokeScript(string scriptName, IEnumerable arguments) + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.InvokeScript(scriptName, arguments); + } + + /// + public Task InvokeScriptAsync(string scriptName) + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.InvokeScriptAsync(scriptName); + } + + /// + public Task InvokeScriptAsync(string scriptName, params string[] arguments) + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.InvokeScriptAsync(scriptName, arguments); + } + + /// + public Task InvokeScriptAsync(string scriptName, IEnumerable arguments) + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.InvokeScriptAsync(scriptName, arguments); + } + + /// + public void MoveFocus(WebViewControlMoveFocusReason reason) + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + _webViewControl?.MoveFocus(reason); + } + + /// + public void Navigate(string source) + { + Navigate(UriHelper.StringToUri(source)); + } + + /// + public void Navigate(Uri source) + { + VerifyAccess(); + + // TODO: Support for pack:// + Source = source; + } + + /// + public void NavigateToLocal(string relativePath) + { + VerifyAccess(); + + do + { + Dispatcher.CurrentDispatcher.DoEvents(); + } + while (!_initializationComplete.WaitOne(InitializationBlockingTime)); + + Verify.IsNotNull(_webViewControl); + _webViewControl.NavigateToLocal(relativePath); + } + + /// + public void NavigateToString(string text) + { + VerifyAccess(); + + do + { + Dispatcher.CurrentDispatcher.DoEvents(); + } + while (!_initializationComplete.WaitOne(InitializationBlockingTime)); + + Verify.IsNotNull(_webViewControl); + _webViewControl.NavigateToString(text); + } + + /// + public void Refresh() + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + _webViewControl?.Refresh(); + } + + /// + public void Stop() + { + VerifyAccess(); + Verify.IsNotNull(_webViewControl); + _webViewControl?.Stop(); + } + + /// + protected override void Initialize() + { + OSVersionHelper.ThrowIfBeforeWindows10April2018(); + + DpiHelper.SetPerMonitorDpiAwareness(); + + Verify.AreEqual(_initializationState, InitializationState.IsInitializing); + + if (_process == null) + { + var privateNetworkEnabled = !Dispatcher.CheckAccess() + ? Dispatcher.Invoke(() => IsPrivateNetworkClientServerCapabilityEnabled) + : IsPrivateNetworkClientServerCapabilityEnabled; + var enterpriseId = !Dispatcher.CheckAccess() + ? Dispatcher.Invoke(() => EnterpriseId) + : EnterpriseId; + + _process = new WebViewControlProcess(new WebViewControlProcessOptions + { + PrivateNetworkClientServerCapability = privateNetworkEnabled + ? WebViewControlProcessCapabilityState.Enabled + : WebViewControlProcessCapabilityState.Disabled, + EnterpriseId = enterpriseId + }); + } + + Dispatcher.InvokeAsync( + async () => + { + Verify.IsNotNull(_process); + + if (_webViewControl == null) + { + var handle = ChildWindow.Handle; + var bounds = new Windows.Foundation.Rect(0, 0, RenderSize.Width, RenderSize.Height); + + _webViewControl = await _process.CreateWebViewControlHostAsync(handle, bounds).ConfigureAwait(false); + } + + Verify.IsNotNull(_webViewControl); + + UpdateSize(RenderSize); + + DestroyWindowCore(ChildWindow); + + SubscribeEvents(); + _webViewControl.IsVisible = true; + + Uri source; + bool javaScriptEnabled; + bool indexDBEnabled; + bool scriptNotifyAllowed; + if (!Dispatcher.CheckAccess()) + { + source = Dispatcher.Invoke(() => Source); + javaScriptEnabled = Dispatcher.Invoke(() => IsJavaScriptEnabled); + indexDBEnabled = Dispatcher.Invoke(() => IsIndexedDBEnabled); + scriptNotifyAllowed = Dispatcher.Invoke(() => IsScriptNotifyAllowed); + } + else + { + source = Source; + javaScriptEnabled = IsJavaScriptEnabled; + indexDBEnabled = IsIndexedDBEnabled; + scriptNotifyAllowed = IsScriptNotifyAllowed; + } + + _webViewControl.Source = source; + _webViewControl.Settings.IsJavaScriptEnabled = javaScriptEnabled; + _webViewControl.Settings.IsIndexedDBEnabled = indexDBEnabled; + _webViewControl.Settings.IsScriptNotifyAllowed = scriptNotifyAllowed; + + _initializationState = InitializationState.IsInitialized; + _initializationComplete.Set(); + }, + DispatcherPriority.Send); + } + + /// + /// Invoked whenever the effective value of any dependency property on this has been updated. The specific dependency property that changed is reported in the arguments parameter. Overrides . + /// + /// The event data that describes the property that changed, as well as old and new values. + /// + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + + var property = e.Property; + + // Look up the property in our map and call the appropriate method to push down + // the changed value to the hosted control + if (property != null && InvalidatorMap.ContainsKey(property)) + { + var invalidator = (PropertyInvalidator)InvalidatorMap[property]; + Verify.IsNotNull(invalidator); + invalidator(this); + } + } + + /// + protected override void UpdateBounds(Rect bounds) + { + UpdateBounds((int)bounds.X, (int)bounds.Y, (int)bounds.Width, (int)bounds.Height); + } + + private static void OnIsEnabledInvalidated(WebView webView) + { + Verify.IsNotNull(webView); + Verify.IsNotNull(webView._webViewControl); + if (webView?._webViewControl != null) + { + // TODO: Is there an equivalent for Win32WebViewHost? + } + } + + private static void OnVisibilityInvalidated(WebView webView) + { + Verify.IsNotNull(webView); + Verify.IsNotNull(webView._webViewControl); + + if (webView?._webViewControl != null) + { + switch (webView.Visibility) + { + case Visibility.Visible: + webView._webViewControl.IsVisible = true; + break; + + case Visibility.Hidden: + webView._webViewControl.IsVisible = false; + break; + + case Visibility.Collapsed: + webView._webViewControl.IsVisible = false; + + // TODO: Update bounds to set PreferredSize? + break; + } + } + } + + private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) + { + if (dependencyObject is WebView wv) + { + if (dependencyPropertyChangedEventArgs.Property.Name == nameof(Source)) + { + Verify.IsTrue(wv.WebViewControlInitialized); + if (wv.WebViewControlInitialized) + { + wv._webViewControl.Navigate(dependencyPropertyChangedEventArgs.NewValue as Uri); + } + } + else if (dependencyPropertyChangedEventArgs.Property.Name == nameof(IsIndexedDBEnabled)) + { + Verify.IsTrue(wv.WebViewControlInitialized); + if (wv.WebViewControlInitialized) + { + wv._webViewControl.Settings.IsIndexedDBEnabled = + (bool)dependencyPropertyChangedEventArgs.NewValue; + } + } + else if (dependencyPropertyChangedEventArgs.Property.Name == nameof(IsJavaScriptEnabled)) + { + Verify.IsTrue(wv.WebViewControlInitialized); + if (wv.WebViewControlInitialized) + { + wv._webViewControl.Settings.IsJavaScriptEnabled = + (bool)dependencyPropertyChangedEventArgs.NewValue; + } + } + else if (dependencyPropertyChangedEventArgs.Property.Name == nameof(IsScriptNotifyAllowed)) + { + Verify.IsTrue(wv.WebViewControlInitialized); + if (wv.WebViewControlInitialized) + { + wv._webViewControl.Settings.IsScriptNotifyAllowed = + (bool)dependencyPropertyChangedEventArgs.NewValue; + } + } + else if (dependencyPropertyChangedEventArgs.Property.Name == nameof(IsPrivateNetworkClientServerCapabilityEnabled)) + { + Verify.IsFalse(wv.WebViewControlInitialized); + if (wv.WebViewControlInitialized) + { + throw new InvalidOperationException(DesignerUI.E_CANNOT_CHANGE_AFTER_INIT); + } + } + else if (dependencyPropertyChangedEventArgs.Property.Name == nameof(EnterpriseId)) + { + Verify.IsFalse(wv.WebViewControlInitialized); + if (wv.WebViewControlInitialized) + { + throw new InvalidOperationException(DesignerUI.E_CANNOT_CHANGE_AFTER_INIT); + } + } + } + } + + private void OnAcceleratorKeyPressed(object sender, WebViewControlAcceleratorKeyPressedEventArgs args) + { + var handler = AcceleratorKeyPressed; + if (handler != null) + { + handler(this, args); + } + } + + private void OnContainsFullScreenElementChanged(object sender, object args) + { + var handler = ContainsFullScreenElementChanged; + if (handler != null) + { + handler(this, args); + } + } + + private void OnContentLoading(object sender, WebViewControlContentLoadingEventArgs args) + { + var handler = ContentLoading; + if (handler != null) + { + handler(this, args); + } + } + + private void OnDOMContentLoaded(object sender, WebViewControlDOMContentLoadedEventArgs args) + { + var handler = DOMContentLoaded; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameContentLoading(object sender, WebViewControlContentLoadingEventArgs args) + { + var handler = FrameContentLoading; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameDOMContentLoaded(object sender, WebViewControlDOMContentLoadedEventArgs args) + { + var handler = FrameDOMContentLoaded; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameNavigationCompleted(object sender, WebViewControlNavigationCompletedEventArgs args) + { + var handler = FrameNavigationCompleted; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameNavigationStarting(object sender, WebViewControlNavigationStartingEventArgs args) + { + var handler = FrameNavigationStarting; + if (handler != null) + { + handler(this, args); + } + } + + private void OnLongRunningScriptDetected(object sender, WebViewControlLongRunningScriptDetectedEventArgs args) + { + var handler = LongRunningScriptDetected; + if (handler != null) + { + handler(this, args); + } + } + + private void OnMoveFocusRequested(object sender, WebViewControlMoveFocusRequestedEventArgs args) + { + var handler = MoveFocusRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNavigationCompleted(object sender, WebViewControlNavigationCompletedEventArgs args) + { + // We could have used + // if (NavigationCompleted != null) NavigationCompleted(this, args); + // However, if there is a subscriber and the moment the null check and the call to + // the event handler by the method is invoked, the subscriber may unsubscribe + // (e.g. on a different thread) and cause a NullReferenceException. + // To work around this create a temporally local variable to store the reference and check that + var handler = NavigationCompleted; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNavigationStarting(object sender, WebViewControlNavigationStartingEventArgs args) + { + var handler = NavigationStarting; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNewWindowRequested(object sender, WebViewControlNewWindowRequestedEventArgs args) + { + var handler = NewWindowRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnPermissionRequested(object sender, WebViewControlPermissionRequestedEventArgs args) + { + var handler = PermissionRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnScriptNotify(object sender, WebViewControlScriptNotifyEventArgs args) + { + var handler = ScriptNotify; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnsafeContentWarningDisplaying(object sender, object args) + { + var handler = UnsafeContentWarningDisplaying; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnsupportedUriSchemeIdentified(object sender, WebViewControlUnsupportedUriSchemeIdentifiedEventArgs args) + { + var handler = UnsupportedUriSchemeIdentified; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnviewableContentIdentified(object sender, WebViewControlUnviewableContentIdentifiedEventArgs args) + { + var handler = UnviewableContentIdentified; + if (handler != null) + { + handler(this, args); + } + } + + private void SubscribeEvents() + { + Verify.IsNotNull(_webViewControl); + if (_webViewControl == null) + { + return; + } + + _webViewControl.AcceleratorKeyPressed += OnAcceleratorKeyPressed; + _webViewControl.ContainsFullScreenElementChanged += OnContainsFullScreenElementChanged; + _webViewControl.ContentLoading += OnContentLoading; + _webViewControl.DOMContentLoaded += OnDOMContentLoaded; + _webViewControl.FrameContentLoading += OnFrameContentLoading; + _webViewControl.FrameDOMContentLoaded += OnFrameDOMContentLoaded; + _webViewControl.FrameNavigationCompleted += OnFrameNavigationCompleted; + _webViewControl.FrameNavigationStarting += OnFrameNavigationStarting; + _webViewControl.LongRunningScriptDetected += OnLongRunningScriptDetected; + _webViewControl.MoveFocusRequested += OnMoveFocusRequested; + _webViewControl.NavigationCompleted += OnNavigationCompleted; + _webViewControl.NavigationStarting += OnNavigationStarting; + _webViewControl.NewWindowRequested += OnNewWindowRequested; + _webViewControl.PermissionRequested += OnPermissionRequested; + _webViewControl.ScriptNotify += OnScriptNotify; + _webViewControl.UnsafeContentWarningDisplaying += OnUnsafeContentWarningDisplaying; + _webViewControl.UnsupportedUriSchemeIdentified += OnUnsupportedUriSchemeIdentified; + _webViewControl.UnviewableContentIdentified += OnUnviewableContentIdentified; + } + + private void UnsubscribeEvents() + { + Verify.IsNotNull(_webViewControl); + if (_webViewControl == null) + { + return; + } + + _webViewControl.AcceleratorKeyPressed -= OnAcceleratorKeyPressed; + _webViewControl.ContainsFullScreenElementChanged -= OnContainsFullScreenElementChanged; + _webViewControl.ContentLoading -= OnContentLoading; + _webViewControl.DOMContentLoaded -= OnDOMContentLoaded; + _webViewControl.FrameContentLoading -= OnFrameContentLoading; + _webViewControl.FrameDOMContentLoaded -= OnFrameDOMContentLoaded; + _webViewControl.FrameNavigationCompleted -= OnFrameNavigationCompleted; + _webViewControl.FrameNavigationStarting -= OnFrameNavigationStarting; + _webViewControl.LongRunningScriptDetected -= OnLongRunningScriptDetected; + _webViewControl.MoveFocusRequested -= OnMoveFocusRequested; + _webViewControl.NavigationCompleted -= OnNavigationCompleted; + _webViewControl.NavigationStarting -= OnNavigationStarting; + _webViewControl.NewWindowRequested -= OnNewWindowRequested; + _webViewControl.PermissionRequested -= OnPermissionRequested; + _webViewControl.ScriptNotify -= OnScriptNotify; + _webViewControl.UnsafeContentWarningDisplaying -= OnUnsafeContentWarningDisplaying; + _webViewControl.UnsupportedUriSchemeIdentified -= OnUnsupportedUriSchemeIdentified; + _webViewControl.UnviewableContentIdentified -= OnUnviewableContentIdentified; + } + + private void UpdateBounds(int x, int y, int width, int height) + { +#if DEBUG_LAYOUT + Debug.WriteLine($"{Name}::{nameof(UpdateBounds)}"); + Debug.Indent(); + Debug.WriteLine($"oldBounds={{x={x} y={y} width={width} height={height}}}"); +#endif + + // Update bounds here to ensure correct draw position + if (IsScalingRequired) + { + width = DpiHelper.LogicalToDeviceUnits(width, DeviceDpi); + height = DpiHelper.LogicalToDeviceUnits(height, DeviceDpi); + } + + // HACK: looks like the vertical pos is counted twice, giving a gap + y = 0; + +#if DEBUG_LAYOUT + Debug.WriteLine($"newBounds={{x={x} y={y} width={width} height={height}}}"); +#endif + if (WebViewControlInitialized) + { + var rect = new Windows.Foundation.Rect( + new Point(x, y), + new Size(width, height)); + + _webViewControl?.UpdateBounds(rect); + } + +#if DEBUG_LAYOUT + Debug.Unindent(); +#endif + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebViewControlProcessExtensions.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebViewControlProcessExtensions.cs new file mode 100644 index 000000000..3ed919555 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebViewControlProcessExtensions.cs @@ -0,0 +1,191 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WPF +{ + /// + /// Extends the funcionality of for WPF. + /// + internal static class WebViewControlProcessExtensions + { + /// + /// Creates a within the context of . + /// + /// An instance of . + /// The host window handle. + /// A containing numerical values that represent the location and size of the control. + /// An instance. + /// + /// is equal to , or + /// is . + /// + internal static IWebView CreateWebView( + this WebViewControlProcess process, + IntPtr hostWindowHandle, + Rect bounds) + { + if (process is null) + { + throw new ArgumentNullException(nameof(process)); + } + + if (hostWindowHandle == IntPtr.Zero) + { + throw new ArgumentNullException(nameof(hostWindowHandle)); + } + + return new WebView(process.CreateWebViewControlHost(hostWindowHandle, bounds)); + } + + /// + /// Creates a within the context of using the to create a HWND and within the specified . + /// + /// An instance of . + /// A instance in which to create a HWND. + /// A containing numerical values that represent the location and size of the control. + /// An instance. + internal static IWebView CreateWebView(this WebViewControlProcess process, Visual visual, Rect bounds) + { + return visual.Dispatcher.Invoke(() => process.CreateWebViewAsync(visual, bounds).GetAwaiter().GetResult()); + } + + /// + /// Creates a within the context of using the to create a HWND. + /// + /// An instance of . + /// A instance in which to create a HWND. + /// An instance. + /// + /// The bounds to draw the are determined by the height and width of the . + /// + /// + internal static IWebView CreateWebView(this WebViewControlProcess process, Visual visual) + { + return visual.Dispatcher.Invoke(() => process.CreateWebViewAsync(visual).GetAwaiter().GetResult()); + } + + /// + /// Creates a within the context of . + /// + /// An instance of . + /// The host window handle. + /// A containing numerical values that represent the location and size of the control. + /// An instance. + /// + /// is equal to , or + /// is . + /// + internal static async Task CreateWebViewAsync( + this WebViewControlProcess process, + IntPtr hostWindowHandle, + Rect bounds) + { + if (process is null) + { + throw new ArgumentNullException(nameof(process)); + } + + if (hostWindowHandle == IntPtr.Zero) + { + throw new ArgumentNullException(nameof(hostWindowHandle)); + } + + return new WebView(await process.CreateWebViewControlHostAsync(hostWindowHandle, bounds).ConfigureAwait(false)); + } + + /// + /// Creates a within the context of using the to create a HWND and within the specified . + /// + /// An instance of . + /// A instance in which to create a HWND. + /// A containing numerical values that represent the location and size of the control. + /// An asynchronous operation that completes with a . + internal static async Task CreateWebViewAsync(this WebViewControlProcess process, Visual visual, Rect bounds) + { + HwndSource sourceHwnd; + if (!visual.Dispatcher.CheckAccess()) + { + sourceHwnd = visual.Dispatcher.Invoke(() => (HwndSource)PresentationSource.FromVisual(visual)); + } + else + { + sourceHwnd = (HwndSource)PresentationSource.FromVisual(visual); + } + + Verify.IsNotNull(sourceHwnd); + + var webViewControlHost = await process.CreateWebViewControlHostAsync(sourceHwnd?.Handle ?? IntPtr.Zero, bounds); + + return !visual.Dispatcher.CheckAccess() + ? visual.Dispatcher.Invoke(() => new WebView(webViewControlHost)) + : new WebView(webViewControlHost); + } + + /// + /// Creates a within the context of using the to create a HWND. + /// + /// An instance of . + /// A instance in which to create a HWND. + /// An asynchronous operation that completes with a . + /// + /// The bounds to draw the are determined by the height and width of the . + /// + /// + internal static Task CreateWebViewAsync(this WebViewControlProcess process, Visual visual) + { + double width; + double height; + + if (!visual.Dispatcher.CheckAccess()) + { + width = visual.Dispatcher.Invoke(() => (double)visual.GetValue(FrameworkElement.ActualWidthProperty)); + height = visual.Dispatcher.Invoke(() => (double)visual.GetValue(FrameworkElement.ActualHeightProperty)); + } + else + { + width = (double)visual.GetValue(FrameworkElement.ActualWidthProperty); + height = (double)visual.GetValue(FrameworkElement.ActualHeightProperty); + } + + return process.CreateWebViewAsync(visual, new Rect(new Size(height, width))); + } + + [SecuritySafeCritical] + internal static WebViewControlHost CreateWebViewControlHost( + this WebViewControlProcess process, + IntPtr hostWindowHandle, + Rect bounds) + { + Verify.IsNotNull(process); + Verify.IsFalse(hostWindowHandle == IntPtr.Zero); + + var rect = new Windows.Foundation.Rect(bounds.X, bounds.Y, bounds.Width, bounds.Height); + return process + .CreateWebViewControlHostAsync(hostWindowHandle, rect) + .GetAwaiter() + .GetResult(); + } + + [SecuritySafeCritical] + internal static Task CreateWebViewControlHostAsync( + this WebViewControlProcess process, + IntPtr hostWindowHandle, + Rect bounds) + { + Verify.IsNotNull(process); + Verify.IsFalse(hostWindowHandle == IntPtr.Zero); + + var rect = new Windows.Foundation.Rect(bounds.X, bounds.Y, bounds.Width, bounds.Height); + return process.CreateWebViewControlHostAsync(hostWindowHandle, rect); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebViewHost.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebViewHost.cs new file mode 100644 index 000000000..9f68ed484 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WPF/WebView/WebViewHost.cs @@ -0,0 +1,254 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Interop; +using Microsoft.Toolkit.Win32.UI.Controls.Interop; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WPF +{ + /// + /// The class hosts a inside of a WPF tree + /// + /// Requires unmanaged code permissions + [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] + [ToolboxItem(false)] + [DesignTimeVisible(false)] + public abstract class WebViewHost : HwndHost + { + static WebViewHost() + { + // register for access keys + EventManager.RegisterClassHandler(typeof(WebViewHost), AccessKeyManager.AccessKeyPressedEvent, new AccessKeyPressedEventHandler(OnAccessKeyPressed)); + + Control.IsTabStopProperty.OverrideMetadata(typeof(WebViewHost), new FrameworkPropertyMetadata(true)); + + FocusableProperty.OverrideMetadata(typeof(WebViewHost), new FrameworkPropertyMetadata(true)); + + KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(WebViewHost), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once)); + } + + /// + /// Initializes a new instance of the class. + /// + protected WebViewHost() + { + DpiHelper.Initialize(); + DpiHelper.SetPerMonitorDpiAwareness(); + + // Get system DPI + DeviceDpi = DpiHelper.DeviceDpi; + + DpiChanged += OnDpiChanged; + SizeChanged += OnSizeChanged; + +#if DEBUG_FOCUS + GotFocus += (o, e) => { Debug.WriteLine($"GotFocus"); }; + GotKeyboardFocus += (o, e) => { Debug.WriteLine("GotKeyboardFocus"); }; + LostFocus += (o, e) => { Debug.WriteLine($"LostFocus"); }; + LostKeyboardFocus += (o, e) => { Debug.WriteLine("LostKeyboardFocus"); }; + KeyUp += (o, e) => + { + Debug.WriteLine($"KeyUp: Key: {e.Key}, SystemKey: {e.SystemKey}"); + }; +#endif + } + + /// + /// Gets the child window. + /// + /// The child window created during . + protected HandleRef ChildWindow { get; private set; } + + /// + /// Gets the current DPI for this control + /// + /// + protected int DeviceDpi { get; private set; } + + /// + /// Gets a value indicating whether scaling is required for the current DPI. + /// + /// if scaling is required; otherwise, . + protected bool IsScalingRequired => DeviceDpi != DpiHelper.LogicalDpi; + + /// + /// Gets the parent handle. + /// + /// The passed in to . + protected HandleRef ParentHandle { get; private set; } + + /// + /// Closes the . + /// + /// + public abstract void Close(); + + /// + /// When overridden in a derived class, creates the window to be hosted. + /// + /// The window handle of the parent window. + /// The handle to the child Win32 window to create. + /// + protected override HandleRef BuildWindowCore(HandleRef hwndParent) + { + ParentHandle = hwndParent; + NativeMethods.EnableMouseInPointer(true); + + if (ChildWindow.Handle == IntPtr.Zero) + { + // Create a simple STATIC HWND + var windowHandle = NativeMethods.CreateWindow( + "Static", + WS.CHILD | WS.VISIBLE | WS.CLIPCHILDREN, + 0, + 0, + 0, + 0, + hwndParent.Handle); + Verify.IsTrue(windowHandle != IntPtr.Zero, "Could not create child window"); + + ChildWindow = new HandleRef(null, windowHandle); + } + + Initialize(); + + return ChildWindow; + } + + /// + /// Destroys the hosted window. + /// + /// A structure that contains the window handle. + protected override void DestroyWindowCore(HandleRef hwnd) + { + NativeMethods.DestroyWindow(hwnd.Handle); + } + + /// + /// Immediately frees any system resources that the might hold. + /// + /// Set to if called from an explicit disposer and otherwise. + protected override void Dispose(bool disposing) + { + try + { + if (disposing) + { + Close(); + DpiChanged -= OnDpiChanged; + SizeChanged -= OnSizeChanged; + } + } + finally + { + base.Dispose(disposing); + } + } + + /// + /// Initializes this instance. + /// + protected abstract void Initialize(); + + /// + /// Processes keyboard input at the keydown message level. + /// + /// The message and associated data. Do not modify this structure. It is passed by reference for performance reasons only. + /// Modifier keys. + /// Always returns . + [SecurityCritical] + [UIPermission(SecurityAction.LinkDemand, Unrestricted = true)] + protected override bool TranslateAcceleratorCore(ref MSG msg, ModifierKeys modifiers) + { + Debug.WriteLine($"HWND: {msg.hwnd}, msg: {msg.message}, wParam: {msg.wParam}, lParam: {msg.lParam}"); + + // TODO: Convert to Win32.WM + // If TAB key was pressed + if (msg.message == 0x0100 && msg.wParam.ToInt32() == 0x09) + { + // Handle case for SHIFT+TAB + // Otherwise, TAB + } + + return base.TranslateAcceleratorCore(ref msg, modifiers); + } + + /// + /// Updates the location and size of . + /// + /// A containing numerical values that represent the location and size of the control. + protected abstract void UpdateBounds(Rect bounds); + + /// + /// Updates the size of the using the current visual offset for location. + /// + /// A containing numerical values that represent the size of the control. + protected virtual void UpdateSize(Size size) + { + var rect = new Rect( + VisualOffset.X, + VisualOffset.Y, + size.Width, + size.Height); + UpdateBounds(rect); + } + + /// + /// When overridden in a derived class, accesses the window process (handle) of the hosted child window. + /// + /// The window handle of the hosted window. + /// The message to act upon. + /// Information that may be relevant to handling the message. This is typically used to store small pieces of information, such as flags. + /// Information that may be relevant to handling the message. This is typically used to reference an object. + /// Whether events resulting should be marked handled. + /// The window handle of the child window. + protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + Debug.WriteLine($"HWND: {hwnd}, msg: {msg} (0x{msg:x4}), wParam: {wParam}, lParam: {lParam}"); + + switch (msg) + { + // WM_DPICHANGED + // WM_DPICHANGED_BEFOREPARENT + // WM_DPICHANGED_AFTERPARENT + default: + return base.WndProc(hwnd, msg, wParam, lParam, ref handled); + } + } + + private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs args) + { + if (args.Handled || args.Scope != null || args.Target != null) + { + return; + } + + args.Target = (UIElement)sender; + } + + private void OnDpiChanged(object o, DpiChangedEventArgs e) + { +#if DEBUG_LAYOUT + Debug.WriteLine("Old DPI: ({0}, {1}), New DPI: ({2}, {3})", e.OldDpi.DpiScaleX, e.OldDpi.DpiScaleY, e.NewDpi.DpiScaleX, e.NewDpi.DpiScaleY); +#endif + Verify.AreEqual(DeviceDpi, e.OldDpi.PixelsPerInchX); + DeviceDpi = (int)e.NewDpi.PixelsPerInchX; + } + + private void OnSizeChanged(object o, SizeChangedEventArgs e) + { + UpdateSize(e.NewSize); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/Constants.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/Constants.cs new file mode 100644 index 000000000..1c42ee6f1 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/Constants.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + internal static class Constants + { + internal const string CategoryAction = "CatAction"; + internal const string CategoryBehavior = "CatBehavior"; + internal const string ComponentDefaultProperty = nameof(WebView.Source); + internal const string ComponentDefaultEvent = nameof(WebView.DOMContentLoaded); + internal const string DescriptionEnterpriseId = "WebViewEnterpriseIdDesc"; + internal const string DescriptionSource = "WebViewSourceDesc"; + + internal const string DescriptionWebViewContainsFullScreenElement = + "WebViewContainsFullScreenElementChangedDesc"; + + internal const string DescriptionWebViewContentLoading = "WebViewContentLoadingDesc"; + internal const string DescriptionWebViewDomContentLoaded = "WebViewDomContentLoadedDesc"; + internal const string DescriptionWebViewFrameContentLoading = "WebViewFrameContentLoadingDesc"; + internal const string DescriptionWebViewFrameDomContentLoaded = "WebViewFrameDomContentLoadedDesc"; + internal const string DescriptionWebViewFrameNavigationCompleted = "WebViewFrameNavigationCompletedDesc"; + internal const string DescriptionWebViewFrameNavigationStarting = "WebViewFrameNavigationStartingDesc"; + internal const string DescriptionWebViewLongRunningScriptDetected = "WebViewLongRunningScriptDetectedDesc"; + internal const string DescriptionWebViewMoveFocusRequested = "WebViewMoveFocusRequestedDesc"; + internal const string DescriptionWebViewNavigationCompleted = "WebViewNavigationCompletedDesc"; + internal const string DescriptionWebViewNavigationStarting = "WebViewNavigationStartingDesc"; + internal const string DescriptionWebViewNewWindowRequested = "WebViewNewWindowRequestedDesc"; + internal const string DescriptionWebViewPermissionRequested = "WebViewPermissionRequestedDesc"; + internal const string DescriptionWebViewScriptNotify = "WebViewScriptNotifyDesc"; + internal const string DescriptionWebViewUnsafeContentWarningDisplaying = "WebViewUnsafeContentWarningDisplayingDesc"; + internal const string DescriptionWebViewUnsupportedUriSchemeIdentified = "WebViewUnsupportedUriSchemeIdentifiedDesc"; + internal const string DescriptionWebViewUnviewableContentIdentified = "WebViewUnviewableContentIdentifiedDesc"; + internal const string DescriptionWebViewWebResourceRequested = "WebViewWebResourceRequestedDesc"; + internal const string InitImmutable = "InvalidOp_Immutable"; + internal const string SecurityPermissionSetName = "FullTrust"; + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/InitializationState.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/InitializationState.cs new file mode 100644 index 000000000..93004be21 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/InitializationState.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + /// + /// Initialization states of object. + /// + /// + /// + internal enum InitializationState + { + /// + /// The state in which the has not been initialized. + /// At this state, all operations on the object would cause InvalidOperationException. + /// The object can only transit to 'IsInitializing' state with call. + /// + Uninitialized, + + /// + /// The state in which the is being initialized. At this state, user can + /// set values into the required properties. The object can only transit to 'IsInitialized' state + /// with call. + /// + IsInitializing, + + /// + /// The state in which the object is fully initialized. At this state the object + /// is fully functional. There is no valid transition out of the state. + /// + IsInitialized + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebBrowserUriTypeConverter.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebBrowserUriTypeConverter.cs new file mode 100644 index 000000000..9037e5a40 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebBrowserUriTypeConverter.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Globalization; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + /// + /// Converts a type to a type for , and vice versa. + /// + public class WebBrowserUriTypeConverter : UriTypeConverter + { + /// + /// Converts the given to the type of this converter, using the specified and information. + /// + /// An that provides a format context. + /// The to use as the current culture. + /// The to convert. + /// An that represents the converted value. + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + var uri = base.ConvertFrom(context, culture, value) as Uri; + if (uri != null && !string.IsNullOrEmpty(uri.OriginalString) && !uri.IsAbsoluteUri) + { + try + { + uri = new Uri("http://" + uri.OriginalString.Trim()); + } + catch (UriFormatException) + { + } + } + + return uri; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.BaseProperties.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.BaseProperties.cs new file mode 100644 index 000000000..d6af24a87 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.BaseProperties.cs @@ -0,0 +1,221 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + /// + public partial class WebView : Control + { + /// + /// Gets or sets a value indicating whether the control can accept data that the user drags onto it. + /// + /// if the control can accept data that the user drags onto it; otherwise, . + /// The value of is modified. + /// cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public override bool AllowDrop + { + get => base.AllowDrop; + set => throw new NotSupportedException(); + } + + /// + /// Gets or sets the background color for the control. + /// + /// A that represents the background color of the control. + /// The value of is modified. + /// cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public override Color BackColor + { + get => base.BackColor; + set => throw new NotSupportedException(); + } + + /// + /// Gets or sets the background image displayed in the control. + /// + /// An that represents the image to display in the background of the control. + /// The value of is modified. + /// cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public override Image BackgroundImage + { + get => base.BackgroundImage; + set => throw new NotSupportedException(); + } + + /// + /// Gets or sets the background image layout as defined in the enumeration. + /// + /// One of the values of . + /// The value of is modified. + /// cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public override ImageLayout BackgroundImageLayout + { + get => base.BackgroundImageLayout; + set => throw new NotSupportedException(); + } + + /// + /// Gets or sets the cursor that is displayed when the mouse pointer is over the control. + /// + /// A that represents the cursor to display when the mouse pointer is over the control. + /// The value of is modified. + /// cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public override Cursor Cursor + { + get => base.Cursor; + set => throw new NotSupportedException(); + } + + // Shadowed because the property is not virtual and we needed to override the behavior + + /// + /// Gets or sets a value indicating whether the control can respond to user interaction. + /// + /// if the control can respond to user interaction; otherwise, . + /// The value of is modified. + /// cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public new bool Enabled + { + get => base.Enabled; + set => throw new NotSupportedException(); + } + + /// + /// Gets or sets the font of the text displayed by the control. + /// + /// The to apply to the text displayed by the control. + /// The value of is modified. + /// cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public override Font Font + { + get => base.Font; + set => throw new NotSupportedException(); + } + + /// + /// Gets or sets the foreground color of the control. + /// + /// The foreground of the control. + /// The value of is modified. + /// cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public override Color ForeColor + { + get => base.ForeColor; + set => throw new NotSupportedException(); + } + + // Shadowed so we can put the attributes here to hide it in the designer + + /// + /// Gets or sets the Input Method Editor (IME) mode of the control. + /// + /// One of the values. The default is . + /// /// The property is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public new ImeMode ImeMode + { + get => base.ImeMode; + set => base.ImeMode = value; + } + + // New so we can put the attributes here to hide it in the designer + + /// + /// Gets or sets padding within the control. + /// + /// A representing the control's internal spacing characteristics. + /// /// The property is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public new Padding Padding + { + get => base.Padding; + set => base.Padding = value; + } + + /// + /// Gets or sets a value indicating whether control's elements are aligned to support locales using right-to-left fonts. + /// + /// One of the values. + /// The value of the property is modified. + /// The property cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [Localizable(false)] + public override RightToLeft RightToLeft + { + get => RightToLeft.No; + set => throw new NotSupportedException(); + } + + /// + /// Gets or sets the text associated with this control. + /// + /// The text displayed in the control. + /// The value of the property is modified. + /// The property cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Bindable(false)] + public override string Text + { + get => string.Empty; + set => throw new NotSupportedException(); + } + + /// + /// Gets or sets a value indicating whether to use the wait cursor for the current control and all child controls. + /// + /// to use the wait cursor for the current control and all child controls; otherwise, . + /// The value of the property is modified. + /// The property cannot be modified and is not visible in the designer. + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public new bool UseWaitCursor + { + get => base.UseWaitCursor; + set => throw new NotSupportedException(); + } + + /// + /// Gets the default size of the control. + /// + /// The default of the control. + protected override Size DefaultSize => new Size(250, 250); + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Events.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Events.cs new file mode 100644 index 000000000..90cde1ac3 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Events.cs @@ -0,0 +1,338 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using WebViewControlAcceleratorKeyPressedEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlAcceleratorKeyPressedEventArgs; +using WebViewControlContentLoadingEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlContentLoadingEventArgs; +using WebViewControlDOMContentLoadedEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlDOMContentLoadedEventArgs; +using WebViewControlLongRunningScriptDetectedEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlLongRunningScriptDetectedEventArgs; +using WebViewControlMoveFocusRequestedEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlMoveFocusRequestedEventArgs; +using WebViewControlNavigationStartingEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlNavigationStartingEventArgs; +using WebViewControlNewWindowRequestedEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlNewWindowRequestedEventArgs; +using WebViewControlPermissionRequestedEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlPermissionRequestedEventArgs; +using WebViewControlScriptNotifyEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlScriptNotifyEventArgs; +using WebViewControlUnsupportedUriSchemeIdentifiedEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlUnsupportedUriSchemeIdentifiedEventArgs; +using WebViewControlUnviewableContentIdentifiedEventArgs = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlUnviewableContentIdentifiedEventArgs; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + /// + public partial class WebView : IWebView + { + /// + public event EventHandler AcceleratorKeyPressed = (sender, args) => { }; + + /// + /// + /// Occurs when the status of whether the current contains a full screen element or not changes. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Justification = "Declaration of WinRT type")] + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewContainsFullScreenElement)] + public event EventHandler ContainsFullScreenElementChanged = (sender, args) => { }; + + /// + /// Occurs when the has started loading new content. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewContentLoading)] + public event EventHandler ContentLoading = (sender, args) => { }; + + /// + /// Occurs when the finished parsing the current content. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewDomContentLoaded)] + public event EventHandler DOMContentLoaded = (sender, args) => { }; + + /// + /// Occurs when a frame in the has started loading new content. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewFrameContentLoading)] + public event EventHandler FrameContentLoading = (sender, args) => { }; + + /// + /// Occurs when a frame in the finished parsing its current content. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "DOM", Justification ="Name of WinRT type")] + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewFrameDomContentLoaded)] + public event EventHandler FrameDOMContentLoaded = (sender, args) => { }; + + /// + /// Occurs when a frame in the finished navigating to new content. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewFrameNavigationCompleted)] + public event EventHandler FrameNavigationCompleted = (sender, args) => { }; + + /// + /// Occurs when a frame in the navigates to new content. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewFrameNavigationStarting)] + public event EventHandler FrameNavigationStarting = (sender, args) => { }; + + /// + /// Occurs periodically while the executes JavaScript, letting you halt the script. + /// + /// + /// Your app might appear unresponsive while scripts are running. This event provides an opportunity to interrupt a long-running + /// script. To determine how long the script has been running, check the + /// property of the object. To halt the script, set the event args + /// property to true. The halted script will + /// not execute again unless it is reloaded during a subseqent navigation. + /// + /// + /// + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewLongRunningScriptDetected)] + public event EventHandler LongRunningScriptDetected = (sender, args) => { }; + + /// + /// Occurs when a focus move is requested. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewMoveFocusRequested)] + public event EventHandler MoveFocusRequested = (sender, args) => { }; + + /// + /// Occurs when the control finished navigating to new content. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewNavigationCompleted)] + public event EventHandler NavigationCompleted = (sender, args) => { }; + + /// + /// Occurs before the navigates to new content. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewNavigationStarting)] + public event EventHandler NavigationStarting = (sender, args) => { }; + + /// eds + /// Occurs when an action is performed that causes content to be opened in a new window. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewNewWindowRequested)] + public event EventHandler NewWindowRequested = (sender, args) => { }; + + /// + /// Occurs when an action in a requires that permission be granted. + /// + /// + /// The types of permission that can be requested are defined in the enumeration. + /// + /// If you don't handle the event, the denies permission by default. + /// + /// When you handle a permission request in , you get a object as + /// the value of the property. You can call Allow to grant the request, + /// Deny to deny the request, or Defer to defer the request until a later time. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewPermissionRequested)] + public event EventHandler PermissionRequested = (sender, args) => { }; + + /// + /// Occurs when the content contained in the control passes a string to the application by using JavaScript. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewScriptNotify)] + public event EventHandler ScriptNotify = (sender, args) => { }; + + /// + /// Occurs when shows a warning page for content that was reported as unsafe by SmartScreen filter. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Justification ="Declaration of WinRT type")] + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewUnsafeContentWarningDisplaying)] + public event EventHandler UnsafeContentWarningDisplaying = (sender, args) => { }; + + /// + /// Occurs when an attempt is made to navigate to a using a scheme that does not support. + /// + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewUnsupportedUriSchemeIdentified)] + public event EventHandler UnsupportedUriSchemeIdentified = (sender, args) => { }; + + /// + /// Occurs when attempts to download an unsupported file. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unviewable", Justification ="Name from WinRT type")] + [StringResourceCategory(Constants.CategoryAction)] + [StringResourceDescription(Constants.DescriptionWebViewUnviewableContentIdentified)] + public event EventHandler UnviewableContentIdentified = (sender, args) => { }; + + private void OnAcceleratorKeyPressed(object sender, WebViewControlAcceleratorKeyPressedEventArgs args) + { + var handler = AcceleratorKeyPressed; + if (handler != null) + { + handler(this, args); + } + } + + private void OnContainsFullScreenElementChanged(object sender, object args) + { + var handler = ContainsFullScreenElementChanged; + if (handler != null) + { + handler(this, args); + } + } + + private void OnContentLoading(object sender, WebViewControlContentLoadingEventArgs args) + { + var handler = ContentLoading; + if (handler != null) + { + handler(this, args); + } + } + + private void OnDOMContentLoaded(object sender, WebViewControlDOMContentLoadedEventArgs args) + { + var handler = DOMContentLoaded; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameContentLoading(object sender, WebViewControlContentLoadingEventArgs args) + { + var handler = FrameContentLoading; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameDOMContentLoaded(object sender, WebViewControlDOMContentLoadedEventArgs args) + { + var handler = FrameDOMContentLoaded; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameNavigationCompleted(object sender, WebViewControlNavigationCompletedEventArgs args) + { + var handler = FrameNavigationCompleted; + if (handler != null) + { + handler(this, args); + } + } + + private void OnFrameNavigationStarting(object sender, WebViewControlNavigationStartingEventArgs args) + { + var handler = FrameNavigationStarting; + if (handler != null) + { + handler(this, args); + } + } + + private void OnLongRunningScriptDetected(object sender, WebViewControlLongRunningScriptDetectedEventArgs args) + { + var handler = LongRunningScriptDetected; + if (handler != null) + { + handler(this, args); + } + } + + private void OnMoveFocusRequested(object sender, WebViewControlMoveFocusRequestedEventArgs args) + { + var handler = MoveFocusRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNavigationCompleted(object sender, WebViewControlNavigationCompletedEventArgs args) + { + // We could have used + // if (NavigationCompleted != null) NavigationCompleted(this, args); + // However, if there is a subscriber and the moment the null check and the call to + // the event handler by the method is invoked, the subscriber may unsubscribe + // (e.g. on a different thread) and cause a NullReferenceException. + // To work around this create a temporarly local variable to store the reference and check that + var handler = NavigationCompleted; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNavigationStarting(object sender, WebViewControlNavigationStartingEventArgs args) + { + var handler = NavigationStarting; + if (handler != null) + { + handler(this, args); + } + } + + private void OnNewWindowRequested(object sender, WebViewControlNewWindowRequestedEventArgs args) + { + var handler = NewWindowRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnPermissionRequested(object sender, WebViewControlPermissionRequestedEventArgs args) + { + var handler = PermissionRequested; + if (handler != null) + { + handler(this, args); + } + } + + private void OnScriptNotify(object sender, WebViewControlScriptNotifyEventArgs args) + { + var handler = ScriptNotify; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnsafeContentWarningDisplaying(object sender, object args) + { + var handler = UnsafeContentWarningDisplaying; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnsupportedUriSchemeIdentified(object sender, WebViewControlUnsupportedUriSchemeIdentifiedEventArgs args) + { + var handler = UnsupportedUriSchemeIdentified; + if (handler != null) + { + handler(this, args); + } + } + + private void OnUnviewableContentIdentified(object sender, WebViewControlUnviewableContentIdentifiedEventArgs args) + { + var handler = UnviewableContentIdentified; + if (handler != null) + { + handler(this, args); + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Init.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Init.cs new file mode 100644 index 000000000..d0b409982 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Init.cs @@ -0,0 +1,206 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using Microsoft.Toolkit.Win32.UI.Controls.Interop; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using WebViewControlProcess = Windows.Web.UI.Interop.WebViewControlProcess; +using WebViewControlProcessCapabilityState = Windows.Web.UI.Interop.WebViewControlProcessCapabilityState; +using WebViewControlProcessOptions = Windows.Web.UI.Interop.WebViewControlProcessOptions; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + /// + public partial class WebView : ISupportInitialize + { + // Initialization flag for ISupportInitialize + private InitializationState _initializationState; + + internal WebView(WebViewControlHost webViewControl) + : this() + { + _webViewControl = webViewControl ?? throw new ArgumentNullException(nameof(webViewControl)); + Process = _webViewControl.Process; + + EnsureInitialized(); + } + + private bool Initialized => _initializationState == InitializationState.IsInitialized; + + private bool Initializing => _initializationState == InitializationState.IsInitializing; + + private bool WebViewControlInitialized => _webViewControl != null; + + void ISupportInitialize.BeginInit() + { + if (Initialized) + { + // Cannot initialize WebView since it is already completely initialized + throw new InvalidOperationException(DesignerUI.E_WEBVIEW_ALREADY_INITIALIZED); + } + + if (Initializing) + { + // Cannot initialize WebView since it is already being initialized + throw new InvalidOperationException(DesignerUI.E_WEBVIEW_ALREADY_INITIALIZING); + } + + _initializationState = InitializationState.IsInitializing; + } + + void ISupportInitialize.EndInit() + { + if (!Initializing) + { + // Cannot complete WebView initialization that is not being initialized + throw new InvalidOperationException(DesignerUI.E_WEBVIEW_NOT_INITIALIZING); + } + + if (!DesignMode) + { + OSVersionHelper.ThrowIfBeforeWindows10April2018(); + } + + try + { + Initialize(); + } + catch (TypeLoadException) + { + // Some types are exposed that the designer tries to reflect over, throwing TypeLoadException + // We're okay to ignore this if we're not in design mode + if (!DesignMode) + { + throw; + } + } + } + + private void CheckInitialized() + { + if (!Initialized) + { + // Initialization incomplete + throw new InvalidOperationException(DesignerUI.E_WEBVIEW_NOT_INITIALIZED); + } + } + + // Ensures this class is initialized. Initialization involves using ISupportInitialize methods + private void EnsureInitialized() + { + // If already disposed, do nothing + if (IsDisposed) + { + throw new ObjectDisposedException(GetType().Name); + } + + // If not already initialized and not already initializing + if (!Initialized && !Initializing) + { + ((ISupportInitialize)this).BeginInit(); + ((ISupportInitialize)this).EndInit(); + } + } + + private void Initialize() + { + Verify.AreEqual(_initializationState, InitializationState.IsInitializing); + Verify.IsFalse(DesignMode); + + // This is causing freezing + if (!DesignMode) + { + OSVersionHelper.ThrowIfBeforeWindows10April2018(); + + if (!WebViewControlInitialized) + { + Verify.IsNull(Process); + + // Was not injected via ctor, create using defaults + Process = new WebViewControlProcess(new WebViewControlProcessOptions + { + PrivateNetworkClientServerCapability = _delayedPrivateNetworkEnabled + ? WebViewControlProcessCapabilityState.Enabled + : WebViewControlProcessCapabilityState.Disabled, + EnterpriseId = _delayedEnterpriseId + }); + _webViewControl = Process.CreateWebViewControlHost(Handle, ClientRectangle); + SubscribeEvents(); + + // Set values. They could have been changed in the designer + IsScriptNotifyAllowed = _delayedIsScriptNotifyAllowed; + IsIndexedDBEnabled = _delayedIsIndexDbEnabled; + IsJavaScriptEnabled = _delayedIsJavaScriptEnabled; + + // This will cause a navigation + Source = _delayedSource; + } + else + { + // Already provided control + SubscribeEvents(); + } + + _webViewControl.IsVisible = true; + } + + _initializationState = InitializationState.IsInitialized; + } + + private void SubscribeEvents() + { + if (_webViewControl == null) + { + return; + } + + _webViewControl.AcceleratorKeyPressed += OnAcceleratorKeyPressed; + _webViewControl.ContainsFullScreenElementChanged += OnContainsFullScreenElementChanged; + _webViewControl.ContentLoading += OnContentLoading; + _webViewControl.DOMContentLoaded += OnDOMContentLoaded; + _webViewControl.FrameContentLoading += OnFrameContentLoading; + _webViewControl.FrameDOMContentLoaded += OnFrameDOMContentLoaded; + _webViewControl.FrameNavigationCompleted += OnFrameNavigationCompleted; + _webViewControl.FrameNavigationStarting += OnFrameNavigationStarting; + _webViewControl.LongRunningScriptDetected += OnLongRunningScriptDetected; + _webViewControl.MoveFocusRequested += OnMoveFocusRequested; + _webViewControl.NavigationCompleted += OnNavigationCompleted; + _webViewControl.NavigationStarting += OnNavigationStarting; + _webViewControl.NewWindowRequested += OnNewWindowRequested; + _webViewControl.PermissionRequested += OnPermissionRequested; + _webViewControl.ScriptNotify += OnScriptNotify; + _webViewControl.UnsafeContentWarningDisplaying += OnUnsafeContentWarningDisplaying; + _webViewControl.UnsupportedUriSchemeIdentified += OnUnsupportedUriSchemeIdentified; + _webViewControl.UnviewableContentIdentified += OnUnviewableContentIdentified; + } + + private void UnsubscribeEvents() + { + if (_webViewControl == null) + { + return; + } + + _webViewControl.AcceleratorKeyPressed -= OnAcceleratorKeyPressed; + _webViewControl.ContainsFullScreenElementChanged -= OnContainsFullScreenElementChanged; + _webViewControl.ContentLoading -= OnContentLoading; + _webViewControl.DOMContentLoaded -= OnDOMContentLoaded; + _webViewControl.FrameContentLoading -= OnFrameContentLoading; + _webViewControl.FrameDOMContentLoaded -= OnFrameDOMContentLoaded; + _webViewControl.FrameNavigationCompleted -= OnFrameNavigationCompleted; + _webViewControl.FrameNavigationStarting -= OnFrameNavigationStarting; + _webViewControl.LongRunningScriptDetected -= OnLongRunningScriptDetected; + _webViewControl.MoveFocusRequested -= OnMoveFocusRequested; + _webViewControl.NavigationCompleted -= OnNavigationCompleted; + _webViewControl.NavigationStarting -= OnNavigationStarting; + _webViewControl.NewWindowRequested -= OnNewWindowRequested; + _webViewControl.PermissionRequested -= OnPermissionRequested; + _webViewControl.ScriptNotify -= OnScriptNotify; + _webViewControl.UnsafeContentWarningDisplaying -= OnUnsafeContentWarningDisplaying; + _webViewControl.UnsupportedUriSchemeIdentified -= OnUnsupportedUriSchemeIdentified; + _webViewControl.UnviewableContentIdentified -= OnUnviewableContentIdentified; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Navigation.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Navigation.cs new file mode 100644 index 000000000..ae02b07bc --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.Navigation.cs @@ -0,0 +1,99 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + // Navigation Journaling + + /// + public partial class WebView : IWebView + { + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool CanGoBack => _webViewControl?.CanGoBack ?? false; + + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool CanGoForward => _webViewControl?.CanGoForward ?? false; + + /// + public bool GoBack() + { + var retval = true; + try + { + _webViewControl.GoBack(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) + { + throw; + } + + retval = false; + } + + return retval; + } + + /// + public bool GoForward() + { + var retval = true; + try + { + _webViewControl.GoForward(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) + { + throw; + } + + retval = false; + } + + return retval; + } + + /// + public override void Refresh() + { + try + { + _webViewControl?.Refresh(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) + { + throw; + } + } + } + + /// + public void Stop() + { + try + { + _webViewControl?.Stop(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) + { + throw; + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.cs new file mode 100644 index 000000000..7988f8cba --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebView.cs @@ -0,0 +1,509 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Threading.Tasks; +using System.Windows.Forms; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Windows.Web.UI.Interop; +using WebViewControlDeferredPermissionRequest = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlDeferredPermissionRequest; +using WebViewControlMoveFocusReason = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlMoveFocusReason; +using WebViewControlProcess = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlProcess; +using WebViewControlSettings = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlSettings; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + /// + /// This class is an implementation of for Windows Forms. This class cannot be inherited. + /// + /// + /// + [Designer(typeof(WebViewDesigner))] + [DefaultProperty(Constants.ComponentDefaultProperty)] + [DefaultEvent(Constants.ComponentDefaultEvent)] + [Docking(DockingBehavior.AutoDock)] + [Description("Embeds a view into your application that renders web content using the Microsoft Edge rendering engine")] + [SecurityCritical] + [PermissionSet(SecurityAction.InheritanceDemand, Name = Constants.SecurityPermissionSetName)] + public sealed partial class WebView : Control, IWebView, ISupportInitialize + { + private string _delayedEnterpriseId = WebViewDefaults.EnterpriseId; + private bool _delayedIsIndexDbEnabled = WebViewDefaults.IsIndexedDBEnabled; + private bool _delayedIsJavaScriptEnabled = WebViewDefaults.IsJavaScriptEnabled; + private bool _delayedIsScriptNotifyAllowed = WebViewDefaults.IsScriptNotifyEnabled; + private bool _delayedPrivateNetworkEnabled = WebViewDefaults.IsPrivateNetworkEnabled; + private Uri _delayedSource; + private WebViewControlHost _webViewControl; + private bool _webViewControlClosed; + + /// + /// Initializes a new instance of the class. + /// + public WebView() + { + Paint += OnWebViewPaint; + Layout += OnWebViewLayout; + } + + /// + /// Gets a value indicating whether is supported in this environment. + /// + /// if this instance is supported; otherwise, . + public static bool IsSupported => WebViewControlHost.IsSupported; + + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool ContainsFullScreenElement + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.ContainsFullScreenElement ?? false; + } + } + + /// + /// Gets a value indicating whether the is currently in design mode. + /// + /// if the is currently in design mode; otherwise, . + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public new bool DesignMode => IsInDesignMode(); + + /// + /// Gets the document title. + /// + /// The document title. + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string DocumentTitle + { + get + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + return _webViewControl?.DocumentTitle; + } + } + + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.EnterpriseId)] + public string EnterpriseId + { + get + { + Verify.IsFalse(IsDisposed); + Verify.Implies(Initializing, !Initialized); + Verify.Implies(Initialized, WebViewControlInitialized); + return WebViewControlInitialized + ? _webViewControl.Process.EnterpriseId + : _delayedEnterpriseId; + } + + set + { + Verify.IsFalse(IsDisposed); + _delayedEnterpriseId = value; + if (!DesignMode) + { + EnsureInitialized(); + if (WebViewControlInitialized + && !string.Equals(_delayedEnterpriseId, _webViewControl.Process.EnterpriseId, StringComparison.OrdinalIgnoreCase)) + { + throw new InvalidOperationException(DesignerUI.E_CANNOT_CHANGE_AFTER_INIT); + } + } + } + } + + /// + /// Gets a value indicating whether this is focused. + /// + /// if focused; otherwise, . + /// + /// Returns if this or any of its child windows has focus. + public override bool Focused + { + get + { + if (base.Focused) + { + return true; + } + + var hwndFocus = UnsafeNativeMethods.GetFocus(); + var ret = hwndFocus != IntPtr.Zero + && NativeMethods.IsChild(new HandleRef(this, Handle), new HandleRef(null, hwndFocus)); + + return ret; + } + } + + /// + /// Gets or sets a value indicating whether this instance is indexed database enabled. + /// + /// if this instance is indexed database enabled; otherwise, . + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.IsIndexedDBEnabled)] + public bool IsIndexedDBEnabled + { + get + { + Verify.IsFalse(IsDisposed); + Verify.Implies(Initializing, !Initialized); + Verify.Implies(Initialized, WebViewControlInitialized); + return WebViewControlInitialized + ? _webViewControl.Settings.IsIndexedDBEnabled + : _delayedIsIndexDbEnabled; + } + + set + { + Verify.IsFalse(IsDisposed); + _delayedIsIndexDbEnabled = value; + if (!DesignMode) + { + EnsureInitialized(); + if (WebViewControlInitialized) + { + _webViewControl.Settings.IsIndexedDBEnabled = value; + } + } + } + } + + /// + /// Gets or sets a value indicating whether the use of JavaScript is allowed. + /// + /// true if the use of JavaScript is allowed; otherwise, false. + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.IsJavaScriptEnabled)] + public bool IsJavaScriptEnabled + { + get + { + Verify.IsFalse(IsDisposed); + Verify.Implies(Initializing, !Initialized); + Verify.Implies(Initialized, WebViewControlInitialized); + return WebViewControlInitialized + ? _webViewControl.Settings.IsJavaScriptEnabled + : _delayedIsJavaScriptEnabled; + } + + set + { + Verify.IsFalse(IsDisposed); + _delayedIsJavaScriptEnabled = value; + if (!DesignMode) + { + EnsureInitialized(); + if (WebViewControlInitialized) + { + _webViewControl.Settings.IsJavaScriptEnabled = value; + } + } + } + } + + /// + /// Gets or sets a value indicating whether is allowed; + /// + /// true if is allowed; otherwise, false. + /// + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.IsScriptNotifyEnabled)] + public bool IsScriptNotifyAllowed + { + get + { + Verify.IsFalse(IsDisposed); + Verify.Implies(Initializing, !Initialized); + Verify.Implies(Initialized, WebViewControlInitialized); + return WebViewControlInitialized + ? _webViewControl.Settings.IsScriptNotifyAllowed + : _delayedIsScriptNotifyAllowed; + } + + set + { + Verify.IsFalse(IsDisposed); + _delayedIsScriptNotifyAllowed = value; + if (!DesignMode) + { + EnsureInitialized(); + if (WebViewControlInitialized) + { + _webViewControl.Settings.IsScriptNotifyAllowed = value; + } + } + } + } + + /// + /// + /// Gets or sets a value indicating whether this instance is private network client server capability enabled. + /// + /// if this instance is private network client server capability enabled; otherwise, . + /// Value cannot be set once the control is initialized. + [StringResourceCategory(Constants.CategoryBehavior)] + [DefaultValue(WebViewDefaults.IsPrivateNetworkEnabled)] + public bool IsPrivateNetworkClientServerCapabilityEnabled + { + get + { + Verify.IsFalse(IsDisposed); + Verify.Implies(Initializing, !Initialized); + Verify.Implies(Initialized, WebViewControlInitialized); + return WebViewControlInitialized + ? _webViewControl.Process.IsPrivateNetworkClientServerCapabilityEnabled + : _delayedPrivateNetworkEnabled; + } + + set + { + Verify.IsFalse(IsDisposed); + _delayedPrivateNetworkEnabled = value; + if (!DesignMode) + { + EnsureInitialized(); + if (WebViewControlInitialized + && _webViewControl.Process.IsPrivateNetworkClientServerCapabilityEnabled != _delayedPrivateNetworkEnabled) + { + throw new InvalidOperationException(DesignerUI.E_CANNOT_CHANGE_AFTER_INIT); + } + } + } + } + + /// + /// Gets a object that the control is hosted in. + /// + /// The object that the control is hosted in. + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public WebViewControlProcess Process { get; private set; } + + /// + /// Gets a object that contains properties to enable or disable features. + /// + /// A object that contains properties to enable or disable features. + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public WebViewControlSettings Settings + { + get + { + Verify.IsFalse(IsDisposed); + Verify.Implies(Initializing, !Initialized); + Verify.Implies(Initialized, WebViewControlInitialized); + return _webViewControl?.Settings; + } + } + + /// + /// Gets or sets the Uniform Resource Identifier (URI) source of the HTML content to display in the . + /// + /// The Uniform Resource Identifier (URI) source of the HTML content to display in the . + [Bindable(true)] + [StringResourceCategory(Constants.CategoryBehavior)] + [StringResourceDescription(Constants.DescriptionSource)] + [TypeConverter(typeof(WebBrowserUriTypeConverter))] + [DefaultValue((string)null)] + public Uri Source + { + get + { + Verify.IsFalse(IsDisposed); + Verify.Implies(Initializing, !Initialized); + Verify.Implies(Initialized, WebViewControlInitialized); + return WebViewControlInitialized + ? _webViewControl.Source + : _delayedSource; + } + + set + { + Verify.IsFalse(IsDisposed); + _delayedSource = value; + if (!DesignMode) + { + EnsureInitialized(); + if (WebViewControlInitialized) + { + if (Initializing && value != null) + { + // During initialization if there is no Source set a navigation to "about:blank" will occur + _webViewControl.Source = value; + } + else if (Initialized) + { + // After the control is initialized send all values, regardless of if they are null + _webViewControl.Source = value; + } + } + } + } + } + + /// + /// Gets the version of EDGEHTML.DLL used by the control. + /// + /// The version of EDGEHTML.DLL used by the control. + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Version Version => _webViewControl?.Version; + + /// + /// Closes this control. + /// + public void Close() + { + var webViewControlAlreadyClosed = _webViewControlClosed; + _webViewControlClosed = true; + + // Unsubscribe all events: + UnsubscribeEvents(); + + if (!webViewControlAlreadyClosed) + { + _webViewControl?.Close(); + _webViewControl?.Dispose(); + } + + _webViewControl = null; + Process = null; + } + + /// + /// Gets the deferred permission request with the specified Id. + /// + /// The Id of the deferred permission request. + /// A object of the specified . + public WebViewControlDeferredPermissionRequest GetDeferredPermissionRequestById(uint id) => _webViewControl?.GetDeferredPermissionRequestById(id); + + /// + public string InvokeScript(string scriptName) => _webViewControl?.InvokeScript(scriptName); + + /// + public string InvokeScript(string scriptName, params string[] arguments) => _webViewControl?.InvokeScript(scriptName, arguments); + + /// + public string InvokeScript(string scriptName, IEnumerable arguments) => _webViewControl?.InvokeScript(scriptName, arguments); + + /// + public Task InvokeScriptAsync(string scriptName) => _webViewControl?.InvokeScriptAsync(scriptName); + + /// + public Task InvokeScriptAsync(string scriptName, params string[] arguments) => + _webViewControl?.InvokeScriptAsync(scriptName, arguments); + + /// + public Task InvokeScriptAsync(string scriptName, IEnumerable arguments) + => _webViewControl?.InvokeScriptAsync(scriptName, arguments); + + /// + public void MoveFocus(WebViewControlMoveFocusReason reason) => _webViewControl?.MoveFocus(reason); + + /// + public void Navigate(Uri source) => _webViewControl?.Navigate(source); + + /// + public void Navigate(string source) + { + Verify.IsFalse(IsDisposed); + Verify.IsNotNull(_webViewControl); + _webViewControl?.Navigate(source); + } + + /// + public void NavigateToLocal(string relativePath) => _webViewControl?.NavigateToLocal(relativePath); + + /// + public void NavigateToString(string text) => _webViewControl?.NavigateToString(text); + + /// + /// Releases the unmanaged resources used by the and its child controls and optionally releases the managed resources. + /// + /// to release both managed and unmanaged resources; to release only unmanaged resources. + protected override void Dispose(bool disposing) + { + try + { + if (disposing) + { + Close(); + _webViewControl?.Dispose(); + _webViewControl = null; + Process = null; + } + } + finally + { + base.Dispose(disposing); + } + } + + private bool IsInDesignMode() + { + var wpfDesignMode = LicenseManager.UsageMode == LicenseUsageMode.Designtime; + var formsDesignMode = System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv"; + return wpfDesignMode || formsDesignMode; + } + + // Ensures the WebViewControl's size stays in sync + private void OnWebViewLayout(object sender, LayoutEventArgs e) + { + // This event is raised once at startup with the AffectedControl and AffectedProperty properties + // on the LayoutEventArgs as null. + if (e.AffectedControl != null && e.AffectedProperty != null) + { + // Ensure that the affected property is the Bounds property to the control + if (e.AffectedProperty == nameof(Bounds)) + { + // In a typical control the DisplayRectangle is the interior canvas of the control + // and in a scrolling control the DisplayRectangle would be larger than the ClientRectangle. + // However, that is abstracted from us in WebView so we need to synchronize the ClientRectangle + // and permit WebView to handle scrolling based on the new viewport + UpdateBounds(ClientRectangle); + } + } + } + + private void OnWebViewPaint(object sender, PaintEventArgs e) + { + if (!DesignMode) + { + return; + } + + using (var g = e.Graphics) + { + using (var hb = new HatchBrush(HatchStyle.ZigZag, Color.Black, BackColor)) + { + g.FillRectangle(hb, ClientRectangle); + } + } + } + + private void UpdateBounds(Rectangle bounds) + { + _webViewControl?.UpdateBounds(bounds); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewControlHostExtensions.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewControlHostExtensions.cs new file mode 100644 index 000000000..8c0b3c46f --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewControlHostExtensions.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Drawing; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + internal static class WebViewControlHostExtensions + { + /// + /// Updates the location and size of . + /// + /// A instance + /// A containing numerical values that represent the location and size of the control. + /// + /// is . + /// is translated into a . + internal static void UpdateBounds(this WebViewControlHost host, Rectangle bounds) + { + Windows.Foundation.Rect CreateBounds() + { + return new Windows.Foundation.Rect( + bounds.X, + bounds.Y, + bounds.Width, + bounds.Height); + } + + if (host is null) + { + throw new ArgumentNullException(nameof(host)); + } + + host.UpdateBounds(CreateBounds()); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewControlProcessExtensions.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewControlProcessExtensions.cs new file mode 100644 index 000000000..23245671c --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewControlProcessExtensions.cs @@ -0,0 +1,200 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Drawing; +using System.Threading.Tasks; +using System.Windows.Forms; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Windows.Foundation; +using WebViewControlProcess = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlProcess; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + /// + /// Extends the funcionality of for Windows Forms. + /// + internal static class WebViewControlProcessExtensions + { + /// + /// Creates a within the context of . + /// + /// An instance of . + /// The parent window handle hosting the control. + /// A containing numerical values that represent the location and size of the control. + /// An instance. + /// + /// is equal to , or + /// is . + /// + internal static IWebView CreateWebView( + this WebViewControlProcess process, + IntPtr hostWindowHandle, + Rectangle bounds) + { + if (process is null) + { + throw new ArgumentNullException(nameof(process)); + } + + if (hostWindowHandle == IntPtr.Zero) + { + throw new ArgumentNullException(nameof(hostWindowHandle)); + } + + return new WebView(process.CreateWebViewControlHost(hostWindowHandle, bounds)); + } + + /// + /// Creates a within the context of . + /// + /// An instance of . + /// An instance of to parent the . + /// An instance. + /// Occurs when is . + internal static IWebView CreateWebView( + this WebViewControlProcess process, + Control control) + { + if (control == null) + { + throw new ArgumentNullException(nameof(control)); + } + + return process.CreateWebView(control, control.Bounds); + } + + /// + /// Creates a within the context of . + /// + /// An instance of . + /// An instance of to parent the . + /// A containing numerical values that represent the location and size of the control. + /// An instance. + /// Occurs when is . + internal static IWebView CreateWebView( + this WebViewControlProcess process, + Control control, + Rectangle bounds) + { + if (control == null) + { + throw new ArgumentNullException(nameof(control)); + } + + return process.CreateWebView(control.Handle, bounds); + } + + /// + /// Creates a within the context of . + /// + /// An instance of . + /// The parent window handle hosting the control. + /// A containing numerical values that represent the location and size of the control. + /// An instance. + /// + /// is equal to , or + /// is . + /// + internal static async Task CreateWebViewAsync( + this WebViewControlProcess process, + IntPtr hostWindowHandle, + Rectangle bounds) + { + if (process is null) + { + throw new ArgumentNullException(nameof(process)); + } + + if (hostWindowHandle == IntPtr.Zero) + { + throw new ArgumentNullException(nameof(hostWindowHandle)); + } + + return new WebView(await process.CreateWebViewControlHostAsync(hostWindowHandle, bounds).ConfigureAwait(false)); + } + + /// + /// Creates a within the context of . + /// + /// An instance of . + /// An instance of to parent the . + /// An instance. + /// Occurs when is . + internal static Task CreateWebViewAsync( + this WebViewControlProcess process, + Control control) + { + if (control == null) + { + throw new ArgumentNullException(nameof(control)); + } + + return process.CreateWebViewAsync(control, control.Bounds); + } + + /// + /// Creates a within the context of . + /// + /// An instance of . + /// An instance of to parent the . + /// A containing numerical values that represent the location and size of the control. + /// An instance. + /// Occurs when is . + internal static async Task CreateWebViewAsync( + this WebViewControlProcess process, + Control control, + Rectangle bounds) + { + if (control == null) + { + throw new ArgumentNullException(nameof(control)); + } + + var webViewControl = await process.CreateWebViewAsync(control.Handle, bounds).ConfigureAwait(false); + control.Controls.Add((Control)webViewControl); + return webViewControl; + } + + /// + /// Creates a within the context of . + /// + /// An instance of . + /// The parent window handle hosting the control. + /// A containing numerical values that represent the location and size of the control. + /// A . + /// is equal to + /// + internal static WebViewControlHost CreateWebViewControlHost( + this WebViewControlProcess process, + IntPtr hostWindowHandle, + Rectangle bounds) + { + Verify.IsNotNull(process); + Verify.IsFalse(hostWindowHandle == IntPtr.Zero); + var f = process.CreateWebViewControlHostAsync(hostWindowHandle, bounds).ConfigureAwait(false); + return f.GetAwaiter().GetResult(); + } + + /// + /// Asynchronously creates a within the context of . + /// + /// An instance of . + /// The parent window handle hosting the control. + /// A containing numerical values that represent the location and size of the control. + /// An asynchronous operation that completes with a . + /// is equal to + internal static Task CreateWebViewControlHostAsync( + this WebViewControlProcess process, + IntPtr hostWindowHandle, + Rectangle bounds) + { + Verify.IsNotNull(process); + Verify.IsFalse(hostWindowHandle == IntPtr.Zero); + + var rect = new Rect(bounds.X, bounds.Y, bounds.Width, bounds.Height); + return process.CreateWebViewControlHostAsync(hostWindowHandle, rect); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewDesigner.cs b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewDesigner.cs new file mode 100644 index 000000000..242003fc4 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.UI.Controls/WinForms/WebView/WebViewDesigner.cs @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections; +using System.ComponentModel; +using System.Security; +using System.Windows.Forms.Design; + +namespace Microsoft.Toolkit.Win32.UI.Controls.WinForms +{ + /// + internal class WebViewDesigner : ControlDesigner + { + public Uri Source + { + get => (Uri)ShadowProperties[nameof(WebView.Source)]; + set => ShadowProperties[nameof(WebView.Source)] = value; + } + + public bool IsScriptNotifyAllowed + { + get => (bool)ShadowProperties[nameof(WebView.IsScriptNotifyAllowed)]; + set => ShadowProperties[nameof(WebView.IsScriptNotifyAllowed)] = value; + } + + public bool IsJavaScriptEnabled + { + get => (bool)ShadowProperties[nameof(WebView.IsJavaScriptEnabled)]; + set => ShadowProperties[nameof(WebView.IsJavaScriptEnabled)] = value; + } + + public bool IsIndexedDBEnabled + { + get => (bool)ShadowProperties[nameof(WebView.IsIndexedDBEnabled)]; + set => ShadowProperties[nameof(WebView.IsIndexedDBEnabled)] = value; + } + + public bool IsPrivateNetworkClientServerCapabilityEnabled + { + get => (bool)ShadowProperties[nameof(WebView.IsPrivateNetworkClientServerCapabilityEnabled)]; + set => ShadowProperties[nameof(WebView.IsPrivateNetworkClientServerCapabilityEnabled)] = value; + } + + protected override InheritanceAttribute InheritanceAttribute + { + [SecurityCritical] + get + { + if (base.InheritanceAttribute == InheritanceAttribute.Inherited) + { + return InheritanceAttribute.InheritedReadOnly; + } + + return base.InheritanceAttribute; + } + } + + public override void InitializeNewComponent(IDictionary defaultValues) + { + base.InitializeNewComponent(defaultValues); + + var webView = (WebView)Component; + if (webView != null) + { + // Set MinimumSize in the designer, so that the control doesn't go to 0-height + webView.MinimumSize = new System.Drawing.Size(20, 20); + } + } + + protected override void PreFilterProperties(IDictionary properties) + { + base.PreFilterProperties(properties); + + // Handle shadowed properties + var shadowProps = new[] + { + nameof(WebView.Source), + nameof(WebView.IsScriptNotifyAllowed), + nameof(WebView.IsJavaScriptEnabled), + nameof(WebView.IsIndexedDBEnabled), + nameof(WebView.IsPrivateNetworkClientServerCapabilityEnabled) + }; + PropertyDescriptor prop; + Attribute[] empty = new Attribute[0]; + + for (var i = 0; i < shadowProps.Length; i++) + { + prop = (PropertyDescriptor)properties[shadowProps[i]]; + if (prop != null) + { + properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(WebViewDesigner), prop, empty); + } + } + } + } +} diff --git a/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.sln b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.sln new file mode 100644 index 000000000..06dc232c0 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.sln @@ -0,0 +1,62 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2018 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Win32.UI.Controls", "Microsoft.Toolkit.Win32.UI.Controls\Microsoft.Toolkit.Win32.UI.Controls.csproj", "{740413D5-C399-49F9-BE0A-1B5D45FB6A1C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Toolkit.Win32.Samples.WinForms.WebView", "Microsoft.Toolkit.Win32.Samples.WinForms.WebView\Microsoft.Toolkit.Win32.Samples.WinForms.WebView.csproj", "{D103E448-64B1-407C-B09E-7C61AF9F2740}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Toolkit.Win32.Samples.WPF.WebView", "Microsoft.Toolkit.Win32.Samples.WPF.WebView\Microsoft.Toolkit.Win32.Samples.WPF.WebView.csproj", "{2FE9AA6A-BD27-438F-9941-221033E4A1DD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9AFF2EBF-08DA-44C1-AC09-187561FF1147}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests.WebView.Shared", "Tests\UnitTests.WebView.Shared\UnitTests.WebView.Shared.csproj", "{B220BE88-944E-45D1-9248-6FAEF53868A3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests.WebView.WinForms", "Tests\UnitTests.WebView.WinForms\UnitTests.WebView.WinForms.csproj", "{10129749-7761-49B8-96B9-94BC833BA60B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests.WebView.WPF", "Tests\UnitTests.WebView.WPF\UnitTests.WebView.WPF.csproj", "{2E49400E-B114-4FAE-B743-6CB57B500E31}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {740413D5-C399-49F9-BE0A-1B5D45FB6A1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {740413D5-C399-49F9-BE0A-1B5D45FB6A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {740413D5-C399-49F9-BE0A-1B5D45FB6A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {740413D5-C399-49F9-BE0A-1B5D45FB6A1C}.Release|Any CPU.Build.0 = Release|Any CPU + {D103E448-64B1-407C-B09E-7C61AF9F2740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D103E448-64B1-407C-B09E-7C61AF9F2740}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D103E448-64B1-407C-B09E-7C61AF9F2740}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D103E448-64B1-407C-B09E-7C61AF9F2740}.Release|Any CPU.Build.0 = Release|Any CPU + {2FE9AA6A-BD27-438F-9941-221033E4A1DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2FE9AA6A-BD27-438F-9941-221033E4A1DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2FE9AA6A-BD27-438F-9941-221033E4A1DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2FE9AA6A-BD27-438F-9941-221033E4A1DD}.Release|Any CPU.Build.0 = Release|Any CPU + {B220BE88-944E-45D1-9248-6FAEF53868A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B220BE88-944E-45D1-9248-6FAEF53868A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B220BE88-944E-45D1-9248-6FAEF53868A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B220BE88-944E-45D1-9248-6FAEF53868A3}.Release|Any CPU.Build.0 = Release|Any CPU + {10129749-7761-49B8-96B9-94BC833BA60B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10129749-7761-49B8-96B9-94BC833BA60B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10129749-7761-49B8-96B9-94BC833BA60B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10129749-7761-49B8-96B9-94BC833BA60B}.Release|Any CPU.Build.0 = Release|Any CPU + {2E49400E-B114-4FAE-B743-6CB57B500E31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E49400E-B114-4FAE-B743-6CB57B500E31}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E49400E-B114-4FAE-B743-6CB57B500E31}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E49400E-B114-4FAE-B743-6CB57B500E31}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {B220BE88-944E-45D1-9248-6FAEF53868A3} = {9AFF2EBF-08DA-44C1-AC09-187561FF1147} + {10129749-7761-49B8-96B9-94BC833BA60B} = {9AFF2EBF-08DA-44C1-AC09-187561FF1147} + {2E49400E-B114-4FAE-B743-6CB57B500E31} = {9AFF2EBF-08DA-44C1-AC09-187561FF1147} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AFDF3CA9-FBAD-4C80-A08A-7B69D21D561E} + EndGlobalSection +EndGlobal diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/ContextSpecification.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/ContextSpecification.cs new file mode 100644 index 000000000..db7f2e037 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/ContextSpecification.cs @@ -0,0 +1,158 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared +{ + /// + /// Serves as a base class for implementing Behavior-Driven Development + /// + /// + /// Behavior-driven development (BDD) is based on test-driven development (TDD). TDD is a software development + /// methodology which essentially states that for each unit of software, a software developer must: + ///
    + ///
  • define a test set for the unit first;
  • + ///
  • then implement the unit;
  • + ///
  • >finally verify that the implementation of the unit makes the tests succeed.
  • + ///
+ /// TDD tends to get far into the detail, which doesn't resonate with non-technical individuals. BDD specifies that + /// tests of any unit of software should be specified in terms of the desired behavior of the unit. + /// BDD takes advantage of user stories to represent the intended behavior of components in a vertical slice, + /// experienced as a user or client would experience the behavior. This perspective keeps focus on and allows + /// the engineer to prioritize what is and isn't important to test. + /// User Stories represent needed conversations: + /// As a [role] + /// I want [some feature / behavior] + /// So that [some benefit / value] + /// Scenarios document the conversation took place, and what should be tested in BDD + /// Given [some initial state / context] + /// When [action occurs] + /// Then [this should be the result] + /// Example using an e-Commerce site concept: + /// As a Customer with Products in my Cart + /// I want to remove an Item from my Cart + /// so that I can change my mind about buying it + /// The scenario of the story breaks down into several elements: + ///
    + ///
  • A case where there are multiple items in the cart and the user removes one, leaving items in the cart
  • + ///
  • A case where there is a single item in the cart and the user removes one, leaving no items in the cart
  • + ///
  • Permutations of the above
  • + ///
+ /// BDD helps the clarification in the following way: + /// Given a Cart with multiple Items in it + /// When a single Item is removed + /// Then the other items are still in the Cart + /// Given a Cart with a single Item in it + /// When a single Item is removed + /// Then the Cart is empty + /// The _Then_ element can be compounded with multiple assertions. For example: + /// Given a Cart with a single Item in it + /// When a single Item is removed + /// Then the Cart is empty + /// And the Cart Subtotal is 0 + /// Notice that the language contains nouns with capital letters (Cart, Item, etc.) to drive out a native domain + /// language + /// (see Evans Fowler (2003). Domain-Driven Design: Tackling complexity in the Heart of Software. Prentice Hall.). + /// The + /// class uses a variation of the Arrange, Act, Assert behavior to allow BDD to work without extra tools within MSTest. + /// Example with code + /// + /// + /// [TestClass] + /// public class When_adding_a_single_item_to_an_empty_cart : ContextSpecification + /// { + /// ICart _cart; + /// + /// protected void override Given() + /// { + /// _cart = CartFactory.Create("TEST"); + /// _cart.AddItem(ProductFactory.Create("SKU")); + /// } + /// + /// protected void override When() + /// { + /// _cart.RemoveItem("SKU"); + /// } + /// + /// [TestMethod] + /// public void then_the_cart_is_empty() + /// { + /// Assert.AreEqual(1, _cart.TotalItems); + /// } + /// + /// [TestMethod] + /// public void then_the_cart_subtotal_is_zero() + /// { + /// Assert.AreEqual(0d, _cart.Subtotal); + /// } + /// } + /// + /// In the generated TRX file from MSTest, the test class and name are specified with the pass result: + /// + /// ------------------------------------------------------------------------------------------------------ + /// Result | Class name | Test Name + /// ------------------------------------------------------------------------------------------------------ + /// Passed When_adding_a_single_item_to_an_empty_cart then_the_cart_is_empty + /// Passed When_adding_a_single_item_to_an_empty_cart then_the_cart_subtotal_is_zero + /// + /// The TRX file is XML, and can be transformed to HTML to generate a report of capabilities of the system + /// automatically + /// during a build activity, yielding a "living spec". + /// More info on BDD: + /// http://en.wikipedia.org/wiki/Behavior-driven_development + /// http://channel9.msdn.com/Events/TechEd/NorthAmerica/2010/DPR302 + ///
+ [DebuggerStepThrough] + public abstract class ContextSpecification + { + public TestContext TestContext { get; set; } + + [TestCleanup] + public void TestCleanup() + { + Cleanup(); + } + + [TestInitialize] + public void TestInitialize() + { + // Arrange + Given(); + // Act + When(); + } + + protected virtual void Cleanup() + { + } + + protected virtual void Given() + { + } + + protected virtual void When() + { + } + + protected virtual void WriteLine(string message) + { +#if DEBUG + Debug.WriteLine(message); +#else + TestContext.WriteLine(message); +#endif + } + + protected virtual void WriteLine(string format, params object[] args) + { +#if DEBUG + Debug.WriteLine(format, args); +#else + TestContext.WriteLine(format, args); +#endif + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/HttpRequestUriEqualityComparer.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/HttpRequestUriEqualityComparer.cs new file mode 100644 index 000000000..1c1f57f8d --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/HttpRequestUriEqualityComparer.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared +{ + internal class HttpRequestUriEqualityComparer : IEqualityComparer + { + private HttpRequestUriEqualityComparer() + { + } + + internal static HttpRequestUriEqualityComparer Default => Nested.Instance; + + public bool Equals(Uri x, Uri y) + { + if (ReferenceEquals(x, y)) return true; + if (ReferenceEquals(x, null)) return false; + if (ReferenceEquals(y, null)) return false; + + return Uri.Compare(x, y, UriComponents.HttpRequestUrl, UriFormat.SafeUnescaped, StringComparison.OrdinalIgnoreCase) == + 0; + } + + public int GetHashCode(Uri obj) + { + return obj.GetHashCode(); + } + + private class Nested + { + internal static readonly HttpRequestUriEqualityComparer Instance = new HttpRequestUriEqualityComparer(); + + // Explict static ctor to tell compiler not to mark type as beforefieldinit + static Nested() { } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/OperatingSystemAssertions.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/OperatingSystemAssertions.cs new file mode 100644 index 000000000..ba8407514 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/OperatingSystemAssertions.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Interop.Win32; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared +{ + public static class OperatingSystemAssertions + { +#pragma warning disable RECS0154 // Parameter is never used + public static void OSBuildShouldBeAtLeast(this Assert _, int buildNumber) => AssertOperatingSystemSinceBuild(buildNumber); +#pragma warning restore RECS0154 // Parameter is never used + +#pragma warning disable RECS0154 // Parameter is never used + public static void OSBuildShouldBeAtLeast(this Assert _, TestConstants.Windows10Builds build) => AssertOperatingSystemSinceBuild((int)build); +#pragma warning restore RECS0154 // Parameter is never used + + private static void AssertOperatingSystemSinceBuild(int buildNumber) + { + var os = NativeMethods.RtlGetVersion(); + if (os.BuildNumber < buildNumber) + { + Assert.Inconclusive($"Required build number {buildNumber}. OS is {os.BuildNumber}"); + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/ProcessExtensions.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/ProcessExtensions.cs new file mode 100644 index 000000000..cb170464e --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/ProcessExtensions.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Management; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared +{ + public static class ProcessExtensions + { + // Define an extension method for type System.Process that returns the command + // line via WMI. + public static string GetCommandLine(this Process process) + { + string cmdLine = null; + using (var searcher = new ManagementObjectSearcher($"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {process.Id}")) + { + // By definition, the query returns at most 1 match, because the process + // is looked up by ID (which is unique by definition). + var matchEnum = searcher.Get().GetEnumerator(); + if (matchEnum.MoveNext()) // Move to the 1st item. + { + cmdLine = matchEnum.Current["CommandLine"]?.ToString(); + } + } + if (cmdLine == null) + { + // Not having found a command line implies 1 of 2 exceptions, which the + // WMI query masked: + // An "Access denied" exception due to lack of privileges. + // A "Cannot process request because the process () has exited." + // exception due to the process having terminated. + // We provoke the same exception again simply by accessing process.MainModule. + var dummy = process.MainModule; // Provoke exception. + } + return cmdLine; + } + + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/Properties/AssemblyInfo.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..1c3c02c25 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/Properties/AssemblyInfo.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; + + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("UnitTests.WebView.Shared")] +[assembly: AssemblyDescription("UnitTests.WebView.Shared")] \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.Builds.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.Builds.cs new file mode 100644 index 000000000..efc62dd36 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.Builds.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared +{ + public static partial class TestConstants + { + // Contains builds that offer functionality or bug fixes for WebView + public enum Windows10Builds + { + Unknown = 0, + InsiderFast17650 = 17650 + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.Uris.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.Uris.cs new file mode 100644 index 000000000..4d07acd14 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.Uris.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared +{ + public static partial class TestConstants + { + public static class Uris + { + /* + * As described in RFC 2606 and RFC 6761, the following domains are maintained for documentation purposes + */ + public static readonly Uri ExampleCom = new Uri("http://example.com", UriKind.Absolute); + public static readonly Uri ExampleNet = new Uri("http://example.net", UriKind.Absolute); + public static readonly Uri ExampleOrg = new Uri("http://example.org", UriKind.Absolute); + + // Local navigation: when using a null value for Source the uri is about:blank + public static readonly Uri AboutBlank = new Uri("about:blank"); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.cs new file mode 100644 index 000000000..fed734391 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/TestConstants.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared +{ + public static partial class TestConstants + { + public static class Timeouts + { + /// + /// A timeout of 30 seconds + /// + public const int Longest = Long * 3; + /// + /// A timeout of 20 seconds + /// + public const int Longer = Long * 2; + /// + /// A timeout of 10 seconds + /// + public const int Long = 10000; + /// + /// A timeout of 5 seconds + /// + public const int Medium = 5000; + /// + /// A timeout of 3 seconds + /// + public const int Short = Shorter * 3; + /// + /// A timeout of 1 second + /// + public const int Shorter = 1000; + } + public static class Categories + { + public const string Init = "Initialization"; + public const string Nav = "Navigation"; + public const string Des = "Designer"; + public const string Proc = "Process"; + public const string Wf = "WinForms"; + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/UnitTests.WebView.Shared.csproj b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/UnitTests.WebView.Shared.csproj new file mode 100644 index 000000000..6808aba95 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/UnitTests.WebView.Shared.csproj @@ -0,0 +1,67 @@ + + + + + Debug + AnyCPU + {B220BE88-944E-45D1-9248-6FAEF53868A3} + Library + Properties + Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared + Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared + v4.6.2 + true + + + + true + bin\Release\ + AnyCPU + TRACE + false + Off + prompt + full + + + TRACE;DEBUG + bin\Debug\ + Off + prompt + full + + + + + + + + + + + + + + + + + + + + 1.2.1 + + + 1.2.1 + + + + + {78d8b77b-2a55-4037-bcc9-b47806039d23} + Microsoft.Toolkit.Win32.UI.Controls + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/UriHostEqualityComparer.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/UriHostEqualityComparer.cs new file mode 100644 index 000000000..e1abf9894 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.Shared/UriHostEqualityComparer.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared +{ + internal class UriHostEqualityComparer : IEqualityComparer + { + private UriHostEqualityComparer() + { + } + + internal static UriHostEqualityComparer Default => Nested.Instance; + + public bool Equals(Uri x, Uri y) + { + if (ReferenceEquals(x, y)) return true; + if (ReferenceEquals(x, null)) return false; + if (ReferenceEquals(y, null)) return false; + + return Uri.Compare(x, y, UriComponents.Host, UriFormat.SafeUnescaped, StringComparison.OrdinalIgnoreCase) == + 0; + } + + public int GetHashCode(Uri obj) + { + return obj.GetHashCode(); + } + + private class Nested + { + internal static readonly UriHostEqualityComparer Instance = new UriHostEqualityComparer(); + + // Explict static ctor to tell compiler not to mark type as beforefieldinit + static Nested() { } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/FunctionalTests/Class1.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/FunctionalTests/Class1.cs new file mode 100644 index 000000000..0723d40d1 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/FunctionalTests/Class1.cs @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Windows; +using System.Windows.Controls; +using System.Windows.Threading; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WPF.WebView.FunctionalTests +{ + [TestClass] + public class Class1 : ContextSpecification + { + private Controls.WPF.WebView _webView; + private Window _window; + + protected override void Given() + { + _window = new Window + { + Title = TestContext.TestName, + Width = 1000, + Height = 800 + }; + + _window.Loaded += (o, e) => { WriteLine("Window.Loaded"); }; + _window.MouseEnter += (o, e) => { WriteLine("Window.MouseEnter"); }; + _window.GotFocus += (o, e) => { WriteLine("Window.GotFocus"); }; + _window.LostFocus += (o, e) => { WriteLine("Window.LostFocus"); }; + _window.Closing += (o, e) => { WriteLine("Window.Closing"); }; + _window.Closed += (o, e) => { WriteLine("Window.Closed"); }; + + + _webView = new Controls.WPF.WebView + { + Name = "WebView1", + HorizontalAlignment = HorizontalAlignment.Stretch, + VerticalAlignment = VerticalAlignment.Stretch, + Height = _window.Height, + Width = _window.Width, + MinHeight = 200, + MinWidth = 200 + }; + var dp = new DockPanel(); + dp.Children.Add(_webView); + _window.Content = dp; + + _webView.NavigationCompleted += (o, e) => + { + _window.Close(); + }; + } + + protected override void When() + { + _window.Loaded += (o, e) => + { + _webView.Navigate(TestConstants.Uris.ExampleCom); + }; + + + + ShowModalWindow(_window); + //_window.Show(); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Short)] + [Ignore] + public void Foo() + { + _webView.Process.ShouldNotBeNull(); + } + + protected override void Cleanup() + { + Dispatcher.CurrentDispatcher.InvokeShutdown(); + + _window.BringIntoView(); + _window.Close(); + + _webView.Dispose(); + _webView = null; + } + + private bool? ShowModalWindow(Window window) + { + // check if we are in the right thread + if (!window.Dispatcher.CheckAccess()) + { + // if not, initialize the delegate and invoke the right thread + ShowModalWindowCallback callback = ShowModalWindow; + return (bool?)window.Dispatcher.Invoke(callback, DispatcherPriority.Normal, window); + } + + // now we are in the right thread, show modal window + return window.ShowDialog(); + } + + private delegate bool? ShowModalWindowCallback(Window window); + + + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/Properties/AssemblyInfo.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..517b9057d --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; + +[assembly: AssemblyTitle("UnitTests.WebView.WPF")] +[assembly: AssemblyDescription("UnitTests.WebView.WPF")] \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/UnitTests.WebView.WPF.csproj b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/UnitTests.WebView.WPF.csproj new file mode 100644 index 000000000..3f9fdda1b --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WPF/UnitTests.WebView.WPF.csproj @@ -0,0 +1,81 @@ + + + + Debug + AnyCPU + {2E49400E-B114-4FAE-B743-6CB57B500E31} + Library + Properties + Microsoft.Toolkit.Win32.UI.Controls.Test.WPF.WebView + Microsoft.Toolkit.Win32.UI.Controls.Test.WPF.WebView + v4.6.2 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + true + + + + + + true + bin\Release\ + AnyCPU + TRACE + Off + prompt + full + + + bin\Debug\ + TRACE;DEBUG + Off + prompt + full + + + + + + + + + + + + + + + + + + {78d8b77b-2a55-4037-bcc9-b47806039d23} + Microsoft.Toolkit.Win32.UI.Controls + + + {b220be88-944e-45d1-9248-6faef53868a3} + UnitTests.WebView.Shared + + + + + + 1.0.4 + + + 1.2.1 + + + 1.2.1 + + + 1.1.20 + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/AssemblyInitializer.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/AssemblyInitializer.cs new file mode 100644 index 000000000..460d6e302 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/AssemblyInitializer.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Windows.Forms; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView +{ + [TestClass] + public class AssemblyInitializer + { + [AssemblyInitialize] + public static void AssemblyInitialize(TestContext context) + { + context.WriteLine("AssemblyInit"); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/AcceleratorKeys/AcceleratorKeysTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/AcceleratorKeys/AcceleratorKeysTests.cs new file mode 100644 index 000000000..babca7e72 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/AcceleratorKeys/AcceleratorKeysTests.cs @@ -0,0 +1,146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using WindowsInput.Native; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.AcceleratorKeys +{ + [TestClass] + public class WebControlReceiveTunnelAndBubble : HostFormWebViewContextSpecification + { + private int _inputCount; + private RoutedInputInfo[] _expectedRoutedInput; + private RoutedInputInfo[] _actualRoutedInput; + private string _content = @" + + + + + +
starting
+ + +"; + + protected override void Given() + { + _expectedRoutedInput = new[] + { + new RoutedInputInfo{RoutingStage = WebViewControlAcceleratorKeyRoutingStage.Tunneling, Key = VirtualKey.Control, IsKeyUp = false, ShouldHandle = false}, + new RoutedInputInfo{RoutingStage = WebViewControlAcceleratorKeyRoutingStage.Bubbling, Key = VirtualKey.Control, IsKeyUp = false, ShouldHandle = false}, + new RoutedInputInfo{RoutingStage = WebViewControlAcceleratorKeyRoutingStage.Tunneling, Key = VirtualKey.A, IsKeyUp = false, ShouldHandle = false}, + // The WebView actually handles the KeyDown for CTRL+A, so the app will not see the bubble phase + // Including it here in a comment for completeness and to make it clear that this is intentional + //new RoutedInputInfo{routingStage = WebViewControlAcceleratorKeyRoutingStage.Bubbling, virtualKey = VirtualKey.A, isKeyUp = false, shouldHandle = false}, + new RoutedInputInfo{RoutingStage = WebViewControlAcceleratorKeyRoutingStage.Tunneling, Key = VirtualKey.A, IsKeyUp = true, ShouldHandle = false}, + new RoutedInputInfo{RoutingStage = WebViewControlAcceleratorKeyRoutingStage.Bubbling, Key = VirtualKey.A, IsKeyUp = true, ShouldHandle = false}, + new RoutedInputInfo{RoutingStage = WebViewControlAcceleratorKeyRoutingStage.Tunneling, Key = VirtualKey.Control, IsKeyUp = true, ShouldHandle = false}, + new RoutedInputInfo{RoutingStage = WebViewControlAcceleratorKeyRoutingStage.Bubbling, Key = VirtualKey.Control, IsKeyUp = true, ShouldHandle = false} + }; + + _actualRoutedInput = new RoutedInputInfo[_expectedRoutedInput.Length]; + + base.Given(); + WebView.IsScriptNotifyAllowed = true; + WebView.IsJavaScriptEnabled = true; + WebView.NavigationCompleted += (o, e) => + { + if (!WebView.Focused) + { + WriteLine("Moving focus to WebView"); + Form.BringToFront(); + WebView.Focus(); + WebView.MoveFocus(WebViewControlMoveFocusReason.Programmatic); + } + else + { + WriteLine("WebView already has focus"); + } + }; + WebView.ScriptNotify += (o, e) => + { + WriteLine($"ScriptNotify received: '{e.Value ?? string.Empty}'"); + + if ("generateKeyPress".Equals(e.Value)) + { + Form.InputSimulator.Keyboard.ModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_A); + WriteLine("Keyboard input generated."); + } + else if ("keyboardInputFound".Equals(e.Value)) + { + WriteLine("Keyboard input received in WebView"); + } + }; + WebView.AcceleratorKeyPressed += (o, e) => + { + WriteLine("Received routed accelerator event"); + _actualRoutedInput[_inputCount] = new RoutedInputInfo() + { + RoutingStage = (WebViewControlAcceleratorKeyRoutingStage)e.RoutingStage, + Key = (VirtualKey)e.VirtualKey, + IsKeyUp = e.EventType == CoreAcceleratorKeyEventType.KeyUp + }; + + _inputCount++; + + if (_expectedRoutedInput.Length == _inputCount) + { + Form.Close(); + } + + }; + + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longer)] + [Ignore("Cannot reliably focus")] + public void InputsAreInTheExpectedOrder() + { + _actualRoutedInput.ShouldEqual(_expectedRoutedInput); + } + } + + public struct RoutedInputInfo + { + public WebViewControlAcceleratorKeyRoutingStage RoutingStage { get; set; } + public VirtualKey Key { get; set; } + public bool IsKeyUp { get; set; } + public bool ShouldHandle { get; set; } + + public override string ToString() + { + return $"Stage: {RoutingStage}, VirtualKey: {Key}, IsDown: {!IsKeyUp}, ShouldHandle: {ShouldHandle}"; + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/BlockTestStartEndContextSpecification.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/BlockTestStartEndContextSpecification.cs new file mode 100644 index 000000000..d1e1af75a --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/BlockTestStartEndContextSpecification.cs @@ -0,0 +1,194 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests +{ + [DebuggerStepThrough] + public abstract class BlockTestStartEndContextSpecification : WebViewContextSpecification + { + protected override void Given() + { + PrintStartEnd( + TestContext.TestName, + nameof(Given), + () => + { + TryAction(WaitForWindowsExceptionReporting); + base.Given(); + + TryAction(() => + { + if (WebView.Process == null) return; + + var process = Process.GetProcessById((int)WebView.Process.ProcessId); + if (process != null) + { + WriteLine($"[{process.Id}] {process.ProcessName}"); + } + + }); + }); + } + + + + protected override void Cleanup() + { + PrintStartEnd( + TestContext.TestName, + nameof(Cleanup), + () => + { + TryAction(WaitForWindowsExceptionReporting); + + // The layer above us should have cleaned everything up; if not log information about it here and clean up for the next test + TryAction(() => + { + if (WebView?.Process != null) + { + var closeRequested = false; + var closeMainWindowRequested = false; + var orphan = false; + + TryAction(PrintProcessDetails); + + while (WebView.Process.ProcessId != 0) + { + orphan = true; + var process = Process.GetProcessById((int)WebView.Process.ProcessId); + if (process != null) + { + WriteLine( + $"{process.ProcessName} (PID: {process.Id}) found; waiting for exit..."); + + if (!process.WaitForExit(TestConstants.Timeouts.Shorter)) + { + var msg = $"{process.ProcessName} (PID: {process.Id}) did not exit as expected; "; + if (!closeRequested && !closeMainWindowRequested) + { + closeRequested = true; + msg += " Process.Close requested..."; + process.Close(); + } + else if (closeRequested && !closeMainWindowRequested) + { + closeMainWindowRequested = true; + msg += " Process.CloseMainWindow requested..."; + process.CloseMainWindow(); + } + else + { + msg += " Process.Kill requested..."; + process.Kill(); + } + WriteLine(msg); + } + } + } + + if (!orphan) + { + WriteLine("WebView processes were cleaned up as expected"); + } + } + + base.Cleanup(); + }); + }); + } + + private void PrintProcessDetails(string processName) + { + var processes = Process.GetProcessesByName(processName); + var msg = $"Running instances of {processName}.exe: "; + if (processes.Length == 0) + { + msg += " NONE\r\n"; + WriteLine(msg); + } + else + { + WriteLine(msg); + var header = "\r\n\r\nName\t\t\tPID\tTitle\r\n------------------------------------------------"; + WriteLine(header); + foreach (var process in processes) + { + WriteLine($"{process.ProcessName}\t{process.Id}\t{process.MainWindowTitle}"); + } + + WriteLine(""); + } + } + + private void PrintProcessDetails() + { + PrintProcessDetails("WWAHost"); + PrintProcessDetails("Win32WebViewHost"); + } + + private void WaitForWindowsExceptionReporting() + { + // We may have had a crash, wait until WER is completed + var processes = Process.GetProcessesByName("WerFault"); + if (processes.Any()) + { + var msg = $"Found {processes.Length} instances of WerFault.exe; waiting for those to exit..."; + WriteLine(msg); + + var tasks = new Task[processes.Length]; + for (var i = 0; i < processes.Length; i++) + { + var p = processes[i]; + var pid = p.Id; + var name = p.ProcessName; + var cl = p.GetCommandLine(); + var testName = string.Empty; + var regexMatch = Regex.Match(cl, @"-p\s(?\d{1,7})", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + if (regexMatch.Success) + { + if (uint.TryParse(regexMatch.Groups["id"].Value, out var testPid)) + { + // NOTE: The PID for Win32WebViewHost.exe is not exposed, so we can't wait for that + var testForProcessId = GetTestNameForProcessId(testPid); + if (!string.IsNullOrEmpty(testForProcessId)) + { + testName = testForProcessId; + } + } + } + + msg = $"\t[{pid}] {name} (\"{cl}\") {testName}"; + WriteLine(msg); + + // Only wait if WER is gathering information from one of our tests + if (string.IsNullOrEmpty(testName)) + { + tasks[i] = Task.CompletedTask; + } + else + { + tasks[i] = Task.Run(() => p.WaitForExit()); + } + } + + + Task.WaitAll(tasks); + } + } + + + + + } + + +} + diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Close/CloseTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Close/CloseTests.cs new file mode 100644 index 000000000..ac6849c24 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Close/CloseTests.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Close +{ + [TestClass] + public class CallCloseOnceAfterInit : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + ((ISupportInitialize) WebView).BeginInit(); + ((ISupportInitialize) WebView).EndInit(); + + WebView.ShouldNotBeNull(); + WebView.Process.ShouldNotBeNull(); + } + + protected override void When() + { + WebView.Close(); + } + + [TestMethod] + public void Close() + { + WebView.Process.ShouldBeNull(); + } + } + + [TestClass] + public class CallCloseTwiceAfterInit : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + ((ISupportInitialize)WebView).BeginInit(); + ((ISupportInitialize)WebView).EndInit(); + + WebView.ShouldNotBeNull(); + WebView.Process.ShouldNotBeNull(); + } + + protected override void When() + { + WebView.Close(); + WebView.Close(); + } + + [TestMethod] + public void Close() + { + WebView.Process.ShouldBeNull(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ControlProcess/EnterpriseIdTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ControlProcess/EnterpriseIdTests.cs new file mode 100644 index 000000000..4b6c55a23 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ControlProcess/EnterpriseIdTests.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Interop; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.ControlProcess +{ + [TestClass] + public class EnterpriseIdTests : ProcessFactoryWebViewContextSpecification + { + protected override void Given() + { + // TODO: Does Windows Information Protection work for WinForms? + OSVersionHelper.UseWindowsInformationProtectionApi.ShouldBeTrue("The operating system does not support Windows Information Protection (WIP) or WIP is not enabled on this device."); + + var o = new WebViewControlProcessOptions() {EnterpriseId = nameof(EnterpriseIdTests)}; + CreateWebView(o); + } + + [TestMethod] + public void Unknown() + { + Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Inconclusive("No implemented behavior for enlightened LOB using WebView."); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/Ctor.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/Ctor.cs new file mode 100644 index 000000000..d063cf489 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/Ctor.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Ctor +{ + [TestClass] + public class CreationTests + { + [TestMethod] + [TestCategory(TestConstants.Categories.Init)] + public void CanInitializeCtorBeginEndInit() + { + var wv = new UI.Controls.WinForms.WebView(); + ((ISupportInitialize)wv).BeginInit(); + ((ISupportInitialize)wv).EndInit(); + } + + [TestMethod] + [TestCategory(TestConstants.Categories.Init)] + public void CanInitializeCtorOnly() + { + var wv = new UI.Controls.WinForms.WebView(); + wv.Process.ShouldBeNull(); + } + + [TestMethod] + [TestCategory(TestConstants.Categories.Init)] + public void DesignerPropertyEqualsSettingsProperty() + { + var wv = new UI.Controls.WinForms.WebView(); + ((ISupportInitialize)wv).BeginInit(); + wv.IsScriptNotifyAllowed = !wv.IsScriptNotifyAllowed; + ((ISupportInitialize)wv).EndInit(); + + wv.IsScriptNotifyAllowed.ShouldEqual(wv.Settings.IsScriptNotifyAllowed); + } + + + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/DesignerPropertySettingsTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/DesignerPropertySettingsTests.cs new file mode 100644 index 000000000..4bb82d37c --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/DesignerPropertySettingsTests.cs @@ -0,0 +1,249 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Ctor +{ + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class ScriptNotifyPropertySetBetweenBeginEndInit : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + } + + protected override void When() + { + ((ISupportInitialize)WebView).BeginInit(); + WebView.IsScriptNotifyAllowed = false; + ((ISupportInitialize)WebView).EndInit(); + } + + [TestMethod] + public void ScriptNotifyIsDisabled() + { + WebView.IsScriptNotifyAllowed.ShouldBeFalse(); + WebView.Settings.IsScriptNotifyAllowed.ShouldBeFalse(); + WebView.Settings.IsScriptNotifyAllowed.ShouldEqual(WebView.IsScriptNotifyAllowed); + } + + protected override void Cleanup() + { + WebView.Dispose(); + base.Cleanup(); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class ScriptNotifyPropertySetAfterEndInit : HostFormWebViewContextSpecification + { + private bool _expected; + + protected override void Given() + { + base.Given(); + _expected = WebView.IsScriptNotifyAllowed != true; + } + + protected override void When() + { + WebView.IsScriptNotifyAllowed = _expected; + } + + [TestMethod] + public void PropertyEqualsSettingsValue() + { + WebView.Settings.IsScriptNotifyAllowed.ShouldEqual(WebView.IsScriptNotifyAllowed); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class ScriptNotifySettingSetAfterEndInit : HostFormWebViewContextSpecification + { + private bool _expected; + + protected override void Given() + { + base.Given(); + _expected = WebView.IsScriptNotifyAllowed != true; + } + + protected override void When() + { + WebView.Settings.IsScriptNotifyAllowed = _expected; + } + + [TestMethod] + public void PropertyEqualsSettingsValue() + { + WebView.IsScriptNotifyAllowed.ShouldEqual(WebView.Settings.IsScriptNotifyAllowed); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class JavaScriptPropertySetBetweenBeginEndInit : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + } + + protected override void When() + { + ((ISupportInitialize)WebView).BeginInit(); + WebView.IsJavaScriptEnabled = false; + ((ISupportInitialize)WebView).EndInit(); + } + + [TestMethod] + public void ScriptNotifyIsDisabled() + { + WebView.IsJavaScriptEnabled.ShouldBeFalse(); + WebView.Settings.IsJavaScriptEnabled.ShouldBeFalse(); + WebView.Settings.IsJavaScriptEnabled.ShouldEqual(WebView.IsJavaScriptEnabled); + } + + protected override void Cleanup() + { + WebView.Close(); + base.Cleanup(); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class JavaScriptPropertySetAfterEndInit : HostFormWebViewContextSpecification + { + private bool _expected; + + protected override void Given() + { + base.Given(); + _expected = WebView.IsJavaScriptEnabled != true; + } + + protected override void When() + { + WebView.IsJavaScriptEnabled = _expected; + } + + [TestMethod] + public void PropertyEqualsSettingsValue() + { + WebView.Settings.IsJavaScriptEnabled.ShouldEqual(WebView.IsJavaScriptEnabled); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class JavaScriptSettingSetAfterEndInit : HostFormWebViewContextSpecification + { + private bool _expected; + + protected override void Given() + { + base.Given(); + _expected = WebView.IsJavaScriptEnabled != true; + } + + protected override void When() + { + WebView.Settings.IsJavaScriptEnabled = _expected; + } + + [TestMethod] + public void PropertyEqualsSettingsValue() + { + WebView.IsJavaScriptEnabled.ShouldEqual(WebView.Settings.IsJavaScriptEnabled); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class IndexDbPropertySetAfterEndInit : HostFormWebViewContextSpecification + { + private bool _expected; + + protected override void Given() + { + base.Given(); + _expected = WebView.IsIndexedDBEnabled != true; + } + + protected override void When() + { + WebView.IsIndexedDBEnabled = _expected; + } + + [TestMethod] + public void PropertyEqualsSettingsValue() + { + WebView.Settings.IsIndexedDBEnabled.ShouldEqual(WebView.IsIndexedDBEnabled); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class IndexDbSettingSetAfterEndInit : HostFormWebViewContextSpecification + { + private bool _expected; + + protected override void Given() + { + base.Given(); + _expected = WebView.IsIndexedDBEnabled != true; + } + + protected override void When() + { + WebView.Settings.IsIndexedDBEnabled = _expected; + } + + [TestMethod] + public void PropertyEqualsSettingsValue() + { + WebView.IsIndexedDBEnabled.ShouldEqual(WebView.Settings.IsIndexedDBEnabled); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class IndexDbPropertySetBetweenBeginEndInit : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + } + + protected override void When() + { + // Behavior like the designer + ((ISupportInitialize)WebView).BeginInit(); + WebView.IsIndexedDBEnabled = false; + ((ISupportInitialize)WebView).EndInit(); + } + + [TestMethod] + public void ScriptNotifyIsDisabled() + { + WebView.IsIndexedDBEnabled.ShouldBeFalse(); + WebView.Settings.IsIndexedDBEnabled.ShouldBeFalse(); + WebView.Settings.IsIndexedDBEnabled.ShouldEqual(WebView.IsIndexedDBEnabled); + } + + protected override void Cleanup() + { + WebView.Close(); + base.Cleanup(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/DesignerTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/DesignerTests.cs new file mode 100644 index 000000000..a74babffe --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/DesignerTests.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Ctor +{ + //TODO: Designer mode + +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/ISupportInitializeDefaultsTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/ISupportInitializeDefaultsTests.cs new file mode 100644 index 000000000..8a86fdd36 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/ISupportInitializeDefaultsTests.cs @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Ctor +{ + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class WebViewBeginEndInitDefaults : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + } + + protected override void When() + { + ((ISupportInitialize)WebView).BeginInit(); + ((ISupportInitialize)WebView).EndInit(); + } + + [TestMethod] + public void IndexDBEnabled() + { + WebView.IsIndexedDBEnabled.ShouldEqual(WebViewDefaults.IsIndexedDBEnabled); + } + + [TestMethod] + public void JavaScriptEnabled() + { + WebView.IsJavaScriptEnabled.ShouldEqual(WebViewDefaults.IsJavaScriptEnabled); + } + + [TestMethod] + public void ScriptNotifyDisabled() + { + WebView.IsScriptNotifyAllowed.ShouldEqual(WebViewDefaults.IsScriptNotifyEnabled); + } + + [TestMethod] + public void PrivateNetworkDisabled() + { + WebView.IsPrivateNetworkClientServerCapabilityEnabled.ShouldEqual(WebViewDefaults.IsPrivateNetworkEnabled); + } + + protected override void Cleanup() + { + WebView.Dispose(); + + base.Cleanup(); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class WebViewControlProcessUnavailableBeforeEndInit : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + } + + [TestMethod] + public void ProcessIsUnavailable() + { + WebView.Process.ShouldBeNull(); + } + + protected override void Cleanup() + { + WebView.Close(); + base.Cleanup(); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class WebViewControlProcessAvailableAfterEndInit : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + ((ISupportInitialize)WebView).BeginInit(); + ((ISupportInitialize)WebView).EndInit(); + } + + [TestMethod] + public void ProcessIsAvailable() + { + WebView.Process.ShouldNotBeNull(); + } + + [TestMethod] + public void SettingsIsAvailable() + { + WebView.Settings.ShouldNotBeNull(); + } + + protected override void Cleanup() + { + WebView.Close(); + base.Cleanup(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/MultipleWebViews.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/MultipleWebViews.cs new file mode 100644 index 000000000..80e33efa3 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/MultipleWebViews.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.Toolkit.Win32.UI.Controls.WinForms; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Ctor +{ + [TestClass] + public class MultipleWebViewsTests : HostFormWebViewContextSpecification + { + private Controls.WinForms.WebView WebView2 { get; set; } + + protected override void Given() + { + // Perform check to see if we can run before we get too far + Assert.That.OSBuildShouldBeAtLeast(TestConstants.Windows10Builds.InsiderFast17650); + + base.Given(); + } + + protected override void When() + { + WebView2 = (Controls.WinForms.WebView)WebView.Process.CreateWebView(Form.Handle, Rectangle.Empty); + } + + [TestMethod] + public void SecondWebViewIsCreated() + { + WebView2.ShouldNotBeNull(); + } + + [TestMethod] + public void SecondWebViewInSameProcess() + { + WebView2.Process.ProcessId.ShouldEqual(WebView.Process.ProcessId); + } + + protected override void Cleanup() + { + WebView2?.Dispose(); + WebView2 = null; + + base.Cleanup(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/WebViewControlProcessCreateWebViewAsyncTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/WebViewControlProcessCreateWebViewAsyncTests.cs new file mode 100644 index 000000000..a02c54b96 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Ctor/WebViewControlProcessCreateWebViewAsyncTests.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.Toolkit.Win32.UI.Controls.WinForms; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Ctor +{ + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + public class WebViewControlProcessCreateWebViewAsync : ProcessFactoryWebViewContextSpecification + { + [TestMethod] + public void ProcessIsNotNull() + { + WebViewControlProcess.ShouldNotBeNull(); + } + + [TestMethod] + public void WebViewIsNotNull() + { + WebView.ShouldNotBeNull(); + } + + [TestMethod] + public void WebViewProcessIsNotNull() + { + WebView.Process.ShouldNotBeNull(); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Init)] + [Ignore("Unstable. The remote procedure call failed. (Exception from HRESULT: 0x800706BE).")] + public class MultipleWebViewsFromOneProcess : ProcessFactoryWebViewContextSpecification + { + private UI.Controls.WinForms.WebView _webView2; + + protected override void When() + { + _webView2 = new UI.Controls.WinForms.WebView(WebViewControlProcess.CreateWebViewControlHost(Form.Handle, Form.ClientRectangle)); + } + + [TestMethod] + public void CanCreateSecondWebView() + { + _webView2.ShouldNotBeNull(); + } + + // TODO: Assert they have the same PID + [TestMethod] + public void BothWebViewHaveSameProcessId() + { + _webView2.Process.ProcessId.ShouldEqual(WebView.Process.ProcessId, "Expected same PID"); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Designer/DesignerTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Designer/DesignerTests.cs new file mode 100644 index 000000000..4574eee33 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Designer/DesignerTests.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Designer +{ + //TODO: Designer mode + [TestClass] + [TestCategory(TestConstants.Categories.Des)] + public class ScriptNotifyPropertySet : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView() + { + IsScriptNotifyAllowed = true + }; + } + + protected override void When() + { + WebView.IsScriptNotifyAllowed = false; + } + + [TestMethod] + //[Timeout(TestConstants.Timeouts.Short)] + public void ScriptNotifyIsDisabled() + { + WebView.IsScriptNotifyAllowed.ShouldBeFalse(); + } + + protected override void Cleanup() + { + try + { + WebView.Close(); + } + finally + { + base.Cleanup(); + } + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Des)] + public class BeginInitAfterScriptNotifyPropertySet : BlockTestStartEndContextSpecification + { + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + } + + protected override void When() + { + WebView.IsScriptNotifyAllowed = false; + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Short)] + [ExpectedException(typeof(InvalidOperationException))] + public void ControlIsAlreadyInitialized() + { + ((ISupportInitialize)WebView).BeginInit(); + } + + protected override void Cleanup() + { + try + { + WebView.Close(); + } + finally + { + base.Cleanup(); + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/DocumentTitle/DocumentTitleTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/DocumentTitle/DocumentTitleTests.cs new file mode 100644 index 000000000..2bec21d59 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/DocumentTitle/DocumentTitleTests.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.DocumentTitle +{ + [TestClass] + public class DocumentTitleNavigateToStringTest : HostFormWebViewContextSpecification + { + public string Expected { get; set; } = "Hello World!"; + private string _actual; + private string _content; + + protected override void Given() + { + _content = $@" + +{Expected} + +

DocumentTitleNavigateToStringTest

+ + +"; + + base.Given(); + WebView.NavigationCompleted += (o, e) => + { + _actual = WebView.DocumentTitle; + Form.Close(); + }; + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + public void DocumentTitleIsExpectedValue() + { + _actual.ShouldEqual(Expected); + } + } + + [TestClass] + public class DocumentTitleNavigateTest : DocumentTitleNavigateToStringTest + { + protected override void Given() + { + Expected = "Example Domain"; + + base.Given(); + } + + protected override void When() + { + NavigateAndWaitForFormClose(TestConstants.Uris.ExampleCom); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/FullScreen/FullScreenTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/FullScreen/FullScreenTests.cs new file mode 100644 index 000000000..6820750c8 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/FullScreen/FullScreenTests.cs @@ -0,0 +1,110 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using WindowsInput.Native; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.FullScreen +{ + [TestClass] + public class WhenFullScreenElement : HostFormWebViewContextSpecification + { + private bool _fullScreenEventCalled; + private bool _fullScreenBeforeEvent; + private bool _fullScreenAfterEvent; + private string _content; + protected override void Given() + { + _content = @" + +WhenFullScreenElement + +

WhenFullScreenElement

+ +
starting
+ + + +"; + + base.Given(); + + WebView.IsJavaScriptEnabled = true; + WebView.IsScriptNotifyAllowed = true; + + _fullScreenBeforeEvent = WebView.ContainsFullScreenElement; + + WebView.ScriptNotify += (o, e) => + { + WriteLine($"ScriptNotify received: '{e.Value ?? string.Empty}"); + + if ("generateKeyPress".Equals(e.Value)) + { + Form.Focus(); + Form.InputSimulator.Keyboard.KeyPress(VirtualKeyCode.TAB); + Form.InputSimulator.Keyboard.KeyPress(VirtualKeyCode.RETURN); + Form.InputSimulator.Keyboard.KeyPress(VirtualKeyCode.ESCAPE); + } + }; + + WebView.DOMContentLoaded += (o, e) => + { + WebView.MoveFocus(WebViewControlMoveFocusReason.Programmatic); + }; + + WebView.ContainsFullScreenElementChanged += (o, e) => + { + WriteLine($"{nameof(WebView.ContainsFullScreenElementChanged)}: Args: {e ?? string.Empty}"); + _fullScreenEventCalled = true; + _fullScreenAfterEvent = WebView.ContainsFullScreenElement; + Form.Close(); + }; + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Medium)] + [Ignore("WebView focus unreliable")] + public void FullScreenEventRaisedWhenFullScreenRequested() + { + _fullScreenEventCalled.ShouldBeTrue(); + _fullScreenBeforeEvent.ShouldBeFalse(); + _fullScreenAfterEvent.ShouldBeTrue(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/HostFormWebViewContextSpecification.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/HostFormWebViewContextSpecification.cs new file mode 100644 index 000000000..20fb93e01 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/HostFormWebViewContextSpecification.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System.Windows.Forms; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests +{ + [TestCategory(TestConstants.Categories.Des)] + public abstract class HostFormWebViewContextSpecification : WebViewFormContextSpecification + { + protected override void CreateWebView() + { + // This is what Windows Forms designer emits + WebView = new UI.Controls.WinForms.WebView(); + ((ISupportInitialize)WebView).BeginInit(); + Form.SuspendLayout(); + WebView.Dock = DockStyle.Fill; + WebView.Size = Form.ClientSize; + WebView.IsScriptNotifyAllowed = true; + WebView.IsIndexedDBEnabled = true; + WebView.IsJavaScriptEnabled = true; + WebView.Visible = true; + Form.Controls.Add(WebView); + ((ISupportInitialize)WebView).EndInit(); + Form.ResumeLayout(false); + Form.PerformLayout(); + + WebView.IsScriptNotifyAllowed.ShouldBeTrue(); + WebView.IsIndexedDBEnabled.ShouldBeTrue(); + WebView.IsJavaScriptEnabled.ShouldBeTrue(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Input/MousewheelTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Input/MousewheelTests.cs new file mode 100644 index 000000000..e7728952f --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Input/MousewheelTests.cs @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Input +{ + [TestClass] + public class MousewheelTests : HostFormWebViewContextSpecification + { + private string _content = @" + + + + + +

Mouse Wheel Chaining Test

+
starting
+ + + +"; + + protected override void Given() + { + base.Given(); + + WebView.IsScriptNotifyAllowed = true; + WebView.IsJavaScriptEnabled = true; + WebView.NavigationCompleted += (o, e) => + { + if (!WebView.Focused) + { + WriteLine("Moving focus to WebView"); + Form.BringToFront(); + Form.Focus(); + WebView.Focus(); + WebView.MoveFocus(WebViewControlMoveFocusReason.Programmatic); + Form.InputSimulator.Mouse.LeftButtonClick(); + } + else + { + WriteLine("WebView already has focus"); + } + }; + WebView.ScriptNotify += (o, e) => + { + WriteLine($"ScriptNotify received: {e.Value ?? String.Empty}"); + + if ("generatedMouseWheelInput".Equals(e.Value)) + { + // When the page is loaded and attached its mouse wheel event listener it signals us to send mouse wheel input + if (!WebView.Focused) + { + WriteLine("Moving focus to WebView"); + Form.BringToFront(); + WebView.Focus(); + WebView.MoveFocus(WebViewControlMoveFocusReason.Programmatic); + } + else + { + WriteLine("WebView already has focus"); + } + Form.InputSimulator.Mouse.VerticalScroll(-500); + + } + else if ("mouseWheelInputFound".Equals(e.Value)) + { + Form.Close(); + } + else + { + Verify.Fail("Unexpected ScriptNotify value: " + e.Value); + } + }; + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Short)] + [Ignore("Cannot reliably focus")] + public void MouseWheelEventsChained() + { + + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/InvokeScript/InvokeScriptTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/InvokeScript/InvokeScriptTests.cs new file mode 100644 index 000000000..a10c9d976 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/InvokeScript/InvokeScriptTests.cs @@ -0,0 +1,175 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.InvokeScript +{ + [TestClass] + public class InvokeScriptAsyncNoArgumentsTests : HostFormWebViewContextSpecification + { + private static string _expected = "exampleReturnValue"; + private string _actual; + private readonly string _content = @" +

" + nameof(InvokeScriptAsyncNoArgumentsTests) + @"

+ +"; + + protected override void Given() + { + base.Given(); + + WebView.NavigationCompleted += (a, b) => + { + _actual = WebView.InvokeScriptAsync("getTextContent", null).GetAwaiter().GetResult(); + Form.Close(); + }; + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + [Ignore("Causing test run to abort")] + public void InvokedScriptReturnedExpectedValue() + { + _actual.ShouldEqual(_expected); + } + } + + [TestClass] + public class InvokeScriptNoArgumentsTests : HostFormWebViewContextSpecification + { + private static string _expected = "exampleReturnValue"; + private string _actual; + private readonly string _content = @" +

" + nameof(InvokeScriptNoArgumentsTests) + @"

+ +"; + + protected override void Given() + { + base.Given(); + + WebView.NavigationCompleted += (a, b) => + { + _actual = (string)WebView.InvokeScript("getTextContent", null); + Form.Close(); + }; + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + [Ignore("Causing test run to abort")] + public void InvokedScriptReturnedExpectedValue() + { + _actual.ShouldEqual(_expected); + } + } + + [TestClass] + public class InvokeScriptAsyncOneArgumentTests : HostFormWebViewContextSpecification + { + private static string _expected = "exampleParameter"; + private string _actual; + private readonly string _content = @" +

" + nameof(InvokeScriptAsyncOneArgumentTests) + @"

+ +"; + + protected override void Given() + { + base.Given(); + + WebView.NavigationCompleted += (a, b) => + { + WriteLine($"Calling {nameof(WebView.InvokeScriptAsync)}"); +#pragma warning disable 4014 + NewMethod(a as UI.Controls.WinForms.WebView); +#pragma warning restore 4014 + }; + } + + private async Task NewMethod(UI.Controls.WinForms.WebView a) + { + _actual = await a.InvokeScriptAsync("echoOneArgument", "exampleParameter").ConfigureAwait(false); + Form.Close(); + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + [Ignore("Causing test run to abort")] + public void InvokedScriptReturnedExpectedValue() + { + _actual.ShouldEqual(_expected); + } + } + + [TestClass] + public class InvokeScriptOneArgumentTests : HostFormWebViewContextSpecification + { + private static string _expected = "exampleParameter"; + private string _actual; + private readonly string _content = @" +

" + nameof(InvokeScriptOneArgumentTests) + @"

+ +"; + + protected override void Given() + { + base.Given(); + + WebView.NavigationCompleted += (a, b) => + { + _actual = (string)WebView.InvokeScript("echoOneArgument", "exampleParameter"); + Form.Close(); + }; + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + [Ignore("Causing test run to abort")] + public void InvokedScriptReturnedExpectedValue() + { + _actual.ShouldEqual(_expected); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/LongRunningJavaScript/LongRunningJavaScriptTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/LongRunningJavaScript/LongRunningJavaScriptTests.cs new file mode 100644 index 000000000..9a23f0033 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/LongRunningJavaScript/LongRunningJavaScriptTests.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.LongRunningJavaScript +{ + [TestClass] + public class LongRunningJavaScriptTests : HostFormWebViewContextSpecification + { + private string _result; + private bool _slowEventRaised; + private string _content = @" +

TEST

+ +"; + + protected override void Given() + { + base.Given(); + WebView.IsJavaScriptEnabled = true; + + // BUG: The content causes browsers to show prompt when loaded externally without a problem + WebView.LongRunningScriptDetected += (o, e) => + { + WriteLine($"LongRunningScriptDetected: {e.ExecutionTime}"); + _slowEventRaised = true; + e.StopPageScriptExecution = true; + + Form.Close(); + }; + + WebView.NavigationCompleted += (o, e) => + { + _result = WebView.InvokeScriptAsync("mySlowFunction", "3000000").Result; + Form.Close(); + }; + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + [Ignore("LongRunningScriptDetected event is not raised")] + public void LongRunningJavaScriptEventRaised() + { + _slowEventRaised.ShouldBeTrue(); + _result.ShouldNotBeNull(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/CanGoBackTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/CanGoBackTests.cs new file mode 100644 index 000000000..ac0590f1a --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/CanGoBackTests.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Navigation +{ + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class AfterNavigatingMoreThanOnce : HostFormWebViewContextSpecification + { + private int _navigationCount; + private bool _canGoBack; + + protected override void Given() + { + base.Given(); + + WebView.NavigationCompleted += (o, e) => + { + if (e.Uri == null) return; + + _navigationCount++; + + WriteLine($"NavCompleted: {e.Uri}"); + e.IsSuccess.ShouldBeTrue($"Navigation failure: {e.WebErrorStatus}"); + if (e.Uri == TestConstants.Uris.ExampleCom) + { + WebView.Navigate(TestConstants.Uris.ExampleNet); + } + else + { + _canGoBack = WebView.CanGoBack; + Form.Close(); + } + }; + } + + protected override void When() + { + NavigateAndWaitForFormClose(TestConstants.Uris.ExampleCom); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Medium)] + public void CanGoBackIsTrue() + { + _navigationCount.ShouldEqual(2); + _canGoBack.ShouldBeTrue(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/CanGoForwardTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/CanGoForwardTests.cs new file mode 100644 index 000000000..f8d4654f0 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/CanGoForwardTests.cs @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Navigation +{ + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class AfterNavigatingMoreThanOnceThenGoingBack : HostFormWebViewContextSpecification + { + private int _navigationCount; + + protected override void Given() + { + base.Given(); + + WebView.NavigationCompleted += (o, e) => + { + _navigationCount++; + WriteLine($"NavCompleted: {e.Uri}; NavCount: {_navigationCount}"); + e.IsSuccess.ShouldBeTrue($"Navigation failure: {e.WebErrorStatus}"); + + if (WebView.CanGoBack) + { + WebView.GoBack(); + } else if (!WebView.CanGoBack && WebView.CanGoForward) + { + Form.Close(); + } + else + { + WebView.Navigate(new Uri(TestConstants.Uris.ExampleCom, "?" + _navigationCount)); + } + + + }; + + } + + protected override void When() + { + NavigateAndWaitForFormClose(TestConstants.Uris.ExampleCom); + } + + [TestMethod] + //[Timeout(TestConstants.Timeouts.Long)] + public void CanGoForwardIsTrue() + { + // NOTE: Due to asynchronous nature the actual assert is in Given() + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/NavigateTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/NavigateTests.cs new file mode 100644 index 000000000..af0fd2187 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/NavigateTests.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Navigation +{ + [TestClass] + public class NavigateStringUri : HostFormWebViewContextSpecification + { + private bool _navigationCompleted; + protected override void Given() + { + base.Given(); + WebView.NavigationCompleted += (o, e) => + { + _navigationCompleted = true; + Form.Close(); + }; + } + + protected override void When() + { + PerformActionAndWaitForFormClose(() => + { + WebView.Navigate(TestConstants.Uris.ExampleOrg.ToString()); + }); + } + + [TestMethod] + public void NavigationCompleted() + { + _navigationCompleted.ShouldBeTrue(); + } + } + + [TestClass] + public class NavigateRelativeUri : HostFormWebViewContextSpecification + { + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void NavigationFailedWithArgumentException() + { + WebView.Navigate(new Uri("/someresource", UriKind.Relative)); + } + } + + [TestClass] + public class NavigateFilePath : HostFormWebViewContextSpecification + { + private string path; + + protected override void Given() + { + var fileName = Guid.NewGuid().ToString("N") + ".txt"; + path = Path.Combine(TestContext.TestRunResultsDirectory, fileName); + + File.WriteAllText( + path, + @" + +HTML on Disk +

HTML on Disk

+ +"); + + base.Given(); + } + + [TestMethod] + [ExpectedException(typeof(Exception), "E_ABORT expected")] + [Ignore] + public void Navigate() + { + PerformActionAndWaitForFormClose(() => + { + WebView.Navigate(new Uri(path)); + }); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/NavigationEvents.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/NavigationEvents.cs new file mode 100644 index 000000000..5f51644e2 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/NavigationEvents.cs @@ -0,0 +1,163 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Navigation +{ + [TestClass] + public class NavigatingFromNavigatingStartingEvent : HostFormWebViewContextSpecification + { + private List _navigatedUris; + + protected override void Given() + { + _navigatedUris = new List(); + + base.Given(); + WebView.NavigationStarting += (o, e) => + { + if (e.Uri != TestConstants.Uris.ExampleOrg) + { + WebView.Navigate(TestConstants.Uris.ExampleOrg); + } + }; + WebView.NavigationCompleted += (o, e) => + { + _navigatedUris.Add(e.Uri); + + if (e.Uri != TestConstants.Uris.ExampleCom) + { + Form.Close(); + } + }; + } + + protected override void When() + { + NavigateAndWaitForFormClose(TestConstants.Uris.ExampleCom); + } + + [TestMethod] + public void NavigatingFromNavigationStartingInterruptsOriginalNavigation() + { + _navigatedUris.Count.ShouldEqual(1, "Starting a new navigation while navigating cancels the original navigation"); + _navigatedUris.ShouldContain(TestConstants.Uris.ExampleOrg); + _navigatedUris.ShouldNotContain(TestConstants.Uris.ExampleCom); + } + } + + [TestCategory(TestConstants.Categories.Nav)] + public abstract class NavigationEventsFiredForHostFormContextSpecification : HostFormWebViewContextSpecification + { + private bool _navStarting; + private bool _contentLoading; + private bool _domContentLoaded; + private bool _navCompleted; + + protected override void Given() + { + base.Given(); + + WebView.NavigationStarting += (o, e) => { _navStarting = true; }; + WebView.ContentLoading += (o, e) => { _contentLoading = true; }; + WebView.DOMContentLoaded += (o, e) => { _domContentLoaded = true; }; + WebView.NavigationCompleted += (o, e) => + { + _navCompleted = true; + Form.Close(); + }; + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Long)] + public void NavigationEventsCompleted() + { + _navStarting.ShouldBeTrue(); + _contentLoading.ShouldBeTrue(); + _domContentLoaded.ShouldBeTrue(); + _navCompleted.ShouldBeTrue(); + } + } + + [TestClass] + public class NavigationEventsFiredForHostFormOnAboutBlank : NavigationEventsFiredForHostFormContextSpecification + { + protected override void When() + { + NavigateAndWaitForFormClose(TestConstants.Uris.AboutBlank); + } + } + + [TestClass] + public class NavigationEventsFiredForHostFormOnNullSource : NavigationEventsFiredForHostFormContextSpecification + { + protected override void When() + { + NavigateAndWaitForFormClose((Uri)null); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class NavigateToStringEvents : NavigationEventsFiredForHostFormContextSpecification + { + private readonly string _content = $@" + + +

{nameof(NavigateToStringEvents)}

+ + +"; + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + + public class NavigationEventsFiredForProcessFactory : ProcessFactoryWebViewContextSpecification + { + private bool _navStarting; + private bool _contentLoading; + private bool _domContentLoaded; + private bool _navCompleted; + + protected override void Given() + { + base.Given(); + + WebView.NavigationStarting += (o, e) => { _navStarting = true; }; + WebView.ContentLoading += (o, e) => { _contentLoading = true; }; + WebView.DOMContentLoaded += (o, e) => { _domContentLoaded = true; }; + WebView.NavigationCompleted += (o, e) => + { + _navCompleted = true; + Form.Close(); + }; + } + + protected override void When() + { + NavigateAndWaitForFormClose(TestConstants.Uris.AboutBlank); + } + + [TestMethod] + //[Timeout(TestConstants.Timeouts.Short)] + public void NavigationEventsCompleted() + { + _navStarting.ShouldBeTrue(); + _contentLoading.ShouldBeTrue(); + _domContentLoaded.ShouldBeTrue(); + _navCompleted.ShouldBeTrue(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/RefreshTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/RefreshTests.cs new file mode 100644 index 000000000..74aac3ade --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/RefreshTests.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Navigation +{ + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class RefreshTests : HostFormWebViewContextSpecification + { + private int _navigations; + protected override void Given() + { + base.Given(); + WebView.NavigationCompleted += (o, e) => + { + _navigations++; + if (_navigations == 2) + { + Form.Close(); + } + else + { + WebView.Refresh(); + } + }; + } + + protected override void When() + { + NavigateAndWaitForFormClose(TestConstants.Uris.ExampleOrg); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + public void RefreshCountsAsNavigation() + { + _navigations.ShouldEqual(2); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/StopTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/StopTests.cs new file mode 100644 index 000000000..033594c38 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/StopTests.cs @@ -0,0 +1,84 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Navigation +{ + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class StopAfterNavigate : HostFormWebViewContextSpecification + { + private System.Windows.Forms.Timer _timer; + private bool _navCompleted; + protected override void Given() + { + _timer = new System.Windows.Forms.Timer + { + Interval = TestConstants.Timeouts.Shorter + }; + _timer.Tick += (o, e) => { Form.Close(); }; + + base.Given(); + WebView.NavigationCompleted += (o, e) => { _navCompleted = true; }; + } + + protected override void When() + { + PerformActionAndWaitForFormClose(() => + { + WebView.Navigate(TestConstants.Uris.ExampleOrg); + _timer.Start(); + WebView.Stop(); + }); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + [Ignore("Causing test run to abort")] + public void StopAfterNavigateDoesNotCompleteNavigation() + { + _navCompleted.ShouldBeFalse(); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class NavigationCancelOnNavigationStarting : HostFormWebViewContextSpecification + { + private System.Windows.Forms.Timer _timer; + private bool _navCompleted; + + protected override void Given() + { + _timer = new System.Windows.Forms.Timer + { + Interval = TestConstants.Timeouts.Shorter + }; + _timer.Tick += (o, e) => { Form.Close(); }; + + base.Given(); + WebView.NavigationStarting += (o, e) => { e.Cancel = true; }; + WebView.NavigationCompleted += (o, e) => { _navCompleted = true; }; + } + + protected override void When() + { + PerformActionAndWaitForFormClose(()=> + { + WebView.Navigate(TestConstants.Uris.ExampleOrg); + _timer.Start(); + }); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + public void NavigationCompletedEventNeverFired() + { + _navCompleted.ShouldBeFalse(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/WebGLTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/WebGLTests.cs new file mode 100644 index 000000000..f27c3f4ba --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Navigation/WebGLTests.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Navigation +{ + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class CanCreateWebGL : HostFormWebViewContextSpecification + { + // Execute some script that creates a WebGLRenderingContext. There is code that + // will prevent the underlying backend (edgeangle.dll) from loading in processes + // that are not part of a package. The process that hosts edgehtml.dll (and thus + // edgeangle.dll) in Win32WebView scenarios should be packaged so the below should + // succeed and not crash. + private string _content = @" +

TEST

+ +"; + + protected override void Given() + { + base.Given(); + + WebView.NavigationCompleted += (o, e) => + { + Form.Close(); + }; + } + + protected override void When() + { + WebView.NavigateToString(_content); + } + + [TestMethod] + public void WebGLContextCreated() + { + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/NewWindow/NewWindowTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/NewWindow/NewWindowTests.cs new file mode 100644 index 000000000..0f3d45931 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/NewWindow/NewWindowTests.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//namespace Microsoft.Windows10.Forms.Controls.FunctionalTests.NewWindow +//{ +// [TestClass] +// public class NewWindowTests : HostFormWebViewContextSpecification +// { +// private bool _newWindowRequested; +// private readonly string _content = $@" +// +// +//

JavaScript window.open

+// +// +//"; + +// protected override void Given() +// { +// base.Given(); + +// WebView.NewWindowRequested += (o, e) => +// { +// _newWindowRequested = true; +// WriteLine($"NewWindowRequested: Uri:{e.Uri}, Referrer: {e.Referrer}, Handled: {e.Handled}"); +// Form.Close(); +// }; +// } + +// protected override void When() +// { +// NavigateToStringAndWaitForFormClose(_content); +// } + +// [TestMethod] +// [Timeout(TestConstants.Timeouts.Short)] +// [Ignore("NewWindowRequested event is not firing")] +// public void NewWindowRequestedEventFired() +// { +// _newWindowRequested.ShouldBeTrue(); +// } +// } +//} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/PartialTrust/PartialTrustTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/PartialTrust/PartialTrustTests.cs new file mode 100644 index 000000000..e80b75bd7 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/PartialTrust/PartialTrustTests.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Security; +using System.Security.Permissions; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.PartialTrust +{ + [TestClass] + public class PartialTrustTest : ContextSpecification + { + [TestMethod] + [ExpectedException(typeof(SecurityException))] + public void UnableToCreateInstance() + { + MediumTrustContext.Create(); + } + + internal static class MediumTrustContext + { + public static T Create() + { + var appDomain = CreatePartialTrustDomain(); + try + { + var t = (T) appDomain.CreateInstanceAndUnwrap(typeof(T).Assembly.FullName, typeof(T).FullName); + return t; + } + catch (Exception e) + { + // Getting a reflection exception since that is how the type is activated + // Interested in the inner-most exception; okay with blowing away the stack for this test + var e2 = e; + while (e2.InnerException != null) + { + e2 = e2.InnerException; + } + + throw e2; + } + } + + public static AppDomain CreatePartialTrustDomain() + { + var setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory }; + var permissions = new PermissionSet(null); + permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); + permissions.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess)); + return AppDomain.CreateDomain("Partial Trust AppDomain: " + DateTime.Now.Ticks, null, setup, permissions); + } + } + + } + + [Serializable] + public class ClassUnderTest : MarshalByRefObject + { + private readonly Context _context; + + public ClassUnderTest() + { + _context = new Context(); + } + + public void Navigate() + { + _context.Navigate(); + } + + private class Context : HostFormWebViewContextSpecification + { + public void Navigate() + { + base.Given(); + base.When(); + base.NavigateAndWaitForFormClose(TestConstants.Uris.AboutBlank); + } + + + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Permissions/GeolocationTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Permissions/GeolocationTests.cs new file mode 100644 index 000000000..e861f03e8 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Permissions/GeolocationTests.cs @@ -0,0 +1,129 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Permissions +{ + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class GeolocationPermissionRequestImmediatelyGranted : HostFormWebViewContextSpecification + { + private WebViewControlPermissionRequest _permissionRequest; +// private string _content = @" +//

TEST

+//
+// +//"; + + protected override void Given() + { + base.Given(); + + WebView.IsJavaScriptEnabled = true; + + WebView.PermissionRequested += (o, e) => + { + e.PermissionRequest.ShouldNotBeNull(); + + _permissionRequest = e.PermissionRequest; + + WriteLine($"Permission Request: Id: {e.PermissionRequest.Id}, PermissionType: {e.PermissionRequest.PermissionType}"); + e.PermissionRequest.PermissionType.ShouldEqual(WebViewControlPermissionType.Geolocation); + + if (e.PermissionRequest.State == WebViewControlPermissionState.Defer) + { + WebView.GetDeferredPermissionRequestById(e.PermissionRequest.Id)?.Allow(); + } + else + { + e.PermissionRequest.Allow(); + } + + Form.Close(); + }; + } + + protected override void When() + { + //BUG: Geolocation request not working with NavigateToString + //NavigateToStringAndWaitForFormClose(_content); + NavigateAndWaitForFormClose(new Uri("https://codepen.io/rjmurillo/pen/MVaKbJ")); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Long)] + public void PermissionRequestReceived() + { + _permissionRequest.ShouldNotBeNull(); + _permissionRequest.State.ShouldEqual(WebViewControlPermissionState.Allow); + } + } + + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class GeolocationPermissionRequestDeferredThenGranted : HostFormWebViewContextSpecification + { + private uint _permissionRequest; + + protected override void Given() + { + base.Given(); + + WebView.IsJavaScriptEnabled = true; + + WebView.PermissionRequested += (o, e) => + { + e.PermissionRequest.ShouldNotBeNull(); + + _permissionRequest = e.PermissionRequest.Id; + + WriteLine($"Permission Request: Id: {e.PermissionRequest.Id}, PermissionType: {e.PermissionRequest.PermissionType}"); + e.PermissionRequest.PermissionType.ShouldEqual(WebViewControlPermissionType.Geolocation); + + if (e.PermissionRequest.State == WebViewControlPermissionState.Defer) + { + } + else + { + e.PermissionRequest.Defer(); + } + + WebView.GetDeferredPermissionRequestById(_permissionRequest)?.Allow(); + Form.Close(); + }; + } + + protected override void When() + { + NavigateAndWaitForFormClose(new Uri("https://codepen.io/rjmurillo/pen/MVaKbJ")); + } + + // TODO: Verify there are no more deferred permission requests + + [TestMethod] + [Timeout(TestConstants.Timeouts.Long)] + public void PermissionRequestReceived() + { + _permissionRequest.ShouldNotEqual(0); + } + } + +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ProcessFactoryWebViewContextSpecification.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ProcessFactoryWebViewContextSpecification.cs new file mode 100644 index 000000000..ea81ed6ff --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ProcessFactoryWebViewContextSpecification.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.Toolkit.Win32.UI.Controls.WinForms; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using WebViewControlProcess = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlProcess; +using WebViewControlProcessOptions = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.WebViewControlProcessOptions; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests +{ + [TestCategory(TestConstants.Categories.Proc)] + public abstract class ProcessFactoryWebViewContextSpecification : WebViewFormContextSpecification + { + protected WebViewControlProcess WebViewControlProcess { get; private set; } + + protected WebViewControlProcessOptions WebViewControlProcessOptions { get; set; } + + protected override void CreateWebView() + { + CreateWebView(new WebViewControlProcessOptions()); + } + + protected virtual void CreateWebView(WebViewControlProcessOptions webViewControlProcessOptions) + { + Form.SuspendLayout(); + WebViewControlProcessOptions = webViewControlProcessOptions; + WebViewControlProcess = new WebViewControlProcess(WebViewControlProcessOptions); + WebView = (Controls.WinForms.WebView)WebViewControlProcess.CreateWebView(Form.Handle, Form.ClientRectangle); + Form.Controls.Add(WebView); + Form.ResumeLayout(false); + Form.PerformLayout(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Scale/ScaleTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Scale/ScaleTests.cs new file mode 100644 index 000000000..975749b13 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Scale/ScaleTests.cs @@ -0,0 +1,8 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Scale +{ + //TODO: Scale tests +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ScriptNotify/ScriptNotifyOnNavigate.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ScriptNotify/ScriptNotifyOnNavigate.cs new file mode 100644 index 000000000..2b6d72d55 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ScriptNotify/ScriptNotifyOnNavigate.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.ScriptNotify +{ + [TestClass] + public class ScriptNotifyOnNavigate : HostFormWebViewContextSpecification + { + private string _parameter; + private string _content; + private bool _scriptNotifyCalled; + + protected override void Given() + { + _parameter = "2"; + _content = $"(()=> {{ window.external.notify('{_parameter}');}})()"; + + base.Given(); + WebView.IsScriptNotifyAllowed = true; + WebView.IsJavaScriptEnabled = true; + + // This runs after Navigate + WebView.NavigationCompleted += (o, e) => + { + // Set up the event handler + WebView.ScriptNotify += (c, a) => + { + _scriptNotifyCalled = true; + a.Value.ShouldEqual(_parameter, "ScriptNotify received, but with different argument."); + Form.Close(); + }; + + // Inject the script + WebView.InvokeScriptAsync("eval", _content); + }; + } + + protected override void When() + { + NavigateAndWaitForFormClose(TestConstants.Uris.ExampleCom); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + public void ScriptNotifyRaised() + { + _scriptNotifyCalled.ShouldBeTrue(); + } + } +} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ScriptNotify/ScriptNotifyOnNavigateToString.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ScriptNotify/ScriptNotifyOnNavigateToString.cs new file mode 100644 index 000000000..e3ff62920 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/ScriptNotify/ScriptNotifyOnNavigateToString.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.ScriptNotify +{ + [TestClass] + [TestCategory(TestConstants.Categories.Nav)] + public class ScriptNotifyOnNavigateToString : HostFormWebViewContextSpecification + { + private string _content; + private bool _scriptNotifyCalled; + + protected override void Given() + { + _content = @" + + + + +"; + + base.Given(); + WebView.IsScriptNotifyAllowed = true; + WebView.IsJavaScriptEnabled = true; + + WebView.ScriptNotify += (c, a) => + { + _scriptNotifyCalled = true; + a.Value.ShouldEqual("Hello World!", "ScriptNotify received, but with different argument."); + Form.Close(); + }; + } + + protected override void When() + { + NavigateToStringAndWaitForFormClose(_content); + } + + [TestMethod] + [Timeout(TestConstants.Timeouts.Longest)] + + public void ScriptNotifyRaised() + { + _scriptNotifyCalled.ShouldBeTrue(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Termination/TerminationTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Termination/TerminationTests.cs new file mode 100644 index 000000000..03c116434 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/Termination/TerminationTests.cs @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Should; + +using System.ComponentModel; +using System.Threading; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests.Termination +{ + [TestClass] + public class TerminationTests : BlockTestStartEndContextSpecification + { + private bool _processExitedEventFired; + private ManualResetEvent _mre; + + protected override void Given() + { + // Perform check to see if we can run before we get too far + Assert.That.OSBuildShouldBeAtLeast(TestConstants.Windows10Builds.InsiderFast17650); + + base.Given(); + + _mre = new ManualResetEvent(false); + } + + protected override void CreateWebView() + { + WebView = new UI.Controls.WinForms.WebView(); + ((ISupportInitialize)WebView).BeginInit(); + ((ISupportInitialize)WebView).EndInit(); + + WebView.ShouldNotBeNull(); + WebView.Process.ShouldNotBeNull(); + WebView.Process.ProcessId.ShouldNotEqual(0U); + + WebView.Process.ProcessExited += (o, e) => + { + _processExitedEventFired = true; + _mre.Set(); + }; + } + + protected override void When() + { + WebView.Process.Terminate(); + } + + [TestMethod] + public void TheTerminatedProcessShouldNoLongerHaveAProcessId() + { + WebView.Process.ProcessId.ShouldEqual(0U); + } + + [TestMethod] + public void TheProcessExitedEventWasRaised() + { + _mre.WaitOne(TestConstants.Timeouts.Short); + _processExitedEventFired.ShouldBeTrue(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/TestHostForm.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/TestHostForm.cs new file mode 100644 index 000000000..68f8fc8bc --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/TestHostForm.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Windows.Forms; +using WindowsInput; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests +{ + public class TestHostForm : Form + { + public InputSimulator InputSimulator { get; } + + public TestHostForm() + { + InputSimulator = new InputSimulator(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/UnsupportedUriScheme/UnsupportedUriSchemeTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/UnsupportedUriScheme/UnsupportedUriSchemeTests.cs new file mode 100644 index 000000000..7b37d5e4e --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/UnsupportedUriScheme/UnsupportedUriSchemeTests.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//namespace Microsoft.Windows10.Forms.Controls.FunctionalTests.UnsupportedUriScheme +//{ +// [TestClass] +// public class UnsupportedUriSchemeTests : HostFormWebViewContextSpecification +// { +// private bool _eventFired; + +// protected override void Given() +// { +// base.Given(); + +// WebView.UnsupportedUriSchemeIdentified += (o, e) => +// { +// WriteLine($"UnsupportedUriSchemeIdentified: Uri: {e.Uri}, Handled: {e.Handled}"); +// _eventFired = true; +// Form.Close(); +// }; +// } + +// protected override void When() +// { +// // Protocol exists as part of RFC6733 +// var uri = new UriBuilder("aaa", "localhost", 1813, ";transport=tcp").Uri; +// WriteLine(uri.ToString()); +// NavigateAndWaitForFormClose(uri); +// } + +// [TestMethod] +// [Timeout(Constants.Timeouts.Medium)] +// [Ignore("E_ABORT (0x80004004) is raised when an unhandled protocol is received")] +// public void UnsupportedUriSchemeEventFiredForAAA() +// { +// _eventFired.ShouldBeTrue(); +// } +// } +//} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebResourceRequested/WebResourceRequestedTests.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebResourceRequested/WebResourceRequestedTests.cs new file mode 100644 index 000000000..2aba2fd62 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebResourceRequested/WebResourceRequestedTests.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//namespace Microsoft.Windows10.Forms.Controls.FunctionalTests.WebResourceRequested +//{ +// [TestClass] +// public class WebResourceRequested : HostFormWebViewContextSpecification +// { +// private Uri _initialUri; +// private Uri _subResourceUri; +// private bool _setEvent; + +// protected override void Given() +// { +// _initialUri = TestConstants.Uris.ExampleCom; +// _subResourceUri = new Uri(TestConstants.Uris.ExampleCom, "foo.js"); + +// base.Given(); + +// WebView.WebResourceRequested += (o, e) => +// { +// WriteLine($"Request received for {e.Request.RequestUri}"); + +// var requestMessage = e.Request; +// var deferral = e.GetDeferral(); +// var responseMessage = new HttpResponseMessage(HttpStatusCode.Ok); +// var isInitialUri = HttpRequestUriEqualityComparer.Default.Equals(_initialUri, requestMessage.RequestUri); +// var isSubResourceUri = HttpRequestUriEqualityComparer.Default.Equals(_subResourceUri, requestMessage.RequestUri); + +// WriteLine($"IsInitialUri: {isInitialUri}"); +// WriteLine($"IsSubResourceUri: {isSubResourceUri}"); + +// // Verify Uri is expected +// if (isInitialUri) +// { +// responseMessage.Content = new HttpStringContent("Redirected response"); +// } +// else if (isSubResourceUri) +// { +// responseMessage.Content = new HttpStringContent(""); + +// // Only set the event once we've received notification of this resource request. +// // This validates that our initial response was actually used by the WebView control +// _setEvent = true; +// Form.Close(); +// } +// else +// { +// Assert.Fail("RequestUri did not match any of the expected values."); +// } + +// e.Response = responseMessage; +// deferral.Complete(); + +// }; +// } + +// protected override void When() +// { +// NavigateAndWaitForFormClose(_initialUri); +// } + +// [TestMethod] +// [Timeout(TestConstants.Timeouts.Longest)] +// public void ARedirectedResourceIsUsedByWebView() +// { +// _setEvent.ShouldBeTrue(); +// } +// } +//} diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebViewContextSpecification.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebViewContextSpecification.cs new file mode 100644 index 000000000..6c4627773 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebViewContextSpecification.cs @@ -0,0 +1,188 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Windows.Forms; +using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; +using Microsoft.Toolkit.Win32.UI.Controls.Test.WebView.Shared; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests +{ + [DebuggerStepThrough] + [TestCategory(TestConstants.Categories.Wf)] + public abstract class WebViewContextSpecification : ContextSpecification + { + private static readonly Dictionary TestPids = new Dictionary(); + + internal static string GetTestNameForProcessId(uint pid) + { + TestPids.TryGetValue(pid, out string test); + return test; + } + + private static bool _alreadyInBlock = false; + protected Controls.WinForms.WebView WebView { get; set; } + + protected override void Cleanup() + { + PrintStartEnd( + TestContext.TestName, + nameof(Cleanup), + () => + { + UnsubscribeWebViewEvents(); + TryAction(() => + { + if (WebView != null && !WebView.IsDisposed) + { + WriteLine("WebView is not null and has not been disposed. Calling Dispose()"); + WebView.Dispose(); + WebView = null; + } + }); + }); + + base.Cleanup(); + } + + protected abstract void CreateWebView(); + + protected override void Given() + { + if (!Controls.WinForms.WebView.IsSupported) + { + // Test cannot execute because we're on the wrong OS + Assert.Inconclusive(DesignerUI.E_NOTSUPPORTED_OS_RS4); + } + + CreateWebView(); + WebView.ShouldNotBeNull(); + WriteLine($"Created WebView: {WebView.Version}"); + WireUpDiagnosticWebViewEvents(); + base.Given(); + } + protected void PrintStartEnd(string className, string methodName, Action a) + { + try + { + if (!_alreadyInBlock) + { + WriteLine($"\r\n=== Starting {className}.{methodName} ==="); + _alreadyInBlock = true; + } + + a(); + } + finally + { + if (_alreadyInBlock) + { + WriteLine($"=== Ending {className}.{methodName} ===\r\n"); + _alreadyInBlock = false; + } + } + } + + protected void TryAction(Action a) + { + try + { + a(); + } + catch (Exception e) + { + if (e.IsSecurityOrCriticalException()) throw; + } + } + + protected void UnsubscribeWebViewEvents() + { + if (WebView == null) return; + + WebView.NavigationStarting -= OnNavigationStarting; + WebView.ContentLoading -= OnContentLoading; + WebView.DOMContentLoaded -= OnDomContentLoaded; + WebView.NavigationCompleted -= OnNavigationCompleted; + + WebView.Disposed -= OnDisposed; + WebView.GotFocus -= OnGotFocus; + WebView.LostFocus -= OnLostFocus; + + if (WebView.Process != null) + { + WebView.Process.ProcessExited -= OnWebViewProcessExited; + } + } + + protected void WireUpDiagnosticWebViewEvents() + { + if (WebView == null) return; + + WebView.NavigationStarting += OnNavigationStarting; + WebView.ContentLoading += OnContentLoading; + WebView.DOMContentLoaded += OnDomContentLoaded; + WebView.NavigationCompleted += OnNavigationCompleted; + + WebView.Disposed += OnDisposed; + WebView.GotFocus += OnGotFocus; + WebView.LostFocus += OnLostFocus; + + if (WebView.Process != null) + { + WebView.Process.ProcessExited += OnWebViewProcessExited; + + // NOTE: There are two PIDs we really care about. One for WWAHost.exe and one for the sandbox Win32WebViewHost.exe + // The following is only for WWAHost.exe + WriteLine($"{nameof(WebView)} created with PID {WebView.Process.ProcessId}\r\n"); + TestPids[WebView.Process.ProcessId] = TestContext.TestName; + } + } + + private void OnLostFocus(object sender, EventArgs e) + { + WriteLine($"{WebView.GetType().Name}.{nameof(WebView.LostFocus)}"); + } + + private void OnGotFocus(object sender, EventArgs e) + { + WriteLine($"{WebView.GetType().Name}.{nameof(WebView.GotFocus)}"); + } + + private void OnDisposed(object sender, EventArgs e) + { + WriteLine($"{WebView.GetType().Name}.{nameof(WebView.Disposed)}"); + } + + private void OnContentLoading(object o, WebViewControlContentLoadingEventArgs a) + { + WriteLine($"{WebView.GetType().Name}.{nameof(WebView.ContentLoading)}: {a.Uri?.ToString() ?? string.Empty}"); + Application.DoEvents(); + } + + private void OnDomContentLoaded(object o, WebViewControlDOMContentLoadedEventArgs a) + { + WriteLine($"{WebView.GetType().Name}.{nameof(WebView.DOMContentLoaded)}: {a.Uri?.ToString() ?? string.Empty}"); + Application.DoEvents(); + } + + private void OnNavigationCompleted(object o, WebViewControlNavigationCompletedEventArgs a) + { + WriteLine($"{WebView.GetType().Name}.{nameof(WebView.NavigationCompleted)}: Uri: {a.Uri?.ToString() ?? string.Empty}, Success: {a.IsSuccess}, Error: {a.WebErrorStatus}"); + Application.DoEvents(); + } + private void OnNavigationStarting(object o, WebViewControlNavigationStartingEventArgs a) + { + WriteLine($"{WebView.GetType().Name}.{nameof(WebView.NavigationStarting)}: {a.Uri?.ToString() ?? string.Empty}"); + Application.DoEvents(); + } + private void OnWebViewProcessExited(object o, object e) + { + WriteLine($"{nameof(WebView)} {nameof(WebViewControlProcess.ProcessExited)}!"); + } + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebViewFormContextSpecification.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebViewFormContextSpecification.cs new file mode 100644 index 000000000..60fb3e338 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/FunctionalTests/WebViewFormContextSpecification.cs @@ -0,0 +1,115 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Windows.Forms; +using Should; + +namespace Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView.FunctionalTests +{ + [DebuggerStepThrough] + public abstract class WebViewFormContextSpecification : BlockTestStartEndContextSpecification + { + protected WebViewFormContextSpecification() + { + Form = new TestHostForm() + { + Width = 1000, + Height = 800 + }; + + Form.MouseEnter += (o, e) => { WriteLine($"Form.MouseEnter"); }; + Form.MouseWheel += (o, e) => { WriteLine($"Form.MouseWheel: {e.Location}"); }; + Form.GotFocus += (o, e) => { WriteLine("Form.GotFocus"); }; + Form.LostFocus += (o, e) => { WriteLine("Form.LostFocus"); }; + Form.KeyPress += (o, e) => { WriteLine($"Form.KeyPress: {e.KeyChar}"); }; + Form.Closing += (o, e) => { WriteLine("Form.Closing"); }; + Form.Closed += (o, e) => { WriteLine("Form.Closed"); }; + } + + protected TestHostForm Form { get; private set; } + + protected override void Cleanup() + { + PrintStartEnd( + TestContext.TestName, + nameof(Cleanup), + () => + { + try + { + if (!Form.IsDisposed) + { + // The Form is supposed to be closed when the test is completed (to signal it is done) + // If it has not been closed and disposed, go ahead and do that so we can unhook + + WriteLine("Closing the form instance..."); + + // Restore foreground to the window before ending the test + Form.BringToFront(); + + Form.Close(); + Form.Dispose(); + } + } + finally + { + base.Cleanup(); + } + }); + } + + protected override void Given() + { + Form.Text = TestContext.TestName; + + base.Given(); + + WebView.ShouldNotBeNull(); + + WebView.NavigationStarting += (o, e) => { Form.Text = $"{TestContext.TestName}: {e.Uri}" ?? string.Empty; }; + WebView.NavigationCompleted += (o, e) => + { + var focused = WebView.Focus(); + WriteLine($"WebView.Focused: {focused}"); + Application.DoEvents(); + }; + } + + protected virtual void NavigateAndWaitForFormClose(Uri uri) + { + PerformActionAndWaitForFormClose(() => + { + WriteLine($"Navigating WebView with URI: {uri}"); + WebView.Navigate(uri); + }); + } + + protected virtual void PerformActionAndWaitForFormClose(Action action) + { + void OnFormLoad(object sender, EventArgs e) + { + Application.DoEvents(); + action(); + } + + WebView.ShouldNotBeNull(); + Form.Load += OnFormLoad; + Application.Run(Form); + } + + protected virtual void NavigateToStringAndWaitForFormClose(string content) + { + PerformActionAndWaitForFormClose(() => + { + WriteLine("Navigating WebView with content:"); + WriteLine(content); + WebView.NavigateToString(content); + }); + } + + + } +} \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/Properties/AssemblyInfo.cs b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..474f97424 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("UnitTests.WebView.WinForms")] +[assembly: AssemblyDescription("UnitTests.WebView.WinForms")] \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/UnitTests.WebView.WinForms.csproj b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/UnitTests.WebView.WinForms.csproj new file mode 100644 index 000000000..2927869b3 --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/UnitTests.WebView.WinForms.csproj @@ -0,0 +1,122 @@ + + + + Debug + AnyCPU + {10129749-7761-49B8-96B9-94BC833BA60B} + Library + Properties + Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView + Microsoft.Toolkit.Win32.UI.Controls.Test.WinForms.WebView + v4.6.2 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + true + + + + + + true + bin\Release\ + AnyCPU + TRACE + Off + prompt + full + + + TRACE;DEBUG + Off + bin\Debug\ + prompt + full + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + + + + + + + + + + + + + + + + + + + + + + + + + + {78d8b77b-2a55-4037-bcc9-b47806039d23} + Microsoft.Toolkit.Win32.UI.Controls + + + {b220be88-944e-45d1-9248-6faef53868a3} + UnitTests.WebView.Shared + + + + + + + + 1.0.4 + + + 1.2.1 + + + 1.2.1 + + + 1.1.20 + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/UnitTests.WebView.WinForms.csproj.DotSettings b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/UnitTests.WebView.WinForms.csproj.DotSettings new file mode 100644 index 000000000..6e7fff86a --- /dev/null +++ b/Microsoft.Toolkit.Win32/Tests/UnitTests.WebView.WinForms/UnitTests.WebView.WinForms.csproj.DotSettings @@ -0,0 +1,2 @@ + + No \ No newline at end of file diff --git a/Microsoft.Toolkit/Extensions/ArrayExtensions.cs b/Microsoft.Toolkit/Extensions/ArrayExtensions.cs new file mode 100644 index 000000000..6d28fdfdd --- /dev/null +++ b/Microsoft.Toolkit/Extensions/ArrayExtensions.cs @@ -0,0 +1,159 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Microsoft.Toolkit.Extensions +{ + /// + /// Helper extension methods for Arrays. + /// + public static class ArrayExtensions + { + /// + /// Fills in values of a multi-dimensional rectangular array to specified value based on the position and size given. + /// Ranges given outside the bounds of the array will fill in as much as possible and ignore elements that should appear outside it. + /// Won't throw bounds exception, just won't do work if ranges out of bounds. + /// + /// Type of array values. + /// Extended type instance. + /// Value to fill with. + /// Row to start on (inclusive, zero-index). + /// Column to start on (inclusive, zero-index). + /// Positive Width of area to fill. + /// Positive Height of area to fill. + public static void Fill(this T[,] array, T value, int row, int col, int width, int height) + { + for (int r = row; r < row + height; r++) + { + for (int c = col; c < col + width; c++) + { + if (r >= 0 && c >= 0 && r < array.GetLength(0) && c < array.GetLength(1)) + { + array[r, c] = value; + } + } + } + } + + /// + /// Retrieve a row as an enumerable from a multi-dimensional rectangular array. + /// + /// Type of rectangular array. + /// Extended type instance. + /// Row record to retrieve, 0-based index. + /// Yielded Enumerable of results. + public static IEnumerable GetRow(this T[,] rectarray, int row) + { + if (row < 0 || row >= rectarray.GetLength(0)) + { + throw new ArgumentOutOfRangeException(nameof(row)); + } + + for (int c = 0; c < rectarray.GetLength(1); c++) + { + yield return rectarray[row, c]; + } + } + + /// + /// Retrieve a column from a multi-dimensional rectangular array. + /// + /// Type of rectangular array. + /// Extended type instance. + /// Column record to retrieve, 0-based index. + /// Yielded Enumerable of results. + public static IEnumerable GetColumn(this T[,] rectarray, int column) + { + if (column < 0 || column >= rectarray.GetLength(1)) + { + throw new ArgumentOutOfRangeException(nameof(column)); + } + + for (int r = 0; r < rectarray.GetLength(0); r++) + { + yield return rectarray[r, column]; + } + } + + /// + /// Retrieve a column from a multi-dimensional jagged array. + /// Will throw an exception if the column is out of bounds, and return default in places where there are no elements from inner arrays. + /// Note: No equivalent GetRow method, as you can use array[row] to retrieve. + /// + /// Type of jagged array. + /// Extended type instance. + /// Column record to retrieve, 0-based index. + /// Yielded Enumerable of column elements for given column and default values for smaller inner arrays. + public static IEnumerable GetColumn(this T[][] rectarray, int column) + { + if (column < 0 || column >= rectarray.Max(array => array.Length)) + { + throw new ArgumentOutOfRangeException(nameof(column)); + } + + for (int r = 0; r < rectarray.GetLength(0); r++) + { + if (column >= rectarray[r].Length) + { + yield return default(T); + + continue; + } + + yield return rectarray[r][column]; + } + } + + /// + /// Joins the array together in a simple string representation. + /// + /// Type of array. + /// Extended type instance. + /// String representation of array. + public static string ToArrayString(this T[] array) + { + return "[" + string.Join(",\t", array) + "]"; + } + + /// + /// Joins the multi-dimensional array together in a string representation. + /// + /// Type of jagged array. + /// Extended type instance. + /// String representation of array. + public static string ToArrayString(this T[][] mdarray) + { + string[] inner = new string[mdarray.GetLength(0)]; + + for (int r = 0; r < mdarray.GetLength(0); r++) + { + inner[r] = string.Join(",\t", mdarray[r]); + } + + return "[[" + string.Join("]," + Environment.NewLine + " [", inner) + "]]"; + } + + /// + /// Joins the rectangular-array together in a string representation. + /// + /// Type of rectangular array. + /// Extended type instance. + /// String representation of array. + public static string ToArrayString(this T[,] rectarray) + { + string[] inner = new string[rectarray.GetLength(0)]; + + for (int r = 0; r < rectarray.GetLength(0); r++) + { + inner[r] = string.Join(",\t", rectarray.GetRow(r)); + } + + return "[[" + string.Join("]," + Environment.NewLine + " [", inner) + "]]"; + } + } +} diff --git a/Microsoft.Toolkit/Extensions/StringExtensions.cs b/Microsoft.Toolkit/Extensions/StringExtensions.cs index 646954553..d816c7e03 100644 --- a/Microsoft.Toolkit/Extensions/StringExtensions.cs +++ b/Microsoft.Toolkit/Extensions/StringExtensions.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System.Globalization; using System.Net; diff --git a/Microsoft.Toolkit/IncrementalLoadingCollection/IIncrementalSource.cs b/Microsoft.Toolkit/IncrementalLoadingCollection/IIncrementalSource.cs index e52afe49d..7dc874a28 100644 --- a/Microsoft.Toolkit/IncrementalLoadingCollection/IIncrementalSource.cs +++ b/Microsoft.Toolkit/IncrementalLoadingCollection/IIncrementalSource.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; diff --git a/UWP Community Toolkit.sln.GhostDoc.user.dic b/UWP Community Toolkit.sln.GhostDoc.user.dic new file mode 100644 index 000000000..97a211f03 --- /dev/null +++ b/UWP Community Toolkit.sln.GhostDoc.user.dic @@ -0,0 +1,10 @@ +ctor +devenv +edgehtml +Geolocation +hwnd +inheritdoc +programmatically +typeof +Unviewable +winmd diff --git a/UWP Community Toolkit.sln.GhostDoc.xml b/UWP Community Toolkit.sln.GhostDoc.xml new file mode 100644 index 000000000..4811d6557 --- /dev/null +++ b/UWP Community Toolkit.sln.GhostDoc.xml @@ -0,0 +1,60 @@ + + + *.min.js + jquery*.js + + + + + + + + .\Microsoft.Toolkit.Win32.UI.Controls\GlobalSuppressions.cs + .\Microsoft.Toolkit.Win32.UI.Controls\Interop\Win32\ExternDll.cs + + + + + .\Help + true + Windows Community Toolkit + MemberName + + + + true + false + false + false + + + true + false + false + false + true + true + false + + + + + + true + true + true + + true + + + + + + + + + + + False + + diff --git a/UnitTests/Converters/Test_AdaptiveHeightValueConverter.cs b/UnitTests/Converters/Test_AdaptiveHeightValueConverter.cs index 7e852c28a..9d10b9f19 100644 --- a/UnitTests/Converters/Test_AdaptiveHeightValueConverter.cs +++ b/UnitTests/Converters/Test_AdaptiveHeightValueConverter.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.UI.Controls; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/UnitTests/Converters/Test_BoolToObjectConverter.cs b/UnitTests/Converters/Test_BoolToObjectConverter.cs index 200ab403f..d8c76ddb3 100644 --- a/UnitTests/Converters/Test_BoolToObjectConverter.cs +++ b/UnitTests/Converters/Test_BoolToObjectConverter.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.UI.Converters; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/UnitTests/Converters/Test_EmptyCollectionToObjectConverter.cs b/UnitTests/Converters/Test_EmptyCollectionToObjectConverter.cs index d10009764..03e57b94e 100644 --- a/UnitTests/Converters/Test_EmptyCollectionToObjectConverter.cs +++ b/UnitTests/Converters/Test_EmptyCollectionToObjectConverter.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using Microsoft.Toolkit.Uwp.UI.Converters; diff --git a/UnitTests/Converters/Test_EmptyStringToObjectConverter.cs b/UnitTests/Converters/Test_EmptyStringToObjectConverter.cs index 95824b195..e52c22ebf 100644 --- a/UnitTests/Converters/Test_EmptyStringToObjectConverter.cs +++ b/UnitTests/Converters/Test_EmptyStringToObjectConverter.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.UI.Converters; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/UnitTests/Extensions/Helpers/ObjectWithNullableBoolProperty.cs b/UnitTests/Extensions/Helpers/ObjectWithNullableBoolProperty.cs new file mode 100644 index 000000000..47911801e --- /dev/null +++ b/UnitTests/Extensions/Helpers/ObjectWithNullableBoolProperty.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Windows.UI.Xaml; +using Windows.UI.Xaml.Data; + +namespace UnitTests.Extensions.Helpers +{ + [Bindable] + public class ObjectWithNullableBoolProperty : DependencyObject + { + public bool? NullableBool + { + get { return (bool?)GetValue(NullableBoolProperty); } + set { SetValue(NullableBoolProperty, value); } + } + + // Using a DependencyProperty as the backing store for NullableBool. This enables animation, styling, binding, etc... + public static readonly DependencyProperty NullableBoolProperty = + DependencyProperty.Register(nameof(NullableBool), typeof(bool?), typeof(ObjectWithNullableBoolProperty), new PropertyMetadata(null)); + } +} diff --git a/UnitTests/Extensions/Test_ArrayExtensions.cs b/UnitTests/Extensions/Test_ArrayExtensions.cs new file mode 100644 index 000000000..df17487dd --- /dev/null +++ b/UnitTests/Extensions/Test_ArrayExtensions.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Diagnostics; +using System.Linq; + +namespace UnitTests.Extensions +{ + [TestClass] + public class Test_ArrayExtensions + { + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_FillArrayMid() + { + bool[,] test = new bool[4, 5]; + + test.Fill(true, 1, 1, 3, 2); + + var expected = new bool[,] + { + { false, false, false, false, false }, + { false, true, true, true, false }, + { false, true, true, true, false }, + { false, false, false, false, false }, + }; + + CollectionAssert.AreEqual( + expected, + test, + "Fill failed. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + test.ToArrayString()); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_FillArrayTwice() + { + bool[,] test = new bool[4, 5]; + + test.Fill(true, 0, 0, 1, 2); + test.Fill(true, 1, 3, 2, 2); + + var expected = new bool[,] + { + { true, false, false, false, false }, + { true, false, false, true, true }, + { false, false, false, true, true }, + { false, false, false, false, false }, + }; + + CollectionAssert.AreEqual( + expected, + test, + "Fill failed. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + test.ToArrayString()); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_FillArrayNegativeSize() + { + bool[,] test = new bool[4, 5]; + + test.Fill(true, 3, 4, -3, -2); + + // TODO: We may want to think about this pattern in the future: + /*var expected = new bool[,] + { + { false, false, false, false, false }, + { false, false, false, false, false }, + { false, false, true, true, true }, + { false, false, true, true, true }, + };*/ + + var expected = new bool[,] + { + { false, false, false, false, false }, + { false, false, false, false, false }, + { false, false, false, false, false }, + { false, false, false, false, false }, + }; + + CollectionAssert.AreEqual( + expected, + test, + "Fill failed. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + test.ToArrayString()); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_FillArrayBottomEdgeBoundary() + { + bool[,] test = new bool[4, 5]; + + test.Fill(true, 1, 2, 2, 4); + + var expected = new bool[,] + { + { false, false, false, false, false }, + { false, false, true, true, false }, + { false, false, true, true, false }, + { false, false, true, true, false }, + }; + + CollectionAssert.AreEqual( + expected, + test, + "Fill failed. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + test.ToArrayString()); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_FillArrayTopLeftCornerNegativeBoundary() + { + bool[,] test = new bool[4, 5]; + + test.Fill(true, -1, -1, 3, 3); + + var expected = new bool[,] + { + { true, true, false, false, false }, + { true, true, false, false, false }, + { false, false, false, false, false }, + { false, false, false, false, false }, + }; + + CollectionAssert.AreEqual( + expected, + test, + "Fill failed. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + test.ToArrayString()); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_FillArrayBottomRightCornerBoundary() + { + bool[,] test = new bool[5, 4]; + + test.Fill(true, 3, 2, 3, 3); + + var expected = new bool[,] + { + { false, false, false, false }, + { false, false, false, false }, + { false, false, false, false }, + { false, false, true, true }, + { false, false, true, true }, + }; + + CollectionAssert.AreEqual( + expected, + test, + "Fill failed. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + test.ToArrayString()); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_Jagged_GetColumn() + { + int[][] array = + { + new int[] { 5, 2, 4 }, + new int[] { 6, 3 }, + new int[] { 7 } + }; + + var col = array.GetColumn(1).ToArray(); + + CollectionAssert.AreEquivalent(new int[] { 2, 3, 0 }, col); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_Jagged_GetColumn_Exception() + { + int[][] array = + { + new int[] { 5, 2, 4 }, + new int[] { 6, 3 }, + new int[] { 7 } + }; + + Assert.ThrowsException(() => + { + array.GetColumn(-1).ToArray(); + }); + + Assert.ThrowsException(() => + { + array.GetColumn(3).ToArray(); + }); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_Rectangular_GetColumn() + { + int[,] array = + { + { 5, 2, 4 }, + { 6, 3, 9 }, + { 7, -1, 0 } + }; + + var col = array.GetColumn(1).ToArray(); + + CollectionAssert.AreEquivalent(new int[] { 2, 3, -1 }, col); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_Rectangular_GetColumn_Exception() + { + int[,] array = + { + { 5, 2, 4 }, + { 6, 3, 0 }, + { 7, 0, 0 } + }; + + Assert.ThrowsException(() => + { + array.GetColumn(-1).ToArray(); + }); + + Assert.ThrowsException(() => + { + array.GetColumn(3).ToArray(); + }); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_Rectangular_GetRow() + { + int[,] array = + { + { 5, 2, 4 }, + { 6, 3, 9 }, + { 7, -1, 0 } + }; + + var col = array.GetRow(1).ToArray(); + + CollectionAssert.AreEquivalent(new int[] { 6, 3, 9 }, col); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_Rectangular_GetRow_Exception() + { + int[,] array = + { + { 5, 2, 4 }, + { 6, 3, 0 }, + { 7, 0, 0 } + }; + + Assert.ThrowsException(() => + { + array.GetRow(-1).ToArray(); + }); + + Assert.ThrowsException(() => + { + array.GetRow(3).ToArray(); + }); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_Rectangular_ToString() + { + int[,] array = + { + { 5, 2, 4 }, + { 6, 3, -1 }, + { 7, 0, 9 } + }; + + string value = array.ToArrayString(); + + Debug.WriteLine(value); + + Assert.AreEqual("[[5,\t2,\t4]," + Environment.NewLine + " [6,\t3,\t-1]," + Environment.NewLine + " [7,\t0,\t9]]", value); + } + + [TestCategory("ArrayExtensions")] + [TestMethod] + public void Test_ArrayExtensions_Jagged_ToString() + { + int[][] array = + { + new int[] { 5, 2 }, + new int[] { 6, 3, -1, 2 }, + new int[] { 7, 0, 9 } + }; + + string value = array.ToArrayString(); + + Debug.WriteLine(value); + + Assert.AreEqual("[[5,\t2]," + Environment.NewLine + " [6,\t3,\t-1,\t2]," + Environment.NewLine + " [7,\t0,\t9]]", value); + } + } +} diff --git a/UnitTests/Extensions/Test_NullableBoolMarkupExtension.cs b/UnitTests/Extensions/Test_NullableBoolMarkupExtension.cs new file mode 100644 index 000000000..39e00efb3 --- /dev/null +++ b/UnitTests/Extensions/Test_NullableBoolMarkupExtension.cs @@ -0,0 +1,177 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Uwp.UI.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; +using UnitTests.Extensions.Helpers; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Markup; + +namespace UnitTests.Extensions +{ + [TestClass] + public class Test_NullableBoolMarkupExtension + { + [TestCategory("NullableBoolMarkupExtension")] + [UITestMethod] + public void Test_NullableBool_MarkupExtension_ProvidesTrue() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var toggle = treeroot.FindChildByName("Check") as CheckBox; + + Assert.IsNotNull(toggle, "Could not find checkbox control in tree."); + + Assert.AreEqual(true, toggle.IsChecked, "Expected checkbox value to be true."); + } + + [TestCategory("NullableBoolMarkupExtension")] + [UITestMethod] + public void Test_NullableBool_MarkupExtension_ProvidesFalse() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var toggle = treeroot.FindChildByName("Check") as CheckBox; + + Assert.IsNotNull(toggle, "Could not find checkbox control in tree."); + + Assert.AreEqual(false, toggle.IsChecked, "Expected checkbox value to be false."); + } + + [TestCategory("NullableBoolMarkupExtension")] + [UITestMethod] + public void Test_NullableBool_MarkupExtension_ProvidesNull() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var toggle = treeroot.FindChildByName("Check") as CheckBox; + + Assert.IsNotNull(toggle, "Could not find checkbox control in tree."); + + Assert.AreEqual(null, toggle.IsChecked, "Expected checkbox value to be null."); + } + + [TestCategory("NullableBoolMarkupExtension")] + [UITestMethod] + public void Test_NullableBool_MarkupExtension_ProvidesNullStillWithTrueValue() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var toggle = treeroot.FindChildByName("Check") as CheckBox; + + Assert.IsNotNull(toggle, "Could not find checkbox control in tree."); + + Assert.AreEqual(null, toggle.IsChecked, "Expected checkbox value to be null."); + } + + [TestCategory("NullableBoolMarkupExtension")] + [UITestMethod] + public void Test_NullableBool_MarkupExtension_ProvidesNullStillWithFalseValue() + { + // Should be no-op as Value is false by default. + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var toggle = treeroot.FindChildByName("Check") as CheckBox; + + Assert.IsNotNull(toggle, "Could not find checkbox control in tree."); + + Assert.AreEqual(null, toggle.IsChecked, "Expected checkbox value to be null."); + } + + [TestCategory("NullableBoolMarkupExtension")] + [UITestMethod] + public void Test_NullableBool_Test_TestObject() + { + // Just test that we can properly parse our object as-is into our test harness. + var treeroot = XamlReader.Load(@" + + + +") as FrameworkElement; + + var obj = treeroot.Resources["OurObject"] as ObjectWithNullableBoolProperty; + + Assert.IsNotNull(obj, "Could not find object in resources."); + + Assert.AreEqual(null, obj.NullableBool, "Expected obj value to be null."); + } + + [TestCategory("NullableBoolMarkupExtension")] + [UITestMethod] + public void Test_NullableBool_DependencyProperty_SystemTrueValueFails() + { + // This is the failure case in the OS currently which causes us to need + // this markup extension. + var exception = Assert.ThrowsException( + () => + { + var treeroot = XamlReader.Load(@" + + + +") as FrameworkElement; + }, "Expected assignment failure during parsing, OS now supports, update documentation."); + + Assert.IsNotNull(exception); + + Assert.IsTrue(exception.Message.Contains("Failed to create a 'Windows.Foundation.IReference`1' from the text 'True'.")); + } + + [TestCategory("NullableBoolMarkupExtension")] + [UITestMethod] + public void Test_NullableBool_DependencyProperty_TrueValue() + { + var treeroot = XamlReader.Load(@" + + + +") as FrameworkElement; + + var obj = treeroot.Resources["OurObject"] as ObjectWithNullableBoolProperty; + + Assert.IsNotNull(obj, "Could not find object in resources."); + + Assert.AreEqual(true, obj.NullableBool, "Expected obj value to be true."); + } + } +} diff --git a/UnitTests/GlobalSuppressions.cs b/UnitTests/GlobalSuppressions.cs index e47d779c5..91eb7f068 100644 --- a/UnitTests/GlobalSuppressions.cs +++ b/UnitTests/GlobalSuppressions.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Build", "SA1208:Using directive for 'System.Collections.Generic' must appear before directive for 'Microsoft.VisualStudio.TestPlatform.UnitTestFramework'", Justification = "UnitTest")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Build", "SA1200:Using directive must appear within a namespace declaration", Justification = "UnitTest")] diff --git a/UnitTests/Helpers/TestParsers.cs b/UnitTests/Helpers/TestParsers.cs index 0f76ef094..213270cac 100644 --- a/UnitTests/Helpers/TestParsers.cs +++ b/UnitTests/Helpers/TestParsers.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. namespace UnitTests { diff --git a/UnitTests/Helpers/Test_BackgroundTaskHelper.cs b/UnitTests/Helpers/Test_BackgroundTaskHelper.cs index e67f9e075..a5275a563 100644 --- a/UnitTests/Helpers/Test_BackgroundTaskHelper.cs +++ b/UnitTests/Helpers/Test_BackgroundTaskHelper.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.Helpers; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/UnitTests/Helpers/Test_ColorHelper.cs b/UnitTests/Helpers/Test_ColorHelper.cs index 4a28e8d4e..464c12ef2 100644 --- a/UnitTests/Helpers/Test_ColorHelper.cs +++ b/UnitTests/Helpers/Test_ColorHelper.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp; using Microsoft.Toolkit.Uwp.Helpers; diff --git a/UnitTests/Helpers/Test_ConnectionHelper.cs b/UnitTests/Helpers/Test_ConnectionHelper.cs index e31c0aaf0..520df30ef 100644 --- a/UnitTests/Helpers/Test_ConnectionHelper.cs +++ b/UnitTests/Helpers/Test_ConnectionHelper.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.Connectivity; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/UnitTests/Helpers/Test_DeepLinkParser.cs b/UnitTests/Helpers/Test_DeepLinkParser.cs index be2b19581..c0a9e14fe 100644 --- a/UnitTests/Helpers/Test_DeepLinkParser.cs +++ b/UnitTests/Helpers/Test_DeepLinkParser.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. namespace Tests { diff --git a/UnitTests/Helpers/Test_ScreenUnitHelper.cs b/UnitTests/Helpers/Test_ScreenUnitHelper.cs index a5af3e226..0e05d8a13 100644 --- a/UnitTests/Helpers/Test_ScreenUnitHelper.cs +++ b/UnitTests/Helpers/Test_ScreenUnitHelper.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp.Helpers; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/UnitTests/Helpers/Test_StorageFileHelper.cs b/UnitTests/Helpers/Test_StorageFileHelper.cs index 7059a7e9a..ca5218860 100644 --- a/UnitTests/Helpers/Test_StorageFileHelper.cs +++ b/UnitTests/Helpers/Test_StorageFileHelper.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.Text; diff --git a/UnitTests/Helpers/Test_StorageHelper.cs b/UnitTests/Helpers/Test_StorageHelper.cs index d0ada8ebb..d8ca8b49b 100644 --- a/UnitTests/Helpers/Test_StorageHelper.cs +++ b/UnitTests/Helpers/Test_StorageHelper.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.Toolkit.Uwp; using Microsoft.Toolkit.Uwp.Helpers; diff --git a/UnitTests/Helpers/Test_StreamHelper.cs b/UnitTests/Helpers/Test_StreamHelper.cs index 6261fc9b7..4cc10793c 100644 --- a/UnitTests/Helpers/Test_StreamHelper.cs +++ b/UnitTests/Helpers/Test_StreamHelper.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.Text; diff --git a/UnitTests/Helpers/Test_WeakEventListener.cs b/UnitTests/Helpers/Test_WeakEventListener.cs index 94be0fd4d..206e4af26 100644 --- a/UnitTests/Helpers/Test_WeakEventListener.cs +++ b/UnitTests/Helpers/Test_WeakEventListener.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/UnitTests/Markdown/Parse/BoldTests.cs b/UnitTests/Markdown/Parse/BoldTests.cs index 6aac26dc4..c7c1d501e 100644 --- a/UnitTests/Markdown/Parse/BoldTests.cs +++ b/UnitTests/Markdown/Parse/BoldTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Parsers.Markdown.Blocks; diff --git a/UnitTests/Markdown/Parse/CodeTests.cs b/UnitTests/Markdown/Parse/CodeTests.cs index a8be5624c..b9a4b7ad2 100644 --- a/UnitTests/Markdown/Parse/CodeTests.cs +++ b/UnitTests/Markdown/Parse/CodeTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Parsers.Markdown.Blocks; diff --git a/UnitTests/Markdown/Parse/HeaderTests.cs b/UnitTests/Markdown/Parse/HeaderTests.cs index f840dcc86..7a307adbc 100644 --- a/UnitTests/Markdown/Parse/HeaderTests.cs +++ b/UnitTests/Markdown/Parse/HeaderTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; diff --git a/UnitTests/Markdown/Parse/HorizontalRuleTests.cs b/UnitTests/Markdown/Parse/HorizontalRuleTests.cs index 64bf44397..aa715af07 100644 --- a/UnitTests/Markdown/Parse/HorizontalRuleTests.cs +++ b/UnitTests/Markdown/Parse/HorizontalRuleTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Parsers.Markdown.Blocks; diff --git a/UnitTests/Markdown/Parse/HyperlinkTests.cs b/UnitTests/Markdown/Parse/HyperlinkTests.cs index ed7d75e19..72384eaa6 100644 --- a/UnitTests/Markdown/Parse/HyperlinkTests.cs +++ b/UnitTests/Markdown/Parse/HyperlinkTests.cs @@ -1,18 +1,10 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Toolkit.Parsers.Markdown; using Microsoft.Toolkit.Parsers.Markdown.Blocks; -using Microsoft.Toolkit.Parsers.Markdown.Enums; using Microsoft.Toolkit.Parsers.Markdown.Inlines; namespace UnitTests.Markdown.Parse @@ -472,9 +464,9 @@ namespace UnitTests.Markdown.Parse [TestCategory("Parse - inline")] public void Hyperlink_Negative_SchemeOnly() { - AssertEqual("http:", + AssertEqual("http", new ParagraphBlock().AddChildren( - new TextRunInline { Text = "http:" })); + new TextRunInline { Text = "http" })); } [TestMethod] @@ -508,9 +500,9 @@ namespace UnitTests.Markdown.Parse [TestCategory("Parse - inline")] public void Hyperlink_Negative_AngleBracketsPrefixOnly() { - AssertEqual("", + AssertEqual("", new ParagraphBlock().AddChildren( - new TextRunInline { Text = "" })); + new TextRunInline { Text = "" })); } [TestMethod] diff --git a/UnitTests/Markdown/Parse/ImageInlineTests.cs b/UnitTests/Markdown/Parse/ImageInlineTests.cs index d7796b69b..110275a9d 100644 --- a/UnitTests/Markdown/Parse/ImageInlineTests.cs +++ b/UnitTests/Markdown/Parse/ImageInlineTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Parsers.Markdown.Blocks; @@ -32,7 +24,9 @@ namespace UnitTests.Markdown.Parse Text = "![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =1)", Tooltip = "SVG logo", ImageWidth = 1, - ImageHeight = 0 + ImageHeight = 0, + RenderUrl = "https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg", + ReferenceId = string.Empty })); } @@ -49,7 +43,9 @@ namespace UnitTests.Markdown.Parse Text = "![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =x1)", Tooltip = "SVG logo", ImageWidth = 0, - ImageHeight = 1 + ImageHeight = 1, + RenderUrl = "https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg", + ReferenceId = string.Empty })); } @@ -66,7 +62,9 @@ namespace UnitTests.Markdown.Parse Tooltip = "SVG logo", Text = "![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =128x64)", ImageWidth = 128, - ImageHeight = 64 + ImageHeight = 64, + RenderUrl = "https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg", + ReferenceId = string.Empty })); } @@ -83,7 +81,9 @@ namespace UnitTests.Markdown.Parse Tooltip = "SVG logo", Text = "![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg%20=32)", ImageWidth = 0, - ImageHeight = 0 + ImageHeight = 0, + RenderUrl = "https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg%20=32", + ReferenceId = string.Empty })); } } diff --git a/UnitTests/Markdown/Parse/ItalicTests.cs b/UnitTests/Markdown/Parse/ItalicTests.cs index c939045b1..b8870aef9 100644 --- a/UnitTests/Markdown/Parse/ItalicTests.cs +++ b/UnitTests/Markdown/Parse/ItalicTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Parsers.Markdown.Blocks; diff --git a/UnitTests/Markdown/Parse/ListTests.cs b/UnitTests/Markdown/Parse/ListTests.cs index bb5a8d1b7..271c43051 100644 --- a/UnitTests/Markdown/Parse/ListTests.cs +++ b/UnitTests/Markdown/Parse/ListTests.cs @@ -1,18 +1,9 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using Microsoft.Toolkit.Parsers.Markdown; using Microsoft.Toolkit.Parsers.Markdown.Blocks; -using Microsoft.Toolkit.Parsers.Markdown.Blocks.List; -using Microsoft.Toolkit.Parsers.Markdown.Enums; using Microsoft.Toolkit.Parsers.Markdown.Inlines; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; diff --git a/UnitTests/Markdown/Parse/MarkdownLinkTests.cs b/UnitTests/Markdown/Parse/MarkdownLinkTests.cs index eb4f14217..603c35e3c 100644 --- a/UnitTests/Markdown/Parse/MarkdownLinkTests.cs +++ b/UnitTests/Markdown/Parse/MarkdownLinkTests.cs @@ -1,17 +1,9 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using Microsoft.Toolkit.Parsers.Markdown; using Microsoft.Toolkit.Parsers.Markdown.Blocks; -using Microsoft.Toolkit.Parsers.Markdown.Enums; using Microsoft.Toolkit.Parsers.Markdown.Inlines; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; diff --git a/UnitTests/Markdown/Parse/ParagraphTests.cs b/UnitTests/Markdown/Parse/ParagraphTests.cs index bdda6e457..ad00cde43 100644 --- a/UnitTests/Markdown/Parse/ParagraphTests.cs +++ b/UnitTests/Markdown/Parse/ParagraphTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Parsers.Markdown.Inlines; @@ -130,9 +122,7 @@ namespace UnitTests.Markdown.Parse [TestCategory("Parse - block")] public void Paragraph_Entities() { - // &wtf; is just to check what happens if the entity doesn't exist. AssertEqual(CollapseWhitespace(@" - &wtf; " & ' @@ -388,7 +378,7 @@ namespace UnitTests.Markdown.Parse ♥ ♦"), new ParagraphBlock().AddChildren( - new TextRunInline { Text = @"&wtf; "" & ' < >     ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ " + + new TextRunInline { Text = @""" & ' < >     ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ " + "¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô " + "õ ö ÷ ø ù ú û ü ý þ ÿ Œ œ Š š Ÿ ƒ ˆ ˜ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ " + "μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω ϑ ϒ ϖ       ‌ ‍ ‎ ‏ – — ‘ ’ ‚ “ ” „ † ‡ • … ‰ ′ ″ ‹ › ‾ ⁄ € ℑ ℘ ℜ ™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ " + diff --git a/UnitTests/Markdown/Parse/ParseTestBase.cs b/UnitTests/Markdown/Parse/ParseTestBase.cs index 3321e62f9..32ebf2365 100644 --- a/UnitTests/Markdown/Parse/ParseTestBase.cs +++ b/UnitTests/Markdown/Parse/ParseTestBase.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Text; diff --git a/UnitTests/Markdown/Parse/ParseTestExtensionMethods.cs b/UnitTests/Markdown/Parse/ParseTestExtensionMethods.cs index e3cb45440..49946f1ec 100644 --- a/UnitTests/Markdown/Parse/ParseTestExtensionMethods.cs +++ b/UnitTests/Markdown/Parse/ParseTestExtensionMethods.cs @@ -1,20 +1,11 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using Microsoft.Toolkit.Parsers.Markdown; using Microsoft.Toolkit.Parsers.Markdown.Blocks; -using Microsoft.Toolkit.Parsers.Markdown.Blocks.List; using Microsoft.Toolkit.Parsers.Markdown.Inlines; namespace UnitTests.Markdown.Parse @@ -27,9 +18,10 @@ namespace UnitTests.Markdown.Parse /// /// Adds one or more child elements to the given parent object. /// - /// - /// - /// + /// the type + /// the parent + /// the elements to add + /// parent public static T AddChildren(this T parent, params object[] elements) { foreach (var child in elements) diff --git a/UnitTests/Markdown/Parse/QuoteTests.cs b/UnitTests/Markdown/Parse/QuoteTests.cs index ed02a162e..00122e54d 100644 --- a/UnitTests/Markdown/Parse/QuoteTests.cs +++ b/UnitTests/Markdown/Parse/QuoteTests.cs @@ -1,21 +1,12 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; +using Microsoft.Toolkit.Parsers.Markdown; using Microsoft.Toolkit.Parsers.Markdown.Blocks; using Microsoft.Toolkit.Parsers.Markdown.Inlines; -using Microsoft.Toolkit.Parsers.Markdown.Blocks.List; -using Microsoft.Toolkit.Parsers.Markdown.Enums; namespace UnitTests.Markdown.Parse { diff --git a/UnitTests/Markdown/Parse/StrikethroughTests.cs b/UnitTests/Markdown/Parse/StrikethroughTests.cs index 90d704865..662e5a70b 100644 --- a/UnitTests/Markdown/Parse/StrikethroughTests.cs +++ b/UnitTests/Markdown/Parse/StrikethroughTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Parsers.Markdown.Blocks; diff --git a/UnitTests/Markdown/Parse/SuperscriptTests.cs b/UnitTests/Markdown/Parse/SuperscriptTests.cs index b6cdcfa53..305f47eba 100644 --- a/UnitTests/Markdown/Parse/SuperscriptTests.cs +++ b/UnitTests/Markdown/Parse/SuperscriptTests.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Parsers.Markdown.Blocks; diff --git a/UnitTests/Markdown/Parse/TableTests.cs b/UnitTests/Markdown/Parse/TableTests.cs index bc6b3d7e2..0930fd7ce 100644 --- a/UnitTests/Markdown/Parse/TableTests.cs +++ b/UnitTests/Markdown/Parse/TableTests.cs @@ -1,20 +1,14 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; +using Microsoft.Toolkit.Parsers.Markdown; using Microsoft.Toolkit.Parsers.Markdown.Blocks; -using Microsoft.Toolkit.Parsers.Markdown.Enums; using Microsoft.Toolkit.Parsers.Markdown.Inlines; +using Microsoft.Toolkit.Parsers.Markdown; + namespace UnitTests.Markdown.Parse { diff --git a/UnitTests/Markdown/TestBase.cs b/UnitTests/Markdown/TestBase.cs index 47f3b51b1..61a02f284 100644 --- a/UnitTests/Markdown/TestBase.cs +++ b/UnitTests/Markdown/TestBase.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.Collections.Concurrent; diff --git a/UnitTests/Properties/AssemblyInfo.cs b/UnitTests/Properties/AssemblyInfo.cs index 8b08009ed..7040645ae 100644 --- a/UnitTests/Properties/AssemblyInfo.cs +++ b/UnitTests/Properties/AssemblyInfo.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System.Reflection; using System.Runtime.InteropServices; diff --git a/UnitTests/Services/Test_BingService.cs b/UnitTests/Services/Test_BingService.cs index dab92da3e..3a3bf10a4 100644 --- a/UnitTests/Services/Test_BingService.cs +++ b/UnitTests/Services/Test_BingService.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System.Threading.Tasks; using Microsoft.Toolkit.Services.Bing; diff --git a/UnitTests/UI/Controls/Test_UniformGrid_AutoLayout.cs b/UnitTests/UI/Controls/Test_UniformGrid_AutoLayout.cs new file mode 100644 index 000000000..8f87ca59b --- /dev/null +++ b/UnitTests/UI/Controls/Test_UniformGrid_AutoLayout.cs @@ -0,0 +1,442 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using Microsoft.Toolkit.Extensions; +using Microsoft.Toolkit.Uwp.UI.Controls; +using Microsoft.Toolkit.Uwp.UI.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; +using Windows.Foundation; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Markup; + +namespace UnitTests.UI.Controls +{ + [TestClass] + #pragma warning disable SA1008 // Opening parenthesis must be spaced correctly + public class Test_UniformGrid_AutoLayout + { + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_AutoLayout_FixedElementSingle() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + var expected = new(int row, int col)[] + { + (0, 0), + (1, 1), + (0, 1), + (0, 2), + (1, 0), + (1, 2), + (2, 0), + (2, 1) + }; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(8, grid.Children.Count); + + grid.Measure(new Size(1000, 1000)); + + // Check all children are in expected places. + for (int i = 0; i < children.Count(); i++) + { + if (expected[i].row == 1 && expected[i].col == 1) + { + // Check our fixed item isn't set to auto-layout. + Assert.AreEqual(false, UniformGrid.GetAutoLayout(children[i])); + } + + Assert.AreEqual(expected[i].row, Grid.GetRow(children[i])); + Assert.AreEqual(expected[i].col, Grid.GetColumn(children[i])); + } + } + + /// + /// Note: This one particular special-case scenario requires 16299 for the . + /// + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_AutoLayout_FixedElementZeroZeroSpecial() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + + +") as FrameworkElement; + + var expected = new(int row, int col)[] + { + (0, 1), + (0, 2), + (1, 0), + (1, 1), + (1, 2), + (2, 0), + (0, 0), + (2, 1) + }; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(8, grid.Children.Count); + + grid.Measure(new Size(1000, 1000)); + + // Check all children are in expected places. + for (int i = 0; i < children.Count(); i++) + { + if (expected[i].row == 0 && expected[i].col == 0) + { + // Check our fixed item isn't set to auto-layout. + Assert.AreEqual(false, UniformGrid.GetAutoLayout(children[i])); + } + + Assert.AreEqual(expected[i].row, Grid.GetRow(children[i])); + Assert.AreEqual(expected[i].col, Grid.GetColumn(children[i])); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_AutoLayout_FixedElementSquare() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + + +") as FrameworkElement; + + var expected = new(int row, int col)[] + { + (0, 0), + (1, 1), + (0, 1), + (0, 2), + (0, 3), + (1, 0), + (1, 3), + (2, 0), + (2, 3) + }; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(9, grid.Children.Count); + + grid.Measure(new Size(1000, 1000)); + + // Check all children are in expected places. + for (int i = 0; i < children.Count(); i++) + { + if (expected[i].row == 1 && expected[i].col == 1) + { + // Check our fixed item isn't set to auto-layout. + Assert.AreEqual(false, UniformGrid.GetAutoLayout(children[i])); + } + + Assert.AreEqual(expected[i].row, Grid.GetRow(children[i])); + Assert.AreEqual(expected[i].col, Grid.GetColumn(children[i])); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_AutoLayout_VerticalElement_FixedPosition() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement); + + Assert.AreEqual(8, grid.Children.Count()); + + grid.Measure(new Size(1000, 1000)); + + var border = treeroot.FindChildByName("OurItem") as Border; + + Assert.IsNotNull(border, "Could not find our item to test."); + + Assert.AreEqual(1, Grid.GetRow(border)); + Assert.AreEqual(1, Grid.GetColumn(border)); + + var border2 = treeroot.FindChildByName("Shifted") as Border; + + Assert.IsNotNull(border2, "Could not find shifted item to test."); + + Assert.AreEqual(2, Grid.GetRow(border2)); + Assert.AreEqual(2, Grid.GetColumn(border2)); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_AutoLayout_VerticalElement() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement); + + Assert.AreEqual(8, grid.Children.Count()); + + grid.Measure(new Size(1000, 1000)); + + var border = treeroot.FindChildByName("OurItem") as Border; + + Assert.IsNotNull(border, "Could not find our item to test."); + + Assert.AreEqual(1, Grid.GetRow(border)); + Assert.AreEqual(1, Grid.GetColumn(border)); + + var border2 = treeroot.FindChildByName("Shifted") as Border; + + Assert.IsNotNull(border2, "Could not find shifted item to test."); + + Assert.AreEqual(2, Grid.GetRow(border2)); + Assert.AreEqual(2, Grid.GetColumn(border2)); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_AutoLayout_HorizontalElement() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement); + + Assert.AreEqual(8, grid.Children.Count()); + + grid.Measure(new Size(1000, 1000)); + + var border = treeroot.FindChildByName("OurItem") as Border; + + Assert.IsNotNull(border, "Could not find our item to test."); + + Assert.AreEqual(0, Grid.GetRow(border)); + Assert.AreEqual(1, Grid.GetColumn(border)); + + var border2 = treeroot.FindChildByName("Shifted") as Border; + + Assert.IsNotNull(border2, "Could not find shifted item to test."); + + Assert.AreEqual(1, Grid.GetRow(border2)); + Assert.AreEqual(0, Grid.GetColumn(border2)); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_AutoLayout_LargeElement() + { + var treeroot = XamlReader.Load(@" + + + + + + + + +") as FrameworkElement; + + var expected = new(int row, int col)[] + { + (0, 0), + (0, 2), + (1, 2), + (2, 0), + (2, 1), + (2, 2), + }; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(6, grid.Children.Count()); + + grid.Measure(new Size(1000, 1000)); + + // Check all children are in expected places. + for (int i = 0; i < children.Count(); i++) + { + Assert.AreEqual(expected[i].row, Grid.GetRow(children[i])); + Assert.AreEqual(expected[i].col, Grid.GetColumn(children[i])); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_AutoLayout_HorizontalElement_FixedPosition() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement); + + Assert.AreEqual(8, grid.Children.Count()); + + grid.Measure(new Size(1000, 1000)); + + var border = treeroot.FindChildByName("OurItem") as Border; + + Assert.IsNotNull(border, "Could not find our item to test."); + + Assert.AreEqual(1, Grid.GetRow(border)); + Assert.AreEqual(1, Grid.GetColumn(border)); + + var border2 = treeroot.FindChildByName("Shifted") as Border; + + Assert.IsNotNull(border2, "Could not find shifted item to test."); + + Assert.AreEqual(2, Grid.GetRow(border2)); + Assert.AreEqual(0, Grid.GetColumn(border2)); + } + } + #pragma warning restore SA1008 // Opening parenthesis must be spaced correctly +} \ No newline at end of file diff --git a/UnitTests/UI/Controls/Test_UniformGrid_Dimensions.cs b/UnitTests/UI/Controls/Test_UniformGrid_Dimensions.cs new file mode 100644 index 000000000..375e9c1b0 --- /dev/null +++ b/UnitTests/UI/Controls/Test_UniformGrid_Dimensions.cs @@ -0,0 +1,234 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using Microsoft.Toolkit.Uwp.UI.Controls; +using Microsoft.Toolkit.Uwp.UI.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Markup; + +namespace UnitTests.UI.Controls +{ + [TestClass] + #pragma warning disable SA1008 // Opening parenthesis must be spaced correctly + public class Test_UniformGrid_Dimensions + { + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetDimensions_NoElements() + { + var treeroot = XamlReader.Load(@" + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(0, grid.Children.Count()); + + var (rows, columns) = UniformGrid.GetDimensions(children, 0, 0, 0); + + Assert.AreEqual(1, rows); + Assert.AreEqual(1, columns); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetDimensions_AllVisible() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(8, grid.Children.Count()); + + var (rows, columns) = UniformGrid.GetDimensions(children, 0, 0, 0); + + Assert.AreEqual(3, rows); + Assert.AreEqual(3, columns); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetDimensions_SomeVisible() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement); + + Assert.AreEqual(8, grid.Children.Count()); + + // TODO: We don't expose this piece of the UniformGrid, but want to test this here for now. + var visible = grid.Children.Where(item => item.Visibility != Visibility.Collapsed && item is FrameworkElement).Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(4, visible.Count()); + + var (rows, columns) = UniformGrid.GetDimensions(visible, 0, 0, 0); + + Assert.AreEqual(2, rows); + Assert.AreEqual(2, columns); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetDimensions_FirstColumn() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(8, grid.Children.Count()); + + var (rows, columns) = UniformGrid.GetDimensions(children, 0, 0, 2); + + Assert.AreEqual(4, rows); + Assert.AreEqual(4, columns); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetDimensions_ElementLarger() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(8, grid.Children.Count()); + + var (rows, columns) = UniformGrid.GetDimensions(children, 0, 0, 0); + + Assert.AreEqual(4, rows); + Assert.AreEqual(4, columns); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetDimensions_FirstColumnEqualsColumns() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + var children = grid.Children.Select(item => item as FrameworkElement).ToArray(); + + Assert.AreEqual(7, grid.Children.Count()); + + // columns == first column + // In WPF, First Column is ignored and we have a 1x7 layout. + var (rows, columns) = UniformGrid.GetDimensions(children, 0, 7, 7); + + Assert.AreEqual(1, rows, "Expected single row."); + Assert.AreEqual(7, columns, "Expected seven columns."); + } + } + #pragma warning restore SA1008 // Opening parenthesis must be spaced correctly +} \ No newline at end of file diff --git a/UnitTests/UI/Controls/Test_UniformGrid_FreeSpots.cs b/UnitTests/UI/Controls/Test_UniformGrid_FreeSpots.cs new file mode 100644 index 000000000..2c7841d5d --- /dev/null +++ b/UnitTests/UI/Controls/Test_UniformGrid_FreeSpots.cs @@ -0,0 +1,206 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using Microsoft.Toolkit.Extensions; +using Microsoft.Toolkit.Uwp.UI.Controls; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; + +namespace UnitTests.UI.Controls +{ + [TestClass] + #pragma warning disable SA1008 // Opening parenthesis must be spaced correctly + public class Test_UniformGrid_FreeSpots + { + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetFreeSpots_Basic() + { + var grid = new UniformGrid(); + + var testref = new TakenSpotsReferenceHolder(new bool[4, 5] + { + { false, true, false, true, false }, + { false, true, true, true, false }, + { false, true, false, true, false }, + { false, false, true, false, false }, + }); + + var results = UniformGrid.GetFreeSpot(testref, 0, false).ToArray(); + + var expected = new(int row, int column)[] + { + (0, 0), (0, 2), (0, 4), + (1, 0), (1, 4), + (2, 0), (2, 2), (2, 4), + (3, 0),(3, 1), (3, 3),(3, 4) + }; + + CollectionAssert.AreEqual( + expected, + results, + "GetFreeSpot failed. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + results.ToArrayString()); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetFreeSpots_FirstColumn() + { + var grid = new UniformGrid(); + + var testref = new TakenSpotsReferenceHolder(new bool[4, 5] + { + { true, false, false, true, false }, + { false, true, true, true, false }, + { false, true, true, true, false }, + { false, false, true, false, false }, + }); + + var results = UniformGrid.GetFreeSpot(testref, 2, false).ToArray(); + + var expected = new(int row, int column)[] + { + (0, 2), (0, 4), + (1, 0), (1, 4), + (2, 0), (2, 4), + (3, 0),(3, 1), (3, 3),(3, 4) + }; + + CollectionAssert.AreEqual( + expected, + results, + "GetFreeSpot failed FirstColumn. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + results.ToArrayString()); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetFreeSpots_FirstColumnEndBoundMinusOne() + { + var grid = new UniformGrid(); + + var testref = new TakenSpotsReferenceHolder(new bool[3, 3] + { + { false, false, false }, + { false, false, false }, + { false, false, false }, + }); + + var results = UniformGrid.GetFreeSpot(testref, 2, false).ToArray(); + + var expected = new(int row, int column)[] + { + (0, 2), + (1, 0),(1, 1),(1, 2), + (2, 0),(2, 1),(2, 2), + }; + + CollectionAssert.AreEqual( + expected, + results, + "GetFreeSpot failed FirstColumn. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + results.ToArrayString()); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetFreeSpots_FirstColumnEndBound() + { + var grid = new UniformGrid(); + + var testref = new TakenSpotsReferenceHolder(new bool[3, 3] + { + { false, false, false }, + { false, false, false }, + { false, false, false }, + }); + + var results = UniformGrid.GetFreeSpot(testref, 3, false).ToArray(); + + var expected = new(int row, int column)[] + { + (0, 0),(0, 1),(0, 2), + (1, 0),(1, 1),(1, 2), + (2, 0),(2, 1),(2, 2), + }; + + CollectionAssert.AreEqual( + expected, + results, + "GetFreeSpot failed FirstColumn. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + results.ToArrayString()); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetFreeSpots_FirstColumnEndBound_TopDown() + { + var grid = new UniformGrid(); + + var testref = new TakenSpotsReferenceHolder(new bool[3, 3] + { + { false, false, false }, + { false, false, false }, + { false, false, false }, + }); + + var results = UniformGrid.GetFreeSpot(testref, 3, true).ToArray(); + + var expected = new(int row, int column)[] + { + (0, 0),(1, 0),(2, 0), + (0, 1),(1, 1),(2, 1), + (0, 2),(1, 2),(2, 2), + }; + + CollectionAssert.AreEqual( + expected, + results, + "GetFreeSpot failed FirstColumn. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + results.ToArrayString()); + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_GetFreeSpots_VerticalOrientation() + { + var grid = new UniformGrid(); + + var testref = new TakenSpotsReferenceHolder(new bool[4, 5] + { + { false, false, false, true, false }, + { false, true, true, false, false }, + { true, false, false, true, false }, + { false, false, true, false, false }, + }); + + var results = UniformGrid.GetFreeSpot(testref, 0, true).ToArray(); + + // top-bottom, transpose of matrix above. + var expected = new(int row, int column)[] + { + (0, 0),(1, 0), (3, 0), + (0, 1), (2, 1),(3, 1), + (0, 2), (2, 2), + (1, 3), (3, 3), + (0, 4),(1, 4),(2, 4),(3, 4) + }; + + CollectionAssert.AreEqual( + expected, + results, + "GetFreeSpot failed RightToLeft. Expected:\n{0}.\nActual:\n{1}", + expected.ToArrayString(), + results.ToArrayString()); + } + } + #pragma warning restore SA1008 // Opening parenthesis must be spaced correctly +} \ No newline at end of file diff --git a/UnitTests/UI/Controls/Test_UniformGrid_RowColDefinitions.cs b/UnitTests/UI/Controls/Test_UniformGrid_RowColDefinitions.cs new file mode 100644 index 000000000..b2926ed27 --- /dev/null +++ b/UnitTests/UI/Controls/Test_UniformGrid_RowColDefinitions.cs @@ -0,0 +1,814 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Toolkit.Uwp.UI.Controls; +using Microsoft.Toolkit.Uwp.UI.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Markup; + +namespace UnitTests.UI.Controls +{ + [TestClass] + #pragma warning disable SA1008 // Opening parenthesis must be spaced correctly + public class Test_UniformGrid_RowColDefinitions + { + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_SetupRowDefinitions_AllAutomatic() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + // Normal Grid's don't have any definitions to start + Assert.AreEqual(0, grid.RowDefinitions.Count); + + //// DO IT AGAIN + //// This is so we can check that it will behave the same again on another pass. + + // We'll have three rows in this setup + grid.SetupRowDefinitions(3); + + // We should now have our rows created + Assert.AreEqual(3, grid.RowDefinitions.Count); + + for (int i = 0; i < grid.RowDefinitions.Count; i++) + { + var rd = grid.RowDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, rd.Height.GridUnitType); + + Assert.AreEqual(1.0, rd.Height.Value); + } + + // We'll have three rows in this setup + grid.SetupRowDefinitions(3); + + // We should now have our rows created + Assert.AreEqual(3, grid.RowDefinitions.Count); + + for (int i = 0; i < grid.RowDefinitions.Count; i++) + { + var rd = grid.RowDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, rd.Height.GridUnitType); + + Assert.AreEqual(1.0, rd.Height.Value); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_SetupRowDefinitions_FirstFixed() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + // We should find our first definition + Assert.AreEqual(1, grid.RowDefinitions.Count); + Assert.AreEqual(48, grid.RowDefinitions[0].Height.Value); + + // We'll have three rows in this setup + grid.SetupRowDefinitions(3); + + // We should now have our rows created + Assert.AreEqual(3, grid.RowDefinitions.Count); + + var rdo = grid.RowDefinitions[0]; + + // Did we mark that our row is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo)); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Height.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Height.Value); + + // Check that we filled in the other two. + for (int i = 1; i < grid.RowDefinitions.Count; i++) + { + var rd = grid.RowDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, rd.Height.GridUnitType); + + Assert.AreEqual(1.0, rd.Height.Value); + } + + //// DO IT AGAIN + //// This is so we can check that it will behave the same again on another pass. + + // We'll have three rows in this setup + grid.SetupRowDefinitions(3); + + // We should now have our rows created + Assert.AreEqual(3, grid.RowDefinitions.Count); + + rdo = grid.RowDefinitions[0]; + + // Did we mark that our row is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo)); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Height.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Height.Value); + + // Check that we filled in the other two. + for (int i = 1; i < grid.RowDefinitions.Count; i++) + { + var rd = grid.RowDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, rd.Height.GridUnitType); + + Assert.AreEqual(1.0, rd.Height.Value); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_SetupRowDefinitions_MiddleFixed() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + // We should find our first definition + Assert.AreEqual(1, grid.RowDefinitions.Count, "Expected to find our row definition."); + Assert.AreEqual(48, grid.RowDefinitions[0].Height.Value); + + Assert.AreEqual(5, grid.Rows, "Rows not set to 5"); + + // We'll have five rows in this setup + grid.SetupRowDefinitions(5); + + // We should now have our rows created + Assert.AreEqual(5, grid.RowDefinitions.Count, "5 RowDefinitions weren't created."); + + // Our original definition should be at index 2 + var rdo = grid.RowDefinitions[0]; + + // Did we mark that our row is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo)); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Height.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Height.Value); + + // Check that we filled in the other two. + for (int i = 1; i < grid.RowDefinitions.Count; i++) + { + var rd = grid.RowDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, rd.Height.GridUnitType); + + Assert.AreEqual(1.0, rd.Height.Value); + } + + //// DO IT AGAIN + //// This is so we can check that it will behave the same again on another pass. + + // We'll have five rows in this setup + grid.SetupRowDefinitions(5); + + // We should now have our rows created + Assert.AreEqual(5, grid.RowDefinitions.Count); + + // Our original definition should be at index 2 + rdo = grid.RowDefinitions[0]; + + // Did we mark that our row is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo)); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Height.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Height.Value); + + // Check that we filled in the other two. + for (int i = 1; i < grid.RowDefinitions.Count; i++) + { + var rd = grid.RowDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, rd.Height.GridUnitType); + + Assert.AreEqual(1.0, rd.Height.Value); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_SetupRowDefinitions_MiddleAndEndFixed() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + // We should find our first definition + Assert.AreEqual(5, grid.RowDefinitions.Count, "Expected to find two row definitions."); + Assert.AreEqual(48, grid.RowDefinitions[2].Height.Value); + Assert.AreEqual(128, grid.RowDefinitions[4].Height.Value); + + Assert.AreEqual(5, grid.Rows, "Rows not set to 5"); + + // We'll have five rows in this setup + grid.SetupRowDefinitions(5); + + // We should now have our rows created + Assert.AreEqual(5, grid.RowDefinitions.Count, "5 RowDefinitions weren't created."); + + // Our original definition should be at index 2 + var rdo = grid.RowDefinitions[2]; + + // Did we mark that our row is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo)); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Height.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Height.Value); + + // Our 2nd original definition should be at index 4 + var rdo2 = grid.RowDefinitions[4]; + + // Did we mark that our row is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo2)); + + Assert.AreNotEqual(GridUnitType.Star, rdo2.Height.GridUnitType); + + Assert.AreNotEqual(1.0, rdo2.Height.Value); + + // Check that we filled in the other two. + for (int i = 0; i < grid.RowDefinitions.Count; i++) + { + if (i == 2 || i == 4) + { + continue; + } + + var rd = grid.RowDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, rd.Height.GridUnitType); + + Assert.AreEqual(1.0, rd.Height.Value); + } + + //// DO IT AGAIN + //// This is so we can check that it will behave the same again on another pass. + + // We'll have five rows in this setup + grid.SetupRowDefinitions(5); + + // We should now have our rows created + Assert.AreEqual(5, grid.RowDefinitions.Count, "5 RowDefinitions weren't created."); + + // Our original definition should be at index 2 + rdo = grid.RowDefinitions[2]; + + // Did we mark that our row is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo)); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Height.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Height.Value); + + // Our 2nd original definition should be at index 4 + rdo2 = grid.RowDefinitions[4]; + + // Did we mark that our row is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo2)); + + Assert.AreNotEqual(GridUnitType.Star, rdo2.Height.GridUnitType); + + Assert.AreNotEqual(1.0, rdo2.Height.Value); + + // Check that we filled in the other two. + for (int i = 0; i < grid.RowDefinitions.Count; i++) + { + if (i == 2 || i == 4) + { + continue; + } + + var rd = grid.RowDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, rd.Height.GridUnitType); + + Assert.AreEqual(1.0, rd.Height.Value); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_SetupColumnDefinitions_AllAutomatic() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + // Normal Grid's don't have any definitions to start + Assert.AreEqual(0, grid.ColumnDefinitions.Count); + + // We'll have three columns in this setup + grid.SetupColumnDefinitions(3); + + // We should now have our columns created + Assert.AreEqual(3, grid.ColumnDefinitions.Count); + + for (int i = 0; i < grid.ColumnDefinitions.Count; i++) + { + var cd = grid.ColumnDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(cd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, cd.Width.GridUnitType); + + Assert.AreEqual(1.0, cd.Width.Value); + } + + //// DO IT AGAIN + //// This is so we can check that it will behave the same again on another pass. + + // We'll have three columns in this setup + grid.SetupColumnDefinitions(3); + + // We should now have our columns created + Assert.AreEqual(3, grid.ColumnDefinitions.Count); + + for (int i = 0; i < grid.ColumnDefinitions.Count; i++) + { + var cd = grid.ColumnDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(cd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, cd.Width.GridUnitType); + + Assert.AreEqual(1.0, cd.Width.Value); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_SetupColumnDefinitions_FirstFixed() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + // We should find our first definition + Assert.AreEqual(1, grid.ColumnDefinitions.Count); + Assert.AreEqual(48, grid.ColumnDefinitions[0].Width.Value); + + // We'll have three columns in this setup + grid.SetupColumnDefinitions(3); + + // We should now have our columns created + Assert.AreEqual(3, grid.ColumnDefinitions.Count); + + var cdo = grid.ColumnDefinitions[0]; + + // Did we mark that our column is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(cdo)); + + Assert.AreNotEqual(GridUnitType.Star, cdo.Width.GridUnitType); + + Assert.AreNotEqual(1.0, cdo.Width.Value); + + // Check that we filled in the other two. + for (int i = 1; i < grid.ColumnDefinitions.Count; i++) + { + var cd = grid.ColumnDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(cd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, cd.Width.GridUnitType); + + Assert.AreEqual(1.0, cd.Width.Value); + } + + //// DO IT AGAIN + //// This is so we can check that it will behave the same again on another pass. + + // We'll have three columns in this setup + grid.SetupColumnDefinitions(3); + + // We should now have our columns created + Assert.AreEqual(3, grid.ColumnDefinitions.Count); + + cdo = grid.ColumnDefinitions[0]; + + // Did we mark that our column is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(cdo)); + + Assert.AreNotEqual(GridUnitType.Star, cdo.Width.GridUnitType); + + Assert.AreNotEqual(1.0, cdo.Width.Value); + + // Check that we filled in the other two. + for (int i = 1; i < grid.ColumnDefinitions.Count; i++) + { + var cd = grid.ColumnDefinitions[i]; + + // Check if we've setup our row to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(cd)); + + // We need to be using '*' layout for all our rows to be even. + Assert.AreEqual(GridUnitType.Star, cd.Width.GridUnitType); + + Assert.AreEqual(1.0, cd.Width.Value); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_SetupColumnDefinitions_MiddleFixed() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + // We should find our first definition + Assert.AreEqual(3, grid.ColumnDefinitions.Count, "Expected to find our Column definition."); + Assert.AreEqual(48, grid.ColumnDefinitions[2].Width.Value); + + Assert.AreEqual(5, grid.Columns, "Columns not set to 5"); + + // We'll have five Columns in this setup + grid.SetupColumnDefinitions(5); + + // We should now have our Columns created + Assert.AreEqual(5, grid.ColumnDefinitions.Count, "5 ColumnDefinitions weren't created."); + + // Our original definition should be at index 2 + var rdo = grid.ColumnDefinitions[2]; + + // Did we mark that our Column is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo), "AutoLayout of 48 Width should be False."); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Width.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Width.Value); + + // Check that we filled in the other two. + for (int i = 3; i < grid.ColumnDefinitions.Count; i++) + { + var rd = grid.ColumnDefinitions[i]; + + // Check if we've setup our Column to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(rd), "AutoLayout should be true. {0}", i); + + // We need to be using '*' layout for all our Columns to be even. + Assert.AreEqual(GridUnitType.Star, rd.Width.GridUnitType); + + Assert.AreEqual(1.0, rd.Width.Value); + } + + //// DO IT AGAIN + //// This is so we can check that it will behave the same again on another pass. + + // We'll have five Columns in this setup + grid.SetupColumnDefinitions(5); + + // We should now have our Columns created + Assert.AreEqual(5, grid.ColumnDefinitions.Count); + + // Our original definition should be at index 2 + rdo = grid.ColumnDefinitions[2]; + + // Did we mark that our Column is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo), "AutoLayout Width 48 should be false 2nd time."); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Width.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Width.Value); + + // Check that we filled in the other two. + for (int i = 3; i < grid.ColumnDefinitions.Count; i++) + { + var rd = grid.ColumnDefinitions[i]; + + // Check if we've setup our Column to automatically layout + Assert.AreEqual(true, UniformGrid.GetAutoLayout(rd), "AutoLayout should be true 2nd time. {0}", i); + + // We need to be using '*' layout for all our Columns to be even. + Assert.AreEqual(GridUnitType.Star, rd.Width.GridUnitType); + + Assert.AreEqual(1.0, rd.Width.Value); + } + } + + [TestCategory("UniformGrid")] + [UITestMethod] + public void Test_UniformGrid_SetupColumnDefinitions_FirstAndEndFixed() + { + var treeroot = XamlReader.Load(@" + + + + + + + + + + + + + + + + + + +") as FrameworkElement; + + Assert.IsNotNull(treeroot, "Could not load XAML tree."); + + var grid = treeroot.FindChildByName("UniformGrid") as UniformGrid; + + Assert.IsNotNull(grid, "Could not find UniformGrid in tree."); + + // We should find our first definition + Assert.AreEqual(5, grid.ColumnDefinitions.Count, "Expected to find two Column definitions."); + Assert.AreEqual(48, grid.ColumnDefinitions[0].Width.Value); + Assert.AreEqual(128, grid.ColumnDefinitions[4].Width.Value); + + Assert.AreEqual(5, grid.Columns, "Columns not set to 5"); + + // We'll have five Columns in this setup + grid.SetupColumnDefinitions(5); + + // We should now have our Columns created + Assert.AreEqual(5, grid.ColumnDefinitions.Count, "5 ColumnDefinitions weren't created."); + + // Our original definition should be at index 2 + var rdo = grid.ColumnDefinitions[0]; + + // Did we mark that our Column is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo)); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Width.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Width.Value); + + // Our 2nd original definition should be at index 4 + var rdo2 = grid.ColumnDefinitions[4]; + + // Did we mark that our Column is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo2)); + ////Assert.AreEqual(4, UniformGrid.GetColumn(rdo2)); + + Assert.AreNotEqual(GridUnitType.Star, rdo2.Width.GridUnitType); + + Assert.AreNotEqual(1.0, rdo2.Width.Value); + + // Check that we filled in the other two. + for (int i = 1; i < grid.ColumnDefinitions.Count - 1; i++) + { + var rd = grid.ColumnDefinitions[i]; + + // Check if we've setup our Column to automatically layout + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our Columns to be even. + Assert.AreEqual(GridUnitType.Star, rd.Width.GridUnitType); + + Assert.AreEqual(1.0, rd.Width.Value); + } + + //// DO IT AGAIN + //// This is so we can check that it will behave the same again on another pass. + + // We'll have five Columns in this setup + grid.SetupColumnDefinitions(5); + + // We should now have our Columns created + Assert.AreEqual(5, grid.ColumnDefinitions.Count, "5 ColumnDefinitions weren't created."); + + // Our original definition should be at index 0 + rdo = grid.ColumnDefinitions[0]; + + // Did we mark that our Column is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo)); + + Assert.AreNotEqual(GridUnitType.Star, rdo.Width.GridUnitType); + + Assert.AreNotEqual(1.0, rdo.Width.Value); + + // Our 2nd original definition should be at index 4 + rdo2 = grid.ColumnDefinitions[4]; + + // Did we mark that our Column is special? + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rdo2)); + + Assert.AreNotEqual(GridUnitType.Star, rdo2.Width.GridUnitType); + + Assert.AreNotEqual(1.0, rdo2.Width.Value); + + // Check that we filled in the other two. + for (int i = 1; i < grid.ColumnDefinitions.Count - 1; i++) + { + var rd = grid.ColumnDefinitions[i]; + + // Check if we've setup our Column to automatically layout + Assert.AreEqual(false, UniformGrid.GetAutoLayout(rd)); + + // We need to be using '*' layout for all our Columns to be even. + Assert.AreEqual(GridUnitType.Star, rd.Width.GridUnitType); + + Assert.AreEqual(1.0, rd.Width.Value); + } + } + } + #pragma warning restore SA1008 // Opening parenthesis must be spaced correctly +} \ No newline at end of file diff --git a/UnitTests/UI/Person.cs b/UnitTests/UI/Person.cs index 42520b1c4..80a70fff3 100644 --- a/UnitTests/UI/Person.cs +++ b/UnitTests/UI/Person.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.ComponentModel; diff --git a/UnitTests/UI/Test_AdvancedCollectionView.cs b/UnitTests/UI/Test_AdvancedCollectionView.cs index 6a6e6c001..9a5f59fe4 100644 --- a/UnitTests/UI/Test_AdvancedCollectionView.cs +++ b/UnitTests/UI/Test_AdvancedCollectionView.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.Collections; diff --git a/UnitTests/UnitTestApp.xaml.cs b/UnitTests/UnitTestApp.xaml.cs index 80a45723d..2091342e3 100644 --- a/UnitTests/UnitTestApp.xaml.cs +++ b/UnitTests/UnitTestApp.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; diff --git a/UnitTests/UnitTests.Notifications.Shared/AssertHelper.cs b/UnitTests/UnitTests.Notifications.Shared/AssertHelper.cs index 4a15a7780..604370abd 100644 --- a/UnitTests/UnitTests.Notifications.Shared/AssertHelper.cs +++ b/UnitTests/UnitTests.Notifications.Shared/AssertHelper.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Uwp.Notifications; diff --git a/UnitTests/UnitTests.Notifications.Shared/TestMail.cs b/UnitTests/UnitTests.Notifications.Shared/TestMail.cs index 5bd71e509..96add14c7 100644 --- a/UnitTests/UnitTests.Notifications.Shared/TestMail.cs +++ b/UnitTests/UnitTests.Notifications.Shared/TestMail.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Uwp.Notifications; diff --git a/UnitTests/UnitTests.Notifications.Shared/TestWeather.cs b/UnitTests/UnitTests.Notifications.Shared/TestWeather.cs index 77afdb853..fd4c5b0a0 100644 --- a/UnitTests/UnitTests.Notifications.Shared/TestWeather.cs +++ b/UnitTests/UnitTests.Notifications.Shared/TestWeather.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Uwp.Notifications; diff --git a/UnitTests/UnitTests.Notifications.Shared/Test_Adaptive_Xml.cs b/UnitTests/UnitTests.Notifications.Shared/Test_Adaptive_Xml.cs index 0e5f163c3..1c9654f4f 100644 --- a/UnitTests/UnitTests.Notifications.Shared/Test_Adaptive_Xml.cs +++ b/UnitTests/UnitTests.Notifications.Shared/Test_Adaptive_Xml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Uwp.Notifications; @@ -124,32 +116,19 @@ namespace UnitTests.Notifications [TestMethod] public void Test_Adaptive_Text_HintMaxLines_BelowMin() { - try + Assert.ThrowsException(() => { new AdaptiveText() { HintMaxLines = 0 }; - } - catch (ArgumentOutOfRangeException) - { - return; - } - - // We can't use the ExpectedException attribute since the UWP testing toolkit doesn't support it :( - Assert.Fail("ArgumentOutOfRangeExceptions should have been thrown."); + }, "ArgumentOutOfRangeExceptions should have been thrown."); } [TestMethod] public void Test_Adaptive_Text_HintMaxLines_AboveMax() { - try - { - new AdaptiveText() { HintMaxLines = -54 }; - } - catch (ArgumentOutOfRangeException) + Assert.ThrowsException(() => { - return; - } - - Assert.Fail("ArgumentOutOfRangeExceptions should have been thrown."); + new AdaptiveText() { HintMaxLines = -54 }; + }, "ArgumentOutOfRangeExceptions should have been thrown."); } [TestMethod] @@ -182,31 +161,19 @@ namespace UnitTests.Notifications [TestMethod] public void Test_Adaptive_Text_HintMinLines_BelowMin() { - try - { - new AdaptiveText() { HintMinLines = 0 }; - } - catch (ArgumentOutOfRangeException) + Assert.ThrowsException(() => { - return; - } - - Assert.Fail("ArgumentOutOfRangeExceptions should have been thrown."); + new AdaptiveText() { HintMinLines = 0 }; + }, "ArgumentOutOfRangeExceptions should have been thrown."); } [TestMethod] public void Test_Adaptive_Text_HintMinLines_AboveMax() { - try - { - new AdaptiveText() { HintMinLines = -54 }; - } - catch (ArgumentOutOfRangeException) + Assert.ThrowsException(() => { - return; - } - - Assert.Fail("ArgumentOutOfRangeExceptions should have been thrown."); + new AdaptiveText() { HintMinLines = -54 }; + }, "ArgumentOutOfRangeExceptions should have been thrown."); } [TestMethod] @@ -246,16 +213,10 @@ namespace UnitTests.Notifications [TestMethod] public void Test_Adaptive_Image_Defaults() { - try - { - AssertAdaptiveChild("exception should be thrown", new AdaptiveImage()); - } - catch (NullReferenceException) + Assert.ThrowsException(() => { - return; - } - - Assert.Fail("NullReferenceException should have been thrown."); + AssertAdaptiveChild("exception should be thrown", new AdaptiveImage()); + }, "NullReferenceException should have been thrown."); } [TestMethod] @@ -285,19 +246,13 @@ namespace UnitTests.Notifications [TestMethod] public void Test_Adaptive_Image_Source_Null() { - try - { + Assert.ThrowsException(() => + { new AdaptiveImage() { Source = null }; - } - catch (ArgumentNullException) - { - return; - } - - Assert.Fail("ArgumentNullException should have been thrown."); + }, "ArgumentNullException should have been thrown."); } [TestMethod] @@ -405,16 +360,10 @@ namespace UnitTests.Notifications [TestMethod] public void Test_Adaptive_Group_Defaults() { - try + Assert.ThrowsException(() => { AssertAdaptiveChild("exception should be thrown since groups need at least one subgroup child", new AdaptiveGroup()); - } - catch (InvalidOperationException) - { - return; - } - - Assert.Fail("InvalidOperationException should have been thrown."); + }, "InvalidOperationException should have been thrown."); } [TestMethod] @@ -492,37 +441,25 @@ namespace UnitTests.Notifications [TestMethod] public void Test_Adaptive_Subgroup_HintWeight_JustBelowMin() { - try + Assert.ThrowsException(() => { AssertAdaptiveSubgroup("exception should be thrown", new AdaptiveSubgroup() { HintWeight = 0 }); - } - catch (ArgumentOutOfRangeException) - { - return; - } - - Assert.Fail("ArgumentOutOfRangeException should have been thrown."); + }, "ArgumentOutOfRangeException should have been thrown."); } [TestMethod] public void Test_Adaptive_Subgroup_HintWeight_BelowMin() { - try + Assert.ThrowsException(() => { AssertAdaptiveSubgroup("exception should be thrown", new AdaptiveSubgroup() { HintWeight = -53 }); - } - catch (ArgumentOutOfRangeException) - { - return; - } - - Assert.Fail("ArgumentOutOfRangeException should have been thrown."); + }, "ArgumentOutOfRangeException should have been thrown."); } [TestMethod] diff --git a/UnitTests/UnitTests.Notifications.Shared/Test_Badge_Xml.cs b/UnitTests/UnitTests.Notifications.Shared/Test_Badge_Xml.cs index 7d302c60c..c68da6c67 100644 --- a/UnitTests/UnitTests.Notifications.Shared/Test_Badge_Xml.cs +++ b/UnitTests/UnitTests.Notifications.Shared/Test_Badge_Xml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Uwp.Notifications; diff --git a/UnitTests/UnitTests.Notifications.Shared/Test_Tile_Xml.cs b/UnitTests/UnitTests.Notifications.Shared/Test_Tile_Xml.cs index 4d3cda4e8..10cdbefc4 100644 --- a/UnitTests/UnitTests.Notifications.Shared/Test_Tile_Xml.cs +++ b/UnitTests/UnitTests.Notifications.Shared/Test_Tile_Xml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using Microsoft.Toolkit.Uwp.Notifications; diff --git a/UnitTests/UnitTests.Notifications.Shared/Test_Toast_Xml.cs b/UnitTests/UnitTests.Notifications.Shared/Test_Toast_Xml.cs index e045351cf..3702b2b53 100644 --- a/UnitTests/UnitTests.Notifications.Shared/Test_Toast_Xml.cs +++ b/UnitTests/UnitTests.Notifications.Shared/Test_Toast_Xml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/UnitTests/UnitTests.Notifications.Shared/TextXboxModern.cs b/UnitTests/UnitTests.Notifications.Shared/TextXboxModern.cs index fa8aa3dad..0f74a66d1 100644 --- a/UnitTests/UnitTests.Notifications.Shared/TextXboxModern.cs +++ b/UnitTests/UnitTests.Notifications.Shared/TextXboxModern.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Toolkit.Uwp.Notifications; diff --git a/UnitTests/UnitTests.Notifications.UWP/Package.appxmanifest b/UnitTests/UnitTests.Notifications.UWP/Package.appxmanifest index 150dfd64e..7ca1bc485 100644 --- a/UnitTests/UnitTests.Notifications.UWP/Package.appxmanifest +++ b/UnitTests/UnitTests.Notifications.UWP/Package.appxmanifest @@ -1,45 +1,28 @@  - - - - - - + + + UnitTests.Notifications.UWP anbare Assets\StoreLogo.png - - - - - + + + + - + \ No newline at end of file diff --git a/UnitTests/UnitTests.Notifications.UWP/Properties/AssemblyInfo.cs b/UnitTests/UnitTests.Notifications.UWP/Properties/AssemblyInfo.cs index 31c5e29d7..9c9371672 100644 --- a/UnitTests/UnitTests.Notifications.UWP/Properties/AssemblyInfo.cs +++ b/UnitTests/UnitTests.Notifications.UWP/Properties/AssemblyInfo.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System.Reflection; using System.Runtime.CompilerServices; diff --git a/UnitTests/UnitTests.Notifications.UWP/UnitTestApp.xaml.cs b/UnitTests/UnitTests.Notifications.UWP/UnitTestApp.xaml.cs index d1e46be55..bed4e6ee9 100644 --- a/UnitTests/UnitTests.Notifications.UWP/UnitTestApp.xaml.cs +++ b/UnitTests/UnitTests.Notifications.UWP/UnitTestApp.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using Windows.ApplicationModel; diff --git a/UnitTests/UnitTests.Notifications.UWP/UnitTests.Notifications.UWP.csproj b/UnitTests/UnitTests.Notifications.UWP/UnitTests.Notifications.UWP.csproj index b1aaca082..adf0cbe78 100644 --- a/UnitTests/UnitTests.Notifications.UWP/UnitTests.Notifications.UWP.csproj +++ b/UnitTests/UnitTests.Notifications.UWP/UnitTests.Notifications.UWP.csproj @@ -11,13 +11,14 @@ UnitTests.Notifications.UWP en-US UAP - 10.0.16299.0 - 10.0.14393.0 + 10.0.17134.0 + 10.0.15063.0 14 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} UnitTests.Notifications.UWP_TemporaryKey.pfx $(VisualStudioVersion) + FEDD74C21ED73DD170EC6D528D2E5289C30874E1 true @@ -102,7 +103,7 @@ - 5.4.2 + 6.0.8 1.2.0 diff --git a/UnitTests/UnitTests.Notifications.UWP/UnitTests.Notifications.UWP_TemporaryKey.pfx b/UnitTests/UnitTests.Notifications.UWP/UnitTests.Notifications.UWP_TemporaryKey.pfx index 4b0de0471..2e250db0e 100644 Binary files a/UnitTests/UnitTests.Notifications.UWP/UnitTests.Notifications.UWP_TemporaryKey.pfx and b/UnitTests/UnitTests.Notifications.UWP/UnitTests.Notifications.UWP_TemporaryKey.pfx differ diff --git a/UnitTests/UnitTests.Notifications.WinRT/Properties/AssemblyInfo.cs b/UnitTests/UnitTests.Notifications.WinRT/Properties/AssemblyInfo.cs index c9f981959..227d7ed94 100644 --- a/UnitTests/UnitTests.Notifications.WinRT/Properties/AssemblyInfo.cs +++ b/UnitTests/UnitTests.Notifications.WinRT/Properties/AssemblyInfo.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System.Reflection; using System.Runtime.CompilerServices; diff --git a/UnitTests/UnitTests.Notifications.WinRT/UnitTestApp.xaml.cs b/UnitTests/UnitTests.Notifications.WinRT/UnitTestApp.xaml.cs index f3923871b..91a90b094 100644 --- a/UnitTests/UnitTests.Notifications.WinRT/UnitTestApp.xaml.cs +++ b/UnitTests/UnitTests.Notifications.WinRT/UnitTestApp.xaml.cs @@ -1,14 +1,6 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; diff --git a/UnitTests/UnitTests.Notifications.WinRT/UnitTests.Notifications.WinRT.csproj b/UnitTests/UnitTests.Notifications.WinRT/UnitTests.Notifications.WinRT.csproj index a36418f3d..cbcaf48e8 100644 --- a/UnitTests/UnitTests.Notifications.WinRT/UnitTests.Notifications.WinRT.csproj +++ b/UnitTests/UnitTests.Notifications.WinRT/UnitTests.Notifications.WinRT.csproj @@ -11,13 +11,14 @@ UnitTests.Notifications.WinRT en-US UAP - 10.0.16299.0 - 10.0.14393.0 + 10.0.17134.0 + 10.0.15063.0 14 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} UnitTests.Notifications.WinRT_TemporaryKey.pfx $(VisualStudioVersion) + 551EC2BDF0E69B0E1444C4BFB95EA1915309A7E6 true @@ -102,7 +103,7 @@ - 5.4.2 + 6.0.8 1.2.0 diff --git a/UnitTests/UnitTests.Notifications.WinRT/UnitTests.Notifications.WinRT_TemporaryKey.pfx b/UnitTests/UnitTests.Notifications.WinRT/UnitTests.Notifications.WinRT_TemporaryKey.pfx new file mode 100644 index 000000000..c1e99c070 Binary files /dev/null and b/UnitTests/UnitTests.Notifications.WinRT/UnitTests.Notifications.WinRT_TemporaryKey.pfx differ diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index a6dc96b8e..4a409907f 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -11,8 +11,8 @@ UnitTests en-US UAP - 10.0.16299.0 - 10.0.14393.0 + 10.0.17134.0 + 10.0.15063.0 14 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} @@ -115,7 +115,7 @@ - 5.4.2 + 6.0.8 1.2.0 @@ -132,6 +132,9 @@ + + + @@ -161,6 +164,10 @@ + + + + diff --git a/Windows Community Toolkit.sln b/Windows Community Toolkit.sln index 0c15be6a8..42ac5d52f 100644 --- a/Windows Community Toolkit.sln +++ b/Windows Community Toolkit.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27130.0 +VisualStudioVersion = 15.0.27004.2002 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{9AD30620-667D-433C-9961-8D885EE7B762}" EndProject @@ -53,8 +53,10 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CFA75BE0-5A44-45DE-8114-426A605B062B}" ProjectSection(SolutionItems) = preProject build\build.cake = build\build.cake + build\build.ps1 = build\build.ps1 Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets + global.json = global.json EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.Notifications.JavaScript", "Microsoft.Toolkit.Uwp.Notifications.JavaScript\Microsoft.Toolkit.Uwp.Notifications.JavaScript.csproj", "{94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}" @@ -72,7 +74,23 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Toolkit.Uwp.UI.Co {DAEB9CEC-C817-33B2-74B2-BC379380DB72} = {DAEB9CEC-C817-33B2-74B2-BC379380DB72} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Toolkit.Parsers", "Microsoft.Toolkit.Parsers\Microsoft.Toolkit.Parsers.csproj", "{42CA4935-54BE-42EA-AC19-992378C08DE6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Parsers", "Microsoft.Toolkit.Parsers\Microsoft.Toolkit.Parsers.csproj", "{42CA4935-54BE-42EA-AC19-992378C08DE6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PlatformSpecific", "PlatformSpecific", "{096ECFD7-7035-4487-9C87-81DCE9389620}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DifferencesGen", "Microsoft.Toolkit.Uwp.PlatformDifferencesGen\DifferencesGen.csproj", "{292D34E8-0F01-4FA8-951D-8232F75A88D5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer", "Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer\Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer.csproj", "{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Toolkit.Uwp.Input.GazeInteraction", "Microsoft.Toolkit.UWP.Input.GazeInteraction\Microsoft.Toolkit.Uwp.Input.GazeInteraction.vcxproj", "{A5E98964-45B1-442D-A07A-298A3221D81E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GazeInputTest", "GazeInputTest\GazeInputTest.csproj", "{A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.UI.Controls.Graph", "Microsoft.Toolkit.Uwp.UI.Controls.Graph\Microsoft.Toolkit.Uwp.UI.Controls.Graph.csproj", "{D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}" + ProjectSection(ProjectDependencies) = postProject + {34398053-FC70-4243-84F9-F355DEFFF66D} = {34398053-FC70-4243-84F9-F355DEFFF66D} + {3DD8AA7C-3569-4E51-992F-0C2257E8878E} = {3DD8AA7C-3569-4E51-992F-0C2257E8878E} + EndProjectSection EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution @@ -81,16 +99,60 @@ Global UnitTests\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems*{efa96b3c-857e-4659-b942-6bef7719f4ca}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug (Anniversary Update)|Any CPU = Debug (Anniversary Update)|Any CPU + Debug (Anniversary Update)|ARM = Debug (Anniversary Update)|ARM + Debug (Anniversary Update)|x64 = Debug (Anniversary Update)|x64 + Debug (Anniversary Update)|x86 = Debug (Anniversary Update)|x86 + Debug (Version 1511)|Any CPU = Debug (Version 1511)|Any CPU + Debug (Version 1511)|ARM = Debug (Version 1511)|ARM + Debug (Version 1511)|x64 = Debug (Version 1511)|x64 + Debug (Version 1511)|x86 = Debug (Version 1511)|x86 Debug|Any CPU = Debug|Any CPU Debug|ARM = Debug|ARM Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Native|Any CPU = Native|Any CPU + Native|ARM = Native|ARM + Native|x64 = Native|x64 + Native|x86 = Native|x86 + Release (Anniversary Update)|Any CPU = Release (Anniversary Update)|Any CPU + Release (Anniversary Update)|ARM = Release (Anniversary Update)|ARM + Release (Anniversary Update)|x64 = Release (Anniversary Update)|x64 + Release (Anniversary Update)|x86 = Release (Anniversary Update)|x86 + Release (Version 1511)|Any CPU = Release (Version 1511)|Any CPU + Release (Version 1511)|ARM = Release (Version 1511)|ARM + Release (Version 1511)|x64 = Release (Version 1511)|x64 + Release (Version 1511)|x86 = Release (Version 1511)|x86 Release|Any CPU = Release|Any CPU Release|ARM = Release|ARM Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|Any CPU.Deploy.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|ARM.Build.0 = Debug|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|ARM.Deploy.0 = Debug|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|x64.Build.0 = Debug|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|x64.Deploy.0 = Debug|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|x86.Build.0 = Debug|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Anniversary Update)|x86.Deploy.0 = Debug|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|Any CPU.Build.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|Any CPU.Deploy.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|ARM.ActiveCfg = Debug|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|ARM.Build.0 = Debug|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|ARM.Deploy.0 = Debug|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|x64.ActiveCfg = Debug|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|x64.Build.0 = Debug|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|x64.Deploy.0 = Debug|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|x86.ActiveCfg = Debug|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|x86.Build.0 = Debug|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug (Version 1511)|x86.Deploy.0 = Debug|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug|Any CPU.ActiveCfg = Debug|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug|Any CPU.Build.0 = Debug|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug|Any CPU.Deploy.0 = Debug|x86 @@ -103,6 +165,34 @@ Global {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug|x86.ActiveCfg = Debug|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug|x86.Build.0 = Debug|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Debug|x86.Deploy.0 = Debug|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Native|Any CPU.ActiveCfg = Release|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Native|ARM.ActiveCfg = Release|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Native|x64.ActiveCfg = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Native|x86.ActiveCfg = Release|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|Any CPU.Deploy.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|ARM.ActiveCfg = Release|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|ARM.Build.0 = Release|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|ARM.Deploy.0 = Release|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|x64.ActiveCfg = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|x64.Build.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|x64.Deploy.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|x86.ActiveCfg = Release|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|x86.Build.0 = Release|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Anniversary Update)|x86.Deploy.0 = Release|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|Any CPU.Build.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|Any CPU.Deploy.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|ARM.ActiveCfg = Release|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|ARM.Build.0 = Release|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|ARM.Deploy.0 = Release|ARM + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|x64.ActiveCfg = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|x64.Build.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|x64.Deploy.0 = Release|x64 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|x86.ActiveCfg = Release|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|x86.Build.0 = Release|x86 + {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release (Version 1511)|x86.Deploy.0 = Release|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release|Any CPU.ActiveCfg = Release|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release|ARM.ActiveCfg = Release|ARM {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release|ARM.Build.0 = Release|ARM @@ -113,6 +203,22 @@ Global {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release|x86.ActiveCfg = Release|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release|x86.Build.0 = Release|x86 {719C43C6-8753-4395-ADAA-2FCC70F76BF3}.Release|x86.Deploy.0 = Release|x86 + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug|Any CPU.Build.0 = Debug|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -121,6 +227,26 @@ Global {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug|x64.Build.0 = Debug|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug|x86.ActiveCfg = Debug|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Debug|x86.Build.0 = Debug|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Native|Any CPU.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Native|ARM.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Native|x64.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Native|x86.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release|Any CPU.Build.0 = Release|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release|ARM.ActiveCfg = Release|Any CPU @@ -129,6 +255,26 @@ Global {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release|x64.Build.0 = Release|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release|x86.ActiveCfg = Release|Any CPU {805F80DF-75C6-4C2F-8FD9-B47F6D0DF5A3}.Release|x86.Build.0 = Release|Any CPU + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug (Anniversary Update)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug (Anniversary Update)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|ARM.Build.0 = Debug (Anniversary Update)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|ARM.Deploy.0 = Debug (Anniversary Update)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|x64.ActiveCfg = Debug (Anniversary Update)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|x64.Build.0 = Debug (Anniversary Update)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|x64.Deploy.0 = Debug (Anniversary Update)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|x86.ActiveCfg = Debug (Anniversary Update)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|x86.Build.0 = Debug (Anniversary Update)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Anniversary Update)|x86.Deploy.0 = Debug (Anniversary Update)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug (Version 1511)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|ARM.ActiveCfg = Debug (Version 1511)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|ARM.Build.0 = Debug (Version 1511)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|ARM.Deploy.0 = Debug (Version 1511)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|x64.ActiveCfg = Debug (Version 1511)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|x64.Build.0 = Debug (Version 1511)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|x64.Deploy.0 = Debug (Version 1511)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|x86.ActiveCfg = Debug (Version 1511)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|x86.Build.0 = Debug (Version 1511)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug (Version 1511)|x86.Deploy.0 = Debug (Version 1511)|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug|Any CPU.ActiveCfg = Debug|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug|Any CPU.Build.0 = Debug|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug|ARM.ActiveCfg = Debug|ARM @@ -140,6 +286,30 @@ Global {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug|x86.ActiveCfg = Debug|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug|x86.Build.0 = Debug|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Debug|x86.Deploy.0 = Debug|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Native|Any CPU.ActiveCfg = Release|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Native|ARM.ActiveCfg = Release|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Native|x64.ActiveCfg = Release|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Native|x86.ActiveCfg = Release|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release (Anniversary Update)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|ARM.ActiveCfg = Release (Anniversary Update)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|ARM.Build.0 = Release (Anniversary Update)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|ARM.Deploy.0 = Release (Anniversary Update)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|x64.ActiveCfg = Release (Anniversary Update)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|x64.Build.0 = Release (Anniversary Update)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|x64.Deploy.0 = Release (Anniversary Update)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|x86.ActiveCfg = Release (Anniversary Update)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|x86.Build.0 = Release (Anniversary Update)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Anniversary Update)|x86.Deploy.0 = Release (Anniversary Update)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|Any CPU.ActiveCfg = Release (Version 1511)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|ARM.ActiveCfg = Release (Version 1511)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|ARM.Build.0 = Release (Version 1511)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|ARM.Deploy.0 = Release (Version 1511)|ARM + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|x64.ActiveCfg = Release (Version 1511)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|x64.Build.0 = Release (Version 1511)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|x64.Deploy.0 = Release (Version 1511)|x64 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|x86.ActiveCfg = Release (Version 1511)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|x86.Build.0 = Release (Version 1511)|x86 + {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release (Version 1511)|x86.Deploy.0 = Release (Version 1511)|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release|Any CPU.ActiveCfg = Release|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release|ARM.ActiveCfg = Release|ARM {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release|ARM.Build.0 = Release|ARM @@ -150,6 +320,22 @@ Global {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release|x86.ActiveCfg = Release|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release|x86.Build.0 = Release|x86 {A139968E-AD78-4E8C-93B8-9A5523BCAC89}.Release|x86.Deploy.0 = Release|x86 + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -158,6 +344,26 @@ Global {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug|x64.Build.0 = Debug|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug|x86.ActiveCfg = Debug|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Debug|x86.Build.0 = Debug|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Native|Any CPU.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Native|ARM.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Native|x64.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Native|x86.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release|Any CPU.Build.0 = Release|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release|ARM.ActiveCfg = Release|Any CPU @@ -166,6 +372,22 @@ Global {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release|x64.Build.0 = Release|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release|x86.ActiveCfg = Release|Any CPU {3DD8AA7C-3569-4E51-992F-0C2257E8878E}.Release|x86.Build.0 = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug|Any CPU.Build.0 = Debug|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -174,6 +396,26 @@ Global {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug|x64.Build.0 = Debug|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug|x86.ActiveCfg = Debug|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Debug|x86.Build.0 = Debug|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Native|Any CPU.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Native|ARM.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Native|x64.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Native|x86.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|Any CPU.ActiveCfg = Release|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|Any CPU.Build.0 = Release|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|ARM.ActiveCfg = Release|Any CPU @@ -182,6 +424,22 @@ Global {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|x64.Build.0 = Release|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|x86.ActiveCfg = Release|Any CPU {B24A296C-B3EB-4E06-A64E-74AC2D1ACC91}.Release|x86.Build.0 = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|Any CPU.Build.0 = Debug|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -190,6 +448,26 @@ Global {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|x64.Build.0 = Debug|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|x86.ActiveCfg = Debug|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Debug|x86.Build.0 = Debug|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|Any CPU.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|ARM.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|x64.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Native|x86.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|Any CPU.ActiveCfg = Release|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|Any CPU.Build.0 = Release|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|ARM.ActiveCfg = Release|Any CPU @@ -198,6 +476,22 @@ Global {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|x64.Build.0 = Release|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|x86.ActiveCfg = Release|Any CPU {7189A42D-6F1A-4FA3-8E00-E2C14FDF167A}.Release|x86.Build.0 = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|Any CPU.Build.0 = Debug|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -206,6 +500,26 @@ Global {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|x64.Build.0 = Debug|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|x86.ActiveCfg = Debug|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Debug|x86.Build.0 = Debug|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Native|Any CPU.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Native|ARM.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Native|x64.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Native|x86.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release|Any CPU.ActiveCfg = Release|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release|Any CPU.Build.0 = Release|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release|ARM.ActiveCfg = Release|Any CPU @@ -214,6 +528,22 @@ Global {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release|x64.Build.0 = Release|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release|x86.ActiveCfg = Release|Any CPU {E9FAABFB-D726-42C1-83C1-CB46A29FEA81}.Release|x86.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug|Any CPU.Build.0 = Debug|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -222,6 +552,30 @@ Global {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug|x64.Build.0 = Debug|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug|x86.ActiveCfg = Debug|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Debug|x86.Build.0 = Debug|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Native|Any CPU.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Native|Any CPU.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Native|ARM.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Native|ARM.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Native|x64.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Native|x64.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Native|x86.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Native|x86.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release|Any CPU.ActiveCfg = Release|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release|Any CPU.Build.0 = Release|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release|ARM.ActiveCfg = Release|Any CPU @@ -230,6 +584,30 @@ Global {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release|x64.Build.0 = Release|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release|x86.ActiveCfg = Release|Any CPU {DAEB9CEC-C817-33B2-74B2-BC379380DB72}.Release|x86.Build.0 = Release|Any CPU + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|Any CPU.Deploy.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|ARM.Build.0 = Debug|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|ARM.Deploy.0 = Debug|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|x64.Build.0 = Debug|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|x64.Deploy.0 = Debug|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|x86.Build.0 = Debug|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Anniversary Update)|x86.Deploy.0 = Debug|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|Any CPU.Build.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|Any CPU.Deploy.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|ARM.ActiveCfg = Debug|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|ARM.Build.0 = Debug|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|ARM.Deploy.0 = Debug|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|x64.ActiveCfg = Debug|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|x64.Build.0 = Debug|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|x64.Deploy.0 = Debug|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|x86.ActiveCfg = Debug|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|x86.Build.0 = Debug|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug (Version 1511)|x86.Deploy.0 = Debug|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug|Any CPU.ActiveCfg = Debug|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug|Any CPU.Build.0 = Debug|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug|ARM.ActiveCfg = Debug|ARM @@ -241,6 +619,34 @@ Global {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug|x86.ActiveCfg = Debug|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug|x86.Build.0 = Debug|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Debug|x86.Deploy.0 = Debug|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Native|Any CPU.ActiveCfg = Release|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Native|ARM.ActiveCfg = Release|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Native|x64.ActiveCfg = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Native|x86.ActiveCfg = Release|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|Any CPU.Deploy.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|ARM.ActiveCfg = Release|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|ARM.Build.0 = Release|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|ARM.Deploy.0 = Release|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|x64.ActiveCfg = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|x64.Build.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|x64.Deploy.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|x86.ActiveCfg = Release|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|x86.Build.0 = Release|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Anniversary Update)|x86.Deploy.0 = Release|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|Any CPU.Build.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|Any CPU.Deploy.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|ARM.ActiveCfg = Release|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|ARM.Build.0 = Release|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|ARM.Deploy.0 = Release|ARM + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|x64.ActiveCfg = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|x64.Build.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|x64.Deploy.0 = Release|x64 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|x86.ActiveCfg = Release|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|x86.Build.0 = Release|x86 + {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release (Version 1511)|x86.Deploy.0 = Release|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release|Any CPU.ActiveCfg = Release|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release|ARM.ActiveCfg = Release|ARM {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release|ARM.Build.0 = Release|ARM @@ -251,6 +657,22 @@ Global {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release|x86.ActiveCfg = Release|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release|x86.Build.0 = Release|x86 {BAB1CAF4-C400-4A7F-A987-C576DE63CFFD}.Release|x86.Deploy.0 = Release|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Anniversary Update)|ARM.Build.0 = Debug|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Anniversary Update)|x64.Build.0 = Debug|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Anniversary Update)|x86.Build.0 = Debug|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Version 1511)|ARM.ActiveCfg = Debug|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Version 1511)|ARM.Build.0 = Debug|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Version 1511)|x64.ActiveCfg = Debug|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Version 1511)|x64.Build.0 = Debug|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Version 1511)|x86.ActiveCfg = Debug|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug (Version 1511)|x86.Build.0 = Debug|x86 {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug|Any CPU.Build.0 = Debug|Any CPU {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug|ARM.ActiveCfg = Debug|ARM @@ -259,14 +681,49 @@ Global {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug|x64.Build.0 = Debug|x64 {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug|x86.ActiveCfg = Debug|x86 {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Debug|x86.Build.0 = Debug|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Native|Any CPU.ActiveCfg = Release|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Native|ARM.ActiveCfg = Release|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Native|x64.ActiveCfg = Release|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Native|x86.ActiveCfg = Release|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Anniversary Update)|ARM.ActiveCfg = Release|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Anniversary Update)|ARM.Build.0 = Release|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Anniversary Update)|x64.ActiveCfg = Release|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Anniversary Update)|x64.Build.0 = Release|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Anniversary Update)|x86.ActiveCfg = Release|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Anniversary Update)|x86.Build.0 = Release|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Version 1511)|ARM.ActiveCfg = Release|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Version 1511)|ARM.Build.0 = Release|ARM + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Version 1511)|x64.ActiveCfg = Release|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Version 1511)|x64.Build.0 = Release|x64 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Version 1511)|x86.ActiveCfg = Release|x86 + {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release (Version 1511)|x86.Build.0 = Release|x86 {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release|Any CPU.Build.0 = Release|Any CPU {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release|ARM.ActiveCfg = Release|ARM {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release|ARM.Build.0 = Release|ARM {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release|x64.ActiveCfg = Release|x64 {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release|x64.Build.0 = Release|x64 {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release|x86.ActiveCfg = Release|x86 {1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C}.Release|x86.Build.0 = Release|x86 + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -275,6 +732,26 @@ Global {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug|x64.Build.0 = Debug|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug|x86.ActiveCfg = Debug|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Debug|x86.Build.0 = Debug|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Native|Any CPU.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Native|ARM.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Native|x64.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Native|x86.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release|Any CPU.ActiveCfg = Release|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release|Any CPU.Build.0 = Release|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release|ARM.ActiveCfg = Release|Any CPU @@ -283,6 +760,22 @@ Global {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release|x64.Build.0 = Release|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release|x86.ActiveCfg = Release|Any CPU {E7697922-9555-4CFB-AEE0-C5F4D657E559}.Release|x86.Build.0 = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug|Any CPU.Build.0 = Debug|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -291,6 +784,26 @@ Global {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug|x64.Build.0 = Debug|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug|x86.ActiveCfg = Debug|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Debug|x86.Build.0 = Debug|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Native|Any CPU.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Native|ARM.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Native|x64.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Native|x86.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release|Any CPU.ActiveCfg = Release|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release|Any CPU.Build.0 = Release|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release|ARM.ActiveCfg = Release|Any CPU @@ -299,6 +812,22 @@ Global {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release|x64.Build.0 = Release|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release|x86.ActiveCfg = Release|Any CPU {B1E850FF-DDE6-44D5-A830-34250E97A687}.Release|x86.Build.0 = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug|Any CPU.Build.0 = Debug|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -307,6 +836,26 @@ Global {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug|x64.Build.0 = Debug|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug|x86.ActiveCfg = Debug|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Debug|x86.Build.0 = Debug|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Native|Any CPU.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Native|ARM.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Native|x64.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Native|x86.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {34398053-FC70-4243-84F9-F355DEFFF66D}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Release|Any CPU.ActiveCfg = Release|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Release|Any CPU.Build.0 = Release|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Release|ARM.ActiveCfg = Release|Any CPU @@ -315,6 +864,22 @@ Global {34398053-FC70-4243-84F9-F355DEFFF66D}.Release|x64.Build.0 = Release|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Release|x86.ActiveCfg = Release|Any CPU {34398053-FC70-4243-84F9-F355DEFFF66D}.Release|x86.Build.0 = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug|Any CPU.Build.0 = Debug|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -323,6 +888,26 @@ Global {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug|x64.Build.0 = Debug|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug|x86.ActiveCfg = Debug|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Debug|x86.Build.0 = Debug|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Native|Any CPU.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Native|ARM.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Native|x64.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Native|x86.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release|Any CPU.ActiveCfg = Release|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release|Any CPU.Build.0 = Release|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release|ARM.ActiveCfg = Release|Any CPU @@ -331,6 +916,22 @@ Global {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release|x64.Build.0 = Release|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release|x86.ActiveCfg = Release|Any CPU {6FE128A8-CEFA-4A61-A987-EC92DE6B538E}.Release|x86.Build.0 = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug|Any CPU.Build.0 = Debug|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -339,6 +940,26 @@ Global {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug|x64.Build.0 = Debug|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug|x86.ActiveCfg = Debug|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Debug|x86.Build.0 = Debug|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Native|Any CPU.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Native|ARM.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Native|x64.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Native|x86.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release|Any CPU.ActiveCfg = Release|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release|Any CPU.Build.0 = Release|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release|ARM.ActiveCfg = Release|Any CPU @@ -347,6 +968,22 @@ Global {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release|x64.Build.0 = Release|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release|x86.ActiveCfg = Release|Any CPU {97EE849B-403C-490E-80ED-D19D7CC153FD}.Release|x86.Build.0 = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Debug|Any CPU.Build.0 = Debug|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -355,15 +992,59 @@ Global {94994424-5F60-4CD8-ABA2-101779066208}.Debug|x64.Build.0 = Debug|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Debug|x86.ActiveCfg = Debug|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Debug|x86.Build.0 = Debug|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Native|Any CPU.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Native|ARM.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Native|x64.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Native|x86.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {94994424-5F60-4CD8-ABA2-101779066208}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Release|Any CPU.ActiveCfg = Release|Any CPU - {94994424-5F60-4CD8-ABA2-101779066208}.Release|Any CPU.Build.0 = Release|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Release|ARM.ActiveCfg = Release|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Release|ARM.Build.0 = Release|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Release|x64.ActiveCfg = Release|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Release|x64.Build.0 = Release|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Release|x86.ActiveCfg = Release|Any CPU {94994424-5F60-4CD8-ABA2-101779066208}.Release|x86.Build.0 = Release|Any CPU + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|Any CPU.Deploy.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|ARM.Build.0 = Debug|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|ARM.Deploy.0 = Debug|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|x64.Build.0 = Debug|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|x64.Deploy.0 = Debug|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|x86.Build.0 = Debug|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Anniversary Update)|x86.Deploy.0 = Debug|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|Any CPU.Build.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|Any CPU.Deploy.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|ARM.ActiveCfg = Debug|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|ARM.Build.0 = Debug|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|ARM.Deploy.0 = Debug|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|x64.ActiveCfg = Debug|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|x64.Build.0 = Debug|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|x64.Deploy.0 = Debug|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|x86.ActiveCfg = Debug|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|x86.Build.0 = Debug|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug (Version 1511)|x86.Deploy.0 = Debug|x86 {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|Any CPU.ActiveCfg = Debug|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|Any CPU.Build.0 = Debug|x86 {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM.ActiveCfg = Debug|ARM {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM.Build.0 = Debug|ARM {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM.Deploy.0 = Debug|ARM @@ -373,6 +1054,34 @@ Global {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x86.ActiveCfg = Debug|x86 {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x86.Build.0 = Debug|x86 {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x86.Deploy.0 = Debug|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Native|Any CPU.ActiveCfg = Release|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Native|ARM.ActiveCfg = Release|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Native|x64.ActiveCfg = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Native|x86.ActiveCfg = Release|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|Any CPU.Deploy.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|ARM.ActiveCfg = Release|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|ARM.Build.0 = Release|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|ARM.Deploy.0 = Release|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|x64.ActiveCfg = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|x64.Build.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|x64.Deploy.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|x86.ActiveCfg = Release|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|x86.Build.0 = Release|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Anniversary Update)|x86.Deploy.0 = Release|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|Any CPU.Build.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|Any CPU.Deploy.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|ARM.ActiveCfg = Release|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|ARM.Build.0 = Release|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|ARM.Deploy.0 = Release|ARM + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|x64.ActiveCfg = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|x64.Build.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|x64.Deploy.0 = Release|x64 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|x86.ActiveCfg = Release|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|x86.Build.0 = Release|x86 + {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release (Version 1511)|x86.Deploy.0 = Release|x86 {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|Any CPU.ActiveCfg = Release|x86 {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|ARM.ActiveCfg = Release|ARM {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|ARM.Build.0 = Release|ARM @@ -383,6 +1092,22 @@ Global {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x86.ActiveCfg = Release|x86 {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x86.Build.0 = Release|x86 {EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x86.Deploy.0 = Release|x86 + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug|Any CPU.Build.0 = Debug|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -391,6 +1116,26 @@ Global {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug|x64.Build.0 = Debug|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug|x86.ActiveCfg = Debug|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Debug|x86.Build.0 = Debug|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Native|Any CPU.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Native|ARM.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Native|x64.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Native|x86.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release|Any CPU.ActiveCfg = Release|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release|Any CPU.Build.0 = Release|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release|ARM.ActiveCfg = Release|Any CPU @@ -399,6 +1144,22 @@ Global {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release|x64.Build.0 = Release|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release|x86.ActiveCfg = Release|Any CPU {94F8D702-3A9D-4CFB-85C9-79FC5DBD8B22}.Release|x86.Build.0 = Release|Any CPU + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Anniversary Update)|Any CPU.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Anniversary Update)|ARM.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Anniversary Update)|ARM.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Anniversary Update)|x64.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Anniversary Update)|x64.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Anniversary Update)|x86.Build.0 = Debug|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Version 1511)|Any CPU.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Version 1511)|Any CPU.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Version 1511)|ARM.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Version 1511)|ARM.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Version 1511)|x64.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Version 1511)|x64.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Version 1511)|x86.ActiveCfg = Debug|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug (Version 1511)|x86.Build.0 = Debug|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|Any CPU.ActiveCfg = Debug|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|Any CPU.Build.0 = Debug|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|ARM.ActiveCfg = Debug|x86 @@ -407,6 +1168,26 @@ Global {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|x64.Build.0 = Debug|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|x86.ActiveCfg = Debug|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|x86.Build.0 = Debug|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Native|Any CPU.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Native|ARM.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Native|x64.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Native|x86.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Anniversary Update)|Any CPU.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Anniversary Update)|ARM.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Anniversary Update)|ARM.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Anniversary Update)|x64.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Anniversary Update)|x64.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Anniversary Update)|x86.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Anniversary Update)|x86.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Version 1511)|Any CPU.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Version 1511)|Any CPU.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Version 1511)|ARM.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Version 1511)|ARM.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Version 1511)|x64.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Version 1511)|x64.Build.0 = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Version 1511)|x86.ActiveCfg = Release|x86 + {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release (Version 1511)|x86.Build.0 = Release|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release|Any CPU.ActiveCfg = Release|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release|Any CPU.Build.0 = Release|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release|ARM.ActiveCfg = Release|x86 @@ -415,6 +1196,22 @@ Global {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release|x64.Build.0 = Release|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release|x86.ActiveCfg = Release|x86 {7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Release|x86.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Anniversary Update)|Any CPU.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Anniversary Update)|ARM.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Anniversary Update)|ARM.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Anniversary Update)|x64.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Anniversary Update)|x64.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Anniversary Update)|x86.Build.0 = Debug|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Version 1511)|Any CPU.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Version 1511)|Any CPU.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Version 1511)|ARM.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Version 1511)|ARM.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Version 1511)|x64.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Version 1511)|x64.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Version 1511)|x86.ActiveCfg = Debug|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug (Version 1511)|x86.Build.0 = Debug|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug|Any CPU.ActiveCfg = Debug|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug|Any CPU.Build.0 = Debug|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug|ARM.ActiveCfg = Debug|x86 @@ -423,6 +1220,30 @@ Global {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug|x64.Build.0 = Debug|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug|x86.ActiveCfg = Debug|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Debug|x86.Build.0 = Debug|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Native|Any CPU.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Native|Any CPU.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Native|ARM.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Native|ARM.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Native|x64.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Native|x64.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Native|x86.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Native|x86.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Anniversary Update)|Any CPU.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Anniversary Update)|ARM.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Anniversary Update)|ARM.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Anniversary Update)|x64.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Anniversary Update)|x64.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Anniversary Update)|x86.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Anniversary Update)|x86.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Version 1511)|Any CPU.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Version 1511)|Any CPU.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Version 1511)|ARM.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Version 1511)|ARM.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Version 1511)|x64.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Version 1511)|x64.Build.0 = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Version 1511)|x86.ActiveCfg = Release|x86 + {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release (Version 1511)|x86.Build.0 = Release|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release|Any CPU.ActiveCfg = Release|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release|Any CPU.Build.0 = Release|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release|ARM.ActiveCfg = Release|x86 @@ -431,6 +1252,22 @@ Global {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release|x64.Build.0 = Release|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release|x86.ActiveCfg = Release|x86 {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1}.Release|x86.Build.0 = Release|x86 + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug|Any CPU.Build.0 = Debug|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -439,6 +1276,26 @@ Global {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug|x64.Build.0 = Debug|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug|x86.ActiveCfg = Debug|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Debug|x86.Build.0 = Debug|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Native|Any CPU.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Native|ARM.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Native|x64.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Native|x86.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release (Version 1511)|x86.Build.0 = Release|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|Any CPU.ActiveCfg = Release|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|Any CPU.Build.0 = Release|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|ARM.ActiveCfg = Release|Any CPU @@ -447,6 +1304,288 @@ Global {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|x64.Build.0 = Release|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|x86.ActiveCfg = Release|Any CPU {42CA4935-54BE-42EA-AC19-992378C08DE6}.Release|x86.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|ARM.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|ARM.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|x64.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|x64.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|x86.ActiveCfg = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Debug|x86.Build.0 = Debug|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|Any CPU.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|ARM.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|x64.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Native|x86.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release (Version 1511)|x86.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|ARM.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|ARM.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|x64.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|x64.Build.0 = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|x86.ActiveCfg = Release|Any CPU + {292D34E8-0F01-4FA8-951D-8232F75A88D5}.Release|x86.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|ARM.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|ARM.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|x64.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|x64.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|x86.ActiveCfg = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Debug|x86.Build.0 = Debug|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|Any CPU.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|ARM.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|x64.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Native|x86.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release (Version 1511)|x86.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|Any CPU.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|ARM.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|ARM.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|x64.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|x64.Build.0 = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|x86.ActiveCfg = Release|Any CPU + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF}.Release|x86.Build.0 = Release|Any CPU + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Anniversary Update)|ARM.Build.0 = Debug|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Anniversary Update)|x64.Build.0 = Debug|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Anniversary Update)|x86.Build.0 = Debug|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Version 1511)|Any CPU.Build.0 = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Version 1511)|ARM.ActiveCfg = Debug|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Version 1511)|ARM.Build.0 = Debug|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Version 1511)|x64.ActiveCfg = Debug|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Version 1511)|x64.Build.0 = Debug|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Version 1511)|x86.ActiveCfg = Debug|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug (Version 1511)|x86.Build.0 = Debug|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|Any CPU.Build.0 = Debug|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|ARM.ActiveCfg = Debug|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|ARM.Build.0 = Debug|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|x64.ActiveCfg = Debug|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|x64.Build.0 = Debug|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|x86.ActiveCfg = Debug|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Debug|x86.Build.0 = Debug|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Native|Any CPU.ActiveCfg = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Native|Any CPU.Build.0 = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Native|ARM.ActiveCfg = Release|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Native|ARM.Build.0 = Release|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Native|x64.ActiveCfg = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Native|x64.Build.0 = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Native|x86.ActiveCfg = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Native|x86.Build.0 = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Anniversary Update)|ARM.ActiveCfg = Release|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Anniversary Update)|ARM.Build.0 = Release|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Anniversary Update)|x64.ActiveCfg = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Anniversary Update)|x64.Build.0 = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Anniversary Update)|x86.ActiveCfg = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Anniversary Update)|x86.Build.0 = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Version 1511)|Any CPU.Build.0 = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Version 1511)|ARM.ActiveCfg = Release|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Version 1511)|ARM.Build.0 = Release|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Version 1511)|x64.ActiveCfg = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Version 1511)|x64.Build.0 = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Version 1511)|x86.ActiveCfg = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release (Version 1511)|x86.Build.0 = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release|Any CPU.ActiveCfg = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release|ARM.ActiveCfg = Release|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release|ARM.Build.0 = Release|ARM + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release|x64.ActiveCfg = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release|x64.Build.0 = Release|x64 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release|x86.ActiveCfg = Release|Win32 + {A5E98964-45B1-442D-A07A-298A3221D81E}.Release|x86.Build.0 = Release|Win32 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|Any CPU.Deploy.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|ARM.Build.0 = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|ARM.Deploy.0 = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|x64.Build.0 = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|x64.Deploy.0 = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|x86.Build.0 = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Anniversary Update)|x86.Deploy.0 = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|Any CPU.Build.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|Any CPU.Deploy.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|ARM.ActiveCfg = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|ARM.Build.0 = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|ARM.Deploy.0 = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|x64.ActiveCfg = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|x64.Build.0 = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|x64.Deploy.0 = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|x86.ActiveCfg = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|x86.Build.0 = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug (Version 1511)|x86.Deploy.0 = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|Any CPU.ActiveCfg = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|ARM.ActiveCfg = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|ARM.Build.0 = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|ARM.Deploy.0 = Debug|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|x64.ActiveCfg = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|x64.Build.0 = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|x64.Deploy.0 = Debug|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|x86.ActiveCfg = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|x86.Build.0 = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Debug|x86.Deploy.0 = Debug|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Native|Any CPU.ActiveCfg = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Native|ARM.ActiveCfg = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Native|x64.ActiveCfg = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Native|x86.ActiveCfg = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|Any CPU.Build.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|Any CPU.Deploy.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|ARM.ActiveCfg = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|ARM.Build.0 = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|ARM.Deploy.0 = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|x64.ActiveCfg = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|x64.Build.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|x64.Deploy.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|x86.ActiveCfg = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|x86.Build.0 = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Anniversary Update)|x86.Deploy.0 = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|Any CPU.ActiveCfg = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|Any CPU.Build.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|Any CPU.Deploy.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|ARM.ActiveCfg = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|ARM.Build.0 = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|ARM.Deploy.0 = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|x64.ActiveCfg = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|x64.Build.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|x64.Deploy.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|x86.ActiveCfg = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|x86.Build.0 = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release (Version 1511)|x86.Deploy.0 = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|Any CPU.ActiveCfg = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|ARM.ActiveCfg = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|ARM.Build.0 = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|ARM.Deploy.0 = Release|ARM + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|x64.ActiveCfg = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|x64.Build.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|x64.Deploy.0 = Release|x64 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|x86.ActiveCfg = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|x86.Build.0 = Release|x86 + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6}.Release|x86.Deploy.0 = Release|x86 + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Anniversary Update)|Any CPU.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Anniversary Update)|Any CPU.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Anniversary Update)|ARM.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Anniversary Update)|ARM.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Anniversary Update)|x64.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Anniversary Update)|x64.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Anniversary Update)|x86.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Anniversary Update)|x86.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Version 1511)|Any CPU.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Version 1511)|Any CPU.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Version 1511)|ARM.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Version 1511)|ARM.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Version 1511)|x64.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Version 1511)|x64.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Version 1511)|x86.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug (Version 1511)|x86.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug|ARM.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug|ARM.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug|x64.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug|x64.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug|x86.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Debug|x86.Build.0 = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Native|Any CPU.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Native|ARM.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Native|x64.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Native|x86.ActiveCfg = Debug|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Anniversary Update)|Any CPU.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Anniversary Update)|Any CPU.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Anniversary Update)|ARM.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Anniversary Update)|ARM.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Anniversary Update)|x64.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Anniversary Update)|x64.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Anniversary Update)|x86.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Anniversary Update)|x86.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Version 1511)|Any CPU.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Version 1511)|Any CPU.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Version 1511)|ARM.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Version 1511)|ARM.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Version 1511)|x64.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Version 1511)|x64.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Version 1511)|x86.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release (Version 1511)|x86.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|Any CPU.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|ARM.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|ARM.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|x64.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|x64.Build.0 = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|x86.ActiveCfg = Release|Any CPU + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -466,6 +1605,10 @@ Global {EFA96B3C-857E-4659-B942-6BEF7719F4CA} = {9333C63A-F64F-4797-82B3-017422668A5D} {7AEFC959-ED7C-4D96-9E92-72609B40FBE0} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC} {6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC} + {292D34E8-0F01-4FA8-951D-8232F75A88D5} = {096ECFD7-7035-4487-9C87-81DCE9389620} + {262BB7CE-EF42-4BF7-B90C-107E6CBB57FF} = {096ECFD7-7035-4487-9C87-81DCE9389620} + {A122EA02-4DE7-413D-BFBF-AF7DFC668DD6} = {B30036C4-D514-4E5B-A323-587A061772CE} + {D4D78CBA-B238-4794-89A0-4F1A2D8FEA97} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5403B0C4-F244-4F73-A35C-FE664D0F4345} diff --git a/build/Build.bat b/build/Build.bat index f54199464..4b8cd487a 100644 --- a/build/Build.bat +++ b/build/Build.bat @@ -1,3 +1,3 @@ @ECHO OFF -PowerShell.exe -file build.ps1 +PowerShell.exe -file "%~dp0build.ps1" PAUSE \ No newline at end of file diff --git a/build/Install-WindowsSDK.ps1 b/build/Install-WindowsSDK.ps1 new file mode 100644 index 000000000..b664dffab --- /dev/null +++ b/build/Install-WindowsSDK.ps1 @@ -0,0 +1,6 @@ +mkdir c:\winsdktemp + +$client = new-object System.Net.WebClient +$client.DownloadFile("https://go.microsoft.com/fwlink/p/?linkid=870807","c:\winsdktemp\winsdksetup.exe") + +Start-Process -Wait "c:\winsdktemp\winsdksetup.exe" "/features OptionId.UWPCpp /q" \ No newline at end of file diff --git a/build/Microsoft.Toolkit.Uwp.Input.GazeInteraction.nuspec b/build/Microsoft.Toolkit.Uwp.Input.GazeInteraction.nuspec new file mode 100644 index 000000000..c39eec4f0 --- /dev/null +++ b/build/Microsoft.Toolkit.Uwp.Input.GazeInteraction.nuspec @@ -0,0 +1,34 @@ + + + + Microsoft.Toolkit.Uwp.Input.GazeInteraction + $version$ + Windows Community Toolkit Eye Gaze Library + Microsoft.Toolkit + Microsoft.Toolkit, nugetuwptoolkit + https://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/master/build/nuget.png + https://github.com/Microsoft/UWPCommunityToolkit/blob/master/license.md + https://github.com/Microsoft/UWPCommunityToolkit + true + A library to integrate gaze interactions using eye trackers into UWP applications + v3.0 release https://github.com/Microsoft/WindowsCommunityToolkit/releases + (c) .NET Foundation and Contributors. All rights reserved. + UWP Toolkit Windows Eye Gaze EyeTracker + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/StyleXaml.bat b/build/StyleXaml.bat index a16b9ea06..b03dcbd2a 100644 --- a/build/StyleXaml.bat +++ b/build/StyleXaml.bat @@ -1,3 +1,3 @@ @ECHO OFF -PowerShell.exe -file build.ps1 -target=StyleXaml +PowerShell.exe -file "%~dp0build.ps1" -target=StyleXaml PAUSE \ No newline at end of file diff --git a/build/UpdateHeaders.bat b/build/UpdateHeaders.bat index 4510df659..166ea2121 100644 --- a/build/UpdateHeaders.bat +++ b/build/UpdateHeaders.bat @@ -1,3 +1,3 @@ @ECHO OFF -PowerShell.exe -file build.ps1 -target=UpdateHeaders +PowerShell.exe -file "%~dp0build.ps1" -target=UpdateHeaders PAUSE \ No newline at end of file diff --git a/build/build.cake b/build/build.cake index 0db9aa5ab..1a148fcb3 100644 --- a/build/build.cake +++ b/build/build.cake @@ -1,3 +1,5 @@ +#module "Cake.Longpath.Module" + #addin "Cake.FileHelpers" #addin "Cake.Powershell" @@ -17,6 +19,7 @@ var target = Argument("target", "Default"); var gitVersioningVersion = "2.1.23"; var signClientVersion = "0.9.0"; +var inheritDocVersion = "1.1.1.1"; ////////////////////////////////////////////////////////////////////// // VARIABLES @@ -25,6 +28,7 @@ var signClientVersion = "0.9.0"; var baseDir = MakeAbsolute(Directory("../")).ToString(); var buildDir = baseDir + "/build"; var Solution = baseDir + "/Windows Community Toolkit.sln"; +var win32Solution = baseDir + "/Microsoft.Toolkit.Win32/Microsoft.Toolkit.Win32.sln"; var toolsDir = buildDir + "/tools"; var binDir = baseDir + "/bin"; @@ -41,6 +45,9 @@ var stylerFile = baseDir + "/settings.xamlstyler"; var versionClient = toolsDir + "/nerdbank.gitversioning/tools/Get-Version.ps1"; string Version = null; +var inheritDoc = toolsDir + "/InheritDoc/tools/InheritDoc.exe"; +var inheritDocExclude = "Foo.*"; + var name = "Windows Community Toolkit"; var address = "https://developer.microsoft.com/en-us/windows/uwp-community-toolkit"; @@ -56,7 +63,7 @@ void VerifyHeaders(bool Replace) Func exclude_objDir = fileSystemInfo => !fileSystemInfo.Path.Segments.Contains("obj"); - var files = GetFiles(baseDir + "/**/*.cs", exclude_objDir).Where(file => + var files = GetFiles(baseDir + "/**/*.cs", exclude_objDir).Where(file => { var path = file.ToString(); return !(path.EndsWith(".g.cs") || path.EndsWith(".i.cs") || System.IO.Path.GetFileName(path).Contains("TemporaryGeneratedFile")); @@ -132,7 +139,7 @@ Task("Version") Version = gitVersioningVersion, OutputDirectory = toolsDir }; - + NuGetInstall(new []{"nerdbank.gitversioning"}, installSettings); Information("\nRetrieving version..."); @@ -155,6 +162,7 @@ Task("Build") .WithTarget("Restore"); MSBuild(Solution, buildSettings); + MSBuild(win32Solution, buildSettings); EnsureDirectoryExists(nupkgDir); @@ -166,12 +174,47 @@ Task("Build") .SetConfiguration("Release") .WithTarget("Build") .WithProperty("GenerateLibraryLayout", "true"); - + + MSBuild(win32Solution, buildSettings); MSBuild(Solution, buildSettings); - - // Invoke the pack target in the end - buildSettings = new MSBuildSettings +}); + +Task("InheritDoc") + .Description("Updates tags from base classes, interfaces, and similar methods") + .IsDependentOn("Build") + .Does(() => +{ + Information("\nDownloading InheritDoc..."); + var installSettings = new NuGetInstallSettings { + ExcludeVersion = true, + Version = inheritDocVersion, + OutputDirectory = toolsDir + }; + + NuGetInstall(new []{"InheritDoc"}, installSettings); + + var args = new ProcessArgumentBuilder() + .AppendSwitchQuoted("-b", baseDir) + .AppendSwitch("-o", "") + .AppendSwitchQuoted("-x", inheritDocExclude); + + var result = StartProcess(inheritDoc, new ProcessSettings { Arguments = args }); + + if (result != 0) { + throw new InvalidOperationException("InheritDoc failed!"); + } + + Information("\nFinished generating documentation with InheritDoc"); +}); + +Task("Package") + .Description("Pack the NuPkg") + .IsDependentOn("InheritDoc") + .Does(() => +{ + // Invoke the pack target in the end + var buildSettings = new MSBuildSettings { MaxCpuCount = 0 } .SetConfiguration("Release") @@ -180,11 +223,40 @@ Task("Build") .WithProperty("PackageOutputPath", nupkgDir); MSBuild(Solution, buildSettings); + MSBuild(win32Solution, buildSettings); + + // Build and pack C++ packages + buildSettings = new MSBuildSettings + { + MaxCpuCount = 0 + } + .SetConfiguration("Native"); + + buildSettings.SetPlatformTarget(PlatformTarget.ARM); + MSBuild(Solution, buildSettings); + + buildSettings.SetPlatformTarget(PlatformTarget.x64); + MSBuild(Solution, buildSettings); + + buildSettings.SetPlatformTarget(PlatformTarget.x86); + MSBuild(Solution, buildSettings); + + var nuGetPackSettings = new NuGetPackSettings + { + OutputDirectory = nupkgDir, + Version = Version + }; + + var nuspecs = GetFiles("./*.nuspec"); + foreach (var nuspec in nuspecs) + { + NuGetPack(nuspec, nuGetPackSettings); + } }); Task("SignNuGet") .Description("Sign the NuGet packages with the Code Signing service") - .IsDependentOn("Build") + .IsDependentOn("Package") .Does(() => { if(!string.IsNullOrWhiteSpace(signClientSecret)) @@ -197,8 +269,8 @@ Task("SignNuGet") }; NuGetInstall(new []{"SignClient"}, installSettings); - var packages = GetFiles(nupkgDir + "/*.nupkg"); - Information("\n Signing " + packages.Count() + " Packages"); + var packages = GetFiles(nupkgDir + "/*.nupkg"); + Information("\n Signing " + packages.Count() + " Packages"); foreach(var package in packages) { Information("\nSubmitting " + package + " for signing..."); @@ -219,7 +291,7 @@ Task("SignNuGet") { throw new InvalidOperationException("Signing failed!"); } - + Information("\nFinished signing " + package); } } @@ -234,7 +306,7 @@ Task("SignNuGet") ////////////////////////////////////////////////////////////////////// Task("Default") - .IsDependentOn("Build"); + .IsDependentOn("Package"); Task("UpdateHeaders") .Description("Updates the headers in *.cs files") @@ -252,7 +324,7 @@ Task("StyleXaml") ExcludeVersion = true, OutputDirectory = toolsDir }; - + NuGetInstall(new []{"xamlstyler.console"}, installSettings); Func exclude_objDir = @@ -266,6 +338,8 @@ Task("StyleXaml") } }); + + ////////////////////////////////////////////////////////////////////// // EXECUTION ////////////////////////////////////////////////////////////////////// diff --git a/build/build.ps1 b/build/build.ps1 index e5d425615..7a24017f8 100644 --- a/build/build.ps1 +++ b/build/build.ps1 @@ -87,6 +87,9 @@ $CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" $NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" $PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" $PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" +$MODULES_DIR = Join-Path $PSScriptRoot "tools/modules" +$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config" +$MODULES_PACKAGES_CONFIG_MD5 = Join-Path $MODULES_DIR "packages.config.md5sum" # Should we use mono? $UseMono = ""; @@ -181,9 +184,49 @@ if (!(Test-Path $CAKE_EXE)) { Throw "Could not find Cake.exe at $CAKE_EXE" } +# Make sure modules folder exists +if ((Test-Path $PSScriptRoot) -and !(Test-Path $MODULES_DIR)) { + Write-Verbose -Message "Creating tools/modules directory..." + New-Item -Path $MODULES_DIR -Type directory | out-null +} + +# Restore modules from NuGet? +if(-Not $SkipToolPackageRestore.IsPresent) { + Push-Location + Set-Location $MODULES_DIR + + # Check for changes in modules packages.config and remove installed tools if true. + [string] $md5Hash = MD5HashFile($MODULES_PACKAGES_CONFIG) + if((!(Test-Path $MODULES_PACKAGES_CONFIG_MD5)) -Or + ($md5Hash -ne (Get-Content $MODULES_PACKAGES_CONFIG_MD5 ))) { + Write-Verbose -Message "Missing or changed modules package.config hash..." + Remove-Item * -Recurse -Exclude packages.config,packages.config.md5sum,nuget.exe + } + + Write-Verbose -Message "Restoring modules from NuGet..." + $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring NuGet modules." + } + else + { + $md5Hash | Out-File $MODULES_PACKAGES_CONFIG_MD5 -Encoding "ASCII" + } + Write-Verbose -Message ($NuGetOutput | out-string) + Pop-Location +} + # Start Cake -Write-Host "Running build script..." $path = Split-Path -Parent $MyInvocation.MyCommand.Definition $Script = "$path/build.cake" + +Write-Host "Bootstrapping Cake..." +Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" --bootstrap" +if ($LASTEXITCODE -ne 0) { + throw "An error occured while bootstrapping Cake." +} + +Write-Host "Running build script..." Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs" exit $LASTEXITCODE \ No newline at end of file diff --git a/build/header.txt b/build/header.txt index ba7fbaffb..45274bad5 100644 --- a/build/header.txt +++ b/build/header.txt @@ -1,11 +1,3 @@ -// ****************************************************************** -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE. -// ****************************************************************** +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. diff --git a/build/setversion.csproj b/build/setversion.csproj new file mode 100644 index 000000000..9f5c4f4ab --- /dev/null +++ b/build/setversion.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/build/version.json b/build/version.json new file mode 100644 index 000000000..f1b52a7dc --- /dev/null +++ b/build/version.json @@ -0,0 +1,8 @@ +{ + "inherit": true, + "cloudBuild": { + "buildNumber": { + "enabled": true + } + } +} diff --git a/docs/.template.md b/docs/.template.md index ed118ee27..537b047f6 100644 --- a/docs/.template.md +++ b/docs/.template.md @@ -14,7 +14,7 @@ dev_langs: # Title The [Control Name](API-Link) ... - + @@ -65,19 +72,54 @@ be raised and the *RefreshIntentCanceledCommand*, if any, will be executed. ## Sample Code -[PullToRefreshListView Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PullToRefreshListView). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[PullToRefreshListView Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PullToRefreshListView). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). -## Default Template +## Moving to RefreshContainer +The 1803 version of Windows now includes its own implementation of [pull-to-refresh](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/pull-to-refresh) controls, having [RefreshContainer](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.refreshcontainer) as the main control. -[PullToRefreshListView XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/PullToRefreshListView/PullToRefreshListView.xaml) is the XAML template used in the toolkit for the default styling. +The PullToRefreshListView and the RefreshContainer share the same concepts and provide mostly the same functionality, with the caveat that the RefreshContainer works only with a touch interface. + +### What developers need to know to move to RefreshContainer? + +* **XAML:** The RefreshContainer is very simple to use. Unlike the PullToRefreshListView, the RefreshContainer isn't based on the ListView control, so to use it you just need to add the XAML element as a parent of the element you'll use as your item container, like a ListView or a ScrollViewer. + +* **Code behind:** The RefreshContainer invokes the RefreshRequested event whenever a refresh is triggered. Unlike most event handlers, it has the peculiarity of coming with a [Deferral](https://docs.microsoft.com/en-us/uwp/api/windows.foundation.deferral) object, that you can get from the [RefreshRequestedEventArgs](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.refreshrequestedeventargs) by calling [GetDeferral](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.refreshrequestedeventargs.getdeferral#Windows_UI_Xaml_Controls_RefreshRequestedEventArgs_GetDeferral). +To notify that your refresh code has completed, you can mark the deferral as completed by calling its Complete method or wrap your refresh code with a using statement of the deferral. + +> [!NOTE] +Being a touch-only control, it's recommended that you also have a refresh button for users without a touch interface. You can trigger the RefreshRequested event by calling the RefreshContainer's RequestRefresh method. + +### Making the transition even easier +Starting with v3.0 of the Windows Community Toolkit, the PullToRefreshListView provides a new property called **UseRefreshContainerWhenPossible**. Setting the value to true will force the PullToRefreshListView to use a template based on the RefreshContainer when running on the 1803 version of Windows and above, and the regular template otherwise. + +Using this property will enable you to take advantage of the RefreshContainer on devices that support it, while providing an experience based on PullToRefreshListView on devices that have not yet updated to the 1803 version of Windows. Make sure to test the experience on multiple OS releases and plan to fully transition to the RefreshContainer as the PullToRefreshListView will be removed from the Windows Community Toolkit in a future major release. + +> [!NOTE] +When using the RefreshContainer, the RefreshIntentCanceled and the PullProgressChanged events are not invoked. In addition, the RefreshIntentCanceledCommand is not executed. + +There are several PullToRefreshListView properties that have no effect when the PullToRefreshListView is using the RefreshContainer: + +* OverscrollLimit +* PullThreshold +* RefreshIndicatorContent +* PullToRefreshLabel +* ReleaseToRefreshLabel +* PullToRefreshContent +* ReleaseToRefreshContent +* IsPullToRefreshWithMouseEnabled + + +## Default Template + +[PullToRefreshListView XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/PullToRefreshListView/PullToRefreshListView.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [PullToRefreshListView source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/PullToRefreshListView) +* [PullToRefreshListView source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/PullToRefreshListView) diff --git a/docs/controls/RadialGauge.md b/docs/controls/RadialGauge.md index 2eb664fab..dbe321beb 100644 --- a/docs/controls/RadialGauge.md +++ b/docs/controls/RadialGauge.md @@ -63,7 +63,7 @@ The Radial Gauge supports animated transitions between configuration states. The ## Control style and template -You can modify the default [Style](https://docs.microsoft.com/uwp/api/windows.ui.xaml.style) and [ControlTemplate](https://docs.microsoft.com/uwp/api/windows.ui.xaml.controls.controltemplate) to give the control a unique appearance. For information about modifying a control's style and template, see [Styling controls](https://msdn.microsoft.com/windows/uwp/controls-and-patterns/styling-controls). The default style, template, and resources that define the look of the control are included in the RadialGauge.xaml file. For design purposes, RadialGauge.xaml is available on [GitHub](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialGauge/RadialGauge.xaml). Styles and resources from different versions of the SDK might have different values. +You can modify the default [Style](https://docs.microsoft.com/uwp/api/windows.ui.xaml.style) and [ControlTemplate](https://docs.microsoft.com/uwp/api/windows.ui.xaml.controls.controltemplate) to give the control a unique appearance. For information about modifying a control's style and template, see [Styling controls](https://msdn.microsoft.com/windows/uwp/controls-and-patterns/styling-controls). The default style, template, and resources that define the look of the control are included in the RadialGauge.xaml file. For design purposes, RadialGauge.xaml is available on [GitHub](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialGauge/RadialGauge.xaml). Styles and resources from different versions of the SDK might have different values. Starting in Toolkit version 2.2, RadialGauge.xaml includes resources that you can use to modify the colors of a control in different visual states without modifying the control template. In apps that target this software development kit (SDK) or later, modifying these resources is preferred to setting properties such as Background and Foreground. For more info, see the Light-weight styling section of the Styling controls article. @@ -76,20 +76,20 @@ This table shows the resources used by the [RadialGauge](https://docs.microsoft. ## Sample Code -[RadialGauge Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RadialGauge). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[RadialGauge Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RadialGauge). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Default Template -[RadialGauge XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialGauge/RadialGauge.xaml) is the XAML template used in the toolkit for the default styling. +[RadialGauge XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialGauge/RadialGauge.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [RadialGauge source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialGauge) +* [RadialGauge source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialGauge) diff --git a/docs/controls/RadialProgressBar.md b/docs/controls/RadialProgressBar.md index c77f3ce25..2cfde3131 100644 --- a/docs/controls/RadialProgressBar.md +++ b/docs/controls/RadialProgressBar.md @@ -39,20 +39,20 @@ The control uses the same dependency properties as the standard Progress Bar, wi ## Sample Code -[RadialProgressBar Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RadialProgressBar). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[RadialProgressBar Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RadialProgressBar). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Default Template -[RadialProgressBar XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialProgressBar/RadialProgressBar.xaml) is the XAML template used in the toolkit for the default styling. +[RadialProgressBar XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialProgressBar/RadialProgressBar.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [RadialProgressBar source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialProgressBar) +* [RadialProgressBar source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/RadialProgressBar) diff --git a/docs/controls/RangeSelector.md b/docs/controls/RangeSelector.md index e9e4a2348..87057d7f5 100644 --- a/docs/controls/RangeSelector.md +++ b/docs/controls/RangeSelector.md @@ -78,19 +78,19 @@ End Sub ## Sample Code -[RangeSelector Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RangeSelector). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[RangeSelector Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RangeSelector). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Default Template -[RangeSelector XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RangeSelector/RangeSelector.xaml) is the XAML template used in the toolkit for the default styling. +[RangeSelector XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RangeSelector/RangeSelector.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [RangeSelector source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/RangeSelector) +* [RangeSelector source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/RangeSelector) diff --git a/docs/controls/RotatorTile.md b/docs/controls/RotatorTile.md index c6efcfaab..1a6326184 100644 --- a/docs/controls/RotatorTile.md +++ b/docs/controls/RotatorTile.md @@ -40,20 +40,20 @@ The [Rotator Tile Control](https://docs.microsoft.com/dotnet/api/microsoft.toolk ## Sample Code -[RotatorTile Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RotatorTile). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[RotatorTile Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RotatorTile). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Default Template -[RotatorTile XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RotatorTile/RotatorTile.xaml) is the XAML template used in the toolkit for the default styling. +[RotatorTile XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/RotatorTile/RotatorTile.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [RotatorTile source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/RotatorTile) +* [RotatorTile source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/RotatorTile) diff --git a/docs/controls/ScrollHeader.md b/docs/controls/ScrollHeader.md index 358b7ecd3..7212d320a 100644 --- a/docs/controls/ScrollHeader.md +++ b/docs/controls/ScrollHeader.md @@ -37,20 +37,20 @@ The [ScrollHeader Control](https://docs.microsoft.com/dotnet/api/microsoft.toolk ## Sample Code -[ScrollHeader Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[ScrollHeader Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ScrollHeader). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Default Template -[ScrollHeader XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/ScrollHeader/ScrollHeader.xaml) is the XAML template used in the toolkit for the default styling. +[ScrollHeader XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/ScrollHeader/ScrollHeader.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [ScrollHeader source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/ScrollHeader) +* [ScrollHeader source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/ScrollHeader) diff --git a/docs/controls/SlidableListItem.md b/docs/controls/SlidableListItem.md index a678f332b..2de038e19 100644 --- a/docs/controls/SlidableListItem.md +++ b/docs/controls/SlidableListItem.md @@ -114,7 +114,7 @@ Private Sub SlidableListItem_SwipeStatusChanged(ByVal sender As SlidableListItem End Sub ``` -If you use `SlidableListItem` in a `ListView` with the `ItemClick` event, you need to be aware the `ItemClick` event is triggered by default when the control has been swiped. If you don’t want this behavior you can set `IsPointerReleasedOnSwipingHandled` to `true` to suppress the `ItemClick` event. If you need more control you can instead check the `SwipeStatus` property in the `ItemClick` event. The following code shows how to do that: +If you use `SlidableListItem` in a `ListView` with the `ItemClick` event, you need to be aware the `ItemClick` event is triggered by default when the control has been swiped. If you don't want this behavior you can set `IsPointerReleasedOnSwipingHandled` to `true` to suppress the `ItemClick` event. If you need more control you can instead check the `SwipeStatus` property in the `ItemClick` event. The following code shows how to do that: ```csharp private void ListView_ItemClick(object sender, ItemClickEventArgs e) @@ -170,19 +170,19 @@ There are several SlidableListItem properties that have no effect when the Slida ## Sample Code -[SlidableListItem Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/SlidableListItem). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[SlidableListItem Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/SlidableListItem). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Default Template -[SlidableListItem XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/SlidableListItem/SlidableListItem.xaml) is the XAML template used in the toolkit for the default styling. +[SlidableListItem XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/SlidableListItem/SlidableListItem.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [SlidableListItem source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/SlidableListItem) +* [SlidableListItem source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/SlidableListItem) diff --git a/docs/controls/StaggeredPanel.md b/docs/controls/StaggeredPanel.md index fca09d422..09eaebedb 100644 --- a/docs/controls/StaggeredPanel.md +++ b/docs/controls/StaggeredPanel.md @@ -40,19 +40,19 @@ The [StaggeredPanel](https://docs.microsoft.com/en-us/dotnet/api/microsoft.toolk ## Sample Code -[StaggeredPanel Sample Page](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/StaggeredPanel). You can see this in action in the Windows Community Toolkit Sample App. +[StaggeredPanel Sample Page](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/StaggeredPanel). You can see this in action in the Windows Community Toolkit Sample App. ## Default Template -[StaggeredPanel XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/StaggeredPanel/StaggeredPanel.xaml) is the XAML template used in the toolkit for the default styling. +[StaggeredPanel XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/StaggeredPanel/StaggeredPanel.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| [Device family](http://go.microsoft.com/fwlink/p/?LinkID=526370#device-families) | Universal, 10.0.14393.0 or higher | +| [Device family](http://go.microsoft.com/fwlink/p/?LinkID=526370#device-families) | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API Source Code -- [StaggeredPanel](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/StaggeredPanel) \ No newline at end of file +- [StaggeredPanel](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/StaggeredPanel) \ No newline at end of file diff --git a/docs/controls/TextToolbar.md b/docs/controls/TextToolbar.md index 4baeec6df..114f9e498 100644 --- a/docs/controls/TextToolbar.md +++ b/docs/controls/TextToolbar.md @@ -46,13 +46,13 @@ When you create the Class, you will need to override the `DefaultButtons` Proper If you want to use a Common Button Template, such as Bold, Italics, etc. You can get those by Instantiating a `CommonButtons` Instance in your Formatter Class, however, you will need to implement the **ButtonActions** Class, and Instantiate it in your Formatter's `ButtonActions` property, or replace the `Action`/`Shift Action` Property on each button you use. _See the MarkDownFormatter Class for reference on how to create a Formatter:_ -[MarkDownFormatter Code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TextToolbar/Formats/MarkDown) +[MarkDownFormatter Code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TextToolbar/Formats/MarkDown) _See the Sample Formatter Class from the Sample App:_ -[SampleFormatter Code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/TextToolbar/SampleFormatter.cs) +[SampleFormatter Code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/TextToolbar/SampleFormatter.cs) _Available CommonButtons:_ -[CommonButton Definitions](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TextToolbar/ToolbarItems/Common) +[CommonButton Definitions](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TextToolbar/ToolbarItems/Common) ## Examples @@ -107,15 +107,15 @@ Toolbar.CustomButtons.Add(New ToolbarSeparator With {.Position = 2}) ## Sample Code -[TextToolbar Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/TextToolbar). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[TextToolbar Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/TextToolbar). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [TextToolbar source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TextToolbar) \ No newline at end of file +* [TextToolbar source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TextToolbar) \ No newline at end of file diff --git a/docs/controls/TileControl.md b/docs/controls/TileControl.md index 292c1301a..085c96e36 100644 --- a/docs/controls/TileControl.md +++ b/docs/controls/TileControl.md @@ -45,19 +45,19 @@ The [Tile Control](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.u ## Sample Code -[TileControl Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/TileControl). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[TileControl Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/TileControl). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Default Template -[TileControl XAML File](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/TileControl/TileControl.xaml) is the XAML template used in the toolkit for the default styling. +[TileControl XAML File](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI.Controls/TileControl/TileControl.xaml) is the XAML template used in the toolkit for the default styling. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | -- | -- | | Namespace | Microsoft.Toolkit.Uwp.UI.Controls | | NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls/) | ## API -* [TileControl source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TileControl) \ No newline at end of file +* [TileControl source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TileControl) \ No newline at end of file diff --git a/docs/controls/UniformGrid.md b/docs/controls/UniformGrid.md new file mode 100644 index 000000000..b1f014eb7 --- /dev/null +++ b/docs/controls/UniformGrid.md @@ -0,0 +1,195 @@ +--- +title: UniformGrid XAML Control +author: michael-hawker +description: The UniformGrid Control presents items in a evenly-spaced set of rows or columns to fill the total available display space. +keywords: windows 10, uwp, uwp community toolkit, uwp toolkit, UniformGrid, xaml control, xaml, grid, layout, responsive +--- + +# UniformGrid XAML Control + +The **UniformGrid Control** is a responsive layout control which arranges items in a evenly-spaced set of rows or columns to fill the total available display space. Each cell in the grid, by default, will be the same size. + +If no value for `Rows` and `Columns` are provided, the UniformGrid will create a square layout based on the total number of visible items. + +If a fixed size is provided for `Rows` and `Columns` then additional children that can't fit in the number of cells provided won't be displayed. + +It differs from the [AdaptiveGridView](https://docs.microsoft.com/en-us/windows/uwpcommunitytoolkit/controls/adaptivegridview) which dictates +its layout based on item sizes to where as the UniformGrid maintains the specified number of Rows and/or Columns. +In addition, UniformGrid is a `Panel` instead of an `ItemsControl`. As such, it could be used as a Panel in such ItemsControls. + +The UWP UniformGrid now inherits from [Grid](https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.Grid) and provides many additional features compared to its predecessor, see more below. + +## WPF Conversion Notes + +When porting your UniformGrid XAML from WPF, just add the `controls:` namespace prefix to your `UniformGrid` and add the `xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"` to your XAML namespace list. + +See further notes below on the additional features the UWP UniformGrid provides compared to the WPF UniformGrid. The behavior of `FirstColumn` has changed slightly, but only in cases where it was previously ignored in WPF. + +## Syntax + +```xaml + + + +``` + +```c# +private void OnInvokeProgress(object sender, GazeProgressEventArgs e) +{ + e.Handled = true; +} +``` + + + + + +## Sample Code + +[GazeInteractionPage](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/GazeInteraction/). You can see all of this in action in the [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). + +## Requirements + +| Device family | Universal,10.0.17134.1 or higher | +| -- | -- | +| Namespace | Microsoft.Toolkit.Uwp.Input.GazeInteraction | +| NuGet package | [NuGet package](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Input.GazeInteraction/) | + +## API Source Code + +* [Gaze Interaction Library source code](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Input.GazeInteraction) + +## Related Topics + +* [Windows 10 Gaze Input APIs](https://docs.microsoft.com/en-us/uwp/api/windows.devices.input.preview) diff --git a/docs/graph/AadLogin.md b/docs/graph/AadLogin.md new file mode 100644 index 000000000..65b146b5f --- /dev/null +++ b/docs/graph/AadLogin.md @@ -0,0 +1,84 @@ +--- +title: AadLogin Control +author: OGcanviz +description: The AadLogin Control leverages existing .NET login libraries to support basic AAD sign-in processes for Microsoft Graph. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, AadLogin Control +--- + +# AadLogin Control + +The [AadLogin Control](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.ui.controls.graph.aadlogin) leverages existing .NET login libraries to support basic AAD sign-in processes for Microsoft Graph, it relies on the [MicrosoftGraphService](../services/MicrosoftGraph.md) for authentication. + +## Syntax + +```xaml + + + +``` + +## Example Image + +![AadLogin animation](../resources/images/Graph/AadLogin.png) + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| RequiredDelegatedPermissions | String[] | Gets required delegated permissions for Graph API access | +| DefaultImage | BitmapImage | The default image displayed when no user is signed in | +| View | [ViewType](https://github.com/Microsoft/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/ProfileCard/ViewType.cs) | The visual layout of the control. Default is `PictureOnly` | +| AllowSignInAsDifferentUser | Boolean | Whether or not the menu item for `Sign in as a different user` is enabled, default value is true | +| SignInDefaultText | String | Default text for sign in button | +| SignOutDefaultText | String | Default text for sign out button | +| SignInAnotherUserDefaultText | String | Default text for `Sign in with another account` button | +| CurrentUserId | String | Gets the unique identifier for current signed in user | + +## Methods + +| Method | Return Type | Description | +| -- | -- | -- | +| SignInAsync | bool | Method to call when to trigger the user signin. UX of the control is updated if successful. Returns false if the user cancels sign in | +| SignOut | void | Method to call to signout the currently signed on user | + +## Events + +| Method | Type | Description | +| -- | -- | -- | +| SignInCompleted | EventHandler<SignInEventArgs> | Occurs when a user signs in | +| SignInFailed | EventHandler<SignInFailedEventArgs> | Occurs when sign in failed when attempting to sign in. Only fires when an exception occurs during the sign in process and not when the user cancels sign in. | +| SignOutCompleted | EventHandler | Occurs when the user clicks on SignOut, or the SignOut() method is called. Developers should clear any cached usage of GraphServiceClient objects they receive this event | + +## Sample Code + +First of all, initialize the [MicrosoftGraphService](../services/MicrosoftGraph.md) with your [Azure AD v2.0 app](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-app-registration), this should be done globally with the combined and unique [delegate permissions](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-scopes) required by all Graph controls and services used in your app. + +```c# +MicrosoftGraphService.Instance.AuthenticationModel = MicrosoftGraphEnums.AuthenticationModel.V2; + +MicrosoftGraphService.Instance.Initialize( + 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + MicrosoftGraphEnums.ServicesToInitialize.UserProfile, + AadLogin.RequiredDelegatedPermissions +); +``` + +[AadLogin Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/AadLogin). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). + +## Default Template + +[AadLogin XAML File](https://github.com/Microsoft/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/AadLogin/AadLogin.xaml) is the XAML template used in the toolkit for the default styling. + +## Requirements + +| Device family | Universal, 10.0.15063.0 or higher | +| -- | -- | +| Namespace | Microsoft.Toolkit.Uwp.UI.Controls.Graph | +| NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls.Graph](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls.Graph/) | + +## API + +* [AadLogin source code](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/AadLogin) diff --git a/docs/graph/PeoplePicker.md b/docs/graph/PeoplePicker.md new file mode 100644 index 000000000..1c7f17651 --- /dev/null +++ b/docs/graph/PeoplePicker.md @@ -0,0 +1,65 @@ +--- +title: PeoplePicker Control +author: OGcanviz +description: The PeoplePicker Control is a simple control that allows for selection of one or more users from an organizational AD. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, PeoplePicker Control +--- + +# PeoplePicker Control + +The [PeoplePicker Control](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.ui.controls.graph.peoplepicker) is a simple control that allows for selection of one or more users from an organizational AD, see more details [here](https://developer.microsoft.com/en-us/graph/docs/concepts/people_example), it relies on the [MicrosoftGraphService](../services/MicrosoftGraph.md) for authentication. + +## Syntax + +```xaml + + + +``` + +## Example Image + +![PeoplePicker animation](../resources/images/Graph/PeoplePicker.png) + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| RequiredDelegatedPermissions | String[] | Gets required delegated permissions for Graph API access | +| AllowMultiple | Boolean | Whether multiple people can be selected | +| SearchResultLimit | Int | Max person returned in the search results | +| PlaceholderText | String | Text to be displayed when no user is selected | +| Selections | ObservableCollection | The selected person list | + +## Sample Code + +First of all, initialize the [MicrosoftGraphService](../services/MicrosoftGraph.md) with your [Azure AD v2.0 app](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-app-registration), this should be done globally with the combined and unique [delegate permissions](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-scopes) required by all Graph controls and services used in your app. + +```c# +MicrosoftGraphService.Instance.AuthenticationModel = MicrosoftGraphEnums.AuthenticationModel.V2; + +MicrosoftGraphService.Instance.Initialize( + 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + MicrosoftGraphEnums.ServicesToInitialize.UserProfile, + PeoplePicker.RequiredDelegatedPermissions +); +``` + +[PeoplePicker Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PeoplePicker). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). + +## Default Template + +[PeoplePicker XAML File](https://github.com/Microsoft/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/PeoplePicker/PeoplePicker.xaml) is the XAML template used in the toolkit for the default styling. + +## Requirements + +| Device family | Universal, 10.0.15063.0 or higher | +| -- | -- | +| Namespace | Microsoft.Toolkit.Uwp.UI.Controls.Graph | +| NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls.Graph](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls.Graph/) | + +## API + +* [PeoplePicker source code](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/PeoplePicker) diff --git a/docs/graph/ProfileCard.md b/docs/graph/ProfileCard.md new file mode 100644 index 000000000..0354d50db --- /dev/null +++ b/docs/graph/ProfileCard.md @@ -0,0 +1,68 @@ +--- +title: ProfileCard Control +author: OGcanviz +description: The ProfileCard Control is a simple way to display a user in multiple different formats and mixes of name/image/e-mail. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, ProfileCard Control +--- + +# ProfileCard Control + +The [ProfileCard Control](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.ui.controls.graph.profilecard) is a simple way to display a user in multiple different formats and mixes of name/image/e-mail, it relies on the [MicrosoftGraphService](../services/MicrosoftGraph.md) for authentication. + +## Syntax + +```xaml + + + +``` + +## Example Image + +![ProfileCard animation](../resources/images/Graph/ProfileCard.png) + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| RequiredDelegatedPermissions | String[] | Gets required delegated permissions for Graph API access | +| UserId | String | Identifier of the user being displayed, this user id can come from the Graph APIs like `/me/people`, `/users`, etc. | +| DisplayMode | [ViewType](https://github.com/Microsoft/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/ProfileCard/ViewType.cs) | The visual layout of the control. Default is `PictureOnly` | +| DefaultImage | BitmapImage | The default image displayed when no user is signed in | +| LargeProfileTitleDefaultText | String | Default title text in LargeProfilePhotoLeft mode or LargeProfilePhotoRight mode when no user is signed in | +| LargeProfileMailDefaultText | String | Default secondary mail text in LargeProfilePhotoLeft mode or LargeProfilePhotoRight mode when no user is signed in | +| NormalMailDefaultText | String | Default mail text in EmailOnly mode when no user is signed in | + +## Sample Code + +First of all, initialize the [MicrosoftGraphService](../services/MicrosoftGraph.md) with your [Azure AD v2.0 app](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-app-registration), this should be done globally with the combined and unique [delegate permissions](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-scopes) required by all Graph controls and services used in your app. + +```c# +MicrosoftGraphService.Instance.AuthenticationModel = MicrosoftGraphEnums.AuthenticationModel.V2; + +MicrosoftGraphService.Instance.Initialize( + 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + MicrosoftGraphEnums.ServicesToInitialize.UserProfile, + ProfileCard.RequiredDelegatedPermissions +); +``` + +[ProfileCard Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ProfileCard). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). + +## Default Template + +[ProfileCard XAML File](https://github.com/Microsoft/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/ProfileCard/ProfileCard.xaml) is the XAML template used in the toolkit for the default styling. + +## Requirements + +| Device family | Universal, 10.0.15063.0 or higher | +| -- | -- | +| Namespace | Microsoft.Toolkit.Uwp.UI.Controls.Graph | +| NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls.Graph](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls.Graph/) | + +## API + +* [ProfileCard source code](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/ProfileCard) diff --git a/docs/graph/SharePointFileList.md b/docs/graph/SharePointFileList.md new file mode 100644 index 000000000..4d0c46542 --- /dev/null +++ b/docs/graph/SharePointFileList.md @@ -0,0 +1,83 @@ +--- +title: SharePointFileList Control +author: OGcanviz +description: The SharePointFileList Control displays a simple list of SharePoint Files. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, SharePointFileList Control +--- + +# SharePointFileList Control + +The [SharePointFileList Control](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.ui.controls.graph.sharepointfilelist) displays a simple list of SharePoint Files, it relies on the [MicrosoftGraphService](../services/MicrosoftGraph.md) for authentication. + +## Syntax + +```xaml + + + +``` + +## Example Image + +![SharePointFileList animation](../resources/images/Graph/SharePointFileList.png) + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| RequiredDelegatedPermissions | String[] | Gets required delegated permissions for Graph API access | +| DriveUrl | String | Full URL of the Drive being displayed | +| DetailPane | [DetailPaneDisplayMode](https://github.com/Microsoft/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/SharePointFileList/DetailPaneDisplayMode.cs) | Determines whether file details are displayed, when a file is selected | +| PageSize | Int | Page size of each request | +| ShareLinkCopiedMessage | String | The message when share link copied | +| AllFilesMessage | String | The label of All Files | +| DeleteConfirmMessage | String | The message of delete confirm dialog | +| DeleteConfirmOkMessage | String | The caption of ok button in delete confirm dialog | +| DeleteConfirmCancelMessage | String | The caption of cancel button in delete confirm dialog | +| UploadingFilesMessageTemplate | String | The template of uploading files | + +## Methods + +| Method | Return Type | Description | +| -- | -- | -- | +| GetDriveUrlFromSharePointUrlAsync | String | Retrieves an appropriate Drive URL from a SharePoint document library root URL | + +## Events + +| Event | Return Type | Description | +| -- | -- | -- | +| FileSelected | EventHandler<FileSelectedEventArgs> | Occurs when one of the menu items in the control is clicked | + +## Sample Code + +First of all, initialize the [MicrosoftGraphService](../services/MicrosoftGraph.md) with your [Azure AD v2.0 app](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-app-registration), this should be done globally with the combined and unique [delegate permissions](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-scopes) required by all Graph controls and services used in your app. + +```c# +MicrosoftGraphService.Instance.AuthenticationModel = MicrosoftGraphEnums.AuthenticationModel.V2; + +MicrosoftGraphService.Instance.Initialize( + 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + MicrosoftGraphEnums.ServicesToInitialize.UserProfile, + SharePointFileList.RequiredDelegatedPermissions +); +``` + +[SharePointFileList Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/SharePointFileList). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). + +## Default Template + +[SharePointFileList XAML File](https://github.com/Microsoft/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/SharePointFileList/SharePointFileList.xaml) is the XAML template used in the toolkit for the default styling. + +## Requirements + +| Device family | Universal, 10.0.15063.0 or higher | +| -- | -- | +| Namespace | Microsoft.Toolkit.Uwp.UI.Controls.Graph | +| NuGet package | [Microsoft.Toolkit.Uwp.UI.Controls.Graph](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI.Controls.Graph/) | + +## API + +* [SharePointFileList source code](https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls.Graph/SharePointFileList) diff --git a/docs/helpers/AdvancedCollectionView.md b/docs/helpers/AdvancedCollectionView.md index 435944ca9..dda9f73bb 100644 --- a/docs/helpers/AdvancedCollectionView.md +++ b/docs/helpers/AdvancedCollectionView.md @@ -203,15 +203,15 @@ End Using ' acv.Refresh() gets called here ## Sample Code -[AdvancedCollectionView sample page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/AdvancedCollectionView). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[AdvancedCollectionView sample page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/AdvancedCollectionView). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.UI | | NuGet package | [Microsoft.Toolkit.Uwp.UI](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI/) | ## API -* [AdvancedCollectionView source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI/AdvancedCollectionView) +* [AdvancedCollectionView source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI/AdvancedCollectionView) diff --git a/docs/helpers/BackgroundTaskHelper.md b/docs/helpers/BackgroundTaskHelper.md index b76c8ea39..432edc555 100644 --- a/docs/helpers/BackgroundTaskHelper.md +++ b/docs/helpers/BackgroundTaskHelper.md @@ -1,7 +1,7 @@ --- title: Background Task Helper author: nmetulev -description: The Background Task Helper helps users interacting with background tasks in an easier manner. +description: The Background Task Helper helps users interact with background tasks in an easier manner. keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, Background Task Helper dev_langs: - csharp @@ -10,7 +10,7 @@ dev_langs: # Background Task Helper -The [Background Task Helper](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.helpers.backgroundtaskhelper) helps users interacting with background tasks in an easier manner. +The [Background Task Helper](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.helpers.backgroundtaskhelper) helps users interact with background tasks in an easier manner. ## Syntax @@ -173,15 +173,15 @@ End Sub ## Sample Code -[Background Task Helper](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BackgroundTaskHelper). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[Background Task Helper](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/BackgroundTaskHelper). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [Background Task source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/BackgroundTaskHelper.cs) +* [Background Task source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/BackgroundTaskHelper.cs) diff --git a/docs/helpers/BindableValueHolder.md b/docs/helpers/BindableValueHolder.md index 007a52530..b5fa4b79e 100644 --- a/docs/helpers/BindableValueHolder.md +++ b/docs/helpers/BindableValueHolder.md @@ -53,11 +53,11 @@ and switching it like that: ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.UI | | NuGet package | [Microsoft.Toolkit.Uwp.UI](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI/) | ## API -* [BindableValueHolder source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI/Helpers/BindableValueHolder.cs) \ No newline at end of file +* [BindableValueHolder source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI/Helpers/BindableValueHolder.cs) \ No newline at end of file diff --git a/docs/helpers/BluetoothLEHelper.md b/docs/helpers/BluetoothLEHelper.md index 488c825ec..27025cc1d 100644 --- a/docs/helpers/BluetoothLEHelper.md +++ b/docs/helpers/BluetoothLEHelper.md @@ -159,4 +159,4 @@ End If ## API -* [BluetoothLEHelper source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Connectivity/BluetoothLEHelper) +* [BluetoothLEHelper source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.Connectivity/BluetoothLEHelper) diff --git a/docs/helpers/CameraHelper.md b/docs/helpers/CameraHelper.md new file mode 100644 index 000000000..14ad7da56 --- /dev/null +++ b/docs/helpers/CameraHelper.md @@ -0,0 +1,122 @@ +--- +title: CameraHelper +author: skommireddi +description: The CameraHelper provides helper methods to easily use the available camera frame sources to preview video, capture video frames and software bitmaps. +keywords: windows 10, uwp, windows community toolkit, windows toolkit, CameraHelper, Camera, Frame Source, Video Frame, Software Bitmap +--- + +# CameraHelper + +The **CameraHelper** provides helper methods to easily use the available camera frame sources to preview video, capture video frames and software bitmaps. The helper currently shows camera frame sources that support color video preview or video record streams. + +> [!IMPORTANT] +Make sure you have the [webcam capability](https://docs.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations#device-capabilities) enabled for your app to access the device's camera. + +## Syntax + +```csharp +// Creates a Camera Helper and gets video frames from an available frame source. +using Microsoft.Toolkit.Uwp.Helpers.CameraHelper; + +CameraHelper cameraHelper = new CameraHelper(); +var result = await _cameraHelper.InitializeAndStartCaptureAsync(); + +// Camera Initialization and Capture failed for some reason +if(result != CameraHelperResult.Success) +{ + // get error information + var errorMessage = result.ToString(); +} +else +{ + // Subscribe to get frames as they arrive + cameraHelper.FrameArrived += CameraHelper_FrameArrived; +} + +private void CameraHelper_FrameArrived(object sender, FrameEventArgs e) +{ + // Gets the current video frame + VideoFrame currentVideoFrame = e.VideoFrame; + + // Gets the software bitmap image + SoftwareBitmap softwareBitmap = currentVideoFrame.SoftwareBitmap; +} +``` + +## Cleaning up resources + +As a developer, you will need to make sure the CameraHelper resources are cleaned up when appropriate. For example, if the CameraHelper is only used on one page, make sure to clean up the CameraHelper when navigating away from the page. + +Likewise, make sure to handle app [suspending](https://docs.microsoft.com/windows/uwp/launch-resume/suspend-an-app) and [resuming](https://docs.microsoft.com/en-us/windows/uwp/launch-resume/resume-an-app) - CameraHelper should be cleaned up when suspending and re-initialized when resuming. + +Call `CameraHelper.CleanupAsync()` to clean up all internal resources. See the [CameraHelper sample page in the sample app](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper) for full example. + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| FrameSourceGroup | MediaFrameSourceGroup | Gets the currently selected MediaFrameSourceGroup for video preview. User can set this property to preview video from a specific source. If no MediaFrameSourceGroup is provided, Camera Helper selects the first available camera source to use for media capture. | +| FrameSource | MediaFrameSource | Gets the currently selected MediaFrameSource for video preview. | + +## Methods + +| Methods | Return Type | Description | +| -- | -- | -- | +| GetFrameSourceGroupsAsync() | Task> | Gets a read only list of MediaFrameSourceGroups that support color video record or video preview streams. +| InitializeAndStartCaptureAsync() | Task| Initializes Media Capture and Frame Reader for video preview and capture frames in real time. | +| CleanUpAsync() | Task | Use this asynchronous method to dispose Camera Helper resources | +| Dispose() | void | Use this method to dispose Camera Helper resources | + +## Events + +| Events | Description | +| -- | -- | +| FrameArrived| Fires when a new frame arrives.| + +## Examples + +Demonstrates using Camera Helper to get video frames from a specific media frame source group. + +```csharp + +using Microsoft.Toolkit.Uwp.Helpers.CameraHelper; + +var availableFrameSourceGroups == await CameraHelper.GetFrameSourceGroupsAsync(); +if(availableFrameSourceGroups != null) +{ + CameraHelper cameraHelper = new CameraHelper() { FrameSourceGroup = availableFrameSourceGroups.FirstOrDefault() }; + var result = await _cameraHelper.InitializeAndStartCaptureAsync(); + + // Camera Initialization succeeded + if(result == CameraHelperResult.Success) + { + // Subscribe to get frames as they arrive + cameraHelper.FrameArrived += CameraHelper_FrameArrived; + + // Optionally set a different frame source format + var newFormat = _cameraHelper.FrameFormatsAvailable.Find((format) => format.VideoFormat.Width == 640); + if (newFormat != null) + { + await _cameraHelper.FrameSource.SetFormatAsync(newFormat); + } + } +} + +``` + +## Sample Code + +[CameraHelper Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/CameraHelper). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). + + +## Requirements + +| Device family | Universal, 10.0.17134.0 or higher | +| --- | --- | +| Namespace | Microsoft.Toolkit.Uwp | +| NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | + +## API Source Code + +- [CameraHelper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/CameraHelper) + diff --git a/docs/helpers/Colors.md b/docs/helpers/Colors.md index 2a2fc3667..9b9ca135a 100644 --- a/docs/helpers/Colors.md +++ b/docs/helpers/Colors.md @@ -55,15 +55,15 @@ Dim redColor As Windows.UI.Color = "Red".ToColor() ## Sample Code -You can find more examples in our [unit tests](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/UnitTests/Helpers/Test_ColorHelper.cs) +You can find more examples in our [unit tests](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/UnitTests/Helpers/Test_ColorHelper.cs) ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [Color Helper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/ColorHelper.cs) +* [Color Helper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/ColorHelper.cs) diff --git a/docs/helpers/Converters.md b/docs/helpers/Converters.md index 2381f8bea..232ae57a9 100644 --- a/docs/helpers/Converters.md +++ b/docs/helpers/Converters.md @@ -79,7 +79,7 @@ and using it like that : ## BoolToVisibilityConverter Examples `BoolToVisibilityConverter` can be used to easily change a boolean value to a Visibility based one. -If targetting 14393 or later, this is done automatically through [x:Bind](https://docs.microsoft.com/windows/uwp/xaml-platform/x-bind-markup-extension). First, declare the converter in your resources: +If targeting 14393 or later, this is done automatically through [x:Bind](https://docs.microsoft.com/windows/uwp/xaml-platform/x-bind-markup-extension). First, declare the converter in your resources: ```xaml @@ -134,7 +134,7 @@ this can be used as follows to hide a list with no items and instead show text t ## StringFormatConverter Examples -`StringFormatConverter` allows you to format a string property upon binding wraping [string.Format](https://docs.microsoft.com/dotnet/api/system.string.format?view=netframework-4.7). +`StringFormatConverter` allows you to format a string property upon binding wrapping [string.Format](https://docs.microsoft.com/dotnet/api/system.string.format?view=netframework-4.7). It only allows for a single input value (the binding string), but can be formatted with the regular string.Format methods. First, add it to your page resources: @@ -154,11 +154,11 @@ then use it like so: ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.UI.Converters | | NuGet package | [Microsoft.Toolkit.Uwp.UI](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI/) | ## API -* [Converters source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI/Converters) +* [Converters source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI/Converters) diff --git a/docs/helpers/DeepLinkParsers.md b/docs/helpers/DeepLinkParsers.md index df6f59481..de507f578 100644 --- a/docs/helpers/DeepLinkParsers.md +++ b/docs/helpers/DeepLinkParsers.md @@ -138,11 +138,11 @@ lastName - Doe ### Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ### API -* [DeepLinkParser source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp/Helpers/DeepLinkParser) \ No newline at end of file +* [DeepLinkParser source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp/Helpers/DeepLinkParser) \ No newline at end of file diff --git a/docs/helpers/DispatcherHelper.md b/docs/helpers/DispatcherHelper.md index ca3669aec..b2913c6fb 100644 --- a/docs/helpers/DispatcherHelper.md +++ b/docs/helpers/DispatcherHelper.md @@ -41,7 +41,7 @@ End Function) Await CoreApplication.MainView.Dispatcher.AwaitableRunAsync(Of T)(Function() End Function) -`` +``` ## Methods @@ -99,11 +99,10 @@ End Function) ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | ## API -* [DispatcherHelper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/DispatcherHelper.cs) - +* [DispatcherHelper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/DispatcherHelper.cs) diff --git a/docs/helpers/HttpHelper.md b/docs/helpers/HttpHelper.md index f7d06f12c..4d4edf3f4 100644 --- a/docs/helpers/HttpHelper.md +++ b/docs/helpers/HttpHelper.md @@ -72,11 +72,11 @@ End Using ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [HttpHelper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/HttpHelper/HttpHelper.cs) +* [HttpHelper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/HttpHelper/HttpHelper.cs) diff --git a/docs/helpers/HttpHelperRequest.md b/docs/helpers/HttpHelperRequest.md index 87a8667ef..6e30fe194 100644 --- a/docs/helpers/HttpHelperRequest.md +++ b/docs/helpers/HttpHelperRequest.md @@ -71,11 +71,11 @@ request.Headers.Authorization = New Windows.Web.Http.Headers.HttpCredentialsHead ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [HttpHelperRequest source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/HttpHelper/HttpHelperRequest.cs) +* [HttpHelperRequest source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/HttpHelper/HttpHelperRequest.cs) diff --git a/docs/helpers/HttpHelperResponse.md b/docs/helpers/HttpHelperResponse.md index 7b9f37e86..95d6221a1 100644 --- a/docs/helpers/HttpHelperResponse.md +++ b/docs/helpers/HttpHelperResponse.md @@ -82,11 +82,11 @@ End Using ## Requirements -| [Device family | Universal, 10.0.14393.0 or higher | +| [Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [HttpHelperResponse source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/HttpHelper/HttpHelperResponse.cs) +* [HttpHelperResponse source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/HttpHelper/HttpHelperResponse.cs) diff --git a/docs/helpers/ImageCache.md b/docs/helpers/ImageCache.md index 001373d85..94db86720 100644 --- a/docs/helpers/ImageCache.md +++ b/docs/helpers/ImageCache.md @@ -71,11 +71,11 @@ Await ImageCache.Instance.ClearAsync() ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [ImageCache source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI/Cache/ImageCache.cs) +* [ImageCache source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.UI/Cache/ImageCache.cs) diff --git a/docs/helpers/IncrementalLoadingCollection.md b/docs/helpers/IncrementalLoadingCollection.md index 780649fb4..3c938c5c5 100644 --- a/docs/helpers/IncrementalLoadingCollection.md +++ b/docs/helpers/IncrementalLoadingCollection.md @@ -129,11 +129,11 @@ PeopleListView.ItemsSource = collection ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [IncrementalLoadingCollection source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp/IncrementalLoadingCollection) +* [IncrementalLoadingCollection source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp/IncrementalLoadingCollection) diff --git a/docs/helpers/NetworkHelper.md b/docs/helpers/NetworkHelper.md index ce2189631..346477da1 100644 --- a/docs/helpers/NetworkHelper.md +++ b/docs/helpers/NetworkHelper.md @@ -29,7 +29,7 @@ A metered connection is an Internet connection that has a data limit or cost ass | Property | Type | Description | | -- | -- | -- | | ConnectionCost | [ConnectionCost](https://docs.microsoft.com/uwp/api/Windows.Networking.Connectivity.ConnectionCost) | Gets connection cost for the current Internet Connection Profile | -| ConnectionType | [ConnectionType(https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.connectivity.connectiontype)] | Gets connection type for the current Internet Connection Profile | +| ConnectionType | [ConnectionType](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.connectivity.connectiontype)] | Gets connection type for the current Internet Connection Profile | | ConnectivityLevel | [NetworkConnectivityLevel](https://docs.microsoft.com/uwp/api/Windows.Networking.Connectivity.NetworkConnectivityLevel) | Gets connectivity level for the current Internet Connection Profile | | IsInternetAvailable | bool | Gets a value indicating whether internet is available across all connections | | IsInternetOnMeteredConnection | bool | Gets a value indicating whether if the current internet connection is metered | @@ -104,16 +104,16 @@ End Select ## Sample Code -[NetworkHelper sample page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/NetworkHelper). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[NetworkHelper sample page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/NetworkHelper). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.Connectivity | | NuGet package | [Microsoft.Toolkit.Uwp.Connectivity](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Connectivity/) | ## API -* [NetworkHelper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.Connectivity/Network/NetworkHelper.cs) +* [NetworkHelper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.Connectivity/Network/NetworkHelper.cs) diff --git a/docs/helpers/ObjectStorage.md b/docs/helpers/ObjectStorage.md index 1c0094e06..2f0d1cd49 100644 --- a/docs/helpers/ObjectStorage.md +++ b/docs/helpers/ObjectStorage.md @@ -203,16 +203,16 @@ Await helper.SaveFileAsync(keySimpleObject, o) ## Sample Code -[Object Storage sample page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Object%20Storage). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[Object Storage sample page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Object%20Storage). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [LocalObjectStorageHelper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/LocalObjectStorageHelper.cs) -* [RoamingObjectStorageHelper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/RoamingObjectStorageHelper.cs) +* [LocalObjectStorageHelper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/LocalObjectStorageHelper.cs) +* [RoamingObjectStorageHelper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/RoamingObjectStorageHelper.cs) diff --git a/docs/helpers/PrintHelper.md b/docs/helpers/PrintHelper.md index 61544d0ea..2596deca6 100644 --- a/docs/helpers/PrintHelper.md +++ b/docs/helpers/PrintHelper.md @@ -18,7 +18,7 @@ Please note that controls cannot be linked to a visual tree. This means that the If you want to use a control from your current XAML page, you can disconnect it before sending it to print (by removing it from its container) or you can create just create a new one from scratch. Please check the sample app code to see how to disconnect/reconnect a control that you want to print: -https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PrintHelper/PrintHelperPage.xaml.cs +https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/PrintHelper/PrintHelperPage.xaml.cs Several events are available to control the printing process: * OnPrintFailed will be triggered if the user cancels the print or if something goes wrong @@ -294,11 +294,11 @@ await printHelper.ShowPrintUIAsync("Windows Community Toolkit Sample App", print ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [Print Helper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/PrintHelper/) +* [Print Helper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/PrintHelper/) diff --git a/docs/helpers/StorageFiles.md b/docs/helpers/StorageFiles.md index d2315b4ed..ea4ac01b9 100644 --- a/docs/helpers/StorageFiles.md +++ b/docs/helpers/StorageFiles.md @@ -102,15 +102,15 @@ Dim isFilePathValid As Boolean = StorageFileHelper.IsFilePathValid("folder/appFi ## Sample Code -You can find more examples in our [unit tests](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/UnitTests/Helpers/Test_StorageFileHelper.cs) +You can find more examples in our [unit tests](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/UnitTests/Helpers/Test_StorageFileHelper.cs) ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [Storage File Helper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/StorageFileHelper.cs) +* [Storage File Helper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/StorageFileHelper.cs) diff --git a/docs/helpers/Streams.md b/docs/helpers/Streams.md index 3ee757f47..a940148ee 100644 --- a/docs/helpers/Streams.md +++ b/docs/helpers/Streams.md @@ -69,15 +69,15 @@ End Using ## Sample Code -You can find more examples in our [unit tests](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/UnitTests/Helpers/Test_StreamHelper.cs) +You can find more examples in our [unit tests](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/UnitTests/Helpers/Test_StreamHelper.cs) ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API Source Code -* [Stream Helper source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/StreamHelper.cs) +* [Stream Helper source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/StreamHelper.cs) diff --git a/docs/helpers/SystemInformation.md b/docs/helpers/SystemInformation.md index cd800ad71..c70369294 100644 --- a/docs/helpers/SystemInformation.md +++ b/docs/helpers/SystemInformation.md @@ -1,13 +1,13 @@ --- title: SystemInformation author: nmetulev -description: The SystemInformation is a static utility class that provides properties with some system, application and device information. +description: The SystemInformation class is a static utility class that provides properties with some system, application and device information. keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, SystemInformation --- # SystemInformation -The [SystemInformation](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.helpers.systeminformation?view=uwp-toolkit-dotnet) is a static utility class that provides properties with some system, application and device information. +The [SystemInformation](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.helpers.systeminformation?view=uwp-toolkit-dotnet) class is a static utility class that provides properties with some system, application and device information. ## Properties @@ -45,11 +45,11 @@ The [SystemInformation](https://docs.microsoft.com/dotnet/api/microsoft.toolkit. ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API -* [SystemInformation source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/SystemInformation.cs) +* [SystemInformation source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/SystemInformation.cs) diff --git a/docs/helpers/ThemeListener.md b/docs/helpers/ThemeListener.md index acff1b983..997d7fbe2 100644 --- a/docs/helpers/ThemeListener.md +++ b/docs/helpers/ThemeListener.md @@ -50,17 +50,17 @@ End Sub ## Sample Code -[Theme Listener Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ThemeListener/ThemeListenerPage.xaml.cs). +[Theme Listener Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ThemeListener/ThemeListenerPage.xaml.cs). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.UI | | NuGet package | [Microsoft.Toolkit.Uwp.UI](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.UI/) | ## API Source Code -- [Theme Listener source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI/Helpers/ThemeListener.cs) \ No newline at end of file +- [Theme Listener source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI/Helpers/ThemeListener.cs) \ No newline at end of file diff --git a/docs/helpers/WeakEventListener.md b/docs/helpers/WeakEventListener.md index e39cd5ef2..dfc18a514 100644 --- a/docs/helpers/WeakEventListener.md +++ b/docs/helpers/WeakEventListener.md @@ -25,15 +25,15 @@ The [WeakEventListener](https://docs.microsoft.com/dotnet/api/microsoft.toolkit. ## Sample Code -You can find examples of WeakEventListener in our [unit tests](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/UnitTests/Helpers/Test_WeakEventListener.cs) +You can find examples of WeakEventListener in our [unit tests](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/UnitTests/Helpers/Test_WeakEventListener.cs) ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp | | NuGet package | [Microsoft.Toolkit.Uwp](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | ## API Source Code -* [WeakEventListener source code](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp/Helpers/WeakEventListener.cs) +* [WeakEventListener source code](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp/Helpers/WeakEventListener.cs) diff --git a/docs/knownissues.md b/docs/knownissues.md index 2d376da1b..38b7c3191 100644 --- a/docs/knownissues.md +++ b/docs/knownissues.md @@ -8,44 +8,28 @@ keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp # Windows Community Toolkit Known Issues > [!NOTE] -For an accurate list of known bugs and issues, take a look at the [issues on GitHub](https://github.com/Microsoft/UWPCommunityToolkit/issues) - - -## Services - -* UnresolvableAssemblyReference when building for Release when using the Microsoft.Toolkit.Uwp.Services package -This error will not be fixed until the 3.0 release as it requires a breaking change. The workaround is to manually add a reference to the Microsoft.IdentityModel.Clients.ActiveDirectory package, version 2.29.0 (or any version between 2.22 and 3.0) - [see issue for more details](https://github.com/Microsoft/UWPCommunityToolkit/issues/1788) +For an accurate list of known bugs and issues, take a look at the [issues on GitHub](https://github.com/Microsoft/WindowsCommunityToolkit//issues) ## Controls -### MasterDetailsView -* Back button does not close the details view in some cases - [see issue for detials](https://github.com/Microsoft/UWPCommunityToolkit/issues/1589) -* Setting background to transparent causes Master and Detail view to overlap in narrow view - [see issue for detials](https://github.com/Microsoft/UWPCommunityToolkit/issues/1117) -* MasterDetailsView does not adapt to keyboard control in details view - [see issue for detials](https://github.com/Microsoft/UWPCommunityToolkit/issues/791) +### InfiniteCanvas +* InfiniteCanvas is not supported on Creators Update - [see issue for details](https://github.com/Microsoft/WindowsCommunityToolkit/issues/2162) +* Visual Studio designer crashes with InfiniteCanvas - [see issue for details](https://github.com/Microsoft/WindowsCommunityToolkit/issues/2160) ### ScrollHeader -* ScrollHeader with `Mode="Sticky"` inside a ListView with grouped items causes the groups' headers to be displayed in front of the header - [see issue for details](https://github.com/Microsoft/UWPCommunityToolkit/issues/1446) +* ScrollHeader with `Mode="Sticky"` inside a ListView with grouped items causes the groups' headers to be displayed in front of the header - [see issue for details](https://github.com/Microsoft/WindowsCommunityToolkit//issues/1446) ### HamburgerMenu -* HamburgerMenu selected indicator moves with keyboard focus - [see issue for details](https://github.com/Microsoft/UWPCommunityToolkit/issues/1306) +* HamburgerMenu selected indicator moves with keyboard focus - [see issue for details](https://github.com/Microsoft/WindowsCommunityToolkit//issues/1306) +### WebView +For the complete list of issues and limitations in this release of the **WebView** control, see [Known Issues of the WebView control for Windows Forms and WPF applications](controls/WebView-known-issues.md). ## Extensions -### Alternating rows -* inserting items does not work propertly - [see issue for details](https://github.com/Microsoft/UWPCommunityToolkit/issues/1837) +### Alternating rows +* inserting items does not work properly - [see issue for details](https://github.com/Microsoft/WindowsCommunityToolkit//issues/1837) ### TextBoxRegEx -* Some phone number formats are not supported - [see issue for details](https://github.com/Microsoft/UWPCommunityToolkit/issues/1821) - - -## Parsers - -### Markdown -* parser combines quotes with any white space in between - [see issue for details](https://github.com/Microsoft/UWPCommunityToolkit/issues/1761) - - -## Notifications - -The Notifications packages do not work with C++ and Javascrpt projects and throw an exception - [see issue for details](https://github.com/Microsoft/UWPCommunityToolkit/issues/1760) \ No newline at end of file +* Some phone number formats are not supported - [see issue for details](https://github.com/Microsoft/WindowsCommunityToolkit//issues/1821) diff --git a/docs/license.md b/docs/license.md index 86da4cccd..5cc93eb77 100644 --- a/docs/license.md +++ b/docs/license.md @@ -1,38 +1,12 @@ #The MIT License (MIT) +Copyright (c) .NET Foundation and Contributors -Copyright (c) Microsoft Corporation +All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -of this software and associated documentation files (the "Software"), to deal - -in the Software without restriction, including without limitation the rights - -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - -copies of the Software, and to permit persons to whom the Software is - -furnished to do so, subject to the following conditions: - - -The above copyright notice and this permission notice shall be included in - -all copies or substantial portions of the Software. - - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - -THE SOFTWARE. +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/docs/notifications/NotificationsOverview.md b/docs/notifications/NotificationsOverview.md index f1681a955..057b48b0f 100644 --- a/docs/notifications/NotificationsOverview.md +++ b/docs/notifications/NotificationsOverview.md @@ -34,11 +34,11 @@ Instead of having to deal with XML, you can now use Windows Community toolkit an ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace for C# | Microsoft.Toolkit.Uwp.Notifications | | Namespace for JavaScript | Microsoft.Toolkit.Uwp.Notifications.Javascript | ## API -* [Notifications source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Notifications/Microsoft.Toolkit.Uwp.Notifications.UWP) +* [Notifications source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Notifications/Microsoft.Toolkit.Uwp.Notifications.UWP) diff --git a/docs/parsers/MarkdownParser.md b/docs/parsers/MarkdownParser.md index 3cba5370d..96059af27 100644 --- a/docs/parsers/MarkdownParser.md +++ b/docs/parsers/MarkdownParser.md @@ -69,11 +69,11 @@ In order to create a Markdown Renderer, you can either implement your own, or in This requires an inherited `IRenderContext`, which allows you to keep track of the Context of the rendering. -The best way to figure out how to create a Renderer, is to look at the [implementation](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/MarkdownTextBlock/Render) for the UWP MarkdownTextBlock control. +The best way to figure out how to create a Renderer, is to look at the [implementation](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.UI.Controls/MarkdownTextBlock/Render) for the UWP MarkdownTextBlock control. ## Sample Code -[Markdown Parser Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/MarkdownParser/MarkdownParserPage.xaml.cs). +[Markdown Parser Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/MarkdownParser/MarkdownParserPage.xaml.cs). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). @@ -86,4 +86,4 @@ You can see this in action in [Windows Community Toolkit Sample App](https://www ## API Source Code -- [Markdown Parser source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Parsers/Markdown) \ No newline at end of file +- [Markdown Parser source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Parsers/Markdown) \ No newline at end of file diff --git a/docs/parsers/RSSParser.md b/docs/parsers/RSSParser.md index 4441d217f..92fa9aad7 100644 --- a/docs/parsers/RSSParser.md +++ b/docs/parsers/RSSParser.md @@ -1,7 +1,7 @@ --- title: RSS Parser author: williamabradley -description: The RSS Parser allows you to parse an RSS content String into RSS Schema. +description: The RSS Parser allows you to parse an RSS content String into an RSS Schema. keywords: windows community toolkit, uwp community toolkit, uwp toolkit, microsoft community toolkit, microsoft toolkit, rss, rss parsing, parser dev_langs: - csharp @@ -10,7 +10,7 @@ dev_langs: # RSS Parser -The [RssParser](https://docs.microsoft.com/en-us/dotnet/api/microsoft.toolkit.parsers.rss.rssparser) class allows you to parse a RSS content String into a RSS Schema. +The [RssParser](https://docs.microsoft.com/en-us/dotnet/api/microsoft.toolkit.parsers.rss.rssparser) class allows you to parse an RSS content String into an RSS Schema. ## Example @@ -79,7 +79,7 @@ End Sub ## Sample Code -[RSS Parser Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RssParser/RssParserPage.xaml.cs). +[RSS Parser Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//blob/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/RssParser/RssParserPage.xaml.cs). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). @@ -92,4 +92,4 @@ You can see this in action in [Windows Community Toolkit Sample App](https://www ## API Source Code -- [RSS Parser source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Parsers/Rss) \ No newline at end of file +- [RSS Parser source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Parsers/Rss) \ No newline at end of file diff --git a/docs/platform-specific/PlatformSpecificAnalyzer.md b/docs/platform-specific/PlatformSpecificAnalyzer.md new file mode 100644 index 000000000..1f5ca2b7c --- /dev/null +++ b/docs/platform-specific/PlatformSpecificAnalyzer.md @@ -0,0 +1,52 @@ +--- +title: UWP Platform Specific Analyzer +author: hermitdave +description: Platform Specific Analyzer is a Roslyn analyzer that analyzes and suggests code fixes to ensure that any version / platform specific API are guarded by correct runtime checks +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, platform specific, platform specific analyzer, roslyn analyzer +dev_langs: + - csharp + - visualbasic +--- + +# Platform Specific Analyzer + +When writing [version](https://docs.microsoft.com/windows/uwp/debug-test-perf/version-adaptive-code) or platform adaptive code, the developers should ensure that code checks for presence of API before calling it. +The platform specific analyzer is a Roslyn Analyzer that can parse through code and suggest fixes where appropriate. + +## Installation + +The analyzer is available both as a nuget package + +* References > Manage NuGet References > install [Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer) + + +## Sample Output + +The analyzer automatically kicks in when code is opened in Visual Studio and supports both C# and Visual Basic + +C# +![Code Analysis](../resources/images/CodeAnalysis.png) + +![Code Analysis](../resources/images/CodeFixSuggestion.png) + +Visual Basic +![Code Analysis](../resources/images/CodeAnalysisVB.png) + +![Code Analysis](../resources/images/CodeFixSuggestionVB.png) + +## Requirements + +| Device family | Universal, 10.0.15063.0 or higher | +| ---------------------------------------------------------------- | ----------------------------------- | +| Namespace | Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer | +| NuGet package | [Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer/) | + +## API Source Code + +- [Platform Specific Analyzer](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.PlatformSpecificAnalyzer) + +## Related Topics + + + +- [Platform Specific Differences Generator](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.ui.platformspecificanalyzerdifferencesgen) diff --git a/docs/platform-specific/PlatformSpecificDifferencesGenerator.md b/docs/platform-specific/PlatformSpecificDifferencesGenerator.md new file mode 100644 index 000000000..3299f37da --- /dev/null +++ b/docs/platform-specific/PlatformSpecificDifferencesGenerator.md @@ -0,0 +1,49 @@ +--- +title: UWP Platform Specific Differences Generator +author: hermitdave +description: Given the min and max SDK versions, the generator loads the appropriate Windows.Foundation.UniversalApiContract.winmd and builds differences in terms of new types and new members. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, platform specific, platform specific differences, platform specific differences generator +dev_langs: + - csharp +--- + +# Platform Specific Differences Generator + +A Platform Specific Analyzer would require to know the differences between various versions of UWP SDK. The Differences Generator provides a means of generating a differences dataset that can then be embedded in the analyzer. + +## Usage + +```cmd +DifferencesGen /min:4.0.0.0 /max:6.0.0.0 +``` + +## Sample Output + +Differences-6.0.0.0.gz + +Differences-5.0.0.0.gz + +## Data format + +All types are fully qualified + +##### Namespace.Type +*Windows.Management.Update.PreviewBuildsState* + +*Windows.Management.Update.PreviewBuildsManager* + +A new type does not have additional methods and properties listed. + +For a type that has additions, the additions are listed alongside +##### Namespace.Type:Method#ParamCount,Property +*Windows.Networking.NetworkOperators.MobileBroadbandModem:TryGetPcoAsync#0,IsInEmergencyCallMode* + +## API Source Code + +- [DifferencesGen](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.PlatformDifferencesGen/Program.cs) + +## Related Topics + + + +- [Platform Specific Analyzer](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.uwp.ui.platformspecificanalyzer) diff --git a/docs/resources/images/CodeAnalysis.png b/docs/resources/images/CodeAnalysis.png new file mode 100644 index 000000000..359340786 Binary files /dev/null and b/docs/resources/images/CodeAnalysis.png differ diff --git a/docs/resources/images/CodeAnalysisVB.png b/docs/resources/images/CodeAnalysisVB.png new file mode 100644 index 000000000..5611a431a Binary files /dev/null and b/docs/resources/images/CodeAnalysisVB.png differ diff --git a/docs/resources/images/CodeFixSuggestion.png b/docs/resources/images/CodeFixSuggestion.png new file mode 100644 index 000000000..6771fbf8d Binary files /dev/null and b/docs/resources/images/CodeFixSuggestion.png differ diff --git a/docs/resources/images/CodeFixSuggestionVB.png b/docs/resources/images/CodeFixSuggestionVB.png new file mode 100644 index 000000000..ff4385b53 Binary files /dev/null and b/docs/resources/images/CodeFixSuggestionVB.png differ diff --git a/docs/resources/images/Controls/InfiniteCanvas.gif b/docs/resources/images/Controls/InfiniteCanvas.gif new file mode 100644 index 000000000..eb9f1ba53 Binary files /dev/null and b/docs/resources/images/Controls/InfiniteCanvas.gif differ diff --git a/docs/resources/images/Controls/UniformGrid/DialogButtons.png b/docs/resources/images/Controls/UniformGrid/DialogButtons.png new file mode 100644 index 000000000..1a09103fa Binary files /dev/null and b/docs/resources/images/Controls/UniformGrid/DialogButtons.png differ diff --git a/docs/resources/images/Controls/UniformGrid/FixedChild.png b/docs/resources/images/Controls/UniformGrid/FixedChild.png new file mode 100644 index 000000000..58897a4f8 Binary files /dev/null and b/docs/resources/images/Controls/UniformGrid/FixedChild.png differ diff --git a/docs/resources/images/Controls/UniformGrid/Orientation.png b/docs/resources/images/Controls/UniformGrid/Orientation.png new file mode 100644 index 000000000..e64f481c1 Binary files /dev/null and b/docs/resources/images/Controls/UniformGrid/Orientation.png differ diff --git a/docs/resources/images/Controls/UniformGrid/SizedChild.png b/docs/resources/images/Controls/UniformGrid/SizedChild.png new file mode 100644 index 000000000..21754da71 Binary files /dev/null and b/docs/resources/images/Controls/UniformGrid/SizedChild.png differ diff --git a/docs/resources/images/Controls/UniformGrid/SizedRowCol.png b/docs/resources/images/Controls/UniformGrid/SizedRowCol.png new file mode 100644 index 000000000..af5c5ff67 Binary files /dev/null and b/docs/resources/images/Controls/UniformGrid/SizedRowCol.png differ diff --git a/docs/resources/images/Controls/UniformGrid/Spacing.png b/docs/resources/images/Controls/UniformGrid/Spacing.png new file mode 100644 index 000000000..18b9127c9 Binary files /dev/null and b/docs/resources/images/Controls/UniformGrid/Spacing.png differ diff --git a/docs/resources/images/Controls/WebView/web-view-samples.png b/docs/resources/images/Controls/WebView/web-view-samples.png new file mode 100644 index 000000000..96e9197ff Binary files /dev/null and b/docs/resources/images/Controls/WebView/web-view-samples.png differ diff --git a/docs/resources/images/Extensions/MiddleClickScrolling.gif b/docs/resources/images/Extensions/MiddleClickScrolling.gif new file mode 100644 index 000000000..d4616ef14 Binary files /dev/null and b/docs/resources/images/Extensions/MiddleClickScrolling.gif differ diff --git a/docs/resources/images/Graph/AadLogin.png b/docs/resources/images/Graph/AadLogin.png new file mode 100644 index 000000000..ab920baf1 Binary files /dev/null and b/docs/resources/images/Graph/AadLogin.png differ diff --git a/docs/resources/images/Graph/PeoplePicker.png b/docs/resources/images/Graph/PeoplePicker.png new file mode 100644 index 000000000..924f4ef5a Binary files /dev/null and b/docs/resources/images/Graph/PeoplePicker.png differ diff --git a/docs/resources/images/Graph/ProfileCard.png b/docs/resources/images/Graph/ProfileCard.png new file mode 100644 index 000000000..906dfb405 Binary files /dev/null and b/docs/resources/images/Graph/ProfileCard.png differ diff --git a/docs/resources/images/Graph/SharePointFileList.png b/docs/resources/images/Graph/SharePointFileList.png new file mode 100644 index 000000000..4768cf5c7 Binary files /dev/null and b/docs/resources/images/Graph/SharePointFileList.png differ diff --git a/docs/services/Bing.md b/docs/services/Bing.md index 299178a80..d15b4ca9a 100644 --- a/docs/services/Bing.md +++ b/docs/services/Bing.md @@ -1,7 +1,7 @@ --- title: Bing Service author: nmetulev -description: The Bing Service allows you to retrieve Bing results. Bing can return web and news results in your language, images, and videos for many countries around the world. +description: The Bing Service allows you to retrieve Bing results. Bing can return web and news results in your language, images, and videos for many countries/regions around the world. keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, bing dev_langs: - csharp @@ -10,7 +10,7 @@ dev_langs: # Bing Service -The **Bing Service** allows you to retrieve Bing results. Bing can return web and news results in your language, images, and videos for many countries around the world. +The **Bing Service** allows you to retrieve Bing results. Bing can return web and news results in your language, images, and videos for many countries/regions around the world. ## Set up Bing API @@ -24,7 +24,7 @@ Choose the *Bing Search - Free* option. After selecting this and agreeing to th ## Syntax ```csharp -using Microsoft.Toolkit.Uwp.Services.Bing; +using Microsoft.Toolkit.Services.Bing; var searchConfig = new BingSearchConfig { @@ -37,7 +37,7 @@ var searchConfig = new BingSearchConfig ListView.ItemsSource = await BingService.Instance.RequestAsync(searchConfig, 50); ``` ```vb -Imports using Microsoft.Toolkit.Uwp.Services.Bing +Imports using Microsoft.Toolkit.Services.Bing Dim searchConfig = New BingSearchConfig With { .Country = BingCountry.UnitedStates, @@ -116,15 +116,15 @@ ListView.ItemsSource = Await BingService.Instance.RequestAsync(searchConfig, 50) ## Sample Code -[Bing Service Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Bing%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[Bing Service Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Bing%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | -| Namespace | Microsoft.Toolkit.Uwp.Services | -| NuGet package | [Microsoft.Toolkit.Uwp.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Services/) | +| Namespace | Microsoft.Toolkit.Services | +| NuGet package | [Microsoft.Toolkit.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Services/) | ## API -* [Bing Service source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Services/Services/Bing) +* [Bing Service source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Services/Services/Bing) diff --git a/docs/services/Facebook.md b/docs/services/Facebook.md index 8af05ff31..e51e5ec4d 100644 --- a/docs/services/Facebook.md +++ b/docs/services/Facebook.md @@ -287,15 +287,15 @@ Class for connecting to Facebook ## Sample Code -[Facebook Service Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Facebook%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[Facebook Service Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Facebook%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.Services | | NuGet package | [Microsoft.Toolkit.Uwp.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Services/) | ## API -* [Facebook Service source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Services/Services/Facebook) +* [Facebook Service source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.Services/Services/Facebook) diff --git a/docs/services/GraphLogin.md b/docs/services/GraphLogin.md new file mode 100644 index 000000000..5c8dec810 --- /dev/null +++ b/docs/services/GraphLogin.md @@ -0,0 +1,107 @@ +--- +title: GraphLogin Component +author: AdamBraden +description: Windows Forms component to authenticate with Azure AD v2 and the Microsoft Graph +keywords: windows 10, uwp, uwp community toolkit, uwp toolkit, Windows Forms, GraphLogin +--- + +# GraphLogin Component + +The [GraphLogin component](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.win32.ui.controls.winforms.graphlogin) is a Windows Forms component that provides an easy to use experience for authenticating with Azure AD and the Microsoft Graph. This component is being provided for Windows Forms developers that need a Microsoft Graph authentication solution on Windows 10 builds 1803 and earlier and on Windows 7. + +This component wraps the Toolkit's **MicrosoftGraphService** for an easy to use Login experience. The control then provides read-only properties about the logged on user and an instance of the **GraphServiceClient** which can be used for additional calls with the Microsoft Graph SDK. + +> [!IMPORTANT] +Before using this component, the application must be registered in the Azure AD v2 endpoint. For more information on registering your app see https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-app-registration. + + +## Syntax +To use this sample code in a Windows Forms application, install the Microsoft.Toolkit.Win32.UI.Controls nuget package, and add a button, 2 labels, and a picturebox on the form. Then drag a GraphLogin component from the toolbox on to the form, and enter the following code: + +```csharp + + using Microsoft.Toolkit.Services.Services.MicrosoftGraph; + + + // Instance of Microsoft Graph + private GraphServiceClient graphClient = null; + + public Form1() + { + InitializeComponent(); + + // values to connect to Microsoft Graph + graphLoginComponent1.ClientId = "{your app's clientid}"; + graphLoginComponent1.Scopes = new string[] { MicrosoftGraphScope.UserRead }; + } + + private async void button1_Click(object sender, EventArgs e) + { + if (!await graphLoginComponent1.LoginAsync()) + { + return; + } + + //update the user's display fields + label1.Text = graphLoginComponent1.DisplayName; + label2.Text = graphLoginComponent1.JobTitle; + pictureBox1.Image = graphLoginComponent1.Photo; + + // Do more things with the graph + graphClient = graphLoginComponent1.GraphServiceClient; + } +``` + + + + + +## Add the GraphLogin component to the Visual Studio Toolbox + + +1. Open the Visual Studio **Toolbox**, then right-click anywhere in the toolbox, and select the **Choose Items** option. + +2. In the **.NET Framework Components** tab of the **Choose Toolbox Items** dialog box. + +3. Use the **Browse** button to locate the **Microsoft.Toolkit.Services.dll** in your NuGet package folder (choose the *net461* folder). + + For help finding that folder, see [Managing the global packages, cache, and temp folders](https://docs.microsoft.com/nuget/consume-packages/managing-the-global-packages-and-cache-folders). + +4. Add that file to the list of Toolbox controls, and then close the **Choose Toolbox Items** dialog box. + + The **GraphLoginComponent** appears in the **General** section of the **Toolbox**. + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| ClientId | string| The ClientId of the application as registered with Azure AD v2 | +| Scopes | string[]| An array of scopes requested for the Microsoft Graph. Use values from the MicrosoftGraphScope enum | +| DisplayName | string | Display name for the logged on user from the Microsoft Graph | +| JobTitle | string | Job title for the logged on user from the Microsoft Graph | +| Email | string | Email address (UPN) for the logged on user from the Microsoft Graph | +| Photo | System.Drawing.Image | Profile picture for the logged on user from the Microsoft Graph | +| GraphServiceClient | Microsoft.Graph.GraphServiceClient | The GraphServiceClient instance for the logged on user from the Microsoft Graph | + + + + +## Methods + + + +| Methods | Return Type | Description | +| -- | -- | -- | +| LoginAsync | bool | Returns true of success, false otherwise | + + +## Requirements + +| Device family | .NetFramework 4.6.1 or higher | +| -- | -- | +| Namespace | Microsoft.Toolkit.Services.WinForms | +| NuGet package | [Microsoft.Toolkit.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Services) | + +## API Source Code + +- [WinForms.GraphLogin](/Microsoft.Toolkit.Services/Services/MicrosoftGraph/WinForms) diff --git a/docs/services/Linkedin.md b/docs/services/Linkedin.md index d643ba84b..57c7aae3b 100644 --- a/docs/services/Linkedin.md +++ b/docs/services/Linkedin.md @@ -19,7 +19,7 @@ The **LinkedIn Service** allows you to retrieve or publish data to the LinkedIn 3. Complete all mandatory fields signified by the red star. If you agree to the terms and conditions, hit **Submit**. 4. Make a note of the **Client Id** and **Client Secret** for your app - you will need to supply these in your code. 5. Take note of the **Default Application Permissions**. You can either set these in this portal or via code. These are the permissions your user will need to agree to for you to make calls on their behalf. -6. Under **OAuth 2.0** you will need to enter a **Authorized Redirect URLs**. For UWP app development purposes this is arbitrary, but it will need to match what you have in your code (e.g. https://github.com/Microsoft/UWPCommunityToolkit). +6. Under **OAuth 2.0** you will need to enter a **Authorized Redirect URLs**. For UWP app development purposes this is arbitrary, but it will need to match what you have in your code (e.g. https://github.com/Microsoft/WindowsCommunityToolkit/). 7. Once you have done, hit **Update**. ## Syntax @@ -56,15 +56,15 @@ Await LinkedInService.Instance.GetUserProfileAsync() Await LinkedInService.Instance.ShareActivityAsync(ShareText.Text) ``` -[LinkedIn Service Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/LinkedIn%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[LinkedIn Service Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/LinkedIn%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.Services | | NuGet package | [Microsoft.Toolkit.Uwp.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Services/) | ## API -* [LinkedIn Service source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Services/Services/LinkedIn) +* [LinkedIn Service source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.Services/Services/LinkedIn) diff --git a/docs/services/MicrosoftGraph.md b/docs/services/MicrosoftGraph.md index 47a140396..a24b544c3 100644 --- a/docs/services/MicrosoftGraph.md +++ b/docs/services/MicrosoftGraph.md @@ -1,7 +1,7 @@ --- title: MicrosoftGraph Service author: nmetulev -description: The MicrosoftGraph Service aim to easily logon to Office 365 Service in order to Retrieve User Information, Retrieve and Send emails, Retrieve User events +description: The MicrosoftGraph Service aim to easily logon to Microsoft Graph service in order to Retrieve User Information, Retrieve and Send emails, Retrieve User events keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, MicrosoftGraph Service dev_langs: - csharp @@ -10,40 +10,50 @@ dev_langs: # MicrosoftGraph Service -The **MicrosoftGraph** Service aim to easily logon to Office 365 Service in order to: +The **MicrosoftGraph** Service allows easy access to the Microsoft Graph in order to: * Retrieve User Information * Retrieve and Send emails * Retrieve User events -## Prerequisites - > [!NOTE] This API will not work on an XBOX UWP Application - -### 1. Get and Office 365 Subscription - -If you don't have one, you need to create an Office 365 Developer Site. There are several ways to create one: - -* [An MSDN subscription](https://msdn.microsoft.com/subscriptions/manage/default.aspx) - This is available to MSDN subscribers with Visual Studio Ultimate and Visual Studio Premium. -* [An existing Office 365 subscription](https://msdn.microsoft.com/library/2ec857d5-dc6f-4cf6-ba45-adc845ef2a25%28Office.15%29.aspx) - You can use an existing Office 365 subscription, which can be any of the following: Office 365 Midsize Business, Office 365 Enterprise, Office 365 Education, Office 365 Government. -* [Free O365 trial](https://portal.office.com/Signup?OfferId=6881A1CB-F4EB-4db3-9F18-388898DAF510&DL=DEVELOPERPACK&ali=1) - You can start with a free 30-day trial, or buy an Office 365 developer subscription. -* [Free O365 Developer](http://dev.office.com/devprogram) - Or Get a One year free Office 365 Developer account -### 2. Register you application in Azure Active Directory +## Get a Client Id -To authenticate your app, you need to register your app with Azure AD, and provide some details about your app. You can register your app manually by using the [Azure Management Portal](http://manage.windowsazure.com), or by using Visual Studio. +To authenticate your app, you need to register your app with Azure AD, and provide some details about your app. -To register your app manually, see [Manually register your app with Azure AD so it can access Office 365 APIs.](https://msdn.microsoft.com/en-us/office/office365/howto/add-common-consent-manually) -To register your app by using Visual Studio, see [Using Visual Studio to register your app and add Office 365 APIs.](https://msdn.microsoft.com/office/office365/HowTo/adding-service-to-your-Visual-Studio-project) +### Register the App to use Azure AD v2 Endpoint + +1. Go to the [App Registration Portal](https://apps.dev.microsoft.com) +2. Click in the "Add an app" button. +3. Enter the app name and click "create" +4. Once the App is created, copy the Application Id to use it later. +5. Next, add a Platform to the App clicking in "Add Platform" and select "Native Application" tile. +6. Scroll to the Microsoft Graph Permissions section (by default the User.Read permission is added). Add the following permissions: Sign in and read user profile, Read user mail, Send mail as a user, Read user calendars. +7. Finally, save your changes. + +### Register the App to use Azure AD v1 Endpoint + +You can register your app manually by using the [Azure Management Portal](http://portal.azure.com), or by using Visual Studio: +1. To register your app by using Visual Studio, see [Using Visual Studio to register your app and add Office 365 APIs.](https://msdn.microsoft.com/office/office365/HowTo/adding-service-to-your-Visual-Studio-project) +2. To register your app manually, see [Manually register your app with Azure AD so it can access Office 365 APIs.](https://msdn.microsoft.com/en-us/office/office365/howto/add-common-consent-manually). Here is a summary to register your App manually: + - Go to the [Azure Management Portal](http://portal.azure.com) + - Go to the "Azure Active Directory" option + - Go to "App Registrations" option + - Click on the "New application registration" button + - Enter a name for your App + - Specify your application as a **Native** + - Specify the Redirect Uri as **urn:ietf:wg:oauth:2.0:oob** + - Click "Create" button After you've registered your app, Azure AD will generate a client ID for your app. You'll need to use this client ID to get your access token. -When you register your app in the [Azure Management Portal](http://manage.windowsazure.com), you will need to configure details about your application with the following steps: +When you register your app in the [Azure Management Portal](http://portal.azure.com), you will need to configure details about your application with the following steps: -1. Specify your application as a **Web application and/or web API** -2. Specify the Redirect Uri as **http://localhost:8000** +1. Click "Settings" button +2. Go to "Required permissions" option 3. Add Application: Choose **Microsoft Graph** API 4. Specify the permission levels the MicrosoftGraph Service requires from the Office 365 API (Microsoft Graph). Choose at least: * **Sign in and read user profile** to access user's profile. @@ -54,14 +64,29 @@ When you register your app in the [Azure Management Portal](http://manage.window |Setting|Value| |----------|:-------------:| -|Web application and/or web API|Yes| -|Redirect Uri|http://localhost:8080| +|Native application|Yes| +|Redirect Uri|urn:ietf:wg:oauth:2.0:oob| |Resource to Add|Microsoft Graph| -|Delegate Permissions |Sign in and read user profile, Read user mail and Send mail, Read user calendars| +|Delegate Permissions |Sign in and read user profile, Read user mail, Send mail as a user, Read user calendars| + +### Testing access to the Graph API +Using ADAL, v1 authentication, registering your application creates an App ID/Client and you can simply paste that into the Client Id field inside of the Microsoft Graph services page. + +Using MSAL, v2 (default) authentication, you can use the same App ID to paste to the Client Id field. You can also optionally provide different permission scopes and a login hint (suggested user name). + + +### Get an Office 365 Subscription + +If you don't have one, you need to create an Office 365 Developer Site. There are several ways to create one: + +* [An MSDN subscription](https://msdn.microsoft.com/subscriptions/manage/default.aspx) - This is available to MSDN subscribers with Visual Studio Ultimate and Visual Studio Premium. +* [An existing Office 365 subscription](https://msdn.microsoft.com/library/2ec857d5-dc6f-4cf6-ba45-adc845ef2a25%28Office.15%29.aspx) - You can use an existing Office 365 subscription, which can be any of the following: Office 365 Midsize Business, Office 365 Enterprise, Office 365 Education, Office 365 Government. +* [Free O365 trial](https://portal.office.com/Signup?OfferId=6881A1CB-F4EB-4db3-9F18-388898DAF510&DL=DEVELOPERPACK&ali=1) - You can start with a free 30-day trial, or buy an Office 365 developer subscription. +* [Free O365 Developer](http://dev.office.com/devprogram) - Or Get a One year free Office 365 Developer account ## Syntax -### Sign in with an Office 365 account +### Sign in with an AAD account ```csharp // Initialize the service @@ -74,6 +99,15 @@ if (!await MicrosoftGraphService.Instance.LoginAsync()) { return; } + +// Create a instance of the service +var msg = new MicrosoftGraphService(ClientId.Text); +// Login via Azure Active Directory +if (!await msg.LoginAsync()) +{ + return; +} + ``` ```vb ' Initialize the service @@ -278,15 +312,15 @@ End If ## Sample Code -[MicrosoftGraph Service Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Microsoft%20Graph%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[MicrosoftGraph Service Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Microsoft%20Graph%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ### Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | -| Namespace | Microsoft.Toolkit.Uwp.Services | -| NuGet package | [Microsoft.Toolkit.Uwp.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Services/) | +| Namespace | Microsoft.Toolkit.Services | +| NuGet package | [Microsoft.Toolkit.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Services/) | ### API -* [MicrosoftGraph Service source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Services/Services/MicrosoftGraph) +* [MicrosoftGraph Service source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Services/Services/MicrosoftGraph) diff --git a/docs/services/MicrosoftTranslator.md b/docs/services/MicrosoftTranslator.md index 480c14e6b..d92371dad 100644 --- a/docs/services/MicrosoftTranslator.md +++ b/docs/services/MicrosoftTranslator.md @@ -49,15 +49,15 @@ Dim translatedText = Await TranslatorService.Instance.TranslateAsync("Hello ever ## Sample Code -[Microsoft Translator Service Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Microsoft%20Translator%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[Microsoft Translator Service Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Microsoft%20Translator%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.Services | | NuGet package | [Microsoft.Toolkit.Uwp.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Services/) | ## API -* [Microsoft Translator Service source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Services/Services/MicrosoftTranslator) +* [Microsoft Translator Service source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.Services/Services/MicrosoftTranslator) diff --git a/docs/services/OneDrive.md b/docs/services/OneDrive.md index fbe2224d5..95fd3a880 100644 --- a/docs/services/OneDrive.md +++ b/docs/services/OneDrive.md @@ -54,7 +54,7 @@ to your application manifest to enable AAD authentication. Capabilities in the m Authentication, sign-in and permission scopes are discussed in more detail in this document, [Authorization and sign-in for OneDrive in Microsoft Graph](https://docs.microsoft.com/en-us/onedrive/developer/rest-api/getting-started/graph-oauth) ### Testing access to the OneDrive API -Registering your applicatioin creates an App ID/Client and you can simply paste that into the Client Id field inside of the OneDrive services page. To use the new flow, you need to select the "Work Or School Accounts Or Microsoft Account" authentication provider option. +Registering your applicatioin creates an App ID/Client and you can simply paste that into the Client Id field inside of the OneDrive services page. ## Syntax @@ -64,7 +64,7 @@ Registering your applicatioin creates an App ID/Client and you can simply paste // Using the new converged authentication of the Microsoft Graph we can simply // call the Initialize method on the OneDriveService singleton when initializing // in UWP applications -Microsoft.Toolkit.Uwp.Services.OneDrive.OneDriveService.Instance.Initialize +Microsoft.Toolkit.Services.OneDrive.OneDriveService.Instance.Initialize (appClientId, scopes, null, @@ -74,7 +74,7 @@ Microsoft.Toolkit.Uwp.Services.OneDrive.OneDriveService.Instance.Initialize ' Using the new converged authentication of the Microsoft Graph we can simply ' call the Initialize method on the OneDriveService singleton when initializing ' in UWP applications -Microsoft.Toolkit.Uwp.Services.OneDrive.OneDriveService.Instance.Initialize(appClientId, scopes, Nothing, Nothing) +Microsoft.Toolkit.Services.OneDrive.OneDriveService.Instance.Initialize(appClientId, scopes, Nothing, Nothing) ``` ### Defining scopes @@ -107,6 +107,7 @@ if (!await OneDriveService.Instance.LoginAsync()) If Not Await OneDriveService.Instance.LoginAsync() Then Throw New Exception("Unable to sign in") End If +``` ### Retrieve the root of your OneDrive @@ -291,15 +292,15 @@ End Using ## Sample Code -[OneDrive Service Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/OneDrive%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[OneDrive Service Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/OneDrive%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | -| Namespace | Microsoft.Toolkit.Uwp.Services | -| NuGet package | [Microsoft.Toolkit.Uwp.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Services/) | +| Namespace | Microsoft.Toolkit.Services | +| NuGet package | [Microsoft.Toolkit.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Services/) | ## API -* [OneDrive Service source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Services/Services/OneDrive) +* [OneDrive Service source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Services/Services/OneDrive) diff --git a/docs/services/Twitter.md b/docs/services/Twitter.md index 0668a38ed..64ac646c5 100644 --- a/docs/services/Twitter.md +++ b/docs/services/Twitter.md @@ -34,10 +34,11 @@ In the code section below the GetUserTimeLineAsync method returns some Tweet obj | Property | Type | Description | | -- | -- | -- | | **CreatedAt** | string | The date and time of the Tweet formatted by Twitter | -| **Text** | string | The text of the Tweet | +| **Text** | string | The text of the Tweet (if retweet, the text might not be complete - use the RetweetedStatus object for the original tweet)| | **Id** | string | The Twitter status identifier | | **GeoData** | TwitterGeoData | A class containing the latitude and longitude of the Tweet | | **User** | TwitterUser | A class containing the user ID, Name, ScreenName, and ProfileImageUrl | +| **RetweetedStatus** | Tweet | if this tweet is a retweet, this object will contain the original tweet | ## Syntax @@ -167,15 +168,15 @@ If you are posting from your app and never seeing them show up in the timeline c ## Sample Code -[Twitter Service Sample Page Source](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Twitter%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). +[Twitter Service Sample Page Source](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Twitter%20Service). You can see this in action in [Windows Community Toolkit Sample App](https://www.microsoft.com/store/apps/9NBLGGH4TLCQ). ## Requirements -| Device family | Universal, 10.0.14393.0 or higher | +| Device family | Universal, 10.0.15063.0 or higher | | --- | --- | | Namespace | Microsoft.Toolkit.Uwp.Services | | NuGet package | [Microsoft.Toolkit.Uwp.Services](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Services/) | ## API -* [Twitter Service source code](https://github.com/Microsoft/UWPCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.Services/Services/Twitter) +* [Twitter Service source code](https://github.com/Microsoft/WindowsCommunityToolkit//tree/master/Microsoft.Toolkit.Uwp.Services/Services/Twitter) diff --git a/docs/toc.md b/docs/toc.md index 020007318..c4d784177 100644 --- a/docs/toc.md +++ b/docs/toc.md @@ -5,6 +5,48 @@ ## [Windows Community Toolkit Nuget Packages](Nuget-Packages.md) ## [Adding the Windows Community Toolkit to your Visual Studio Toolbox](Toolbox-Support.md) +# Controls +## [AdaptiveGridView](controls/AdaptiveGridView.md) +## [BladeView](controls/BladeView.md) +## [CameraPreview](controls/CameraPreview.md) +## [Carousel](controls/Carousel.md) +## [DataGrid](controls/DataGrid.md) +## [DockPanel](controls/DockPanel.md) +## [DropShadowPanel Control](controls/DropShadowPanel.md) +## [Expander Control](controls/Expander.md) +## [GridSplitter](controls/GridSplitter.md) +## [HamburgerMenu](controls/HamburgerMenu.md) +## [HeaderedContentControl](controls/HeaderedContentControl.md) +## [HeaderedItemsControl](controls/HeaderedItemsControl.md) +## [HeaderedTextBlock](controls/HeaderedTextBlock.md) +## [ImageEx](controls/ImageEx.md) +## [InAppNotification](controls/InAppNotification.md) +## [InfiniteCanvas](controls/InfiniteCanvas.md) +## [LayoutTransformControl](controls/LayoutTransformControl.md) +## [Loading](controls/Loading.md) +## [MarkdownTextBlock](controls/MarkdownTextBlock.md) +## [MasterDetailsView](controls/MasterDetailsView.md) +## [Menu Control](controls/Menu.md) +## Microsoft Graph Controls +### [AadLogin](graph/AadLogin.md) +### [PeoplePicker](graph/PeoplePicker.md) +### [ProfileCard](graph/ProfileCard.md) +### [SharePointFileList](graph/SharePointFileList.md) +## [OrbitView](controls/OrbitView.md) +## [PullToRefreshListView](controls/PullToRefreshListview.md) +## [RadialGauge](controls/RadialGauge.md) +## [RadialProgressBar](controls/RadialProgressBar.md) +## [RangeSelector](controls/RangeSelector.md) +## [RotatorTile](controls/RotatorTile.md) +## [ScrollHeader](controls/ScrollHeader.md) +## [SlidableListItem](controls/SlidableListItem.md) +## [StaggeredPanel](controls/StaggeredPanel.md) +## [TextToolbar](controls/TextToolbar.md) +## [TileControl](controls/TileControl.md) +## [UniformGrid](controls/UniformGrid.md) +## [WebView (win32)](controls/WebView.md) +## [WrapPanel](controls/WrapPanel.md) + # Animations ## [AnimationSet](animations/AnimationSet.md) ## [Blur](animations/Blur.md) @@ -31,51 +73,21 @@ ## [ImageBlendBrush](brushes/ImageBlendBrush.md) ## [RadialGradientBrush](brushes/RadialGradientBrush.md) -# Controls -## [AdaptiveGridView](controls/AdaptiveGridView.md) -## [Blade](controls/BladeView.md) -## [Carousel](controls/Carousel.md) -## [DataGrid](controls/DataGrid.md) -## [DockPanel](controls/DockPanel.md) -## [DropShadowPanel Control](controls/DropShadowPanel.md) -## [Expander Control](controls/Expander.md) -## [GridSplitter](controls/GridSplitter.md) -## [HamburgerMenu](controls/HamburgerMenu.md) -## [HeaderedContentControl](controls/HeaderedContentControl.md) -## [HeaderedItemsControl](controls/HeaderedItemsControl.md) -## [HeaderedTextBlock](controls/HeaderedTextBlock.md) -## [ImageEx](controls/ImageEx.md) -## [InAppNotification](controls/InAppNotification.md) -## [Loading](controls/Loading.md) -## [MarkdownTextBlock](controls/MarkdownTextBlock.md) -## [MasterDetailsView](controls/MasterDetailsView.md) -## [Menu Control](controls/Menu.md) -## [OrbitView](controls/OrbitView.md) -## [PullToRefreshListView](controls/PullToRefreshListview.md) -## [RadialGauge](controls/RadialGauge.md) -## [RadialProgressBar](controls/RadialProgressBar.md) -## [RangeSelector](controls/RangeSelector.md) -## [RotatorTile](controls/RotatorTile.md) -## [ScrollHeader](controls/ScrollHeader.md) -## [SlidableListItem](controls/SlidableListItem.md) -## [StaggeredPanel](controls/StaggeredPanel.md) -## [TextToolbar](controls/TextToolbar.md) -## [TileControl](controls/TileControl.md) -## [WrapPanel](controls/WrapPanel.md) - -# Developer tools -## [AlignmentGrid](developer-tools/AlignmentGrid.md) -## [FocusTracker](developer-tools/FocusTracker.md) - # Extensions +## [ArrayExtensions](extensions/ArrayExtensions.md) ## [Composition Visual Layer Extensions](extensions/VisualExtensions.md) ## [FrameworkElementExtensions](extensions/FrameworkElementExtensions.md) ## [HyperlinkExtensions](extensions/HyperlinkExtensions.md) ## [ListViewExtensions](extensions/ListViewExtensions.md) ## [Logical Tree](extensions/LogicalTree.md) +## [Matrix Extensions](extensions/MatrixExtensions.md) +### [Extra Matrix Helpers](extensions/MatrixHelperEx.md) +### [Transform Extensions](extensions/TransformExtensions.md) ## [Mouse Cursor](extensions/MouseCursor.md) ## [NavigationView Styles](extensions/NavigationView.md) +## [NullableBoolMarkup](extensions/NullableBoolMarkup.md) ## [ScrollViewerExtensions](extensions/ScrollViewerExtensions.md) +## [StringExtensions](extensions/StringExtensions.md) ## [SurfaceDialTextboxHelper](extensions/SurfaceDialTextboxHelper.md) ## [TextBoxMask](extensions/TextBoxMask.md) ## [TextBoxRegex](extensions/TextBoxRegex.md) @@ -88,6 +100,7 @@ ## [BackgroundTaskHelper](helpers/BackgroundTaskHelper.md) ## [BindableValueHolder](helpers/BindableValueHolder.md) ## [BluetoothLEHelper](helpers/BluetoothLEHelper.md) +## [CameraHelper](helpers/CameraHelper.md) ## [Colors](helpers/Colors.md) ## [Converters](helpers/Converters.md) ## [DeepLinkParser](helpers/DeepLinkParsers.md) @@ -106,20 +119,28 @@ ## [ThemeListener](helpers/ThemeListener.md) ## [WeakEventListener](helpers/WeakEventListener.md) -# Notifications -## [Notifications Overview](notifications/NotificationsOverview.md) - -# Parsers -## [MarkdownParser](parsers/MarkdownParser.md) -## [RSSParser](parsers/RSSParser.md) - # Services ## [Bing Service](services/Bing.md) ## [Facebook Service](services/Facebook.md) ## [LinkedIn Service](services/Linkedin.md) ## [Microsoft Graph Service](services/MicrosoftGraph.md) +### [GraphLogin (WinForms)](services/GraphLogin.md) ## [Microsoft Translator Service](services/MicrosoftTranslator.md) ## [OneDrive Service](services/OneDrive.md) ## [Twitter Service](services/Twitter.md) -# [Known Issues](knownissues.md) \ No newline at end of file +# Parsers +## [MarkdownParser](parsers/MarkdownParser.md) +## [RSSParser](parsers/RSSParser.md) + +# Developer tools +## [AlignmentGrid](developer-tools/AlignmentGrid.md) +## [FocusTracker](developer-tools/FocusTracker.md) + +# [GazeInteractionLibrary](gaze/GazeInteractionLibrary.md) + +# [Notifications](notifications/NotificationsOverview.md) + +# [Platform Specific Analyzer](platform-specific/PlatformSpecificAnalyzer.md) + +# [Known Issues](knownissues.md) diff --git a/global.json b/global.json new file mode 100644 index 000000000..838ecd774 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "MSBuild.Sdk.Extras": "1.4.0" + } +} \ No newline at end of file diff --git a/license.md b/license.md index ce7252d16..0dec51757 100644 --- a/license.md +++ b/license.md @@ -4,7 +4,7 @@ Copyright (c) .NET Foundation and Contributors All rights reserved. -# MIT License +# MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/readme.md b/readme.md index cb0d03949..d063a887c 100644 --- a/readme.md +++ b/readme.md @@ -6,8 +6,9 @@ The Windows Community Toolkit is a collection of helper functions, custom contro ## Build status | Target | Branch | Status | Recommended Nuget packages version | | ------ | ------ | ------ | ------ | -| Production | rel/2.2.0 | [![Build status](https://ci.appveyor.com/api/projects/status/o60lv2tt1nbtklw8/branch/rel/2.2.0?svg=true)](https://ci.appveyor.com/project/dotnetfoundation/uwpcommunitytoolkit/branch/rel/2.2.0) | [![NuGet](https://img.shields.io/nuget/v/Microsoft.Toolkit.Uwp.svg)](https://www.nuget.org/packages/Microsoft.Toolkit.Uwp/) | -| Pre-release beta testing | master | [![Build status](https://ci.appveyor.com/api/projects/status/o60lv2tt1nbtklw8/branch/master?svg=true)](https://ci.appveyor.com/project/dotnetfoundation/uwpcommunitytoolkit/branch/master) | [![MyGet](https://img.shields.io/dotnet.myget/uwpcommunitytoolkit/vpre/Microsoft.Toolkit.Uwp.svg)](https://dotnet.myget.org/gallery/uwpcommunitytoolkit) | +| Pre-release beta testing | master | [![Build status](https://dotnetfoundation.visualstudio.com/_apis/public/build/definitions/696bc9fd-f160-4e97-a1bd-7cbbb3b58f66/10/badge)](https://dotnetfoundation.visualstudio.com/696bc9fd-f160-4e97-a1bd-7cbbb3b58f66/_build/index?definitionId=10) | [![MyGet](https://img.shields.io/dotnet.myget/uwpcommunitytoolkit/vpre/Microsoft.Toolkit.Uwp.svg)](https://dotnet.myget.org/gallery/uwpcommunitytoolkit) | + + ## Getting started Please read the [getting Started with the Windows Community Toolkit](https://docs.microsoft.com/windows/uwpcommunitytoolkit/getting-started) page for more detailed information about using the toolkit. @@ -42,9 +43,9 @@ Once you search you should see a list similar to the one below (versions may be | Microsoft.Toolkit.Uwp.DeveloperTools | XAML user controls and services to help developer building their app | ## Supported SDKs -* Anniversary Update (14393) * Creators Update (15063) * Fall Creators Update (16299) +* April 2018 Update (17134) ## Features @@ -66,13 +67,13 @@ Once you search you should see a list similar to the one below (versions may be * [Scale](https://docs.microsoft.com/windows/uwpcommunitytoolkit/animations/Scale/) ### Brushes -* [BackdropBlurBrush](http://docs.uwpcommunitytoolkit.com/en/master/brushes/BackdropBlurBrush/) -* [BackdropGammaTransferBrush](http://docs.uwpcommunitytoolkit.com/en/master/brushes/BackdropGammaTransferBrush/) -* [BackdropInvertBrush](http://docs.uwpcommunitytoolkit.com/en/master/brushes/BackdropInvertBrush/) -* [BackdropSaturationBrush](http://docs.uwpcommunitytoolkit.com/en/master/brushes/BackdropSaturationBrush/) -* [BackdropSepiaBrush](http://docs.uwpcommunitytoolkit.com/en/master/brushes/BackdropSepiaBrush/) -* [ImageBlendBrush](http://docs.uwpcommunitytoolkit.com/en/master/brushes/ImageBlendBrush/) -* [RadialGradientBrush](http://docs.uwpcommunitytoolkit.com/en/master/brushes/RadialGradientBrush/) +* [BackdropBlurBrush](https://docs.microsoft.com/windows/uwpcommunitytoolkit/brushes/BackdropBlurBrush/) +* [BackdropGammaTransferBrush](https://docs.microsoft.com/windows/uwpcommunitytoolkit/brushes/BackdropGammaTransferBrush/) +* [BackdropInvertBrush](https://docs.microsoft.com/windows/uwpcommunitytoolkit/brushes/BackdropInvertBrush/) +* [BackdropSaturationBrush](https://docs.microsoft.com/windows/uwpcommunitytoolkit/brushes/BackdropSaturationBrush/) +* [BackdropSepiaBrush](https://docs.microsoft.com/windows/uwpcommunitytoolkit/brushes/BackdropSepiaBrush/) +* [ImageBlendBrush](https://docs.microsoft.com/windows/uwpcommunitytoolkit/brushes/ImageBlendBrush/) +* [RadialGradientBrush](https://docs.microsoft.com/windows/uwpcommunitytoolkit/brushes/RadialGradientBrush/) ### Controls * [AdaptiveGridView](https://docs.microsoft.com/windows/uwpcommunitytoolkit/controls/AdaptiveGridView/) @@ -89,6 +90,7 @@ Once you search you should see a list similar to the one below (versions may be * [HeaderedTextBlock](https://docs.microsoft.com/windows/uwpcommunitytoolkit/controls/HeaderedTextBlock/) * [ImageEx](https://docs.microsoft.com/windows/uwpcommunitytoolkit/controls/ImageEx/) * [InAppNotification](https://docs.microsoft.com/windows/uwpcommunitytoolkit/controls/InAppNotification/) +* [InfiniteCanvas](https://docs.microsoft.com/windows/uwpcommunitytoolkit/controls/InfiniteCanvas/) * [Loading](https://docs.microsoft.com/windows/uwpcommunitytoolkit/controls/Loading/) * [MarkdownTextBlock](https://docs.microsoft.com/windows/uwpcommunitytoolkit/controls/MarkdownTextBlock/) * [MasterDetailsView](https://docs.microsoft.com/windows/uwpcommunitytoolkit/controls/MasterDetailsView/) @@ -116,7 +118,7 @@ Once you search you should see a list similar to the one below (versions may be * [ListViewExtensions](https://docs.microsoft.com/windows/uwpcommunitytoolkit/extensions/ListViewBase/) * [LogicalTree](https://docs.microsoft.com/windows/uwpcommunitytoolkit/extensions/LogicalTree/) * [MouseCursor](https://docs.microsoft.com/windows/uwpcommunitytoolkit/extensions/MouseCursor/) -* [NavigationView Styles](https://docs.uwpcommunitytoolkit.com/windows/uwpcommunitytoolkit/extensions/NavigationView/) +* [NavigationView Styles](https://docs.microsoft.com/windows/uwpcommunitytoolkit/extensions/NavigationView/) * [ScrollViewerExtensions](https://docs.microsoft.com/windows/uwpcommunitytoolkit/extensions/ScrollViewerExtensions/) * [SurfaceDialTextbox](https://docs.microsoft.com/windows/uwpcommunitytoolkit/extensions/SurfaceDialTextboxHelper/) * [TextBoxMask](https://docs.microsoft.com/windows/uwpcommunitytoolkit/extensions/TextBoxMask/) diff --git a/version.json b/version.json index 136c2736f..a91f60bb0 100644 --- a/version.json +++ b/version.json @@ -1,5 +1,5 @@ { - "version": "3.0.0-build.{height}", + "version": "3.1.0-build.{height}", "publicReleaseRefSpec": [ "^refs/heads/master$", // we release out of master "^refs/heads/dev$", // we release out of dev @@ -10,7 +10,7 @@ }, "cloudBuild": { "buildNumber": { - "enabled": true + "enabled": false } } }