XAML WinUI 3:强制鼠标指针与用户控件交互,当它“souldnot”

bbmckpt7  于 2023-02-06  发布在  其他
关注(0)|答案(1)|浏览(252)

我正在创建一个WinUI 3用户控件,为了简单起见,可以将其描述为美化的滑块:

  • 每当用户按下其左键(PointerPressed事件)时,指针移动开始被跟踪。
  • 每当用户释放其左击(PointerReleased事件)时,此跟踪就会停止。
    示例XAML
<UserControl [...] >
    <Border Name="MainArea"
            PointerPressed="StartCapturing"
            PointerReleased="StopCapturing"
            PointerMoved="CaptureCoords"
            [...] >

        <!-- [...] -->

    </Border>
</UserControl>

示例C#

bool _isCapturing = false;

private void CalculateCoords(PointerRoutedEventArgs args){

    // max distance is [w,h]. min distance is [0,0]
    var h = MainArea.ActualHeight;
    var w = MainArea.ActualWidth;
    
    // Coordinates relative to the MainArea element;
    var pos = args.GetCurrentPoint(MainArea).Position;
    var (x, y) = (pos.X, pos.Y);
    
    // clip 0% - 100%
    x = x < 0 ? 0 : (x > w ? w : x);
    y = y < 0 ? 0 : (y > h ? h : y);

    // convert to percentages
    var (x_perc, y_perc) = (x/w, y/h);

    // Do stuff with the two percentages
   
}

public void StartCapturing(object? sender, PointerRoutedEventArgs args){
    _isCapturing = true;
    CalculateCoords(args);
}

public void CaptureCoords(object? sender, PointerRoutedEventArgs args){
    if (!_isCapturing) return;
    CalculateCoords(args);
}

public void StopCapturing(object? sender, PointerRoutedEventArgs args){
    _isCapturing = false;
    CalculateCoords(args);
}

当光标在控件内部时,这种方法可以正常工作。当光标离开元素时,问题就出现了:移动跟踪停止,并且如果在边界框外释放单击,则即使没有按下单击,一旦鼠标重新进入边界框,捕获也将继续。
这些问题是可以预料到的。为了消除这些问题,我想到过但不知道如何实施的唯一可能的解决方案是:

  • 强制捕获鼠标事件,即使指针退出控件
  • 将鼠标移动限制在控件的边界框内

有办法做到这两件事吗?

6ioyuze2

6ioyuze21#

您可以在StartCapturing中使用CapturePointer
您通常会捕获指针,因为您希望当前指针操作启动应用中的行为。在这种情况下,您通常不希望其他元素处理来自该指针操作的任何其他事件,直到您的行为完成或通过释放指针捕获取消为止。如果捕获了指针,则只有具有捕获的元素才会获取指针的输入事件。和其他元素不会激发事件,即使指针移动到它们的边界内。例如,考虑具有两个相邻元素的UI。**通常,如果您将指针从一个元素移动到另一个元素,您将首先从第一个元素获取PointerMoved事件,然后从第二个元素获取。但如果第一个元素已捕获指针,则第一个元素继续接收PointerMoved事件,即使捕获的指针离开其边界。**此外,当捕获的指针进入第二个元素时,第二个元素不会为捕获的指针触发PointerEntered事件。

public void StartCapturing(object sender, PointerRoutedEventArgs args)
{
     _isCapturing = true;
     CalculateCoords(args);
     MainArea.CapturePointer(args.Pointer);
        
 }

相关问题