2016-08-05 12 views
2

Bei der Erstellung eines benutzerdefinierten Steuerelements versuche ich, die Mausposition auf einem Canvas zu erhalten, das ein Container in meinem benutzerdefinierten Steuerelement ist. Problem ist, wenn ich mein customcontrol in eine Test-App, nur ein Raster in einem Fenster, was ich bekomme, ist immer die Mausposition auf dem Fenster selbst, aber nicht die Mausposition auf meinem customcontrol.So erhalten Sie die Mausposition auf einem Teil von CustomControl

public class HueWheel : Control 
{ 
    static HueWheel() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(HueWheel), new FrameworkPropertyMetadata(typeof(HueWheel))); 
    } 
    private bool _isPressed = false; 
    //private Canvas _templateCanvas = null; 
    private Canvas _PART_FirstCanvas; 
    private Canvas _PART_SecondCanvas; 
    private Slider _PART_Slider; 

    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 
     _PART_FirstCanvas = (Canvas)GetTemplateChild("PART_FirstCanvas"); 
     _PART_SecondCanvas = (Canvas)GetTemplateChild("PART_SecondCanvas"); 
     _PART_Slider = (Slider)GetTemplateChild("PART_Slider"); 
    } 

    protected override void OnMouseMove(MouseEventArgs e) 
    { 
     if (_isPressed) 
     { 
      const double RADIUS = 150; 
      Point newPos = e.GetPosition(_PART_SecondCanvas); 
      double angle = MyHelper.GetAngleR(newPos, RADIUS); 
      _PART_Slider.Value = (_PART_Slider.Maximum - _PART_Slider.Minimum) * angle/(2 * Math.PI); 
     } 
    } 

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) 
    { 
     _isPressed = true; 
    } 

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
    { 
     _isPressed = false; 
    } 
} 

Dies ist das XAML in generic.xaml

enthalten
<Style TargetType="{x:Type local:HueWheel}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:HueWheel}"> 
       <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> 
        <Slider x:Name="PART_Slider"> 
         <Slider.Template> 
          <ControlTemplate> 
           <Canvas x:Name="PART_FirstCanvas" Width="300" Height="300"> 
             <Image Stretch="Fill" Source="Assets/HueCircle.PNG" Focusable="False" Height="300" Width="300" RenderTransformOrigin="0.5,0.5"> 
              <Image.RenderTransform> 
               <TransformGroup> 
                <ScaleTransform/> 
                <SkewTransform/> 
                <RotateTransform Angle="270"/> 
                <TranslateTransform/> 
               </TransformGroup> 
              </Image.RenderTransform> 
             </Image> 
             <Ellipse Fill="Transparent" Width="300" Height="300" Canvas.Left="0" Canvas.Top="0"/> 
             <Canvas x:Name="PART_SecondCanvas"> 
              <Line Stroke="Transparent" StrokeThickness="5" X1="150" Y1="150" X2="150" Y2="0"/> 
              <Ellipse Fill="Black" Width="20" Height="20" Canvas.Left="140" Canvas.Top="30"/> 
              <Canvas.RenderTransform> 
               <RotateTransform CenterX="150" CenterY="150"> 
                <RotateTransform.Angle> 
                 <MultiBinding Converter="{StaticResource ValueAngleConverter}"> 
                  <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value"/> 
                  <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum"/> 
                  <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum"/> 
                 </MultiBinding> 
                </RotateTransform.Angle> 
               </RotateTransform> 
              </Canvas.RenderTransform> 
             </Canvas> 
            </Canvas> 
          </ControlTemplate> 
         </Slider.Template> 
        </Slider> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Auch die Mausposition wird nur ausgegeben, wenn die Maus auf Leinwand ist, ist es so Art Hälfte, hier zu arbeiten ... wenig verwirren.

Dies sind die beiden Funktions I zur Winkelberechnung verwenden:

public static double GetAngle(double value, double maximum, double minimum) 
{ 
    double current = (value/(maximum - minimum)) * 360; 
    if (current == 360) 
     current = 359.999; 

    return current; 
} 


public static double GetAngleR(Point pos, double radius) 
{ 
    Point center = new Point(radius, radius); 
    double xDiff = center.X - pos.X; 
    double yDiff = center.Y - pos.Y; 
    double r = Math.Sqrt(xDiff * xDiff + yDiff * yDiff); 

    double angle = Math.Acos((center.Y - pos.Y)/r); 

    if (pos.X < radius) 
     angle = 2 * Math.PI - angle; 

    if (Double.IsNaN(angle)) 
     return 0.0; 
    else 
     return angle; 
} 

Jeder Hinweis?

Danke

+0

Mögliches Duplikat von [Absolute Position des Elements innerhalb des Fensters in wpf erhalten] (http://stackoverflow.com/questions/386731/get-absolute-position-of-element-within-the-window-in-wpf) – stijn

+1

das ist kein Duplikat, wie ich versuche, die Position innerhalb des Customcontrol, nicht innerhalb des Fensters zu bekommen. – lecloneur

Antwort

1

_PART_SecondCanvas und _PART_FirstCanvas sind null, weil sie das Kind gehören Slider ‚s Steuervorlage, und nicht die "main" HueWheel Vorlage. Daher können Sie sie nicht mit GetTemplateChild() von HueWheel erreichen.

In OnApplyTemplate(), müssen Sie den Regler zuerst finden, dann seine Vorlage anwenden und schließlich FindName() auf dass Vorlage rufen Sie die Canvas-Elemente zu finden:

public override void OnApplyTemplate() 
{ 
    base.OnApplyTemplate(); 
    //_PART_FirstCanvas = (Canvas)GetTemplateChild("PART_FirstCanvas"); 
    //_PART_SecondCanvas = (Canvas)GetTemplateChild("PART_SecondCanvas"); 
    _PART_Slider = (Slider)GetTemplateChild("PART_Slider"); 

    _PART_Slider.ApplyTemplate(); 

    var sliderTemplate = _PART_Slider.Template; 
    _PART_FirstCanvas = (Canvas)sliderTemplate.FindName("PART_FirstCanvas", _PART_Slider); 
    _PART_SecondCanvas = (Canvas)sliderTemplate.FindName("PART_SecondCanvas", _PART_Slider); 
} 

Quelle: How do I get the Children of a ContentPresenter?

Einmal Sie finden tatsächlich _PART_SecondCanvas und _PART_FirstCanvas, Ihre OnMouseMove() Funktion sollte tun, was Sie erwarten.

1

In Ihrem Code

Point ControlPos = e.GetPosition (this); 
Point WindowPos = e.GetPosition(Application.Current.MainWindow); 

Werden Sie geben - Koordinaten in der Steuerung und Fensterkoordinaten.

+0

aber ich möchte die Mausposition in meinem customcontrol-Code abrufen, damit es wiederverwendbar ist. – lecloneur

+0

Was ist "ich" in Ihrem Vorschlag? – lecloneur

+0

Und Sie können die relative Position auch direkt aufrufen, indem Sie 'e.GetPosition (Application.Current.MainWindow);' –