2017-04-23 60 views
0

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

在下面的代码中,我有一个带有子图像的画布。子图像通过拖放添加,画布本身包含在外部网格中。在子图像上使用放大镜时,被放大区域的来源较高,放大镜左侧。 (源代码改编自: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); 
     } 
+0

样品缺少sliderTargetSize,BoolToVis和b:ImageCanvasBehavior –

+0

@WaltRitscher已失要简洁。无论如何,这些都不是放大镜相对于鼠标的位置。 ImageCanvasBehavior允许在画布上拖放图像。 (它没有别的)。 BoolToVis是可见性的标准真/假,并且SliderTargetSize被替换为ValueChanged事件。 –

回答

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); 
}