diff --git a/Samples/FocusVisuals/cs-winui/App.xaml b/Samples/FocusVisuals/cs-winui/App.xaml
new file mode 100644
index 000000000..da5ae2e4e
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/App.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/FocusVisuals/cs-winui/App.xaml.cs b/Samples/FocusVisuals/cs-winui/App.xaml.cs
new file mode 100644
index 000000000..47d4c2d12
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/App.xaml.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml;
+
+namespace FocusVisualsSample;
+
+public partial class App : Application
+{
+ public App()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
+ {
+ var window = new MainWindow();
+ window.Activate();
+ }
+}
diff --git a/Samples/FocusVisuals/cs-winui/Assets/AppIcon.ico b/Samples/FocusVisuals/cs-winui/Assets/AppIcon.ico
new file mode 100644
index 000000000..235dad2c5
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/AppIcon.ico differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/LockScreenLogo.scale-200.png b/Samples/FocusVisuals/cs-winui/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 000000000..33f889e10
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/LockScreenLogo.scale-200.png differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/SplashScreen.scale-200.png b/Samples/FocusVisuals/cs-winui/Assets/SplashScreen.scale-200.png
new file mode 100644
index 000000000..802c79d6d
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/SplashScreen.scale-200.png differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/Square150x150Logo.scale-200.png b/Samples/FocusVisuals/cs-winui/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 000000000..ddba42adb
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/Square150x150Logo.scale-200.png differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.scale-200.png b/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 000000000..9327dd748
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.scale-200.png differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 000000000..e51416a8e
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png b/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png
new file mode 100644
index 000000000..bf063eb4d
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/StoreLogo.png b/Samples/FocusVisuals/cs-winui/Assets/StoreLogo.png
new file mode 100644
index 000000000..be865f0c3
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/StoreLogo.png differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/Wide310x150Logo.scale-200.png b/Samples/FocusVisuals/cs-winui/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 000000000..314d297f2
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/Samples/FocusVisuals/cs-winui/Assets/yammer_share.png b/Samples/FocusVisuals/cs-winui/Assets/yammer_share.png
new file mode 100644
index 000000000..cb68ef0f5
Binary files /dev/null and b/Samples/FocusVisuals/cs-winui/Assets/yammer_share.png differ
diff --git a/Samples/FocusVisuals/cs-winui/FocusVisualsSample.csproj b/Samples/FocusVisuals/cs-winui/FocusVisualsSample.csproj
new file mode 100644
index 000000000..266fa2488
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/FocusVisualsSample.csproj
@@ -0,0 +1,42 @@
+
+
+ WinExe
+ net9.0-windows10.0.19041.0
+ 10.0.17763.0
+ FocusVisualsSample
+ app.manifest
+ x86;x64;ARM64
+ win-x86;win-x64;win-arm64
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/FocusVisuals/cs-winui/FocusVisualsSample.sln b/Samples/FocusVisuals/cs-winui/FocusVisualsSample.sln
new file mode 100644
index 000000000..d21ef8b49
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/FocusVisualsSample.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FocusVisualsSample", "FocusVisualsSample.csproj", "{BCDC1789-5958-4152-87F6-3BED4C6E4B2F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|Any CPU.Build.0 = Debug|x86
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|ARM64.Build.0 = Debug|ARM64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|x64.ActiveCfg = Debug|x64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|x64.Build.0 = Debug|x64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|x64.Deploy.0 = Debug|x64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|x86.ActiveCfg = Debug|x86
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Debug|x86.Build.0 = Debug|x86
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|Any CPU.ActiveCfg = Release|x86
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|Any CPU.Build.0 = Release|x86
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|ARM64.ActiveCfg = Release|ARM64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|ARM64.Build.0 = Release|ARM64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|ARM64.Deploy.0 = Release|ARM64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|x64.ActiveCfg = Release|x64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|x64.Build.0 = Release|x64
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|x86.ActiveCfg = Release|x86
+ {BCDC1789-5958-4152-87F6-3BED4C6E4B2F}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/FocusVisuals/cs-winui/MainWindow.xaml b/Samples/FocusVisuals/cs-winui/MainWindow.xaml
new file mode 100644
index 000000000..bd894f255
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/MainWindow.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/FocusVisuals/cs-winui/MainWindow.xaml.cs b/Samples/FocusVisuals/cs-winui/MainWindow.xaml.cs
new file mode 100644
index 000000000..1d619f6d3
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/MainWindow.xaml.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using FocusVisualsSample.Scenarios;
+
+namespace FocusVisualsSample;
+
+public sealed partial class MainWindow : Window
+{
+ public MainWindow()
+ {
+ InitializeComponent();
+
+ ExtendsContentIntoTitleBar = true;
+ SetTitleBar(AppTitleBar);
+
+ AppWindow.SetIcon("Assets/AppIcon.ico");
+
+ // Select the first navigation item on startup.
+ NavView.SelectedItem = NavView.MenuItems[0];
+ }
+
+ private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
+ {
+ if (args.SelectedItem is NavigationViewItem item)
+ {
+ var tag = item.Tag?.ToString();
+ switch (tag)
+ {
+ case "CustomFocusVisuals":
+ ContentFrame.Navigate(typeof(CustomFocusVisualsPage));
+ break;
+ case "CustomControlUsage":
+ ContentFrame.Navigate(typeof(CustomControlUsagePage));
+ break;
+ }
+ }
+ }
+}
diff --git a/Samples/FocusVisuals/cs-winui/Package.appxmanifest b/Samples/FocusVisuals/cs-winui/Package.appxmanifest
new file mode 100644
index 000000000..0688e3747
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/Package.appxmanifest
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ FocusVisualsSample
+ AppPublisher
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/FocusVisuals/cs-winui/Properties/launchSettings.json b/Samples/FocusVisuals/cs-winui/Properties/launchSettings.json
new file mode 100644
index 000000000..ff7687954
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+ "profiles": {
+ "FocusVisualsSample (Package)": {
+ "commandName": "MsixPackage"
+ },
+ "FocusVisualsSample (Unpackaged)": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Samples/FocusVisuals/cs-winui/Scenarios/CustomControlUsagePage.xaml b/Samples/FocusVisuals/cs-winui/Scenarios/CustomControlUsagePage.xaml
new file mode 100644
index 000000000..b7633cb07
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/Scenarios/CustomControlUsagePage.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+ The same focus visuals used for in-box controls can be applied to custom controls as well.
+ Simply set Control.UseSystemFocusVisuals to True, and it will draw the focus visuals around the bounds of your control.
+ If you need to specify a specific template part to be the bounds of the focus visual, use the attached property Control.IsTemplateFocusTarget and set it to true.
+
+
+
+
+
+
diff --git a/Samples/FocusVisuals/cs-winui/Scenarios/CustomControlUsagePage.xaml.cs b/Samples/FocusVisuals/cs-winui/Scenarios/CustomControlUsagePage.xaml.cs
new file mode 100644
index 000000000..06bfe365a
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/Scenarios/CustomControlUsagePage.xaml.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml.Controls;
+
+namespace FocusVisualsSample.Scenarios;
+
+public sealed partial class CustomControlUsagePage : Page
+{
+ public CustomControlUsagePage()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/Samples/FocusVisuals/cs-winui/Scenarios/CustomFocusVisualsPage.xaml b/Samples/FocusVisuals/cs-winui/Scenarios/CustomFocusVisualsPage.xaml
new file mode 100644
index 000000000..33e95e116
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/Scenarios/CustomFocusVisualsPage.xaml
@@ -0,0 +1,243 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ With Windows 10, the system now draws the focus visuals for all of the inbox controls, and can be used for custom controls as well.
+ In this example, we will show you how to customize the focus visuals, if the 1px black and white border does not suit your needs.
+ Look in the Page.Resources of this page to see the source for this sample.
+ The 3 steps you need to define your own focus visuals for any inbox control are:
+ 1) Re-template the control and add in your desired visual (here we've added a red rectangle)
+ 2) Add back the FocusStates VisualStateGroup (see the control template code for the proper state names)
+ 3) Set Control.UseSystemFocusVisuals to False
+
+
+
+
+
+
diff --git a/Samples/FocusVisuals/cs-winui/Scenarios/CustomFocusVisualsPage.xaml.cs b/Samples/FocusVisuals/cs-winui/Scenarios/CustomFocusVisualsPage.xaml.cs
new file mode 100644
index 000000000..1b7704ad1
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/Scenarios/CustomFocusVisualsPage.xaml.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml.Controls;
+
+namespace FocusVisualsSample.Scenarios;
+
+public sealed partial class CustomFocusVisualsPage : Page
+{
+ public CustomFocusVisualsPage()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/Samples/FocusVisuals/cs-winui/SocialMediaCounter.cs b/Samples/FocusVisuals/cs-winui/SocialMediaCounter.cs
new file mode 100644
index 000000000..59cdff350
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/SocialMediaCounter.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Media;
+
+namespace FocusVisualsSample;
+
+public sealed class SocialMediaCounter : HyperlinkButton
+{
+ public static readonly DependencyProperty ShareImageProperty =
+ DependencyProperty.Register(nameof(ShareImage), typeof(ImageSource), typeof(SocialMediaCounter), new PropertyMetadata(null));
+
+ public ImageSource ShareImage
+ {
+ get => (ImageSource)GetValue(ShareImageProperty);
+ set => SetValue(ShareImageProperty, value);
+ }
+
+ public static readonly DependencyProperty NumOfSharesProperty =
+ DependencyProperty.Register(nameof(NumOfShares), typeof(int), typeof(SocialMediaCounter), new PropertyMetadata(0));
+
+ public int NumOfShares
+ {
+ get => (int)GetValue(NumOfSharesProperty);
+ set => SetValue(NumOfSharesProperty, value);
+ }
+
+ public SocialMediaCounter()
+ {
+ DefaultStyleKey = typeof(SocialMediaCounter);
+ }
+}
diff --git a/Samples/FocusVisuals/cs-winui/Themes/Generic.xaml b/Samples/FocusVisuals/cs-winui/Themes/Generic.xaml
new file mode 100644
index 000000000..cc929214b
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/Themes/Generic.xaml
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/Samples/FocusVisuals/cs-winui/app.manifest b/Samples/FocusVisuals/cs-winui/app.manifest
new file mode 100644
index 000000000..0922bf544
--- /dev/null
+++ b/Samples/FocusVisuals/cs-winui/app.manifest
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+
+
+
\ No newline at end of file
diff --git a/Samples/TouchKeyboard/cs-winui/App.xaml b/Samples/TouchKeyboard/cs-winui/App.xaml
new file mode 100644
index 000000000..0cf584a01
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/App.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/TouchKeyboard/cs-winui/App.xaml.cs b/Samples/TouchKeyboard/cs-winui/App.xaml.cs
new file mode 100644
index 000000000..551ccb65b
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/App.xaml.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml;
+
+namespace TouchKeyboard;
+
+public partial class App : Application
+{
+ private Window _window;
+
+ public App()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnLaunched(LaunchActivatedEventArgs args)
+ {
+ _window = new MainWindow();
+ _window.Activate();
+ }
+}
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/AppIcon.ico b/Samples/TouchKeyboard/cs-winui/Assets/AppIcon.ico
new file mode 100644
index 000000000..235dad2c5
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/AppIcon.ico differ
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/LockScreenLogo.scale-200.png b/Samples/TouchKeyboard/cs-winui/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 000000000..33f889e10
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/LockScreenLogo.scale-200.png differ
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/SplashScreen.scale-200.png b/Samples/TouchKeyboard/cs-winui/Assets/SplashScreen.scale-200.png
new file mode 100644
index 000000000..802c79d6d
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/SplashScreen.scale-200.png differ
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/Square150x150Logo.scale-200.png b/Samples/TouchKeyboard/cs-winui/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 000000000..ddba42adb
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/Square150x150Logo.scale-200.png differ
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.scale-200.png b/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 000000000..9327dd748
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.scale-200.png differ
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 000000000..e51416a8e
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png b/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png
new file mode 100644
index 000000000..bf063eb4d
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png differ
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/StoreLogo.png b/Samples/TouchKeyboard/cs-winui/Assets/StoreLogo.png
new file mode 100644
index 000000000..be865f0c3
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/StoreLogo.png differ
diff --git a/Samples/TouchKeyboard/cs-winui/Assets/Wide310x150Logo.scale-200.png b/Samples/TouchKeyboard/cs-winui/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 000000000..314d297f2
Binary files /dev/null and b/Samples/TouchKeyboard/cs-winui/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/Samples/TouchKeyboard/cs-winui/CustomTextBox.cs b/Samples/TouchKeyboard/cs-winui/CustomTextBox.cs
new file mode 100644
index 000000000..80f8b88fb
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/CustomTextBox.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Media;
+
+namespace TouchKeyboard;
+
+///
+/// Custom TextBox control derived from TextBox class.
+///
+public class CustomTextBox : TextBox
+{
+ public CustomTextBox()
+ {
+ FontFamily = new FontFamily("Times New Roman");
+ FontStyle = Windows.UI.Text.FontStyle.Italic;
+ BorderThickness = new Thickness(1);
+ }
+}
diff --git a/Samples/TouchKeyboard/cs-winui/MainWindow.xaml b/Samples/TouchKeyboard/cs-winui/MainWindow.xaml
new file mode 100644
index 000000000..6dfcd31c7
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/MainWindow.xaml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/TouchKeyboard/cs-winui/MainWindow.xaml.cs b/Samples/TouchKeyboard/cs-winui/MainWindow.xaml.cs
new file mode 100644
index 000000000..2e9db08d9
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/MainWindow.xaml.cs
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace TouchKeyboard;
+
+public sealed partial class MainWindow : Window
+{
+ public static new MainWindow Current { get; private set; }
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ Current = this;
+
+ ExtendsContentIntoTitleBar = true;
+ SetTitleBar(AppTitleBar);
+ AppWindow.SetIcon("Assets/AppIcon.ico");
+
+ NavView.SelectedItem = NavView.MenuItems[0];
+ }
+
+ private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
+ {
+ if (args.SelectedItem is NavigationViewItem item)
+ {
+ var tag = item.Tag?.ToString();
+ switch (tag)
+ {
+ case "Scenario1":
+ ContentFrame.Navigate(typeof(Scenario1_Launch));
+ break;
+ case "Scenario2":
+ ContentFrame.Navigate(typeof(Scenario2_ShowHideEvents));
+ break;
+ case "Scenario3":
+ ContentFrame.Navigate(typeof(Scenario3_ShowHideMethods));
+ break;
+ case "Scenario4":
+ ContentFrame.Navigate(typeof(Scenario4_ShowView));
+ break;
+ }
+ }
+
+ StatusInfoBar.IsOpen = false;
+ }
+
+ public void NotifyUser(string message, InfoBarSeverity severity)
+ {
+ DispatcherQueue.TryEnqueue(() =>
+ {
+ StatusInfoBar.Message = message;
+ StatusInfoBar.Severity = severity;
+ StatusInfoBar.IsOpen = !string.IsNullOrEmpty(message);
+ });
+ }
+}
diff --git a/Samples/TouchKeyboard/cs-winui/Package.appxmanifest b/Samples/TouchKeyboard/cs-winui/Package.appxmanifest
new file mode 100644
index 000000000..660e9b702
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Package.appxmanifest
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ TouchKeyboard
+ AppPublisher
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/TouchKeyboard/cs-winui/Properties/launchSettings.json b/Samples/TouchKeyboard/cs-winui/Properties/launchSettings.json
new file mode 100644
index 000000000..4f258d3a3
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+ "profiles": {
+ "TouchKeyboard (Unpackaged)": {
+ "commandName": "Project"
+ },
+ "TouchKeyboard (Package)": {
+ "commandName": "MsixPackage"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Samples/TouchKeyboard/cs-winui/Scenario1_Launch.xaml b/Samples/TouchKeyboard/cs-winui/Scenario1_Launch.xaml
new file mode 100644
index 000000000..3e9cfaac0
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Scenario1_Launch.xaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+ The touch keyboard displays
+ when touch or pen is used to set focus on a XAML text control
+ (such as TextBox, RichTextBox, and PasswordBox)
+ or a control derived from a XAML text control,
+ subject to the note below.
+
+
+
+
+
+
+ The keyboard hides when you tap the button.
+
+
+
+
+
+
+ The touch keyboard displays automatically when
+ 1. A hardware keyboard is not active, and
+ 2. Either of the following is true:
+
+
+ 2a. Tablet mode is turned on, or
+ 2b. "Show the touch keyboard when not in tablet mode
+ and there's no keyboard attached" is enabled in
+ Settings → Devices → Typing.
+
+
+
+
diff --git a/Samples/TouchKeyboard/cs-winui/Scenario1_Launch.xaml.cs b/Samples/TouchKeyboard/cs-winui/Scenario1_Launch.xaml.cs
new file mode 100644
index 000000000..ccd5dd3b6
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Scenario1_Launch.xaml.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml.Controls;
+
+namespace TouchKeyboard;
+
+public sealed partial class Scenario1_Launch : Page
+{
+ public Scenario1_Launch()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/Samples/TouchKeyboard/cs-winui/Scenario2_ShowHideEvents.xaml b/Samples/TouchKeyboard/cs-winui/Scenario2_ShowHideEvents.xaml
new file mode 100644
index 000000000..9c9617e9a
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Scenario2_ShowHideEvents.xaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+ The Showing and Hiding events are raised when the touch keyboard is shown or hidden.
+
+
+
+ Last event:
+
+
+
+
+
+
+
+ See the note in scenario 1 for the rules regarding the touch keyboard.
+
+
+
+
diff --git a/Samples/TouchKeyboard/cs-winui/Scenario2_ShowHideEvents.xaml.cs b/Samples/TouchKeyboard/cs-winui/Scenario2_ShowHideEvents.xaml.cs
new file mode 100644
index 000000000..f85664709
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Scenario2_ShowHideEvents.xaml.cs
@@ -0,0 +1,66 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Navigation;
+using Windows.UI.ViewManagement;
+
+namespace TouchKeyboard;
+
+///
+/// Sample page to subscribe show/hide event of Touch Keyboard.
+///
+public sealed partial class Scenario2_ShowHideEvents : Page
+{
+ private InputPane _inputPane;
+
+ public Scenario2_ShowHideEvents()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ base.OnNavigatedTo(e);
+
+ var window = MainWindow.Current;
+ if (window is null)
+ {
+ return;
+ }
+
+ var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
+ _inputPane = InputPaneInterop.GetForWindow(hwnd);
+
+ _inputPane.Showing += OnShowing;
+ _inputPane.Hiding += OnHiding;
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ if (_inputPane is not null)
+ {
+ _inputPane.Showing -= OnShowing;
+ _inputPane.Hiding -= OnHiding;
+ _inputPane = null;
+ }
+
+ base.OnNavigatedFrom(e);
+ }
+
+ private void OnShowing(InputPane sender, InputPaneVisibilityEventArgs e)
+ {
+ DispatcherQueue.TryEnqueue(() =>
+ {
+ LastInputPaneEventRun.Text = "Showing";
+ });
+ }
+
+ private void OnHiding(InputPane sender, InputPaneVisibilityEventArgs e)
+ {
+ DispatcherQueue.TryEnqueue(() =>
+ {
+ LastInputPaneEventRun.Text = "Hiding";
+ });
+ }
+}
diff --git a/Samples/TouchKeyboard/cs-winui/Scenario3_ShowHideMethods.xaml b/Samples/TouchKeyboard/cs-winui/Scenario3_ShowHideMethods.xaml
new file mode 100644
index 000000000..b65883a34
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Scenario3_ShowHideMethods.xaml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This scenario hides the touch keyboard with TryHide() when you press Enter,
+ so that it won't cover the results below the text box.
+ When the results are cleared, it shows the touch keyboard again.
+
+
+ See the note in scenario 1 for the rules regarding the touch keyboard.
+
+
+
+
+
+
+
+
diff --git a/Samples/TouchKeyboard/cs-winui/Scenario3_ShowHideMethods.xaml.cs b/Samples/TouchKeyboard/cs-winui/Scenario3_ShowHideMethods.xaml.cs
new file mode 100644
index 000000000..45e5fc0cf
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Scenario3_ShowHideMethods.xaml.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Navigation;
+using Windows.UI.ViewManagement;
+
+namespace TouchKeyboard;
+
+///
+/// Sample page to call TryShow/TryHide methods.
+///
+public sealed partial class Scenario3_ShowHideMethods : Page
+{
+ private InputPane _inputPane;
+
+ public Scenario3_ShowHideMethods()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ base.OnNavigatedTo(e);
+
+ var window = MainWindow.Current;
+ if (window is null)
+ {
+ return;
+ }
+
+ var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
+ _inputPane = InputPaneInterop.GetForWindow(hwnd);
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ FadeOutResults.Stop();
+ _inputPane = null;
+ base.OnNavigatedFrom(e);
+ }
+
+ private void WordListBox_OnKeyUp(object sender, KeyRoutedEventArgs e)
+ {
+ if (e.Key == Windows.System.VirtualKey.Enter)
+ {
+ string text = WordListBox.Text;
+ if (text.Length > 0)
+ {
+ _inputPane?.TryHide();
+ ResultsTextBlock.Text = text;
+ FadeOutResults.Begin();
+ }
+ }
+ }
+
+ private void OnFadeOutCompleted(object sender, object e)
+ {
+ ResultsTextBlock.Text = "";
+ _inputPane?.TryShow();
+ }
+}
diff --git a/Samples/TouchKeyboard/cs-winui/Scenario4_ShowView.xaml b/Samples/TouchKeyboard/cs-winui/Scenario4_ShowView.xaml
new file mode 100644
index 000000000..dd0209f87
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Scenario4_ShowView.xaml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+ Showing a specific view.
+
+
+ This scenario shows the Emoji keyboard when the text box receives focus.
+
+
+
+
+
+
+
+
diff --git a/Samples/TouchKeyboard/cs-winui/Scenario4_ShowView.xaml.cs b/Samples/TouchKeyboard/cs-winui/Scenario4_ShowView.xaml.cs
new file mode 100644
index 000000000..3f32a85d6
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/Scenario4_ShowView.xaml.cs
@@ -0,0 +1,109 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Runtime.InteropServices;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Windows.UI.ViewManagement.Core;
+using WinRT.Interop;
+
+namespace TouchKeyboard;
+
+///
+/// Sample page to show the Emoji keyboard.
+///
+public sealed partial class Scenario4_ShowView : Page
+{
+ public Scenario4_ShowView()
+ {
+ InitializeComponent();
+ }
+
+ private void TextBox_GotFocus(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ var window = MainWindow.Current;
+ if (window is null) return;
+
+ var hwnd = WindowNative.GetWindowHandle(window);
+
+ var interopIid = new Guid("0576AB31-A310-4C40-B31F-CECDAE573C13");
+ var coreInputViewIid = typeof(CoreInputView).GUID;
+
+ // Create HString manually
+ const string runtimeClass = "Windows.UI.ViewManagement.Core.CoreInputView";
+ int hr = WindowsCreateString(runtimeClass, runtimeClass.Length, out var hstring);
+ if (hr != 0)
+ {
+ MainWindow.Current?.NotifyUser("Failed to create activation string.", InfoBarSeverity.Warning);
+ return;
+ }
+
+ try
+ {
+ hr = RoGetActivationFactory(hstring, ref interopIid, out var factoryPtr);
+ if (hr != 0 || factoryPtr == IntPtr.Zero)
+ {
+ MainWindow.Current?.NotifyUser("CoreInputView activation factory not available.", InfoBarSeverity.Warning);
+ return;
+ }
+
+ try
+ {
+ var interop = (ICoreInputViewInterop)Marshal.GetObjectForIUnknown(factoryPtr);
+ interop.GetForWindow(hwnd, ref coreInputViewIid, out var resultPtr);
+
+ if (resultPtr != IntPtr.Zero)
+ {
+ try
+ {
+ var coreInputView = (CoreInputView)Marshal.GetObjectForIUnknown(resultPtr);
+ coreInputView.TryShow(CoreInputViewKind.Emoji);
+ }
+ finally
+ {
+ Marshal.Release(resultPtr);
+ }
+ }
+ }
+ finally
+ {
+ Marshal.Release(factoryPtr);
+ }
+ }
+ finally
+ {
+ WindowsDeleteString(hstring);
+ }
+ }
+ catch (Exception ex)
+ {
+ MainWindow.Current?.NotifyUser($"Error showing emoji keyboard: {ex.Message}", InfoBarSeverity.Error);
+ }
+ }
+
+ [DllImport("combase.dll", PreserveSig = true)]
+ private static extern int RoGetActivationFactory(
+ IntPtr activatableClassId,
+ ref Guid iid,
+ out IntPtr factory);
+
+ [DllImport("combase.dll", PreserveSig = true)]
+ private static extern int WindowsCreateString(
+ [MarshalAs(UnmanagedType.LPWStr)] string sourceString,
+ int length,
+ out IntPtr hstring);
+
+ [DllImport("combase.dll", PreserveSig = true)]
+ private static extern int WindowsDeleteString(IntPtr hstring);
+
+ [ComImport]
+ [Guid("0576AB31-A310-4C40-B31F-CECDAE573C13")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ private interface ICoreInputViewInterop
+ {
+ void GetForWindow(nint appWindow, ref Guid riid, out IntPtr coreInputView);
+ }
+}
diff --git a/Samples/TouchKeyboard/cs-winui/TouchKeyboard.csproj b/Samples/TouchKeyboard/cs-winui/TouchKeyboard.csproj
new file mode 100644
index 000000000..dad3df801
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/TouchKeyboard.csproj
@@ -0,0 +1,39 @@
+
+
+ WinExe
+ net9.0-windows10.0.19041.0
+ 10.0.17763.0
+ TouchKeyboard
+ app.manifest
+ x86;x64;ARM64
+ win-x86;win-x64;win-arm64
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/TouchKeyboard/cs-winui/TouchKeyboard.sln b/Samples/TouchKeyboard/cs-winui/TouchKeyboard.sln
new file mode 100644
index 000000000..da66a8976
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/TouchKeyboard.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchKeyboard", "TouchKeyboard.csproj", "{07D524E6-9222-4904-A9CE-52E831629ECD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|Any CPU.Build.0 = Debug|x86
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|ARM64.Build.0 = Debug|ARM64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|x64.ActiveCfg = Debug|x64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|x64.Build.0 = Debug|x64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|x64.Deploy.0 = Debug|x64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|x86.ActiveCfg = Debug|x86
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Debug|x86.Build.0 = Debug|x86
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|Any CPU.ActiveCfg = Release|x86
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|Any CPU.Build.0 = Release|x86
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|ARM64.ActiveCfg = Release|ARM64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|ARM64.Build.0 = Release|ARM64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|ARM64.Deploy.0 = Release|ARM64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|x64.ActiveCfg = Release|x64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|x64.Build.0 = Release|x64
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|x86.ActiveCfg = Release|x86
+ {07D524E6-9222-4904-A9CE-52E831629ECD}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/TouchKeyboard/cs-winui/app.manifest b/Samples/TouchKeyboard/cs-winui/app.manifest
new file mode 100644
index 000000000..83d8c0ba2
--- /dev/null
+++ b/Samples/TouchKeyboard/cs-winui/app.manifest
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+
+
+
\ No newline at end of file