RadialController Class

Definition

Represents a wheel input device or accessory such as the Surface Dial.

Surface Dial with Surface Studio and Pen.

With a form factor based on a rotate action (or gesture), the Surface Dial is intended as a secondary, multi-modal input device that complements input from a primary device. In most cases, the device is manipulated by a user's non-dominant hand while performing a task with their dominant hand (such as inking with a pen). It is not designed for precision pointer input (like touch, pen, or mouse).

The Surface Dial also supports both a press and hold action and a click action. Press and hold has a single function: display a menu of commands. If the menu is active, the rotate and click input is processed by the menu. Otherwise, the input is passed to your app for processing.

The RadialController and related APIs (see end of topic) enable you to customize both the integrated command menu and the interaction experience supported by your app.

public ref class RadialController sealed
/// [Windows.Foundation.Metadata.ContractVersion(Windows.Foundation.UniversalApiContract, 196608)]
/// [Windows.Foundation.Metadata.MarshalingBehavior(Windows.Foundation.Metadata.MarshalingType.Agile)]
class RadialController final
[Windows.Foundation.Metadata.ContractVersion(typeof(Windows.Foundation.UniversalApiContract), 196608)]
[Windows.Foundation.Metadata.MarshalingBehavior(Windows.Foundation.Metadata.MarshalingType.Agile)]
public sealed class RadialController
Public NotInheritable Class RadialController
Inheritance
Object Platform::Object IInspectable RadialController
Attributes

Windows requirements

Device family
Windows 10 Anniversary Edition (introduced in 10.0.14393.0)
API contract
Windows.Foundation.UniversalApiContract (introduced in v3.0)

Examples

In this example, we add a custom tool to the Surface Dial menu and declare the RadialController input handlers.

  1. First, we create a reference to the RadialController object for the Surface Dial (myController) by calling CreateForCurrentView.
  2. We then create an instance of a RadialControllerMenuItem (myItem) by calling RadialControllerMenuItem.CreateFromIcon.
  3. Next, we append that item to the collection of menu items.
  4. We declare the input event handlers (ButtonClicked and RotationChanged) for the RadialController object.
  5. Finally, we define the event handlers.
public sealed partial class MainPage : Page
 {
     RadialController myController;

     public MainPage()
     {
         this.InitializeComponent();
         // Create a reference to the RadialController.
         myController = RadialController.CreateForCurrentView();

         // Create an icon for the custom tool.
         RandomAccessStreamReference icon =
           RandomAccessStreamReference.CreateFromUri(
             new Uri("ms-appx:///Assets/StoreLogo.png"));

         // Create a menu item for the custom tool.
         RadialControllerMenuItem myItem =
           RadialControllerMenuItem.CreateFromIcon("Sample", icon);

         // Add the custom tool to the RadialController menu.
         myController.Menu.Items.Add(myItem);

         // Declare input handlers for the RadialController.
         myController.ButtonClicked += MyController_ButtonClicked;
         myController.RotationChanged += MyController_RotationChanged;
     }

     // Handler for rotation input from the RadialController.
     private void MyController_RotationChanged(RadialController sender,
       RadialControllerRotationChangedEventArgs args)
     {
         if (RotationSlider.Value + args.RotationDeltaInDegrees > 100)
         {
             RotationSlider.Value = 100;
             return;
         }
         else if (RotationSlider.Value + args.RotationDeltaInDegrees < 0)
         {
             RotationSlider.Value = 0;
             return;
         }
         RotationSlider.Value += args.RotationDeltaInDegrees;
     }

     // Handler for click input from the RadialController.
     private void MyController_ButtonClicked(RadialController sender,
       RadialControllerButtonClickedEventArgs args)
     {
         ButtonToggle.IsOn = !ButtonToggle.IsOn;
     }
 }

In the initialization function shown here, we declare the various input event handlers for the RadialController object.

// Create and configure our radial controller.
private void InitializeController() 
{
    // Create a reference to the RadialController.
    radialController = RadialController.CreateForCurrentView();
    // Set rotation resolution to 1 degree of sensitivity.
    radialController.RotationResolutionInDegrees = 1;

    // Declare input handlers for the RadialController.
    radialController.ButtonClicked += (sender, args) =>
    { RadialController_ButtonClicked(sender, args); };
    radialController.RotationChanged += (sender, args) =>
    { RadialController_RotationChanged(sender, args); };

    radialController.ControlAcquired += (sender, args) =>
    { RadialController_ControlAcquired(sender, args); };
    radialController.ControlLost += (sender, args) =>
    { RadialController_ControlLost(sender, args); };
    radialController.ScreenContactStarted += (sender, args) =>
    { RadialController_ScreenContactStarted(sender, args); };
    radialController.ScreenContactContinued += (sender, args) =>
    { RadialController_ScreenContactContinued(sender, args); };
    radialController.ScreenContactEnded += (sender, args) =>
    { RadialController_ScreenContactEnded(sender, args); };
    AddToLog("Input handlers created");

    // Create the custom menu items.
    CreateMenuItems();
    // Specify the menu items.
    ConfigureMenu();
}

