2012-04-13 7 views
2

Ich bin ziemlich neu zu WPF, so dass ich das meiste davon die harte (aber Spaß) Art und Weise lernen. Ich konstruiere eine HSV-ähnliche Colorpicker-Benutzersteuerung und möchte das Verhalten erhalten, wo der Daumen, den ich verwende, da der "Selektor" auf einen elliptischen Bereich (Kreis tatsächlich) beschränkt ist. Wenn sie nach außen bewegt wird, sollte der Wahlschalter an der Seite bleiben und sich überhaupt nicht bewegen. Ich glaube, das ist das häufigste GUI-Verhalten, also sollte es sich so verhalten. Fühlen Sie sich frei, ein besseres Verhalten vorzuschlagen!Limit Thumb auf elliptischen Bereich

Gibt es eine gemeinsame, bekannte und empfohlene Lösung oder ist es jedem selbst überlassen, das Rad jedes Mal neu zu erfinden?

Irgendwelche guten Ideen, wie man das löst?

-Code-behind:

public partial class HSVColorPicker : UserControl 
{ 
    public HSVColorPicker() 
    { 
     InitializeComponent(); 
    } 

    void onDragDelta(object sender, DragDeltaEventArgs e) 
    { 
     Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange); 
     Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange); 
    } 
} 

XAML:

<Grid> 
    <Canvas x:Name="canvas"> 
     <Image x:Name="wheel" Source="colorwheel.png" Width="300" Margin="5,5,0,0"/> 
     <Thumb Name="thumb" DragDelta="onDragDelta" Canvas.Left="104" Canvas.Top="68" Template="{StaticResource thumbTemplate}" /> 
    </Canvas> 
</Grid> 

Während ich hier bin, ist der Daumen immer hinter dem Cursor zieht, gibt es eine andere Möglichkeit, dies zu schaffen? Wie ich schon sagte, ich bin neu in WPF und GUI-Erstellung insgesamt, vielleicht gibt es offensichtliche Lösungen, die mir nicht eingefallen sind;)

Antwort

1

ich umdenken tat und den Daumen vollständig fallen gelassen, einen Dummy-Kreis mit (benannt Daumen) statt. Jetzt höre ich zu, mouse-down, mouse-up und mousemove auf der Leinwand und bestimmen, was möglich sein sollte und nicht. Das hat die nette Eigenschaft, dass der Daumen an der Farbradkante klebt, wenn die Maus den Bereich verlässt, aber der Bereich ist ein bisschen größer als das Farbrad, um es einfach zu machen, einen Punkt am Rand zu bekommen. Nicht vollständig, aber es hat meine Frage gelöst, also poste ich es so, wie es in diesem Moment ist.

