Do ukończenia mojego efektu musiałem rozwiązać pewien problem: przesuwanie i zmiana rozmiaru własnej kontrolki WPF.
Próbowałem najpierw zrobić to "po swojemu" czyli reagować odpowiednio na zdarzenia kliknięcia lewego przycisku myszki i ruchu myszki. Jednak efekt nie był zadowalający. Gdy ruchy myszką były za szybkie, kursor wylatywał poza obszar reagujący na kliknięcie i kontrolka przestawała się przesuwać.
Na szczęście WPF posiada lepsze rozwiązania a mianowicie Thumb.
Jest to obiekt który reaguje na zdarzenie bardzo pomocne przy przesuwaniu i zmianie rozmiarów własnych obiektów - DragDelta.
W moim przypadku wyglądało to tak:
Na screenie widać 4 kontrolki (jedna jest oznaczona strzałkami) które reprezentują pasma przepustowe dla filtra opartego na FFT. Chciałem aby poprzez zmianę rozmiarów i przesuwanie ich, wpływały na przetwarzanie sygnału. Thumb okazał sie idealny do tego rozwiązania.
Strzałki na rysunku pokazują 3 obiekty Thumb. Te po bokach odpowiadają za zmianę rozmiaru a całe środkowe wypełnienie za przesunięcie w poziomie.
Poniżej fragment kodu XAML kontrolki "BandControl"
Widać że dodatkowo został zdefiniowany szablon dla Thumba. Jest to niezbędne jeśli chce się uzyskać inny wygląd niż standardowy "trójwymiarowy" szary prostokąt (coś jak brzegi okien w starszych windowsach).
Wewnątrz szablonu, kolorowy prostokąt przyjmuje tło takie jak wpisane zostanie do kontrolki Thumb za pomocą TemplateBinding.
Dalej w XAMLu wystarszy dla każdego Thumba przypisać odpowiedni szablon i gotowe.
W konstruktorze kontrolki w pliku .cs dla każdego Thumba przypisałem odpowiednią metodę do zdarzenia DragDelta:
public BandControl() { this.InitializeComponent(); moveArea.DragDelta += MoveThumb_DragDelta; resizeLeft.DragDelta += ResizeLeft_DragDelta; resizeRight.DragDelta += ResizeRight_DragDelta; }
Powyższe metody zaimplementowałem w następujący sposób:
private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e) { if(this.Margin.Left + e.HorizontalChange > 0 && (this.Margin.Left + this.Width + e.HorizontalChange) < parentWidth) this.Margin = new Thickness( this.Margin.Left + e.HorizontalChange, this.Margin.Top, this.Margin.Right, this.Margin.Bottom); RaiseBarChangedEvent(); } private void ResizeLeft_DragDelta(object sender, DragDeltaEventArgs e) { if((this.ActualWidth - e.HorizontalChange) > 10 && (this.Margin.Left + e.HorizontalChange) > 0){ this.Margin = new Thickness( this.Margin.Left + e.HorizontalChange, this.Margin.Top, this.Margin.Right, this.Margin.Bottom); this.Width -= e.HorizontalChange; e.Handled = true; } RaiseBarChangedEvent(); } private void ResizeRight_DragDelta(object sender, DragDeltaEventArgs e) { if((this.ActualWidth + e.HorizontalChange) > 10 && (this.Margin.Left + this.Width + e.HorizontalChange) < parentWidth){ this.Width += e.HorizontalChange; e.Handled = true; } RaiseBarChangedEvent(); }
Dzięki temu mamy pewność że kontrolki nie wydostaną się poza obszar rodzica.
Rozmiar rodzica jest znany dzięki dodaniu nowego konstruktora przyjmującego jako parametr kontrolkę o poziom wyżej:
public BandControl(Display d) : this() { parentWidth = d.Width; }
Polecam także ten link, z którego korzystałem aby dowiedzieć się jak działa Thumb.
Brak komentarzy:
Prześlij komentarz