2013-04-01 7 views
13

Ich brauche eine Daumensteuerung, die mit einer Maus skaliert werden kann. Wenn der Benutzer die Maus über eines der Enden bewegt, sollte ein Größencursor angezeigt werden, und wenn der Benutzer auf das Ende des Steuerelements klickt und es zieht, wird die Größe geändert.Verwenden von WPF Ich suche nach einer Möglichkeit, eine Thumb-Steuerung mit der Maus zu vergrößern, um eine Kante zu ziehen.

Ich begann zu denken, dass ich ein benutzerdefiniertes Steuerelement erstellen sollte, das aus drei Daumensteuerelementen erstellt wird. Es würde einen Hauptdaumen und dann einen für jedes Ende geben, das die Größenänderung behandeln würde, aber ich entschied, dass das keine gute Lösung war.

Ich denke, dass ein besserer Ansatz wäre, ein einzelnes Thumb-Steuerelement zu verwenden und dann ein Adorner-Popup am Ende des Steuerelements zu haben, über das die Maus schwebt. Wie würden Sie bei diesem Ansatz feststellen, dass sich die Maus über einer bestimmten Kontrollregion befindet? Beispiele, wie man dies oder irgendeine Hilfe tut, würde sehr geschätzt werden.

+1

ich diese Probe in der Vergangenheit verwendet haben, aber Sie müssen die Kontrolle klicken. Vielleicht können Sie es anpassen, um Maus-Hover-Ereignisse zu abonnieren (Hittest oder etwas) http://denisvuyka.wordpress.com/2007/10/15/wpf-simple-adorner-usage-with-drag-and-resize-operations/ –

Antwort

22

ist hier, den ich vor einer Weile gemacht, es erlaubt Move und Resize, aber Sie können die Move Logik entfernen und es sollte funktionieren (der Stil noch ein bisschen chaotisch, aber es funktioniert ziemlich gut)

seine basierend auf ContentControl so können Sie jede Element innen addieren und Bewegen/Größe auf einem Canvas, verwendet es 3 Adorners, eine für Resize, eine für Verschieben und eine Information (aktuelle Größe)

Hier ist ein voll funktionierendes Beispiel anzuzeigen wenn Sie testen/verwenden/ändern/verbessern wollen :)

Code:

namespace WpfApplication21 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 
    } 

    public class ResizeThumb : Thumb 
    { 
     public ResizeThumb() 
     { 
      DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta); 
     } 

     private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e) 
     { 
      Control designerItem = this.DataContext as Control; 

      if (designerItem != null) 
      { 
       double deltaVertical, deltaHorizontal; 

       switch (VerticalAlignment) 
       { 
        case VerticalAlignment.Bottom: 
         deltaVertical = Math.Min(-e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight); 
         designerItem.Height -= deltaVertical; 
         break; 
        case VerticalAlignment.Top: 
         deltaVertical = Math.Min(e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight); 
         Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + deltaVertical); 
         designerItem.Height -= deltaVertical; 
         break; 
        default: 
         break; 
       } 

       switch (HorizontalAlignment) 
       { 
        case HorizontalAlignment.Left: 
         deltaHorizontal = Math.Min(e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth); 
         Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + deltaHorizontal); 
         designerItem.Width -= deltaHorizontal; 
         break; 
        case HorizontalAlignment.Right: 
         deltaHorizontal = Math.Min(-e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth); 
         designerItem.Width -= deltaHorizontal; 
         break; 
        default: 
         break; 
       } 
      } 

      e.Handled = true; 
     } 
    } 


    public class MoveThumb : Thumb 
    { 
     public MoveThumb() 
     { 
      DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta); 
     } 

     private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e) 
     { 
      Control designerItem = this.DataContext as Control; 

      if (designerItem != null) 
      { 
       double left = Canvas.GetLeft(designerItem); 
       double top = Canvas.GetTop(designerItem); 

       Canvas.SetLeft(designerItem, left + e.HorizontalChange); 
       Canvas.SetTop(designerItem, top + e.VerticalChange); 
      } 
     } 
    } 

    public class SizeAdorner : Adorner 
    { 
     private Control chrome; 
     private VisualCollection visuals; 
     private ContentControl designerItem; 

     protected override int VisualChildrenCount 
     { 
      get 
      { 
       return this.visuals.Count; 
      } 
     } 

     public SizeAdorner(ContentControl designerItem) 
      : base(designerItem) 
     { 
      this.SnapsToDevicePixels = true; 
      this.designerItem = designerItem; 
      this.chrome = new Control(); 
      this.chrome.DataContext = designerItem; 
      this.visuals = new VisualCollection(this); 
      this.visuals.Add(this.chrome); 
     } 

     protected override Visual GetVisualChild(int index) 
     { 
      return this.visuals[index]; 
     } 

     protected override Size ArrangeOverride(Size arrangeBounds) 
     { 
      this.chrome.Arrange(new Rect(new Point(0.0, 0.0), arrangeBounds)); 
      return arrangeBounds; 
     } 
    } 
} 

XAML:

