diff --git a/README.md b/README.md
index 822ede9c4..5a5fd35ff 100644
--- a/README.md
+++ b/README.md
@@ -225,10 +225,11 @@ For additional Windows samples, see [Windows on GitHub](http://microsoft.github.
diff --git a/Samples/BasicInput/README.md b/Samples/BasicInput/README.md
index ddf14fb13..6ba485223 100644
--- a/Samples/BasicInput/README.md
+++ b/Samples/BasicInput/README.md
@@ -51,6 +51,11 @@ To obtain information about Microsoft Visual Studio and the tools for developing
## Related topics
+### Samples
+
+* [ComplexInk](/Samples/ComplexInk)
+* [Pen haptics](/Samples/PenHaptics)
+
### Reference
[PointerPoint](https://msdn.microsoft.com/library/windows/apps/windows.ui.input.pointerpoint.aspx)
diff --git a/Samples/ComplexInk/README.md b/Samples/ComplexInk/README.md
index e36db9777..f72ea65a4 100644
--- a/Samples/ComplexInk/README.md
+++ b/Samples/ComplexInk/README.md
@@ -56,11 +56,14 @@ To obtain information about Windows 10 development, go to the [Windows Dev Cente
To obtain information about Microsoft Visual Studio and the tools for developing Windows apps, go to [Visual Studio](http://go.microsoft.com/fwlink/?LinkID=532422)
## Related topics
---------------
[Getting started with apps](http://msdn.microsoft.com/library/windows/apps/)
-## Reference
+### Samples
+
+[Pen haptics](/Samples/PenHaptics)
+
+### Reference
[Windows.UI.Input.Inking](http://msdn.microsoft.com/library/windows/apps/br208524)
diff --git a/Samples/Geolocation/cppwinrt/Geolocation.vcxproj b/Samples/Geolocation/cppwinrt/Geolocation.vcxproj
index 5f259f63c..d0be49bbf 100644
--- a/Samples/Geolocation/cppwinrt/Geolocation.vcxproj
+++ b/Samples/Geolocation/cppwinrt/Geolocation.vcxproj
@@ -14,7 +14,7 @@
trueWindows Store10.0
- 10.0.19041.0
+ 10.0.22000.0$(WindowsTargetPlatformVersion)
diff --git a/Samples/Geolocation/cppwinrt/Scenario1_TrackPosition.cpp b/Samples/Geolocation/cppwinrt/Scenario1_TrackPosition.cpp
index 50c7716aa..1952d3f4e 100644
--- a/Samples/Geolocation/cppwinrt/Scenario1_TrackPosition.cpp
+++ b/Samples/Geolocation/cppwinrt/Scenario1_TrackPosition.cpp
@@ -173,12 +173,14 @@ namespace winrt::SDKTemplate::implementation
ScenarioOutput_Latitude().Text(L"No data");
ScenarioOutput_Longitude().Text(L"No data");
ScenarioOutput_Accuracy().Text(L"No data");
+ ScenarioOutput_IsRemoteSource().Text(L"No data");
}
else
{
ScenarioOutput_Latitude().Text(to_hstring(position.Coordinate().Point().Position().Latitude));
ScenarioOutput_Longitude().Text(to_hstring(position.Coordinate().Point().Position().Longitude));
ScenarioOutput_Accuracy().Text(to_hstring(position.Coordinate().Accuracy()));
+ ScenarioOutput_IsRemoteSource().Text(to_hstring(position.Coordinate().IsRemoteSource()));
}
}
}
diff --git a/Samples/Geolocation/cppwinrt/Scenario2_GetPosition.cpp b/Samples/Geolocation/cppwinrt/Scenario2_GetPosition.cpp
index ff0fef887..b5cc3f369 100644
--- a/Samples/Geolocation/cppwinrt/Scenario2_GetPosition.cpp
+++ b/Samples/Geolocation/cppwinrt/Scenario2_GetPosition.cpp
@@ -118,6 +118,7 @@ namespace winrt::SDKTemplate::implementation
ScenarioOutput_Longitude().Text(L"No data");
ScenarioOutput_Accuracy().Text(L"No data");
ScenarioOutput_Source().Text(L"No data");
+ ScenarioOutput_IsRemoteSource().Text(L"No data");
ShowSatelliteData(false);
}
else
@@ -126,6 +127,7 @@ namespace winrt::SDKTemplate::implementation
ScenarioOutput_Longitude().Text(to_hstring(position.Coordinate().Point().Position().Longitude));
ScenarioOutput_Accuracy().Text(to_hstring(position.Coordinate().Accuracy()));
ScenarioOutput_Source().Text(to_hstring(position.Coordinate().PositionSource()));
+ ScenarioOutput_IsRemoteSource().Text(to_hstring(position.Coordinate().IsRemoteSource()));
if (position.Coordinate().PositionSource() == PositionSource::Satellite)
{
diff --git a/Samples/Geolocation/cppwinrt/Scenario6_GetLastVisit.cpp b/Samples/Geolocation/cppwinrt/Scenario6_GetLastVisit.cpp
index 183e3d836..2ffd9ec26 100644
--- a/Samples/Geolocation/cppwinrt/Scenario6_GetLastVisit.cpp
+++ b/Samples/Geolocation/cppwinrt/Scenario6_GetLastVisit.cpp
@@ -73,6 +73,7 @@ namespace winrt::SDKTemplate::implementation
ScenarioOutput_Accuracy().Text(L"No data");
ScenarioOutput_Timestamp().Text(L"No data");
ScenarioOutput_VisitStateChange().Text(L"No data");
+ ScenarioOutput_IsRemoteSource().Text(L"No data");
}
else
{
@@ -86,12 +87,14 @@ namespace winrt::SDKTemplate::implementation
ScenarioOutput_Latitude().Text(L"No data");
ScenarioOutput_Longitude().Text(L"No data");
ScenarioOutput_Accuracy().Text(L"No data");
+ ScenarioOutput_IsRemoteSource().Text(L"No data");
}
else
{
ScenarioOutput_Latitude().Text(to_hstring(visit.Position().Coordinate().Point().Position().Latitude));
ScenarioOutput_Longitude().Text(to_hstring(visit.Position().Coordinate().Point().Position().Longitude));
ScenarioOutput_Accuracy().Text(to_hstring(visit.Position().Coordinate().Accuracy()));
+ ScenarioOutput_IsRemoteSource().Text(to_hstring(visit.Position().Coordinate().IsRemoteSource()));
}
}
}
diff --git a/Samples/Geolocation/cppwinrt/Scenario7_ForegroundVisits.cpp b/Samples/Geolocation/cppwinrt/Scenario7_ForegroundVisits.cpp
index 9ab6ff0e4..6701ca870 100644
--- a/Samples/Geolocation/cppwinrt/Scenario7_ForegroundVisits.cpp
+++ b/Samples/Geolocation/cppwinrt/Scenario7_ForegroundVisits.cpp
@@ -117,12 +117,14 @@ namespace winrt::SDKTemplate::implementation
ScenarioOutput_Latitude().Text(L"No data");
ScenarioOutput_Longitude().Text(L"No data");
ScenarioOutput_Accuracy().Text(L"No data");
+ ScenarioOutput_IsRemoteSource().Text(L"No data");
}
else
{
ScenarioOutput_Latitude().Text(to_hstring(visit.Position().Coordinate().Point().Position().Latitude));
ScenarioOutput_Longitude().Text(to_hstring(visit.Position().Coordinate().Point().Position().Longitude));
ScenarioOutput_Accuracy().Text(to_hstring(visit.Position().Coordinate().Accuracy()));
+ ScenarioOutput_IsRemoteSource().Text(to_hstring(visit.Position().Coordinate().IsRemoteSource()));
}
}
diff --git a/Samples/Geolocation/cs/Geolocation.csproj b/Samples/Geolocation/cs/Geolocation.csproj
index 8759f826d..767f6dc16 100644
--- a/Samples/Geolocation/cs/Geolocation.csproj
+++ b/Samples/Geolocation/cs/Geolocation.csproj
@@ -14,8 +14,8 @@
Geolocationen-USUAP
- 10.0.19041.0
- 10.0.19041.0
+ 10.0.22000.0
+ $(TargetPlatformVersion)14true512
diff --git a/Samples/Geolocation/cs/Package.appxmanifest b/Samples/Geolocation/cs/Package.appxmanifest
index 3985381b4..097763c0a 100644
--- a/Samples/Geolocation/cs/Package.appxmanifest
+++ b/Samples/Geolocation/cs/Package.appxmanifest
@@ -8,7 +8,7 @@
Assets\StoreLogo-sdk.png
-
+
diff --git a/Samples/Geolocation/cs/Scenario1_TrackPosition.xaml.cs b/Samples/Geolocation/cs/Scenario1_TrackPosition.xaml.cs
index 26e5af79d..490f59ef6 100644
--- a/Samples/Geolocation/cs/Scenario1_TrackPosition.xaml.cs
+++ b/Samples/Geolocation/cs/Scenario1_TrackPosition.xaml.cs
@@ -197,12 +197,14 @@ private void UpdateLocationData(Geoposition position)
ScenarioOutput_Latitude.Text = "No data";
ScenarioOutput_Longitude.Text = "No data";
ScenarioOutput_Accuracy.Text = "No data";
+ ScenarioOutput_IsRemoteSource.Text = "No data";
}
else
{
ScenarioOutput_Latitude.Text = position.Coordinate.Point.Position.Latitude.ToString();
ScenarioOutput_Longitude.Text = position.Coordinate.Point.Position.Longitude.ToString();
ScenarioOutput_Accuracy.Text = position.Coordinate.Accuracy.ToString();
+ ScenarioOutput_IsRemoteSource.Text = position.Coordinate.IsRemoteSource.ToString();
}
}
}
diff --git a/Samples/Geolocation/cs/Scenario2_GetPosition.xaml.cs b/Samples/Geolocation/cs/Scenario2_GetPosition.xaml.cs
index 210e766c9..777ed7fb0 100644
--- a/Samples/Geolocation/cs/Scenario2_GetPosition.xaml.cs
+++ b/Samples/Geolocation/cs/Scenario2_GetPosition.xaml.cs
@@ -136,6 +136,7 @@ private void UpdateLocationData(Geoposition position)
ScenarioOutput_Longitude.Text = "No data";
ScenarioOutput_Accuracy.Text = "No data";
ScenarioOutput_Source.Text = "No data";
+ ScenarioOutput_IsRemoteSource.Text = "No data";
ShowSatelliteData(false);
}
else
@@ -144,6 +145,7 @@ private void UpdateLocationData(Geoposition position)
ScenarioOutput_Longitude.Text = position.Coordinate.Point.Position.Longitude.ToString();
ScenarioOutput_Accuracy.Text = position.Coordinate.Accuracy.ToString();
ScenarioOutput_Source.Text = position.Coordinate.PositionSource.ToString();
+ ScenarioOutput_IsRemoteSource.Text = position.Coordinate.IsRemoteSource.ToString();
if (position.Coordinate.PositionSource == PositionSource.Satellite)
{
diff --git a/Samples/Geolocation/cs/Scenario6_GetLastVisit.xaml.cs b/Samples/Geolocation/cs/Scenario6_GetLastVisit.xaml.cs
index 06af6bd46..a79e7bad9 100644
--- a/Samples/Geolocation/cs/Scenario6_GetLastVisit.xaml.cs
+++ b/Samples/Geolocation/cs/Scenario6_GetLastVisit.xaml.cs
@@ -95,12 +95,14 @@ private void UpdateLastVisit(Geovisit visit)
ScenarioOutput_Latitude.Text = "No data";
ScenarioOutput_Longitude.Text = "No data";
ScenarioOutput_Accuracy.Text = "No data";
+ ScenarioOutput_IsRemoteSource.Text = "No data";
}
else
{
ScenarioOutput_Latitude.Text = visit.Position.Coordinate.Point.Position.Latitude.ToString();
ScenarioOutput_Longitude.Text = visit.Position.Coordinate.Point.Position.Longitude.ToString();
ScenarioOutput_Accuracy.Text = visit.Position.Coordinate.Accuracy.ToString();
+ ScenarioOutput_IsRemoteSource.Text = visit.Position.Coordinate.IsRemoteSource.ToString();
}
}
}
diff --git a/Samples/Geolocation/cs/Scenario7_ForegroundVisits.xaml.cs b/Samples/Geolocation/cs/Scenario7_ForegroundVisits.xaml.cs
index 12a09a2a2..c6ec2d988 100644
--- a/Samples/Geolocation/cs/Scenario7_ForegroundVisits.xaml.cs
+++ b/Samples/Geolocation/cs/Scenario7_ForegroundVisits.xaml.cs
@@ -137,12 +137,14 @@ private void UpdateVisitData(Geovisit visit)
ScenarioOutput_Latitude.Text = "No data";
ScenarioOutput_Longitude.Text = "No data";
ScenarioOutput_Accuracy.Text = "No data";
+ ScenarioOutput_IsRemoteSource.Text = "No data";
}
else
{
ScenarioOutput_Latitude.Text = visit.Position.Coordinate.Point.Position.Latitude.ToString();
ScenarioOutput_Longitude.Text = visit.Position.Coordinate.Point.Position.Longitude.ToString();
ScenarioOutput_Accuracy.Text = visit.Position.Coordinate.Accuracy.ToString();
+ ScenarioOutput_IsRemoteSource.Text = visit.Position.Coordinate.IsRemoteSource.ToString();
}
}
}
diff --git a/Samples/Geolocation/shared/Scenario1_TrackPosition.xaml b/Samples/Geolocation/shared/Scenario1_TrackPosition.xaml
index 8f5d71bbe..25ed9d66b 100644
--- a/Samples/Geolocation/shared/Scenario1_TrackPosition.xaml
+++ b/Samples/Geolocation/shared/Scenario1_TrackPosition.xaml
@@ -35,15 +35,18 @@
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
Application is not able to get location data. Go to
diff --git a/Samples/Geolocation/shared/Scenario2_GetPosition.xaml b/Samples/Geolocation/shared/Scenario2_GetPosition.xaml
index 3f0945dc2..fac3c3c86 100644
--- a/Samples/Geolocation/shared/Scenario2_GetPosition.xaml
+++ b/Samples/Geolocation/shared/Scenario2_GetPosition.xaml
@@ -46,19 +46,22 @@
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Geolocation/shared/Scenario6_GetLastVisit.xaml b/Samples/Geolocation/shared/Scenario6_GetLastVisit.xaml
index 0aeab384b..036ab0a8b 100644
--- a/Samples/Geolocation/shared/Scenario6_GetLastVisit.xaml
+++ b/Samples/Geolocation/shared/Scenario6_GetLastVisit.xaml
@@ -39,17 +39,20 @@
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
Application is not able to get location data. Go to
diff --git a/Samples/Geolocation/shared/Scenario7_ForegroundVisits.xaml b/Samples/Geolocation/shared/Scenario7_ForegroundVisits.xaml
index c773b4c02..7b04e5187 100644
--- a/Samples/Geolocation/shared/Scenario7_ForegroundVisits.xaml
+++ b/Samples/Geolocation/shared/Scenario7_ForegroundVisits.xaml
@@ -36,17 +36,20 @@
+
-
-
-
-
-
+
+
+
+
+
+
+
Application is not able to get location data. Go to
diff --git a/Samples/PenHaptics/README.md b/Samples/PenHaptics/README.md
new file mode 100644
index 000000000..aa67180a6
--- /dev/null
+++ b/Samples/PenHaptics/README.md
@@ -0,0 +1,75 @@
+---
+page_type: sample
+languages:
+- csharp
+products:
+- windows
+- windows-uwp
+urlFragment: PenHaptics
+extendedZipContent:
+- path: SharedContent
+ target: SharedContent
+- path: LICENSE
+ target: LICENSE
+description: "Shows how to use pen haptics in Universal Windows apps."
+---
+
+
+
+# Pen haptics sample
+
+This sample shows how to use Windows 11 pen haptics API to trigger haptic feedback on a pen that supports haptics.
+
+Specifically, this sample shows how to:
+
+- **Get SimpleHapticsController from pen input:** this sample shows how to go from pointer ID to PenDevice and then to SimpleHapticsController. This requires haptics support from both the pen and a compliant machine that supports the particular pen.
+- **Check pen haptics capabilities:** SimpleHapticsController has properties for pen hardware capabilities, such as IsIntensitySupported, IsPlayCountSupported, SupportedFeedback, etc.
+- **Start and stop haptic feedback:** start and stop feedback using variations of SendHapticFeedback and StopFeedback API
+- **Trigger both inking and interaction haptic feedback:** the code shows how to trigger inking feedback for inking scenarios and interaction feedback for user interactions
+
+**Note** The Windows universal samples require Visual Studio to build and Windows 11 to execute.
+
+To obtain information about Windows 11 development, go to the [Windows Dev Center](http://go.microsoft.com/fwlink/?LinkID=532421)
+
+To obtain information about Microsoft Visual Studio and the tools for developing Windows apps, go to [Visual Studio](http://go.microsoft.com/fwlink/?LinkID=532422)
+
+## Related topics
+
+### Samples
+
+[BasicInput](/Samples/BasicInput)
+
+[ComplexInk](/Samples/ComplexInk)
+
+### Reference
+
+[PenDevice](https://docs.microsoft.com/en-us/uwp/api/windows.devices.input.pendevice)
+
+[SimpleHapticsController](https://docs.microsoft.com/en-us/uwp/api/windows.devices.haptics.simplehapticscontroller)
+
+[Windows pen and ink interactions](https://docs.microsoft.com/en-us/windows/apps/design/input/pen-and-stylus-interactions)
+
+## System requirements
+
+**Client:** Windows 11
+
+## Build the sample
+
+1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with the sample you want to build.
+2. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**.
+3. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the subfolder for this specific sample, then the subfolder for your preferred language (C++, C#, or JavaScript). Double-click the Visual Studio Solution (.sln) file.
+4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
+
+## Run the sample
+
+The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
+
+### Deploying the sample
+
+- Select Build > Deploy Solution.
+
+### Deploying and running the sample
+
+- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
diff --git a/Samples/PenHaptics/cppwinrt/Package.appxmanifest b/Samples/PenHaptics/cppwinrt/Package.appxmanifest
new file mode 100644
index 000000000..3040ae525
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Package.appxmanifest
@@ -0,0 +1,39 @@
+
+
+
+
+
+ PenHaptics C++/WinRT Sample
+ Microsoft Corporation
+ Assets\storelogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/PenHaptics/cppwinrt/PenHaptics.sln b/Samples/PenHaptics/cppwinrt/PenHaptics.sln
new file mode 100644
index 000000000..62c02cd83
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/PenHaptics.sln
@@ -0,0 +1,43 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31624.102
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PenHaptics", "PenHaptics.vcxproj", "{2E3ED2B8-4564-4318-85F1-68BD8F29D560}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|ARM.ActiveCfg = Debug|ARM
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|ARM.Build.0 = Debug|ARM
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|ARM.Deploy.0 = Debug|ARM
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|x64.ActiveCfg = Debug|x64
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|x64.Build.0 = Debug|x64
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|x64.Deploy.0 = Debug|x64
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|x86.ActiveCfg = Debug|Win32
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|x86.Build.0 = Debug|Win32
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Debug|x86.Deploy.0 = Debug|Win32
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|ARM.ActiveCfg = Release|ARM
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|ARM.Build.0 = Release|ARM
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|ARM.Deploy.0 = Release|ARM
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|x64.ActiveCfg = Release|x64
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|x64.Build.0 = Release|x64
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|x64.Deploy.0 = Release|x64
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|x86.ActiveCfg = Release|Win32
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|x86.Build.0 = Release|Win32
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {72760E03-10FF-4586-BB6A-D40E8FF82EF8}
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/PenHaptics/cppwinrt/PenHaptics.vcxproj b/Samples/PenHaptics/cppwinrt/PenHaptics.vcxproj
new file mode 100644
index 000000000..d8c7f7c9e
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/PenHaptics.vcxproj
@@ -0,0 +1,211 @@
+
+
+
+
+ $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), LICENSE))\SharedContent
+
+
+ true
+ {2E3ED2B8-4564-4318-85F1-68BD8F29D560}
+ PenHaptics
+ SDKTemplate
+ en-US
+ 15.0
+ true
+ Windows Store
+ 10.0
+ 10.0.22000.0
+ $(WindowsTargetPlatformVersion)
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ Unicode
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);$(SharedContentDir)\cppwinrt
+ true
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ 4453;28204
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+ ..\shared\Scenario1_InkCanvasTactileFeedback.xaml
+
+
+ ..\shared\Scenario2_SupportedTactileFeedback.xaml
+
+
+ ..\shared\Scenario3_InkingFeedback.xaml
+
+
+ ..\shared\Scenario4_InteractionFeedback.xaml
+
+
+ ..\shared\Scenario5_InkingAndInteractionFeedback.xaml
+
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+
+
+
+
+
+ Styles\Styles.xaml
+
+
+
+
+ $(SharedContentDir)\xaml\App.xaml
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+ SampleConfiguration.h
+
+
+ ..\shared\Scenario1_InkCanvasTactileFeedback.xaml
+
+
+ ..\shared\Scenario2_SupportedTactileFeedback.xaml
+
+
+ ..\shared\Scenario3_InkingFeedback.xaml
+
+
+ ..\shared\Scenario4_InteractionFeedback.xaml
+
+
+ ..\shared\Scenario5_InkingAndInteractionFeedback.xaml
+
+
+ Create
+ pch.h
+
+
+ Project.idl
+
+
+
+
+ $(SharedContentDir)\xaml\MainPage.xaml
+
+
+
+
+
+ Designer
+
+
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/PenHaptics/cppwinrt/PenHaptics.vcxproj.filters b/Samples/PenHaptics/cppwinrt/PenHaptics.vcxproj.filters
new file mode 100644
index 000000000..74aafa7d1
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/PenHaptics.vcxproj.filters
@@ -0,0 +1,62 @@
+
+
+
+
+ 4416d50a-7676-4d0a-9b2c-91ff70c6047f
+ bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/PenHaptics/cppwinrt/Project.idl b/Samples/PenHaptics/cppwinrt/Project.idl
new file mode 100644
index 000000000..dec756859
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Project.idl
@@ -0,0 +1,45 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+namespace SDKTemplate
+{
+ [default_interface]
+ runtimeclass Scenario1_InkCanvasTactileFeedback : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario1_InkCanvasTactileFeedback();
+
+ Windows.UI.Xaml.Controls.InkCanvas appInkCanvas{ get; };
+ }
+
+ [default_interface]
+ runtimeclass Scenario2_SupportedTactileFeedback : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario2_SupportedTactileFeedback();
+ }
+
+ [default_interface]
+ runtimeclass Scenario3_InkingFeedback : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario3_InkingFeedback();
+ }
+
+ [default_interface]
+ runtimeclass Scenario4_InteractionFeedback : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario4_InteractionFeedback();
+ }
+
+ [default_interface]
+ runtimeclass Scenario5_InkingAndInteractionFeedback : Windows.UI.Xaml.Controls.Page
+ {
+ Scenario5_InkingAndInteractionFeedback();
+ }
+}
diff --git a/Samples/PenHaptics/cppwinrt/SampleConfiguration.cpp b/Samples/PenHaptics/cppwinrt/SampleConfiguration.cpp
new file mode 100644
index 000000000..ad46c1193
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/SampleConfiguration.cpp
@@ -0,0 +1,68 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include
+#include "MainPage.h"
+#include "SampleConfiguration.h"
+
+using namespace winrt;
+using namespace winrt::Windows::Foundation::Collections;
+using namespace winrt::Windows::Devices::Haptics;
+using namespace winrt::SDKTemplate;
+
+hstring implementation::MainPage::FEATURE_NAME()
+{
+ return L"PenHaptics C++/WinRT Sample";
+}
+
+IVector implementation::MainPage::scenariosInner = winrt::single_threaded_observable_vector(
+{
+ Scenario{ L"Ink Canvas Tactile Feedback", xaml_typename() },
+ Scenario{ L"Query Tactile Feedback Support", xaml_typename() },
+ Scenario{ L"Inking Feedback", xaml_typename() },
+ Scenario{ L"Interaction Feedback", xaml_typename() },
+ Scenario{ L"Inking and Interaction Feedback", xaml_typename() },
+});
+
+std::map const& SDKTemplate::WaveformNamesMap()
+{
+ static const std::map map
+ {
+ { L"BrushContinuous", KnownSimpleHapticsControllerWaveforms::BrushContinuous() },
+ { L"BuzzContinuous", KnownSimpleHapticsControllerWaveforms::BuzzContinuous() },
+ { L"ChiselMarkerContinuous", KnownSimpleHapticsControllerWaveforms::ChiselMarkerContinuous() },
+ { L"Click", KnownSimpleHapticsControllerWaveforms::Click() },
+ { L"EraserContinuous", KnownSimpleHapticsControllerWaveforms::EraserContinuous() },
+ { L"Error", KnownSimpleHapticsControllerWaveforms::Error() },
+ { L"GalaxyPenContinuous", KnownSimpleHapticsControllerWaveforms::GalaxyPenContinuous() },
+ { L"Hover", KnownSimpleHapticsControllerWaveforms::Hover() },
+ { L"InkContinuous", KnownSimpleHapticsControllerWaveforms::InkContinuous() },
+ { L"MarkerContinuous", KnownSimpleHapticsControllerWaveforms::MarkerContinuous() },
+ { L"PencilContinuous", KnownSimpleHapticsControllerWaveforms::PencilContinuous() },
+ { L"Release", KnownSimpleHapticsControllerWaveforms::Release() },
+ { L"RumbleContinuous", KnownSimpleHapticsControllerWaveforms::RumbleContinuous() },
+ { L"Success", KnownSimpleHapticsControllerWaveforms::Success() },
+ };
+ return map;
+}
+
+SimpleHapticsControllerFeedback SDKTemplate::FindSupportedFeedback(SimpleHapticsController const& hapticsController, uint16_t waveform)
+{
+ for (auto&& feedback : hapticsController.SupportedFeedback())
+ {
+ if (feedback.Waveform() == waveform)
+ {
+ return feedback;
+ }
+ }
+ return nullptr;
+}
diff --git a/Samples/PenHaptics/cppwinrt/SampleConfiguration.h b/Samples/PenHaptics/cppwinrt/SampleConfiguration.h
new file mode 100644
index 000000000..f67cbe98d
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/SampleConfiguration.h
@@ -0,0 +1,19 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "pch.h"
+
+namespace winrt::SDKTemplate
+{
+ std::map const& WaveformNamesMap();
+ Windows::Devices::Haptics::SimpleHapticsControllerFeedback FindSupportedFeedback(Windows::Devices::Haptics::SimpleHapticsController const& hapticsController, uint16_t waveform);
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario1_InkCanvasTactileFeedback.cpp b/Samples/PenHaptics/cppwinrt/Scenario1_InkCanvasTactileFeedback.cpp
new file mode 100644
index 000000000..4e229346a
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario1_InkCanvasTactileFeedback.cpp
@@ -0,0 +1,32 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "Scenario1_InkCanvasTactileFeedback.h"
+#include "Scenario1_InkCanvasTactileFeedback.g.cpp"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+using namespace Windows::UI::Xaml;
+
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario1_InkCanvasTactileFeedback::Scenario1_InkCanvasTactileFeedback()
+ {
+ InitializeComponent();
+ }
+
+ void Scenario1_InkCanvasTactileFeedback::OnSizeChanged(IInspectable const&, SizeChangedEventArgs const&)
+ {
+ outputGrid().Width(RootGrid().ActualWidth());
+ outputGrid().Height(RootGrid().ActualHeight() / 2);
+ }
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario1_InkCanvasTactileFeedback.h b/Samples/PenHaptics/cppwinrt/Scenario1_InkCanvasTactileFeedback.h
new file mode 100644
index 000000000..32fbda6b2
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario1_InkCanvasTactileFeedback.h
@@ -0,0 +1,32 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario1_InkCanvasTactileFeedback.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario1_InkCanvasTactileFeedback : Scenario1_InkCanvasTactileFeedbackT
+ {
+ Scenario1_InkCanvasTactileFeedback();
+
+ void OnSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e);
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario1_InkCanvasTactileFeedback : Scenario1_InkCanvasTactileFeedbackT
+ {
+ };
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario2_SupportedTactileFeedback.cpp b/Samples/PenHaptics/cppwinrt/Scenario2_SupportedTactileFeedback.cpp
new file mode 100644
index 000000000..bc2b253d4
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario2_SupportedTactileFeedback.cpp
@@ -0,0 +1,113 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "SampleConfiguration.h"
+#include "Scenario2_SupportedTactileFeedback.h"
+#include "Scenario2_SupportedTactileFeedback.g.cpp"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+using namespace Windows::Devices::Haptics;
+using namespace Windows::Devices::Input;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Input;
+
+// This sample shows how to query the pen currently providing input to the system to see
+// if it supports tactile feedback and, if so, what features it supports
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario2_SupportedTactileFeedback::Scenario2_SupportedTactileFeedback()
+ {
+ InitializeComponent();
+ }
+
+ // The PointerEnter event will get fired as soon as Pointer input is received.
+ // This event handler implementation will query the device providing input to see if it's a pen and
+ // then check to see the pen supports tactile feedback and, if so, what features it supports
+ void Scenario2_SupportedTactileFeedback::Pointer_Entered(IInspectable const&, PointerRoutedEventArgs const& e)
+ {
+ // If the current Pointer device is not a pen, exit
+ if (e.Pointer().PointerDeviceType() != PointerDeviceType::Pen)
+ {
+ supportedFeatures().Text(L"");
+ supportedFeedback().Text(L"");
+ return;
+ }
+
+ // Attempt to retrieve the PenDevice from the current PointerId
+ penDevice = PenDevice::GetFromPointerId(e.Pointer().PointerId());
+
+ // If a PenDevice cannot be retrieved based on the PointerId, it does not support
+ // advanced pen features, such as tactile feedback
+ if (penDevice == nullptr)
+ {
+ statusText().Text(L"Advanced pen features not supported");
+ supportedFeatures().Text(L"");
+ supportedFeedback().Text(L"");
+ return;
+ }
+
+ // Check to see if the current PenDevice supports tactile feedback by seeing if it
+ // has a SimpleHapticsController
+ hapticsController = penDevice.SimpleHapticsController();
+ if (hapticsController == nullptr)
+ {
+ statusText().Text(L"This pen does not provide tactile feedback");
+ return;
+ }
+
+ // Check which tactile feedback features are supported
+ std::wstring message = L"Supported Haptics Features:\n";
+ if (hapticsController.IsIntensitySupported())
+ {
+ message.append(L"Intensity\n");
+ }
+ if (hapticsController.IsPlayCountSupported())
+ {
+ message.append(L"PlayCount\n");
+ }
+ if (hapticsController.IsPlayDurationSupported())
+ {
+ message.append(L"PlayDuration\n");
+ }
+ if (hapticsController.IsReplayPauseIntervalSupported())
+ {
+ message.append(L"ReplayPauseInterval\n");
+ }
+ supportedFeatures().Text(message);
+
+ // Check which feedback waveforms are supported
+ message = L"Supported Feedback:\n";
+ for (SimpleHapticsControllerFeedback feedback : hapticsController.SupportedFeedback())
+ {
+ uint16_t waveform = feedback.Waveform();
+ for (auto [name, value] : WaveformNamesMap())
+ {
+ if (waveform == value)
+ {
+ message.append(name);
+ message.append(L"\n");
+ break;
+ }
+ }
+ }
+ supportedFeedback().Text(message);
+ statusText().Text(L"");
+ }
+
+ // Clear the current penDevice and hapticsController on PointerExit
+ void Scenario2_SupportedTactileFeedback::Pointer_Exited(IInspectable const&, PointerRoutedEventArgs const&)
+ {
+ penDevice = nullptr;
+ hapticsController = nullptr;
+ }
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario2_SupportedTactileFeedback.h b/Samples/PenHaptics/cppwinrt/Scenario2_SupportedTactileFeedback.h
new file mode 100644
index 000000000..1fbde1a44
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario2_SupportedTactileFeedback.h
@@ -0,0 +1,36 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario2_SupportedTactileFeedback.g.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario2_SupportedTactileFeedback : Scenario2_SupportedTactileFeedbackT
+ {
+ Scenario2_SupportedTactileFeedback();
+
+ void Pointer_Entered(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+ void Pointer_Exited(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+
+ private:
+ Windows::Devices::Haptics::SimpleHapticsController hapticsController{ nullptr };
+ Windows::Devices::Input::PenDevice penDevice{ nullptr };
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario2_SupportedTactileFeedback : Scenario2_SupportedTactileFeedbackT
+ {
+ };
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario3_InkingFeedback.cpp b/Samples/PenHaptics/cppwinrt/Scenario3_InkingFeedback.cpp
new file mode 100644
index 000000000..10ae43f2c
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario3_InkingFeedback.cpp
@@ -0,0 +1,131 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "SampleConfiguration.h"
+#include "Scenario3_InkingFeedback.h"
+#include "Scenario3_InkingFeedback.g.cpp"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+using namespace Windows::Devices::Haptics;
+using namespace Windows::Devices::Input;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Input;
+
+
+// This sample shows how to play inking feedback tactile signals, how to
+// adjust the intensity of the tactile signal, and how to fall back to a default
+// waveform if the desired waveform is not supported by the current PenDevice
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario3_InkingFeedback::Scenario3_InkingFeedback()
+ {
+ InitializeComponent();
+ }
+
+ // The PointerEnter event will get fired as soon as Pointer input is received.
+ // This event handler implementation will query the device providing input to see if it's a pen and
+ // then check to see the pen supports tactile feedback and, if so, configure the PenDevice
+ // to send the appropriate tactile signal based on what is selected in the dropdown.
+ void Scenario3_InkingFeedback::HapticCanvas_Entered(IInspectable const&, PointerRoutedEventArgs const& e)
+ {
+ // If the current Pointer device is not a pen, exit
+ if (e.Pointer().PointerDeviceType() != PointerDeviceType::Pen)
+ {
+ return;
+ }
+
+ // Attempt to retrieve the PenDevice from the current PointerId
+ penDevice = PenDevice::GetFromPointerId(e.Pointer().PointerId());
+
+ // If a PenDevice cannot be retrieved based on the PointerId, it does not support
+ // advanced pen features, such as tactile feedback
+ if (penDevice == nullptr)
+ {
+ statusText().Text(L"Advanced pen features not supported");
+ return;
+ }
+
+ // Check to see if the current PenDevice supports tactile feedback by seeing if it
+ // has a SimpleHapticsController
+ hapticsController = penDevice.SimpleHapticsController();
+ if (hapticsController == nullptr)
+ {
+ statusText().Text(L"This pen does not provide tactile feedback");
+ return;
+ }
+
+ // Get feedback based on the user's selected waveform and what the haptic controller supports
+ std::wstring message;
+ currentFeedback = GetSelectedFeedbackOrFallback(message);
+
+ // Send the current feedback to the PenDevice's SimpleHapticsController.
+ // Once sent, inking tactile feedback will be triggered as soon as the pen tip touches
+ // the screen and will be stopped once the pen tip is lifted from the screen.
+ // Also, check to see if the current PenDevice's SimpleHapticsController supports
+ // setting the intensity value of the tactile feedback. If so, set it based
+ // on the slider. If not, send the waveform without custom intensity.
+ if (hapticsController.IsIntensitySupported())
+ {
+ hapticsController.SendHapticFeedback(currentFeedback, intensitySlider().Value() / 100.0);
+ message.append(L"\nIntensity set to " + to_hstring(intensitySlider().Value()) + L"%");
+ }
+ else
+ {
+ hapticsController.SendHapticFeedback(currentFeedback);
+ message.append(L"\nSetting intensity is not supported by this pen");
+ }
+ statusText().Text(message);
+ }
+
+ // Stop sending the tactile feedback and clear the current penDevice and hapticsController on PointerExit.
+ // Stopping the feedback is important as it clears the tactile signal from the PenDevice's
+ // SimpleHapticsController, ensuring that it has a clean state once it next enters range.
+ void Scenario3_InkingFeedback::HapticCanvas_Exited(IInspectable const&, PointerRoutedEventArgs const&)
+ {
+ penDevice = nullptr;
+ statusText().Text(L"");
+ if (hapticsController != nullptr)
+ {
+ hapticsController.StopFeedback();
+ hapticsController = nullptr;
+ currentFeedback = nullptr;
+ }
+ }
+
+ // Get feedback which matches the currently selected waveform in the dropdown.
+ // To get the feedback, the SimpleHapticsController's SupportedFeedback list must be traversed
+ // to see if a matching feedback is present.
+ // This is important because InkContinuous is the only Inking waveform required to be
+ // supported by every pen with haptics.
+ // If no matching feedback is found in the SupportedFeedback list, this method returns
+ // InkContinuous as a guaranteed fallback.
+ SimpleHapticsControllerFeedback Scenario3_InkingFeedback::GetSelectedFeedbackOrFallback(std::wstring& message)
+ {
+ // Look up the waveform the user selected.
+ hstring name = waveformComboBox().SelectionBoxItem().as();
+ uint16_t waveform = WaveformNamesMap().at(name);
+
+ // See if the haptics controller supports the selected waveform.
+ SimpleHapticsControllerFeedback feedback = FindSupportedFeedback(hapticsController, waveform);
+ if (feedback != nullptr)
+ {
+ message = L"Waveform set to " + name;
+ return feedback;
+ }
+
+ // It does not. Use InkContinuous as a fallback.
+ message = name + L" is not supported by this pen, so falling back to InkContinuous";
+ return FindSupportedFeedback(hapticsController, KnownSimpleHapticsControllerWaveforms::InkContinuous());
+ }
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario3_InkingFeedback.h b/Samples/PenHaptics/cppwinrt/Scenario3_InkingFeedback.h
new file mode 100644
index 000000000..e1375f64d
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario3_InkingFeedback.h
@@ -0,0 +1,41 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario3_InkingFeedback.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario3_InkingFeedback : Scenario3_InkingFeedbackT
+ {
+ Scenario3_InkingFeedback();
+
+ void HapticCanvas_Entered(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+ void HapticCanvas_Exited(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+
+ private:
+ Windows::Devices::Haptics::SimpleHapticsController hapticsController{ nullptr };
+ Windows::Devices::Input::PenDevice penDevice{ nullptr };
+ Windows::Devices::Haptics::SimpleHapticsControllerFeedback currentFeedback{ nullptr };
+
+ Windows::Devices::Haptics::SimpleHapticsControllerFeedback GetSelectedFeedbackOrFallback(std::wstring& message);
+
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario3_InkingFeedback : Scenario3_InkingFeedbackT
+ {
+ };
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario4_InteractionFeedback.cpp b/Samples/PenHaptics/cppwinrt/Scenario4_InteractionFeedback.cpp
new file mode 100644
index 000000000..b7b8563be
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario4_InteractionFeedback.cpp
@@ -0,0 +1,138 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "SampleConfiguration.h"
+#include "Scenario4_InteractionFeedback.h"
+#include "Scenario4_InteractionFeedback.g.cpp"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+using namespace Windows::Devices::Haptics;
+using namespace Windows::Devices::Input;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Input;
+
+
+// This sample shows how to play Interaction feedback tactile signals, how to
+// adjust the intensity of the tactile signal, and how to fall back to a default
+// waveform if the desired waveform is not supported by the current PenDevice
+namespace winrt::SDKTemplate::implementation
+{
+ Scenario4_InteractionFeedback::Scenario4_InteractionFeedback()
+ {
+ InitializeComponent();
+ }
+
+ // The PointerEnter event will get fired as soon as Pointer input is received.
+ // This event handler implementation will query the device providing input to see if it's a pen and
+ // then check to see the pen supports tactile feedback
+ void Scenario4_InteractionFeedback::MainGrid_Entered(IInspectable const&, PointerRoutedEventArgs const& e)
+ {
+ // If the current Pointer device is not a pen, exit
+ if (e.Pointer().PointerDeviceType() != PointerDeviceType::Pen)
+ {
+ return;
+ }
+
+ // Attempt to retrieve the PenDevice from the current PointerId
+ penDevice = PenDevice::GetFromPointerId(e.Pointer().PointerId());
+
+ // If a PenDevice cannot be retrieved based on the PointerId, it does not support
+ // advanced pen features, such as tactile feedback
+ if (penDevice == nullptr)
+ {
+ statusText().Text(L"Advanced pen features not supported");
+ return;
+ }
+
+ // Check to see if the current PenDevice supports tactile feedback by seeing if it
+ // has a SimpleHapticsController
+ hapticsController = penDevice.SimpleHapticsController();
+ if (hapticsController == nullptr)
+ {
+ statusText().Text(L"This pen does not provide tactile feedback");
+ return;
+ }
+ }
+
+ // Stop sending the tactile feedback and clear the current penDevice and hapticsController on PointerExit.
+ // Stopping the feedback is important as it clears the tactile signal from the PenDevice's
+ // SimpleHapticsController, ensuring that it has a clean state once it next enters range.
+ void Scenario4_InteractionFeedback::MainGrid_Exited(IInspectable const&, PointerRoutedEventArgs const&)
+ {
+ penDevice = nullptr;
+ statusText().Text(L"");
+ if (hapticsController != nullptr)
+ {
+ hapticsController.StopFeedback();
+ hapticsController = nullptr;
+ currentFeedback = nullptr;
+ }
+ }
+
+ // Send the selected waveform upon the button being clicked
+ void Scenario4_InteractionFeedback::SendFeedback_Clicked(IInspectable const&, RoutedEventArgs const&)
+ {
+ if (hapticsController == nullptr)
+ {
+ return;
+ }
+
+ // Get the current feedback based on what is selected in the dropdown
+ std::wstring message;
+ currentFeedback = GetSelectedFeedbackOrFallback(message);
+
+ // Send the current feedback to the PenDevice's SimpleHapticsController.
+ // Once sent, unlike inking feedback, the feedback will be played immediately.
+ // Also, check to see if the current PenDevice's SimpleHapticsController supports
+ // setting the intensity value of the tactile feedback. If so, set it based
+ // on the slider. If not, send the waveform without custom intensity.
+ if (hapticsController.IsIntensitySupported())
+ {
+ hapticsController.SendHapticFeedback(currentFeedback, intensitySlider().Value() / 100);
+ message.append(L"\nIntensity set to " + to_hstring(intensitySlider().Value()) + L"%");
+ }
+ else
+ {
+ hapticsController.SendHapticFeedback(currentFeedback);
+ message.append(L"\nSetting intensity is not supported by this pen");
+ }
+ statusText().Text(message);
+ }
+
+ // Get the currently selected waveform in the dropdown.
+ // To get the waveform, the SimpleHapticsController's SupportedFeedback list must be traversed
+ // to see if the desired waveform is present.
+ // This is important because Click is the only Interaction waveform required to be
+ // supported by every pen with haptics.
+ // If the desired waveform is not in the SupportedFeedback list, this method returns
+ // Click as a guaranteed fallback.
+ SimpleHapticsControllerFeedback Scenario4_InteractionFeedback::GetSelectedFeedbackOrFallback(std::wstring& message)
+ {
+ // Look up the waveform the user selected.
+ hstring name = waveformComboBox().SelectionBoxItem().as();
+ uint16_t waveform = WaveformNamesMap().at(name);
+
+ // See if the haptics controller supports the selected waveform.
+ SimpleHapticsControllerFeedback feedback = FindSupportedFeedback(hapticsController, waveform);
+ if (feedback != nullptr)
+ {
+ message = L"Waveform set to " + name;
+ return feedback;
+ }
+
+ // It does not. Use Click as a fallback.
+ message = name + L" is not supported by this pen, so falling back to Click";
+ return FindSupportedFeedback(hapticsController, KnownSimpleHapticsControllerWaveforms::Click());
+ }
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario4_InteractionFeedback.h b/Samples/PenHaptics/cppwinrt/Scenario4_InteractionFeedback.h
new file mode 100644
index 000000000..8e9b19858
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario4_InteractionFeedback.h
@@ -0,0 +1,42 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario4_InteractionFeedback.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario4_InteractionFeedback : Scenario4_InteractionFeedbackT
+ {
+ Scenario4_InteractionFeedback();
+
+ void MainGrid_Entered(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+ void MainGrid_Exited(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+ void SendFeedback_Clicked(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ Windows::Devices::Haptics::SimpleHapticsController hapticsController{ nullptr };
+ Windows::Devices::Input::PenDevice penDevice{ nullptr };
+ Windows::Devices::Haptics::SimpleHapticsControllerFeedback currentFeedback{ nullptr };
+
+ Windows::Devices::Haptics::SimpleHapticsControllerFeedback GetSelectedFeedbackOrFallback(std::wstring& message);
+
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario4_InteractionFeedback : Scenario4_InteractionFeedbackT
+ {
+ };
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario5_InkingAndInteractionFeedback.cpp b/Samples/PenHaptics/cppwinrt/Scenario5_InkingAndInteractionFeedback.cpp
new file mode 100644
index 000000000..10549f87a
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario5_InkingAndInteractionFeedback.cpp
@@ -0,0 +1,300 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "SampleConfiguration.h"
+#include "Scenario5_InkingAndInteractionFeedback.h"
+#include "Scenario5_InkingAndInteractionFeedback.g.cpp"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+using namespace Windows::Devices::Haptics;
+using namespace Windows::Devices::Input;
+using namespace Windows::UI;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Shapes;
+
+
+// This sample shows how to use Inking and Interaction tactile signals in
+// conjunction with each other.
+// Namely, this sample plays the InkContinuous waveform when dragging a movable
+// rectangle and then plays the Click waveform when the rectangle is in range
+// of a snap gridline and, finally, if the movable rectangle snaps to a gridline
+// upon release, it plays the Click waveform one more time.
+namespace winrt::SDKTemplate::implementation
+{
+ // Set the initial configuration of the canvas and the rectangles
+ Scenario5_InkingAndInteractionFeedback::Scenario5_InkingAndInteractionFeedback()
+ {
+ InitializeComponent();
+ InitializeGridLines();
+ InitializeManipulationTransforms();
+ }
+
+ // Draw gridlines based on the gridSize
+ void Scenario5_InkingAndInteractionFeedback::InitializeGridLines()
+ {
+ SolidColorBrush darkGray(Colors::DarkGray());
+ double width = hapticCanvas().Width();
+ double height = hapticCanvas().Height();
+ for (int i = 0; i <= width; i += gridSize)
+ {
+ Line currLine;
+ currLine.Stroke(darkGray);
+ currLine.X1(i);
+ currLine.X2(i);
+ currLine.Y1(0);
+ currLine.Y2(height);
+ hapticCanvas().Children().Append(currLine);
+ }
+ for (int i = 0; i <= height; i += gridSize)
+ {
+ Line currLine;
+ currLine.Stroke(darkGray);
+ currLine.X1(0);
+ currLine.X2(width);
+ currLine.Y1(i);
+ currLine.Y2(i);
+ hapticCanvas().Children().Append(currLine);
+ }
+ }
+
+ // Configure the Manipulation transforms that are used to drag the rectangle around
+ void Scenario5_InkingAndInteractionFeedback::InitializeManipulationTransforms()
+ {
+ previousTransform = MatrixTransform();
+ previousTransform.Matrix(MatrixHelper::Identity());
+ deltaTransform = CompositeTransform();
+ topLeft = Point(75, 75);
+ deltaTransform.TranslateX(topLeft.X);
+ deltaTransform.TranslateY(topLeft.Y);
+
+ transforms = TransformGroup();
+ transforms.Children().ReplaceAll({ previousTransform, deltaTransform });
+
+ // Set the render transform on the rect
+ movableRect().RenderTransform(transforms);
+ }
+
+
+ // The PointerEnter event will get fired as soon as Pointer input is received in the movableRect.
+ // This event handler implementation will query the device providing input to see if it's a pen and
+ // then check to see the pen supports tactile feedback and, if so, configure the PenDevice
+ // to send the InkContinuous tactile signal.
+ void Scenario5_InkingAndInteractionFeedback::MovableRect_Entered(IInspectable const&, PointerRoutedEventArgs const& e)
+ {
+ // If the current Pointer device is not a pen, exit
+ if (e.Pointer().PointerDeviceType() != PointerDeviceType::Pen)
+ {
+ return;
+ }
+
+ // Attempt to retrieve the PenDevice from the current PointerId
+ penDevice = PenDevice::GetFromPointerId(e.Pointer().PointerId());
+
+ // If a PenDevice cannot be retrieved based on the PointerId, it does not support
+ // advanced pen features, such as tactile feedback
+ if (penDevice == nullptr)
+ {
+ statusText().Text(L"Advanced pen features not supported");
+ return;
+ }
+
+ // Check to see if the current PenDevice supports tactile feedback by seeing if it
+ // has a SimpleHapticsController
+ hapticsController = penDevice.SimpleHapticsController();
+ if (hapticsController == nullptr)
+ {
+ statusText().Text(L"This pen does not provide tactile feedback");
+ return;
+ }
+
+ // Send the InkContinuous waveform to the PenDevice's SimpleHapticsController.
+ // Once sent, inking continuous tactile feedback will be triggered as soon as the pen tip touches
+ // the screen and will be stopped once the pen tip is lifted from the screen.
+ // Also, check to see if the current PenDevice's SimpleHapticsController supports
+ // setting the intensity value of the tactile feedback. If so, set it to 0.75.
+ // If not, send the waveform with the default intensity.
+ SimpleHapticsControllerFeedback feedback = FindSupportedFeedback(hapticsController, KnownSimpleHapticsControllerWaveforms::InkContinuous());
+ if (feedback != nullptr)
+ {
+ if (hapticsController.IsIntensitySupported())
+ {
+ hapticsController.SendHapticFeedback(feedback, 0.75);
+ }
+ else
+ {
+ hapticsController.SendHapticFeedback(feedback);
+ }
+ }
+ }
+
+ // Stop sending the tactile feedback and clear the current penDevice and hapticsController on PointerExit.
+ // Stopping the feedback is important as it clears the tactile signal from the PenDevice's
+ // SimpleHapticsController, ensuring that it has a clean state once it next enters range.
+ void Scenario5_InkingAndInteractionFeedback::MovableRect_Exited(IInspectable const&, PointerRoutedEventArgs const&)
+ {
+ penDevice = nullptr;
+ statusText().Text(L"");
+ if (hapticsController != nullptr)
+ {
+ hapticsController.StopFeedback();
+ hapticsController = nullptr;
+ }
+ }
+
+ // Change the color of the movableRect once a manipulation is started. This coincides with the pen
+ // touching down inside the rectangle, so this color change will happen at the same time that the
+ // InkContinuous waveform begins playing.
+ void Scenario5_InkingAndInteractionFeedback::MovableRect_ManipulationStarted(IInspectable const&, ManipulationStartedRoutedEventArgs const&)
+ {
+ movableRect().Style(MovableRectangleDragged());
+ }
+
+ // Update the position of the movableRect and update the previewRect as needed
+ void Scenario5_InkingAndInteractionFeedback::MovableRect_ManipulationDelta(IInspectable const&, ManipulationDeltaRoutedEventArgs const& e)
+ {
+ previousTransform.Matrix(transforms.Value());
+
+ // Look at the Delta property of the ManipulationDeltaRoutedEventArgs to retrieve the X and Y changes
+ Point translation = e.Delta().Translation;
+ deltaTransform.TranslateX(translation.X);
+ deltaTransform.TranslateY(translation.Y);
+ topLeft.X += translation.X;
+ topLeft.Y += translation.Y;
+ UpdatePreviewRect();
+ }
+
+ // Update the visibilty or position of the previewRect based on the location
+ // of the movableRect.
+ // If the previewRect is snapped to a given gridline for the first time,
+ // play the Click tactile signal.
+ void Scenario5_InkingAndInteractionFeedback::UpdatePreviewRect()
+ {
+ if (IsInSnapRange())
+ {
+ previewRect().Visibility(Visibility::Visible);
+ Point newPreviewTopLeft = GetSnappedPoint();
+
+ // Check to see if this is the first time that the previewRect is in range of a given gridline
+ // and send the Click tactile signal if so
+ bool sendHaptics = true;
+ if ((previewTopLeft.X == newPreviewTopLeft.X && previewTopLeft.Y == newPreviewTopLeft.Y) ||
+ (previewTopLeft.X == newPreviewTopLeft.X && newPreviewTopLeft.Y == topLeft.Y) ||
+ (previewTopLeft.Y == newPreviewTopLeft.Y && newPreviewTopLeft.X == topLeft.X))
+ {
+ sendHaptics = false;
+ }
+ if (previewTopLeft.X != newPreviewTopLeft.X || previewTopLeft.Y != newPreviewTopLeft.Y)
+ {
+ previewTopLeft = newPreviewTopLeft;
+ previewRect().Translation({ previewTopLeft.X, previewTopLeft.Y, 0 });
+ if (hapticsController != nullptr && sendHaptics)
+ {
+ SimpleHapticsControllerFeedback feedback = FindSupportedFeedback(hapticsController, KnownSimpleHapticsControllerWaveforms::Click());
+ if (feedback != nullptr)
+ {
+ hapticsController.SendHapticFeedback(feedback);
+ }
+ }
+ }
+ }
+ else
+ {
+ previewRect().Visibility(Visibility::Collapsed);
+ previewTopLeft = Point(-1, -1);
+ }
+ }
+
+ // When the manipulation is over, reset the color of the movableRect and
+ // snap it to a gridline if appropriate
+ void Scenario5_InkingAndInteractionFeedback::MovableRect_ManipulationCompleted(IInspectable const&, ManipulationCompletedRoutedEventArgs const&)
+ {
+ movableRect().Style(MovableRectangle());
+ if (IsInSnapRange())
+ {
+ SnapMovableRectToGridLines();
+ }
+ }
+
+ // Updates the position of the movableRect to snap to the appropriate gridline(s).
+ // In addition, play the Click tactile signal to provide additional feedback to the user that it has snapped.
+ void Scenario5_InkingAndInteractionFeedback::SnapMovableRectToGridLines()
+ {
+ topLeft = GetSnappedPoint();
+ previousTransform = MatrixTransform();
+ previousTransform.Matrix(MatrixHelper::Identity());
+ deltaTransform.TranslateX(topLeft.X);
+ deltaTransform.TranslateY(topLeft.Y);
+
+ transforms = TransformGroup();
+ transforms.Children().ReplaceAll({ previousTransform, deltaTransform });
+
+ movableRect().RenderTransform(transforms);
+
+ if (hapticsController != nullptr)
+ {
+ SimpleHapticsControllerFeedback feedback = FindSupportedFeedback(hapticsController, KnownSimpleHapticsControllerWaveforms::Click());
+ if (feedback != nullptr)
+ {
+ hapticsController.SendHapticFeedback(feedback);
+ }
+ }
+ }
+
+ // Retrieve the point corresponding to the top-left corner of where the movableRect would snap to
+ // if released.
+ Point Scenario5_InkingAndInteractionFeedback::GetSnappedPoint()
+ {
+ Point snappedPoint;
+ float remainderX = (float)fmod(topLeft.X, gridSize);
+ if (remainderX <= snapDistance)
+ {
+ snappedPoint.X = topLeft.X - remainderX;
+ }
+ else if (remainderX >= gridSize - snapDistance)
+ {
+ snappedPoint.X = topLeft.X + gridSize - remainderX;
+ }
+ else
+ {
+ snappedPoint.X = topLeft.X;
+ }
+ float remainderY = (float)fmod(topLeft.Y, gridSize);
+ if (remainderY <= snapDistance)
+ {
+ snappedPoint.Y = topLeft.Y - remainderY;
+ }
+ else if (remainderY >= gridSize - snapDistance)
+ {
+ snappedPoint.Y = topLeft.Y + gridSize - remainderY;
+ }
+ else
+ {
+ snappedPoint.Y = topLeft.Y;
+ }
+ return snappedPoint;
+ }
+
+ // Check to see if the movableRect is currently within snapping range of a gridline
+ bool Scenario5_InkingAndInteractionFeedback::IsInSnapRange()
+ {
+ float remainderX = (float)fmod(topLeft.X, gridSize);
+ float remainderY = (float)fmod(topLeft.Y, gridSize);
+ return remainderX <= snapDistance ||
+ remainderX >= gridSize - snapDistance ||
+ remainderY <= snapDistance ||
+ remainderY >= gridSize - snapDistance;
+ }
+}
diff --git a/Samples/PenHaptics/cppwinrt/Scenario5_InkingAndInteractionFeedback.h b/Samples/PenHaptics/cppwinrt/Scenario5_InkingAndInteractionFeedback.h
new file mode 100644
index 000000000..6ec46220c
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/Scenario5_InkingAndInteractionFeedback.h
@@ -0,0 +1,54 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "Scenario5_InkingAndInteractionFeedback.g.h"
+#include "MainPage.h"
+
+namespace winrt::SDKTemplate::implementation
+{
+ struct Scenario5_InkingAndInteractionFeedback : Scenario5_InkingAndInteractionFeedbackT
+ {
+ Scenario5_InkingAndInteractionFeedback();
+
+ void MovableRect_Entered(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+ void MovableRect_Exited(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+ void MovableRect_ManipulationStarted(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::ManipulationStartedRoutedEventArgs const&);
+ void MovableRect_ManipulationDelta(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::ManipulationDeltaRoutedEventArgs const& e);
+ void MovableRect_ManipulationCompleted(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::Input::ManipulationCompletedRoutedEventArgs const&);
+
+ private:
+ const int gridSize = 100;
+ const double snapDistance = 20.0;
+ Windows::Foundation::Point topLeft;
+ Windows::Foundation::Point previewTopLeft{ -1, -1 };
+ Windows::UI::Xaml::Media::TransformGroup transforms{ nullptr };
+ Windows::UI::Xaml::Media::MatrixTransform previousTransform{ nullptr };
+ Windows::UI::Xaml::Media::CompositeTransform deltaTransform{ nullptr };
+ Windows::Devices::Input::PenDevice penDevice{ nullptr };
+ Windows::Devices::Haptics::SimpleHapticsController hapticsController{ nullptr };
+
+ void InitializeGridLines();
+ void InitializeManipulationTransforms();
+ void UpdatePreviewRect();
+ void SnapMovableRectToGridLines();
+ Windows::Foundation::Point GetSnappedPoint();
+ bool IsInSnapRange();
+ };
+}
+
+namespace winrt::SDKTemplate::factory_implementation
+{
+ struct Scenario5_InkingAndInteractionFeedback : Scenario5_InkingAndInteractionFeedbackT
+ {
+ };
+}
diff --git a/Samples/PenHaptics/cppwinrt/packages.config b/Samples/PenHaptics/cppwinrt/packages.config
new file mode 100644
index 000000000..a125ab51d
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Samples/PenHaptics/cppwinrt/pch.cpp b/Samples/PenHaptics/cppwinrt/pch.cpp
new file mode 100644
index 000000000..01484ff5a
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/pch.cpp
@@ -0,0 +1,6 @@
+//
+// pch.cpp
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/Samples/PenHaptics/cppwinrt/pch.h b/Samples/PenHaptics/cppwinrt/pch.h
new file mode 100644
index 000000000..766a18c10
--- /dev/null
+++ b/Samples/PenHaptics/cppwinrt/pch.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include
+#include "winrt/Windows.Foundation.h"
+#include "winrt/Windows.Foundation.Collections.h"
+#include "winrt/Windows.Foundation.Numerics.h"
+#include "winrt/Windows.ApplicationModel.Activation.h"
+#include "winrt/Windows.Devices.Haptics.h"
+#include "winrt/Windows.Devices.Input.h"
+#include "winrt/Windows.System.h"
+#include "winrt/Windows.UI.h"
+#include "winrt/Windows.UI.Core.h"
+#include "winrt/Windows.UI.Xaml.h"
+#include "winrt/Windows.UI.Xaml.Automation.Peers.h"
+#include "winrt/Windows.UI.Xaml.Controls.h"
+#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
+#include "winrt/Windows.UI.Xaml.Documents.h"
+#include "winrt/Windows.UI.Xaml.Input.h"
+#include "winrt/Windows.UI.Xaml.Interop.h"
+#include "winrt/Windows.UI.Xaml.Markup.h"
+#include "winrt/Windows.UI.Xaml.Media.h"
+#include "winrt/Windows.UI.Xaml.Navigation.h"
+#include "winrt/Windows.UI.Xaml.Shapes.h"
+#include
+#include