简体   繁体   English

WinUI 3:强制鼠标指针在“不应该”时与用户控件交互

[英]WinUI 3 : Force Mouse Pointer to interact with a User Control, when it "souldn't"

I'm creating a WinUI 3 User Control that -for sake of simplicity- can be described as glorified slider:我正在创建一个 WinUI 3 用户控件,为了简单起见,它可以被描述为美化 slider:

  • Whenever user presses their left click ( PointerPressed event), Pointer movement starts being tracked.每当用户按下左键单击( PointerPressed事件)时,指针移动就会开始被跟踪。
  • Whenever uses releases their left click ( PointerReleased event), this tracking stops.每当用户释放他们的左键单击( PointerReleased事件)时,此跟踪就会停止。

Sample XAML样品XAML

<UserControl [...] >
    <Border Name="MainArea"
            PointerPressed="StartCapturing"
            PointerReleased="StopCapturing"
            PointerMoved="CaptureCoords"
            [...] >

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

    </Border>
</UserControl>

Sample C#样品 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);
}

This methodology works fine while the cursor is inside the control.当 cursor 在控件内时,此方法工作正常。 The problem comes when the cursor leaves the element: Movement tracking stops and, if click is released outside of the bounding box, the capturing will continue once the mouse re-enters the bounding box, even without click pressed.当 cursor 离开元素时,问题就来了:移动跟踪停止,如果在边界框外释放点击,即使没有按下点击,一旦鼠标重新进入边界框,捕获也会继续。

These problems where to be expected.这些问题在意料之中。 To eliminate them, the only possible solutions I have thought of but don't know how to implement them, are:为了消除它们,我想到但不知道如何实施的唯一可能的解决方案是:

  • Force-Capture Mouse events, even when pointer exits the control强制捕获鼠标事件,即使指针退出控件
  • Restrain mouse movement within control's bounding box限制控件边界框内的鼠标移动

Is there a way to do any of these two things?有没有办法做这两件事?

You can use CapturePointer in StartCapturing .您可以在StartCapturing中使用CapturePointer

You typically capture the pointer because you want the current pointer action to initiate a behavior in your app.您通常捕获指针是因为您希望当前指针操作在您的应用程序中启动一个行为。 In this case you typically don't want other elements to handle any other events that come from that pointer's actions, until your behavior is either completed or is canceled by releasing the pointer capture .在这种情况下,您通常不希望其他元素处理来自该指针操作的任何其他事件,直到您的行为完成或通过释放指针捕获而取消 If a pointer is captured, only the element that has capture gets the pointer's input events, and other elements don't fire events even if the pointer moves into their bounds.如果指针被捕获,则只有捕获的元素会获取指针的输入事件,而其他元素即使指针移入它们的边界也不会触发事件。 For example, consider a UI that has two adjacent elements.例如,考虑一个具有两个相邻元素的 UI。 Normally, if you moved the pointer from one element to the other, you'd first get PointerMoved events from the first element, and then from the second element.通常,如果将指针从一个元素移动到另一个元素,您将首先从第一个元素获取 PointerMoved 事件,然后从第二个元素获取。 But if the first element has captured the pointer, then the first element continues to receive PointerMoved events even if the captured pointer leaves its bounds.但是,如果第一个元素捕获了指针,那么即使捕获的指针离开其边界,第一个元素也会继续接收 PointerMoved 事件。 Also, the second element doesn't fire PointerEntered events for a captured pointer when the captured pointer enters it.此外,当捕获的指针进入时,第二个元素不会为捕获的指针触发 PointerEntered 事件。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM