Bring new meaning to a hands-on user experience: Create a tactile app with Surface Dial

Windows Developer
Windows Developer
Published in
4 min readDec 12, 2017

The Surface Dial is a unique peripheral that can change the way people work by augmenting pen and mouse-based tasks. Surface Dial controls are supported by computers with Bluetooth LE capabilities, and support is quick and easy to add to your UWP apps.

Surface Dial will work with any app for basic scrolling, zooming and undo actions. With additional coding, functionality can be extended beyond these basic tasks.

Microsoft has already updated most of the Office suite of applications with integrated support for the Surface Dial. Plus, heavyweights like Corel and Adobe have implemented Dial-based features.

For example, in Adobe Photoshop, the Surface Dial can be used to control brush parameters including size, hardness, opacity, flow and smoothing. In Adobe Illustrator, the Surface Dial enables navigation between artboards, selection and operation of common drawing tools and adjustment of object arrangement.

Figure 1- The Surface Dial in use on a Surface Studio screen

Adding Support

First introduced as part of Surface Studio, an updated RadialController class in the Windows 10 Fall Creators Update contains all the functionality necessary for working with the Surface Dial (and potentially other third-party radial devices as they become available).

The update also means that it only takes a few simple steps to make a UWP app responsive to the Surface Dial: Obtain an instance of the class, add custom menu items and handle a few events.

A custom menu item (also known as a custom tool) is, in turn, added to the radial menu that appears on-screen with a long-press to the Surface Dial. The image below shows this menu with four default menu items and two custom options (the first of which is selected).

Figure 2- Surface Dial on-screen menu with 4 default and 2 custom tools.

In fact, for your app to recognize when the Surface Dial is active, you must create one or more custom menu items and add them to the instance of the RadialController class you created for your view. To get started, create an instance of the RadialController class in the page where you need it by calling the CreateForCurrentView method off the static class. This will give you an instance of the RadialController where you can add one or more custom tools. For example:

public sealed partial class DialSamplePage: Page
{
private RadialController dial;
public DialSamplePage()
{
this.InitializeComponent();// Obtain instance of the RadialController for the page.
this.dial = RadialController.CreateForCurrentView();
// Define the first custom tool.
var icon1Uri = new Uri("ms-appx:///Assets/Tool1.png");
var icon1 = RandomAccessStreamReference.CreateFromUri(icon1Uri);
var tool1 = RadialControllerMenuItem.CreateFromIcon("Sample 1", icon1);
tool1.Tag = "tool1";
// Define the second custom tool.
var icon2Uri = new Uri("ms-appx:///Assets/Tool2.png");
var icon2 = RandomAccessStreamReference.CreateFromUri(icon2Uri);
var tool2 = RadialControllerMenuItem.CreateFromIcon("Sample 2", icon2);
tool2.Tag = "tool2";
// Add the two tools to the RadialController menu.
this.dial.Menu.Items.Add(tool1);
this.dial.Menu.Items.Add(tool2);
}
}

Once the page has a reference to the RadialController instance, you can handle any of the following events:

  • ButtonClicked
  • ButtonHolding
  • ButtonPressed
  • ButtonReleased
  • RotationChanged
  • ControlAcquired
  • ControlLost
  • ScreenContactStarted
  • ScreenContactContinued
  • ScreenContactEnded

Learn more about these individual events, and when they’re raised, here.

Handling a RadialController event is the same as handling just about every other event in the .Net Framework; simply attach handlers to the events you want to include. The two most common events to handle on the RadialContoller are the ButtonClicked (yes, the Surface Dial acts as one big button and can be pressed) and RotationChanged events:

this.dial.ButtonClicked += Dial_ButtonClicked;
this.dial.RotationChanged += Dial_RotationChanged;

Then implement a handler for each event. Here’s the ButtonClicked event handler:

private void Dial_ButtonClicked(RadialController sender,
RadialControllerButtonClickedEventArgs args)
{
// Only support button click for tool1.
var tool = this.dial.Menu.GetSelectedMenuItem();
if ((string)tool.Tag != "tool1") { return; }
this.IsOnSwitch.IsOn = !this.IsOnSwitch.IsOn;
}

Since the event handlers are attached to the RadialController and not to individual menu items, you’ll have to determine which tool is “active.” One way to check the active tool is to use the Menu property of the RadialController and call the GetSelectedMenuItem method (another may be to handle the ControlAcquired event, which is thrown whenever a custom tool is selected from the radial menu).

An app could perform different actions depending upon which tool was selected from the Surface Dial’s menu. In the following example, the two tools run different actions when the Surface Dial is rotated:

private void Dial_RotationChanged(RadialController sender,
RadialControllerRotationChangedEventArgs args)
{
var tool = this.dial.Menu.GetSelectedMenuItem();
if ((string)tool.Tag == “tool1”)
{
this.UpdateProgress(args.RotationDeltaInDegrees);
}
else
{
this.UpdateColor(args.RotationDeltaInDegrees);
}
}

Learn more about making your existing apps more engaging by going to the Windows Dev Center.

--

--

Windows Developer
Windows Developer

Everything you need to know to develop great apps, games and other experiences for Windows.