Share via


InputNonClientPointerSource Class

Definition

Processes pointer input and window messages in the non-client area of a window.

public ref class InputNonClientPointerSource sealed
/// [Windows.Foundation.Metadata.ContractVersion(Microsoft.Foundation.WindowsAppSDKContract, 65540)]
/// [Windows.Foundation.Metadata.MarshalingBehavior(Windows.Foundation.Metadata.MarshalingType.Agile)]
/// [Windows.Foundation.Metadata.Threading(Windows.Foundation.Metadata.ThreadingModel.Both)]
class InputNonClientPointerSource final
[Windows.Foundation.Metadata.ContractVersion(typeof(Microsoft.Foundation.WindowsAppSDKContract), 65540)]
[Windows.Foundation.Metadata.MarshalingBehavior(Windows.Foundation.Metadata.MarshalingType.Agile)]
[Windows.Foundation.Metadata.Threading(Windows.Foundation.Metadata.ThreadingModel.Both)]
public sealed class InputNonClientPointerSource
Public NotInheritable Class InputNonClientPointerSource
Inheritance
Object Platform::Object IInspectable InputNonClientPointerSource
Attributes

Examples

The following example shows how a non-XAML application can use InputNonClientPointerSource APIs to implement a custom tab control.

public class ApplicationWindow
{
    public AppWindow AppWindow { get; }
    public static List<ApplicationWindow> Windows { get; } = new();

    public void ApplicationWindow()
    {
        this.AppWindow = CreateAppWindow();

        // We'll keep each window in a list to keep them alive until the user closes them.
        Windows.Add(this);

        this.AppWindow.Destroying += (AppWindow sender, object args) =>
        {
            Windows.Remove(this);
        };

        InputNonClientPointerSource nonClientPointerSource = 
            InputNonClientPointerSource.GetForWindowId(this.AppWindow.Id);

        nonClientPointerSource.SetRegionRects(NonClientRegionKind.Caption, GetTabRegion());

        // EnteringMoveSize doesn't correspond to a move-size window message.
        // It's raisedon WM_NCLBUTTONDOWN when we're about to enter the move-size loop.
        nonClientPointerSource.EnteringMoveSize += OnEnteringMoveSize;
        nonClientPointerSource.EnteredMoveSize += OnEnteredMoveSize;
        nonClientPointerSource.WindowRectChanging += OnWindowRectChanging;
        nonClientPointerSource.ExitedMoveSize += OnExitedMoveSize;

        // Note that InputNonClientPointerSource also has a WindowRectChanged event that 
        // corresponds to WM_WINDOWPOSCHANGED, but we don't need to handle it for the 
        // purposes of smooth tab tear-out.
    }

    private void OnEnteringMoveSize(InputNonClientPointerSource sender, EnteringMoveSizeEventArgs args)
    {
        if (this.SelectedTabs.Count == this.Tabs.Count)
        {
            // If all tabs are selected, then we aren't tearing out any tab, 
            // so we'll just allow the window to be dragged normally instead of 
            // creating a new window to host torn-out tabs.
            return;
        }

        // Create a new initially hidden window to host the torn-out tab.
        ApplicationWindow tornOutWindow = new();
        tornOutWindow.AppWindow.IsVisible = false;
        args.MoveSizeWindowId(tornOutWindow.AppWindow.Id);
    }

    private void OnEnteredMoveSize(InputNonClientPointerSource sender, EnteredMoveSizeEventArgs args)
    {
        // Initialize the tab tear-out state machine. 
        // This is necessary even if we didn't create a new window in OnEnteringMoveSize,
        // because we still need to handle the case where the user drags the tabs on top of 
        // another tab control to merge them into that other tab control.
    }

    private void OnWindowRectChanging(InputNonClientPointerSource sender, WindowRectChangingEventArgs args)
    {
        //
        // Update the tab tear-out state machine:
        //
        //    1. If the user has dragged the selected tabs out of the tab control's bounds, 
        //       show the new window created to host them and move the selected tabs 
        //       to the new window's tab control.
        //    2. If the user is dragging on a tab control in a window where all the tabs are selected, 
        //       allow the window to be dragged as normal.
        //    3. If the user has dragged a tab control window on top of another window's tab control, 
        //       hide the window being dragged and move the tabs being dragged to the other 
        //       window's tab control.
        //
    }

    private void OnExitedMoveSize(InputNonClientPointerSource sender, ExitedMoveSizeEventArgs args)
    {
        // Finalize the tab tear-out state machine.  Destroy any hidden windows.
    }

    private AppWindow CreateAppWindow()
    {
        // Create an AppWindow and set up its content.
    }
}

Remarks

The non-client area of a window includes elements such as the title bar, menu bar, or window frame.

These APIs can also be used by custom controls and in scenarios that depend on the completion of a move or resize (such as regenerating resources).

Properties

DispatcherQueue

Gets the dispatcher queue associated with the InputNonClientPointerSource object.

Methods

ClearAllRegionRects()

Deletes all region types within the non-client area of a window from the InputNonClientPointerSource.

ClearRegionRects(NonClientRegionKind)

Deletes each region of the specified type within the non-client area of a window from the InputNonClientPointerSource.

GetForWindowId(WindowId)

Retrieves an InputNonClientPointerSource object for the specified window.

GetRegionRects(NonClientRegionKind)

Gets the partition boundaries for each region of the specified type within the non-client area of a window.

SetRegionRects(NonClientRegionKind, RectInt32[])

Sets the partition boundaries of each region in the non-client area of a window.

Events

CaptionTapped

Occurs when the window caption reports a tap action by the pointer.

EnteredMoveSize

Occurs when the window has entered a move-size loop.

EnteringMoveSize

Occurs when the window is about to enter a move-size loop.

ExitedMoveSize

Occurs when the window has exited a move-size loop.

PointerEntered

Occurs when the pointer enters a region of the non-client area of the window..

PointerExited

Occurs when the pointer exits a region of the non-client area of the window..

PointerMoved

Occurs when the pointer is moved while within a region of the non-client area of the window.

PointerPressed

Occurs when a press action (such as a touch press or mouse click) within a region of the non-client area of the window is received for the pointer.

PointerReleased

Occurs when the pointer device associated with a prior InputNonClientPointerSource.PointerPressed action is released while within a region of the non-client area of the window.

RegionsChanged

Occurs on a change to the partition boundaries of a region in the non-client area of a window.

WindowRectChanged

Occurs when the window position has finished changing.

WindowRectChanging

Occurs when the window rect is about to change.

Applies to