In the ButtonClicked handler, the interaction sets the state of a toggle button to checked or unchecked.

// Occurs when the wheel device is pressed and then released 
// while a customRadialController tool is active.
// NOTE: Your app does not receive this event when the RadialController 
// menu is active or a built-in tool is active
// Send click input to toggle button of active region.
private void RadialController_ButtonClicked(RadialController sender,
  RadialControllerButtonClickedEventArgs args)
{
    toggles[activeMenuItemIndex].IsOn = !toggles[activeMenuItemIndex].IsOn;
}

In the RotationChanged handler, the interaction modifies the value of a slider.

// Occurs when the wheel device is rotated while a custom 
// RadialController tool is active.
// NOTE: Your app does not receive this event when the RadialController 
// menu is active or a built-in tool is active
// Send rotation input to slider of active region.
private void RadialController_RotationChanged(RadialController sender,
  RadialControllerRotationChangedEventArgs args)
{
    Slider slider = sliders[activeMenuItemIndex];
    if (slider.Value + args.RotationDeltaInDegrees > 100)
    {
        slider.Value = 100;
        return;
    }
    else if (slider.Value + args.RotationDeltaInDegrees < 0)
    {
        slider.Value = 0;
        return;
    }
    slider.Value += args.RotationDeltaInDegrees;
    AddToLog("\nRotation: " + sliders[activeMenuItemIndex].Name + " value changed to " + slider.Value);
}

Remarks

Version history

Windows version SDK version Value added
1703 15063 ButtonHolding
1703 15063 ButtonPressed
1703 15063 ButtonReleased

Properties

Menu

Gets a reference to the menu associated with the RadialController object.

RotationResolutionInDegrees

Gets or sets the minimum rotational value required for the RadialController object to fire a RotationChanged event.

UseAutomaticHapticFeedback

Gets or sets whether haptic feedback is enabled on the wheel device for each RotationChanged event fired by the RadialController.

Methods

CreateForCurrentView()

Instantiates a RadialController object for the wheel device and binds it to the active application.

IsSupported()

Retrieves a value that indicates whether wheel devices are supported by the system.

Events

ButtonClicked

Occurs when the wheel device is pressed and then released while a custom RadialController tool is active.

Your app does not receive this event when:

Note

When a time threshold is crossed, click becomes a press and hold action. In this case, the integrated menu of contextual app commands associated with the RadialController object is displayed, and subsequent rotate and click events are processed by the menu.

ButtonHolding

Occurs when the user presses and holds down the wheel device.

ButtonPressed

Occurs when the wheel device is pressed.

ButtonReleased

Occurs when the wheel device is pressed and then released.

ControlAcquired

Occurs when a custom RadialController tool (defined by an app) is selected from the menu, or when an app associated with the RadialController object is brought to the foreground while a custom RadialController tool is active.

ControlLost

Occurs while a custom RadialController tool (defined by an app) is active, and either the app associated with the RadialController object is sent to the background, or the user activates the RadialController menu.

RotationChanged

Occurs when the wheel device is rotated while a custom RadialController tool is active.

Your app does not receive this event when:

ScreenContactContinued

Occurs only when the wheel device is moved while in contact with the digitizer surface, and a custom RadialController tool is active.

Your app does not receive this event when:

Tip

In addition to the default press and hold menu experience, the Surface Dial can also be placed directly on the screen of the Surface Studio. This enables a special "on-screen" menu.

By detecting both the contact location and bounds of the Surface Dial, the system can handle occlusion by the device and display a larger version of the menu that wraps around the outside of the Dial. This same info can also be used by your app to adapt the UI for both the presence of the device and its anticipated usage, such as the placement of the user's hand and arm.

This event occurs after ScreenContactStarted and stops on ScreenContactEnded.

ScreenContactEnded

Occurs when a wheel device that is in contact with the digitizer surface is removed (or is no longer detected), and a custom RadialController tool is active.

Your app does not receive this event when:

Tip

In addition to the default press and hold menu experience, the Surface Dial can also be placed directly on the screen of the Surface Studio. This enables a special "on-screen" menu.

By detecting both the contact location and bounds of the Surface Dial, the system can handle occlusion by the device and display a larger version of the menu that wraps around the outside of the Dial. This same info can also be used by your app to adapt the UI for both the presence of the device and its anticipated usage, such as the placement of the user's hand and arm.

This event occurs after ScreenContactStarted.

ScreenContactStarted

Occurs when initial contact is detected between a wheel device and the digitizer surface, and a custom RadialController tool is active.

Your app does not receive this event when:

Tip

In addition to the default press and hold menu experience, the Surface Dial can also be placed directly on the screen of the Surface Studio. This enables a special "on-screen" menu.

By detecting both the contact location and bounds of the Surface Dial, the system can handle occlusion by the device and display a larger version of the menu that wraps around the outside of the Dial. This same info can also be used by your app to adapt the UI for both the presence of the device and its anticipated usage, such as the placement of the user's hand and arm.

Applies to

See also