<Window x:Class="WpfApplication21.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication21" 
     Title="MainWindow" Height="350" Width="525"> 

    <Window.Resources> 

     <Style TargetType="{x:Type ContentControl}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type ContentControl}"> 
         <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"> 
          <local:MoveThumb Cursor="SizeAll"> 
           <local:MoveThumb.Style> 
            <Style TargetType="{x:Type local:MoveThumb}"> 
             <Setter Property="Template"> 
              <Setter.Value> 
               <ControlTemplate TargetType="{x:Type local:MoveThumb}"> 
                <Rectangle Fill="Transparent" /> 
               </ControlTemplate> 
              </Setter.Value> 
             </Setter> 
            </Style> 
           </local:MoveThumb.Style> 
          </local:MoveThumb> 
          <Control x:Name="resizer"> 
           <Control.Style> 
            <Style TargetType="{x:Type Control}"> 
             <Setter Property="Template"> 
              <Setter.Value> 
               <ControlTemplate TargetType="{x:Type Control}"> 
                <Grid> 
                 <Grid Opacity="0" Margin="-3"> 
                  <local:ResizeThumb Height="3" Cursor="SizeNS" VerticalAlignment="Top" HorizontalAlignment="Stretch"/> 
                  <local:ResizeThumb Width="3" Cursor="SizeWE" VerticalAlignment="Stretch" HorizontalAlignment="Left"/> 
                  <local:ResizeThumb Width="3" Cursor="SizeWE" VerticalAlignment="Stretch" HorizontalAlignment="Right"/> 
                  <local:ResizeThumb Height="3" Cursor="SizeNS" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/> 
                  <local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNWSE" VerticalAlignment="Top" HorizontalAlignment="Left"/> 
                  <local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNESW" VerticalAlignment="Top" HorizontalAlignment="Right"/> 
                  <local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNESW" VerticalAlignment="Bottom" HorizontalAlignment="Left"/> 
                  <local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNWSE" VerticalAlignment="Bottom" HorizontalAlignment="Right"/> 
                 </Grid> 
                 <Grid IsHitTestVisible="False" Opacity="1" Margin="-3"> 
                  <Grid.Resources> 
                   <Style TargetType="{x:Type Ellipse}"> 
                    <Setter Property="SnapsToDevicePixels" Value="true" /> 
                    <Setter Property="Stroke" Value="#FFC8C8C8" /> 
                    <Setter Property="StrokeThickness" Value=".5" /> 
                    <Setter Property="Width" Value="7" /> 
                    <Setter Property="Height" Value="7" /> 
                    <Setter Property="Margin" Value="-2" /> 
                    <Setter Property="Fill" Value="Silver" /> 
                   </Style> 
                  </Grid.Resources> 
                  <Rectangle SnapsToDevicePixels="True" StrokeThickness="1" Margin="1" Stroke="Black" StrokeDashArray="4 4"/> 
                  <Ellipse HorizontalAlignment="Left" VerticalAlignment="Top"/> 
                  <Ellipse HorizontalAlignment="Right" VerticalAlignment="Top"/> 
                  <Ellipse HorizontalAlignment="Left" VerticalAlignment="Bottom"/> 
                  <Ellipse HorizontalAlignment="Right" VerticalAlignment="Bottom"/> 
                 </Grid> 
                </Grid> 
               </ControlTemplate> 
              </Setter.Value> 
             </Setter> 
            </Style> 
           </Control.Style> 
          </Control> 
          <Grid x:Name="sizeInfo" SnapsToDevicePixels="True"> 
           <Path Stroke="Red" StrokeThickness="1" Height="10" VerticalAlignment="Bottom" Margin="-2,0,-2,-15" Stretch="Fill" Data="M0,0 0,10 M 0,5 100,5 M 100,0 100,10"/> 
           <TextBlock Text="{Binding Width}" Background="White" Padding="3,0,3,0" Foreground="Red" Margin="0,0,0,-18" HorizontalAlignment="Center" VerticalAlignment="Bottom"/> 
           <Path Stroke="Red" StrokeThickness="1" Width="10" HorizontalAlignment="Right" Margin="0,-2,-15,-2" Stretch="Fill" Data="M5,0 5,100 M 0,0 10,0 M 0,100 10,100"/> 
           <TextBlock Text="{Binding Height}" Background="White" Foreground="Red" Padding="3,0,3,0" Margin="0,0,-18,0" HorizontalAlignment="Right" VerticalAlignment="Center"> 
            <TextBlock.LayoutTransform> 
             <RotateTransform Angle="90" CenterX="1" CenterY="0.5"/> 
            </TextBlock.LayoutTransform> 
           </TextBlock> 
          </Grid> 
          <ContentPresenter Content="{TemplateBinding Content}"/> 
         </Grid> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter TargetName="sizeInfo" Property="Visibility" Value="Visible" /> 
          </Trigger> 
          <Trigger Property="IsMouseOver" Value="False"> 
           <Setter TargetName="sizeInfo" Property="Visibility" Value="Hidden" /> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

    </Window.Resources> 

    <Canvas> 
     <ContentControl Width="183" Height="110" Canvas.Left="166" Canvas.Top="50" /> 
    </Canvas> 
</Window> 

Ergebnis:

enter image description hereenter image description here

Mit Inhalt innen (Button)

enter image description here

Leider die Cursor nicht zeigen, wenn SnipTool mit

+1

Brillante Antwort !! +1 –

+0

Danke für Ihre Hilfe. Von Ihrem Beispiel konnte ich die Dinge so arbeiten lassen, wie ich es brauchte. – user1401827