private bool mousePressed { get; set; } 
    private bool mouseWithinArea { get; set; } 
    private Point circleMiddlePoint { get; set; } 
    private int margin; 
    private double mPX; 
    private double mPY; 
    private double localXpos; 
    private double globalXpos 
    { 
     get 
     { 
      return localXpos + mPX; 
     } 
     set 
     { 
      localXpos = value - mPX; 
      Canvas.SetLeft(thumb, value); 
     } 
    } 
    private double localYpos; 
    private double globalYpos 
    { 
     get 
     { 
      return mPY - localYpos; 
     } 
     set 
     { 
      localYpos = mPY - value; 
      Canvas.SetTop(thumb, value); 
     } 
    } 

    public HSVColorPicker() 
    { 
     InitializeComponent(); 
     wheel.Width = 300; 
     margin = 15; 
     mPX = 150+margin; 
     mPY = 150+margin; 
     circleMiddlePoint = new Point(mPX, mPY); 
    } 

    private void CalcPosition(double X, double Y) 
    { 
     double radius = wheel.Width/2.0; 
     double vectorX = X - mPX; 
     double vectorY = Y - mPY; 
     double distance = Math.Sqrt(vectorX * vectorX + vectorY * vectorY); 
     if (distance > radius) 
     { 
      double factor = radius/distance; 
      vectorX *= factor; 
      vectorY *= factor; 
     } 
     globalXpos = vectorX + mPX; 
     globalYpos = vectorY + mPY; 
    } 

    private void wheel_MouseDown(object sender, MouseButtonEventArgs e) 
    { 
     if (mouseWithinArea) 
     { 
      mousePressed = true; 
      Point mousePoint = e.GetPosition(this); 
      CalcPosition(mousePoint.X, mousePoint.Y); 
     } 
    } 

    private void wheel_MouseMove(object sender, MouseEventArgs e) 
    { 
     Point mousePoint = e.GetPosition(this); 
     double relX = mousePoint.X - mPX; 
     double relY = mPY - mousePoint.Y; 
     if (mouseWithinArea) 
     { 
      if (Math.Sqrt(relX * relX + relY * relY) > 150+margin) 
      { 
       mouseWithinArea = false; 
      } 
      else 
      { 
       if (mousePressed) 
       { 
        CalcPosition(mousePoint.X, mousePoint.Y); 
       } 
      } 
     } 
     else 
     { 
      if (Math.Sqrt(relX * relX + relY * relY) < 150+margin) 
      { 
       mouseWithinArea = true; 
       if (mousePressed) 
       { 
        CalcPosition(mousePoint.X, mousePoint.Y); 
       } 
      } 
     } 
    } 

    private void wheel_MouseUp(object sender, MouseButtonEventArgs e) 
    { 
     mousePressed = false; 
    } 
} 

<Canvas x:Name="canvas" Background="Transparent" MouseDown="wheel_MouseDown" MouseMove="wheel_MouseMove" MouseUp="wheel_MouseUp" Width="330" Height="330"> 
     <Image x:Name="wheel" Source="colorwheel.png" Width="300" Margin="15,15,0,0" /> 
     <Ellipse Margin="0,0,0,0" 
       x:Name="outerEll" 
       Stroke="Silver" 
       StrokeThickness="15" 
       Width="330" 
       Height="330"/> 
     <Ellipse Name="thumb" Stroke="Black" Fill="Silver" Canvas.Left="150" Canvas.Top="150" Width="15" Height="15" Margin="-12" /> 
    </Canvas> 
0

Sie möchten, dass die Mitte des Daumens in Ihrem Farbrad liegt. Der Abstand zwischen der Mitte des Daumens und der Mitte des Farbrads (dh der Mitte der Leinwand) muss kleiner als oder gleich dem Radius des Farbrads sein die Seite Ihrer Leinwand).

Ungeprüfte C# -Code:

void onDragDelta(object sender, DragDeltaEventArgs e) 
{ 
    double radius = canvas.RenderSize.Width/2.0; 
    double thumbCenterX = Canvas.GetLeft(thumb) - thumb.RenderSize.Width + e.HorizontalChange; 
    double thumbCenterY = Canvas.GetTop(thumb) - thumb.RenderSize.Height + e.VerticalChange; 
    double colorWheelCenterX = canvas.RenderSize.Width/2.0; 
    double colorWheelCenterY = canvas.RenderSize.Height/2.0; 
    double vectorX = thumbCenterX - colorWheelCenterX; 
    double vectorY = thumbCenterY - colorWheelCenterY; 
    double distance = Math.Sqrt(vectorX * vectorX + vectorY * vectorY); 
    if(distance > radius) { 
     double factor = radius/distance; 
     vectorX *= factor; 
     vectorY *= factor; 
    } 
    Canvas.SetLeft(thumb, colorWheelCenterX + vectorX - thumb.RenderSize.Width/2.0); 
    Canvas.SetTop(thumb, colorWheelCenterY + vectorY - thumb.RenderSize.Height/2.0); 
} 
+0

Danke, obwohl es nicht unbeweglich an der Kante bleibt, während der Cursor draußen ist, haben Sie definitiv einen großen Teil der Arbeit! Der Daumen und der Cursor werden auch getrennt, wenn der Cursor verlässt und wieder eingeht, also werde ich etwas debuggen und Ihre Antwort akzeptieren. Wird meine endgültige Lösung posten, wenn Sie fertig sind. – Bob