See the question and my original answer on StackOverflow

Here is a way to load a custom cursor from a .cur file or from any native HCURSOR. It's based on WinApp SDK's IInputCursorStaticsInterop interface that allows to define an InputCursor from a native HCURSOR.

So for this XAML:

<Window
    x:Class="WinUI3App.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <StackPanel>
        <Border
            x:Name="pencilZone"
            Width="50"
            Height="50"
            Background="LightGreen" />
    </StackPanel>
</Window>

And this window:

public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var cursor = CursorUtilities.LoadCursor(Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.Windows),
            @"cursors\aero_pen.cur"));

        pencilZone.ChangeCursor(cursor);
    }
}

This is what you should see:

enter image description here

#nullable enable
using System;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;

namespace WinUI3Tools;

public static class CursorUtilities
{
    public static void ChangeCursor(this UIElement element, InputCursor? cursor)
    {
        ArgumentNullException.ThrowIfNull(element);
        // the stupid hack...
        typeof(UIElement).InvokeMember("ProtectedCursor", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, element, new[] { cursor });
    }

    public static InputCursor? LoadCursor(string filePath)
    {
        ArgumentNullException.ThrowIfNull(filePath);
        var hcursor = LoadCursorFromFileW(filePath);
        if (hcursor == 0)
            throw new Win32Exception(Marshal.GetLastWin32Error());

        return CreateCursorFromHCURSOR(hcursor);
    }

    public static InputCursor? CreateCursorFromHCURSOR(nint hcursor)
    {
        if (hcursor == 0)
            return null;

        const string classId = "Microsoft.UI.Input.InputCursor";
        _ = WindowsCreateString(classId, classId.Length, out var hs);
        _ = RoGetActivationFactory(hs, typeof(IActivationFactory).GUID, out var fac);
        _ = WindowsDeleteString(hs);
        if (fac is not IInputCursorStaticsInterop interop)
            return null;

        interop.CreateFromHCursor(hcursor, out var cursorAbi);
        if (cursorAbi == 0)
            return null;

        return WinRT.MarshalInspectable<InputCursor>.FromAbi(cursorAbi);
    }

    [ComImport, Guid("ac6f5065-90c4-46ce-beb7-05e138e54117"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IInputCursorStaticsInterop
    {
        // IInspectable unused methods
        void GetIids();
        void GetRuntimeClassName();
        void GetTrustLevel();

        [PreserveSig]
        int CreateFromHCursor(nint hcursor, out nint inputCursor);
    }

    [ComImport, Guid("00000035-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IActivationFactory
    {
        // IInspectable unused methods
        void GetIids();
        void GetRuntimeClassName();
        void GetTrustLevel();

        [PreserveSig]
        int ActivateInstance(out nint instance);
    }

    [DllImport("api-ms-win-core-winrt-l1-1-0.dll")]
    private static extern int RoGetActivationFactory(nint runtimeClassId, [MarshalAs(UnmanagedType.LPStruct)] Guid iid, out IActivationFactory factory);

    [DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern nint LoadCursorFromFileW(string name);

    [DllImport("user32", CharSet = CharSet.Unicode)]
    private static extern bool DestroyCursor(nint hcursor);

    [DllImport("api-ms-win-core-winrt-string-l1-1-0", CharSet = CharSet.Unicode)]
    private static extern int WindowsCreateString(string? sourceString, int length, out nint @string);

    [DllImport("api-ms-win-core-winrt-string-l1-1-0", CharSet = CharSet.Unicode)]
    private static extern int WindowsDeleteString(nint @string);
}