Wpf 用户控件边界外的鼠标事件问题

3
我遇到了一个奇怪的问题,不知道该如何解决。
我正在从头开始创建一个颜色选择器。我通过创建一组用户控件,并将它们组合在“主控件”中来实现这个目标。
例如,当用户在色调选择器上拖动时,我会处理鼠标按下、移动和抬起事件(在色调选择器用户控件内部)。
一个简单的布尔值决定了实际移动的发生情况。
//Mouse down
 _isDrag = true;

//Mouse Move
if(!_isDrag) return; 
//Moving the position indicator shape thingy
//Calculating the hue

//Mouse Up
_isDrag = false;

但是,如果鼠标抬起事件发生在色相选择器的边界之外,那么鼠标抬起事件将不会触发。 因此,当用户返回到色相选择器区域时,形状指示器会出现问题。
我相信答案肯定存在,但是恐怕我的搜索能力无法胜任。 我不知道该找什么。
谢谢您的时间。
解决方案:
private bool _isDrag;

    //Request Mouse capture for the Container
    private void MsDown(object sender, MouseButtonEventArgs e)
    {
        _isDrag = true;
        Mouse.Capture(MainContainer);
    }

    //Release Mouse capture
    private void MsUp(object sender, MouseButtonEventArgs e)
    {
        _isDrag = false;
        Mouse.Capture(null);
    }

    //Move the handle vertically along the main container, with respect to it's width - so it's centered.
    private void MsMove(object sender, MouseEventArgs e)
    {
        if (!_isDrag) return;
        Canvas.SetTop(Handle, e.GetPosition(ContentRow).Y - Handle.ActualHeight / 2);
    }

感谢您的回答!

编辑2:

关于我的问题,我进行了跟进。虽然Capture基本上解决了问题,但我注意到,如果快速拖动超出用户控件的边界,有时手柄会靠近边缘卡住。如果我慢慢移动鼠标,就不会发生这种情况。很奇怪。另外,我永远无法达到0和.ActualHeight。

所以,我在这里发布我的修复方法,以防其他人遇到这个问题。

我将我的网格分成了这样:

<Grid.ColumnDefinitions>
        <ColumnDefinition Width="7"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="7"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="7"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="7"></RowDefinition>
    </Grid.RowDefinitions>

数字 7 的大小是我的手柄(一个圆)的一半。

内容区域(实际上可以进行可视化交互的区域)位于中间单元格中(在一个具有虚假命中测试可见性的单独网格中)。

跨越整个主网格的是一个不可见的矩形,用于命中测试。

要移动手柄,

        private void MoveHandle()
    {
        _pos.X = _pos.X - Handle.ActualWidth/2;
        _pos.Y = _pos.Y - Handle.ActualHeight / 2;
         //this is just to be sure. I'm paranoid. Being a color picker, these actually matter a lot.
        _pos.X = Math.Max(Math.Min(_pos.X, RectColor.ActualWidth - Handle.ActualWidth/2), -Handle.ActualWidth / 2);
        _pos.Y = Math.Max(Math.Min(_pos.Y, RectColor.ActualHeight -Handle.ActualWidth/2), -Handle.ActualHeight/2);

        Canvas.SetLeft(Handle, _pos.X);
        Canvas.SetTop(Handle, _pos.Y);
    }

我不知道为什么之前的代码 几乎 可以工作。它基本上和以前一样。但是,不知怎么的,这个表现好了一百万倍。祝你好运!

1个回答

5
您要查找的搜索词是Mouse Capture。在MouseDown中捕获鼠标,并且您可以在鼠标离开您的控制后继续获取鼠标事件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接