WPF 让ScrollViewer支持鼠标中键滚动缩放内容
public class ScrollViewerMouseWheelScaleBehavior : Behavior<ScrollViewer>
{
public static readonly DependencyProperty MaxScaleProperty = DependencyProperty.Register("MaxScale", typeof(double), typeof(ScrollViewerMouseWheelScaleBehavior), new PropertyMetadata(10.0));
public static readonly DependencyProperty MinScaleProperty = DependencyProperty.Register("MinScale", typeof(double), typeof(ScrollViewerMouseWheelScaleBehavior), new PropertyMetadata(0.1d));
public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register("Scale", typeof(double), typeof(ScrollViewerMouseWheelScaleBehavior), new FrameworkPropertyMetadata(1.0));
public double MaxScale
{
get { return (double)GetValue(MaxScaleProperty); }
set { SetValue(MaxScaleProperty, value); }
}
public double MinScale
{
get { return (double)GetValue(MinScaleProperty); }
set { SetValue(MinScaleProperty, value); }
}
public double Scale
{
get { return (double)GetValue(ScaleProperty); }
set { SetValue(ScaleProperty, value); }
}
public EventHandler<ScaleChangedEventArgs> ScaleChanged { get; set; }
ScrollViewer scrollviewer;
FrameworkElement Content;
public ScrollViewerMouseWheelScaleBehavior() { }
public ScrollViewerMouseWheelScaleBehavior(double scale, EventHandler<ScaleChangedEventArgs> scaleChanged)
{
Scale = scale;
this.ScaleChanged = scaleChanged;
}
protected override void OnAttached()
{
base.OnAttached();
scrollviewer = AssociatedObject;
scrollviewer.PreviewMouseWheel += Target_PreviewMouseWheel;
scrollviewer.PreviewKeyDown += Scrollviewer_PreviewKeyDown;
Content = scrollviewer.Content as FrameworkElement;
}
private void Scrollviewer_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.NumPad0)
{
// 當 Ctrl + NumPad0 被按下時,重置縮放比例
OnScaleChanged(1.0);
e.Handled = true; // 阻止事件的傳播
}
}
private void OnScaleChanged(double newScale)
{
newScale = Math.Max(MinScale, Math.Min(newScale, MaxScale));
if (newScale == this.Scale) return;
double oldScale = this.Scale;
this.Scale = newScale;
if (Content != null)
{
double oldWidth = Content.Width;
double oldHeight = Content.Height;
Content.Width = Content.Width / oldScale * newScale;
Content.Height = Content.Height / oldScale * newScale;
Point mousePos = Mouse.GetPosition(Content);
double scrollh = scrollviewer.HorizontalOffset + (Content.Width - oldWidth) * mousePos.X / oldWidth;
double scrollv = scrollviewer.VerticalOffset + (Content.Height - oldHeight) * mousePos.Y / oldHeight;
if (scrollh > 0)
scrollviewer.ScrollToHorizontalOffset(scrollh);
if (scrollv > 0)
scrollviewer.ScrollToVerticalOffset(scrollv);
ScaleChanged?.Invoke(scrollviewer, new ScaleChangedEventArgs(oldScale, newScale));
}
}
private void Target_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftCtrl))
{
double newScale = this.Scale;
// 使用 Ctrl 鍵時縮放
if (e.Delta > 0)
newScale += 0.01; // 放大
else
newScale -= 0.01; // 縮小
// 限制縮放比例在一定範圍內
newScale = Math.Max(MinScale, Math.Min(newScale, MaxScale));
OnScaleChanged(newScale);
e.Handled = true; // 阻止滾輪事件的傳播
}
}
}
public class ScaleChangedEventArgs : EventArgs
{
public double OldScale { get; private set; }
public double NewScale { get; private set; }
public ScaleChangedEventArgs(double oldScale, double newScale)
{
OldScale = oldScale;
NewScale = newScale;
}
}
使用案例:
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Interaction.GetBehaviors(scrollviewer).Add(new ScrollViewerMouseWheelScaleBehavior(scale, OnMesureScale));
}
void MesureScale(object sender, ScaleChangedEventArgs args)
{
double oldscale = args.OldScale;
double newScale = args.NewScale;
//foreach (FrameworkElement child in paintAreaCanvas.Children)
//{
// if (child == null || child.DataContext == null) continue;
// var ele = child.DataContext as PaintElement;
// if (ele == null) continue;
// child.SetValue(TextElement.FontSizeProperty, ele.FontSize * newScale); // 調整字體大小
// child.SetValue(Canvas.LeftProperty, ele.X * newScale);
// child.SetValue(Canvas.TopProperty, ele.Y * newScale);
// child.SetValue(FrameworkElement.WidthProperty, ele.Width * newScale);
// child.SetValue(FrameworkElement.HeightProperty, ele.Height * newScale);
//}
Console.WriteLine($"縮放比例: {scale:P0}");
}
浙公网安备 33010602011771号