You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET MAUI(Windows)中使用自定义.cur文件作为光标?

.NET MAUI Windows 自定义.cur光标问题

我在.NET MAUI Windows应用中尝试使用自定义.cur格式光标文件,切换内置光标(如Hand、Arrow)时功能正常,但加载自定义.cur文件后,光标仅在标题栏变化,主窗口内容区域无变化。

现有可行的内置光标代码

using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.Maui.Platform;

// 设置内置手型光标示例
var window = (Application.Current.Windows[0].Handler.PlatformView as MauiWinUIWindow);
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);

var cursor = InputSystemCursor.Create(InputSystemCursorShape.Hand);
InputCursor inputCursor = cursor;
window.CoreWindow.PointerCursor = inputCursor;

尝试的自定义光标代码(未达预期)

using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.Maui.Platform;
using System.Runtime.InteropServices;

public static class CursorHelper
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr LoadCursorFromFile(string filename);

    [DllImport("user32.dll")]
    private static extern IntPtr SetCursor(IntPtr hCursor);

    public static void SetCustomCursor(string filePath)
    {
        IntPtr hCursor = LoadCursorFromFile(filePath);
        if (hCursor != IntPtr.Zero)
        {
            SetCursor(hCursor);
        }
    }
}

调用方式:

CursorHelper.SetCustomCursor("dot.cur");

疑问

  1. 如何在.NET MAUI Windows应用中正确设置自定义.cur文件作为光标?
  2. 是否应使用WinUI互操作替代user32.dll?
  3. 将.cur文件嵌入为资源是否是正确做法?
  4. 是否需要手动处理PointerMoved事件?

解决方案与回答

1. 正确设置自定义.cur光标的方法

问题核心是SetCursor仅临时修改光标,WinUI内容区域会自动重置光标状态。正确做法是将自定义光标转换为WinUI的InputCursor对象,再赋值给窗口的CoreWindow.PointerCursor,让框架统一管理整个窗口的光标显示。

2. 优先使用WinUI互操作替代user32.dll

是的,直接基于WinUI API实现更贴合MAUI的WinUI集成逻辑,避免原生API与框架的冲突。可以通过InputCursor.CreateFromPointer将user32加载的光标句柄转换为WinUI兼容的InputCursor,或直接用WinUI的文件加载API读取光标。

3. 将.cur文件嵌入为资源是推荐做法

嵌入资源能避免打包后的文件路径问题,确保应用运行时可稳定访问光标文件。只需将文件的生成操作设为Embedded resource,再通过程序集资源流读取即可。

4. 不需要手动处理PointerMoved事件

只要正确设置CoreWindow.PointerCursor,WinUI框架会自动在整个窗口(包括内容区域)应用光标,无需手动监听指针移动事件。

可运行的完整代码示例

步骤1:配置光标文件

将dot.cur添加到项目(比如Resources文件夹),右键文件→属性:

  • 生成操作:Embedded resource
  • 复制到输出目录:如果较新则复制

步骤2:自定义光标帮助类

using Microsoft.UI.Input;
using Microsoft.Maui.Platform;
using System.IO;
using System.Reflection;

public static class CustomCursorHelper
{
    public static void SetCustomCursor(string resourceFullName)
    {
        var window = Application.Current.Windows[0].Handler.PlatformView as MauiWinUIWindow;
        if (window == null) return;

        // 从嵌入资源读取光标流
        var assembly = Assembly.GetExecutingAssembly();
        using var resourceStream = assembly.GetManifestResourceStream(resourceFullName);
        if (resourceStream == null) return;

        // 将流写入临时文件(WinUI需要文件路径加载光标)
        var tempFilePath = Path.Combine(Path.GetTempPath(), "temp_custom_cursor.cur");
        using var fileStream = new FileStream(tempFilePath, FileMode.Create);
        resourceStream.CopyTo(fileStream);

        // 加载光标并转换为WinUI InputCursor
        var cursorHandle = LoadCursorFromFile(tempFilePath);
        if (cursorHandle != IntPtr.Zero)
        {
            var inputCursor = InputCursor.CreateFromPointer(cursorHandle);
            window.CoreWindow.PointerCursor = inputCursor;
        }

        // 清理临时文件
        File.Delete(tempFilePath);
    }

    [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern IntPtr LoadCursorFromFile(string filename);
}

步骤3:调用方法

在页面的OnAppearing或按钮点击事件中调用(注意资源名称格式:项目命名空间.文件夹名.文件名.cur):

// 示例:项目命名空间为MauiCursorDemo,光标放在Resources文件夹
CustomCursorHelper.SetCustomCursor("MauiCursorDemo.Resources.dot.cur");

替代方案:直接用WinUI StorageFile加载

如果光标文件设为Content类型(生成操作选Content,复制到输出目录),可直接用WinUI异步API加载:

using Microsoft.UI.Input;
using Microsoft.Maui.Platform;
using Windows.Storage;

public static async Task SetCustomCursorAsync(string relativeFilePath)
{
    var window = Application.Current.Windows[0].Handler.PlatformView as MauiWinUIWindow;
    if (window == null) return;

    var fullPath = Path.Combine(AppContext.BaseDirectory, relativeFilePath);
    var storageFile = await StorageFile.GetFileFromPathAsync(fullPath);
    var inputCursor = await InputCursor.CreateFromFileAsync(storageFile);
    window.CoreWindow.PointerCursor = inputCursor;
}

调用方式:

await SetCustomCursorAsync("Resources/dot.cur");

内容的提问来源于stack exchange,提问作者Murad Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 10:44:52