Je n'ai vu aucun contrôle comme celui-ci (bien que cela fait un moment que j'ai regardé tous les contrôles que les fournisseurs de contrôle WPF offraient), mais il est relativement simple d'en créer un.
Tout ce que vous avez à faire est de créer un contrôle personnalisé contenant une image (ou un dessin XAML) que vous pouvez faire pivoter pour suivre la souris. Ensuite, lier un RotateTransform à un DependencyProperty « Angle » sur votre contrôle personnalisé de sorte que lorsque « angle » est mis à jour, l'image/dessin tourne pour correspondre:
<UserControl x:Class="VolumeControlLibrary.VolumeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VolumeControlLibrary"
Height="60" Width="60">
<Image Source="/VolumeControl;component/knob.png" RenderTransformOrigin="0.5,0.5" >
<Image.RenderTransform>
<RotateTransform Angle="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:VolumeControl}}, Path=Angle}"/>
</Image.RenderTransform>
</Image>
</UserControl>
Réglage RenderTransformOrigin « 0,5, 0,5 » assure que la le contrôle tourne autour de son centre, plutôt que de tourner autour du coin supérieur gauche; nous devrons compenser cela dans le calcul de l'angle aussi.
Dans le fichier code-behind pour votre contrôle, ajouter des gestionnaires pour la souris et l'angle DependencyProperty:
public partial class VolumeControl : UserControl
{
// Using a DependencyProperty backing store for Angle.
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(double), typeof(VolumeControl), new UIPropertyMetadata(0.0));
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
public VolumeControl()
{
InitializeComponent();
this.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
this.MouseUp += new MouseButtonEventHandler(OnMouseUp);
this.MouseMove += new MouseEventHandler(OnMouseMove);
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(this);
}
private void OnMouseUp(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(null);
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (Mouse.Captured == this)
{
// Get the current mouse position relative to the volume control
Point currentLocation = Mouse.GetPosition(this);
// We want to rotate around the center of the knob, not the top corner
Point knobCenter = new Point(this.ActualHeight/2, this.ActualWidth/2);
// Calculate an angle
double radians = Math.Atan((currentLocation.Y - knobCenter.Y)/
(currentLocation.X - knobCenter.X));
this.Angle = radians * 180/Math.PI;
// Apply a 180 degree shift when X is negative so that we can rotate
// all of the way around
if (currentLocation.X - knobCenter.X < 0)
{
this.Angle += 180;
}
}
}
}
La capture de la souris assure que votre contrôle continuera d'obtenir des mises à jour de souris même lorsque l'utilisateur mouses hors de le contrôle (jusqu'à ce qu'ils relâchent le clic), et en obtenant la position de la souris par rapport à l'élément courant (le contrôle), votre calcul devrait toujours être le même quel que soit le rendu du contrôle à l'écran.
Dans cet exemple, lorsque la souris se déplace, nous calculons l'angle entre celle-ci et le centre du contrôle, puis définissons cet angle sur Angle DependencyProperty que nous avons créé. Étant donné que l'image que nous affichons est liée à cette propriété d'angle, WPF applique automatiquement la nouvelle valeur, ce qui entraîne la rotation du bouton en combinaison avec le déplacement de la souris. L'utilisation du contrôle dans votre solution est facile; il suffit d'ajouter:
<local:VolumeControl />
Vous lierait à la propriété Angle sur VolumeControl si vous voulez lier la valeur du bouton à quelque chose dans votre application; cette valeur est actuellement en degrés, mais pourrait ajouter une propriété supplémentaire pour convertir entre un angle en degrés et une valeur qui a du sens pour vous (par exemple, une valeur de 0 à 10).
Je ne sais pas trop où mettre chaque bit de code. J'ai particulièrement du mal à faire fonctionner la partie DependencyProperty. –
OK, j'ai mis tout le code dans un contrôle utilisateur et mis à jour le poste; vous devriez être capable de copier et coller le code dans votre solution. –
Belle solution - si vous vouliez aller plus simple, beaucoup de contrôles prennent juste le dY du mouvement de la souris et traduisent cela à la valeur du cadran. –