难以正确定位画布的子元素中的鼠标位置

时间:2017-04-23 19:56:36

标签: wpf xaml

WPF

在下面的代码中,我有一个带有子图像的Canvas。通过拖放添加子图像,并且Canvas本身包含在外部Grid中。当在儿童图像上使用放大镜时,被放大的区域的源更高并且放大器的左侧。 (源代码改编自:A Magnifier

这是如何解决的?

生成的图像。放大镜的中心应该在“S”之上,而不是在它的右边。

Mouse Position is wrong

XAML:
 <ScrollViewer Name="TheScrollViewer" Grid.Row ="2" Grid.RowSpan="2" Grid.Column="1" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Auto"  >

            <Grid ShowGridLines="True" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="60"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>

         <Canvas Grid.Column="1" Grid.Row="1" Background="Blue" Name="mainUI" PreviewMouseMove="OnMoveOverMainUI"
                        Panel.ZIndex="{Binding ImageLayer.ZIndex}" Visibility="{Binding ImageLayer.Visibility}" >
                    <i:Interaction.Behaviors>
                        <b:ImageCanvasBehavior Source ="{Binding ImageLayer.Source}" />
                    </i:Interaction.Behaviors>
                </Canvas>
<Canvas HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="1" Grid.Row="1" Panel.ZIndex="1000" >
                    <Canvas Name="magnifierCanvas" IsHitTestVisible="False" 
                                Visibility="{Binding ElementName=checkEnableMagnifier,Path=IsChecked, Converter={StaticResource BoolToVis}}">
                        <Line StrokeThickness="30" X1="200" Y1="200" X2="300" Y2="300">
                            <Line.Stroke>
                                <LinearGradientBrush StartPoint="0.78786,1" EndPoint="1,0.78786">
                                    <GradientStop Offset="0" Color="DarkGreen" />
                                    <GradientStop Offset="0.9" Color="LightGreen" />
                                    <GradientStop Offset="1" Color="Green" />
                                </LinearGradientBrush>
                            </Line.Stroke>
                        </Line>
                        <Ellipse Width="250" Height="250" Fill="White" />
                        <Ellipse Width="250" Height="250" Name="magnifierEllipse" StrokeThickness="3">
                            <Ellipse.Fill>
                                <VisualBrush ViewboxUnits="Absolute" Viewbox="0,0,50,50"
                         ViewportUnits="RelativeToBoundingBox" Viewport="0,0,1,1"/>
                            </Ellipse.Fill>
                            <Ellipse.Stroke>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                    <GradientStop Offset="0" Color="#AAA" />
                                    <GradientStop Offset="1" Color="#111" />
                                </LinearGradientBrush>
                            </Ellipse.Stroke>
                        </Ellipse>
                        <Ellipse Canvas.Left="2" Canvas.Top="2" StrokeThickness="4" Width="246" Height="246">
                            <Ellipse.Stroke>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                    <GradientStop Offset="0" Color="#555" />
                                    <GradientStop Offset="1" Color="#EEE" />
                                </LinearGradientBrush>
                            </Ellipse.Stroke>

                        </Ellipse>
                    </Canvas>
                </Canvas>
             </Grid>
         </ScrollViewer>

Code-Behind:
   private void ZoomChanged(object sender, EventArgs e)
        {
            if (magnifierEllipse != null)
            {
                VisualBrush b = (VisualBrush)magnifierEllipse.Fill;
                Rect viewBox = b.Viewbox;
                double val = sliderTargetSize.Value;
                viewBox.Width = val;
                viewBox.Height = val;
                b.Viewbox = viewBox;
            }
        }

        private void OnMoveOverMainUI(object sender, MouseEventArgs e)
        {
            VisualBrush b = (VisualBrush)magnifierEllipse.Fill;
            Point pos = e.MouseDevice.GetPosition(mainUI);
            Rect viewBox = b.Viewbox;
            double xoffset = viewBox.Width / 2.0;
            double yoffset = viewBox.Height / 2.0;
            viewBox.X = pos.X - xoffset;
            viewBox.Y = pos.Y - yoffset;
            b.Viewbox = viewBox;
            Canvas.SetLeft(magnifierCanvas, pos.X - magnifierEllipse.Width / 2);
            Canvas.SetTop(magnifierCanvas, pos.Y - magnifierEllipse.Height / 2);
        }

1 个答案:

答案 0 :(得分:0)

修正了问题。当在自己的窗口中时,此过程很有效 - 在网格内的用户控件中不是这样。

private void OnMoveOverMainUI(object sender, MouseEventArgs e)
        {
            VisualBrush b = (VisualBrush)magnifierEllipse.Fill;
            Point pos = e.MouseDevice.GetPosition(mainUI);
            Rect viewBox = b.Viewbox;
            double xoffset = viewBox.Width / 2.0;
            double yoffset = viewBox.Height / 2.0;
            viewBox.X = pos.X - xoffset;
            viewBox.Y = pos.Y - yoffset;
            b.Viewbox = viewBox;
            Canvas.SetLeft(magnifierCanvas, pos.X - magnifierEllipse.Width / 2);
            Canvas.SetTop(magnifierCanvas, pos.Y - magnifierEllipse.Height / 2);
        }

我需要的更正版本是:

private void OnMoveOverMainUI(object sender, MouseEventArgs e)
                {
                    // Get position of the mainUI to its ancestor the MainGrid
                    Point relativePoint = mainUI.TransformToAncestor(MainGrid)
                                     .Transform(new Point(0, 0));

                    // Get position of the Mouse relative to the mainUI
                    Point pp = e.MouseDevice.GetPosition(mainUI);

                    // Get position of the mouse relative to the MainGrid.
                    Point pos = new Point(pp.X + relativePoint.X, pp.Y + relativePoint.Y);

                    VisualBrush b = (VisualBrush)magnifierEllipse.Fill;

                    Rect viewBox = b.Viewbox;
                    double xoffset = viewBox.Width / 2.0;
                    double yoffset = viewBox.Height / 2.0;
                    viewBox.X = pos.X - xoffset;
                    viewBox.Y = pos.Y - yoffset;
                    b.Viewbox = viewBox;
                    Canvas.SetLeft(magnifierCanvas, pos.X - magnifierEllipse.Width / 2 - relativePoint.X);
                    Canvas.SetTop(magnifierCanvas, pos.Y - magnifierEllipse.Height / 2 - relativePoint.Y);
}