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

如何在WinUI 3应用中锁定鼠标位置实现3D物体旋转

解决方案

CapturePointer仅负责捕获指针事件,不会限制光标物理移动或隐藏光标。要实现锁定光标位置+隐藏光标的需求,需要结合Win32 API控制光标行为,同时在指针移动时重置光标位置。

步骤1:引入Win32 API声明

在窗口类中添加以下DllImport声明,用于直接控制系统光标:

[DllImport("user32.dll")]
private static extern bool SetCursorPos(int X, int Y);

[DllImport("user32.dll")]
private static extern bool ShowCursor(bool bShow);

[DllImport("user32.dll")]
private static extern bool GetCursorPos(out POINT lpPoint);

// 辅助结构体,用于存储光标坐标
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
    public int X;
    public int Y;
}

步骤2:添加状态变量

在MainWindow类中添加变量,记录光标锁定状态和初始锁定位置:

private bool _isCursorLocked = false;
private POINT _lockedCursorPos;

步骤3:修改指针事件处理逻辑

替换原有事件代码,实现光标锁定、重置、隐藏的完整逻辑:

public MainWindow()
{
    InitializeComponent();
    View3dControl.PointerPressed += View3dControl_PointerPressed;
    View3dControl.PointerMoved += View3dControl_PointerMoved;
    View3dControl.PointerReleased += View3dControl_PointerReleased;
    View3dControl.PointerExited += View3dControl_PointerExited; // 处理光标意外移出面板的情况
}

private void View3dControl_PointerPressed(object sender, PointerRoutedEventArgs e)
{
    var panel = (SwapChainPanel)sender;
    // 捕获指针,确保事件仅由当前面板接收
    panel.CapturePointer(e.Pointer);
    // 记录当前光标在屏幕上的位置
    GetCursorPos(out _lockedCursorPos);
    // 隐藏系统光标
    ShowCursor(false);
    _isCursorLocked = true;
    e.Handled = true;
}

private void View3dControl_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    if (!_isCursorLocked) return;

    // 获取当前光标位置
    GetCursorPos(out POINT currentPos);
    // 计算光标移动偏移量,用于控制3D物体旋转
    int deltaX = currentPos.X - _lockedCursorPos.X;
    int deltaY = currentPos.Y - _lockedCursorPos.Y;

    // 此处添加你的3D物体旋转逻辑,示例:
    // Rotate3DObject(deltaX * 0.1f, deltaY * 0.1f);

    // 强制将光标重置回初始锁定位置,避免光标移动到屏幕边界
    SetCursorPos(_lockedCursorPos.X, _lockedCursorPos.Y);
    e.Handled = true;
}

private void View3dControl_PointerReleased(object sender, PointerRoutedEventArgs e)
{
    var panel = (SwapChainPanel)sender;
    panel.ReleasePointerCapture(e.Pointer);
    // 恢复光标显示
    ShowCursor(true);
    _isCursorLocked = false;
    e.Handled = true;
}

// 可选:光标意外移出面板时,强制恢复正常状态
private void View3dControl_PointerExited(object sender, PointerRoutedEventArgs e)
{
    if (_isCursorLocked)
    {
        ShowCursor(true);
        _isCursorLocked = false;
        ((SwapChainPanel)sender).ReleasePointerCapture(null);
    }
}

关键说明

  • SetCursorPos强制重置光标位置,解决屏幕边界限制问题
  • ShowCursor控制光标显示/隐藏,提升3D操作的沉浸感
  • deltaX/deltaY是旋转3D物体的核心输入,可根据需求乘以灵敏度系数调整旋转速度
  • PointerExited事件处理用于避免光标意外移出面板后无法恢复的异常情况

内容的提问来源于stack exchange,提问作者Peter Grundmann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:47:43