惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
T
Threatpost
P
Palo Alto Networks Blog
NISL@THU
NISL@THU
O
OpenAI News
Project Zero
Project Zero
G
GRAHAM CLULEY
P
Privacy International News Feed
A
Arctic Wolf
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
M
MIT News - Artificial intelligence
T
Threat Research - Cisco Blogs
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
D
Docker
aimingoo的专栏
aimingoo的专栏
博客园 - 【当耐特】
N
Netflix TechBlog - Medium
云风的 BLOG
云风的 BLOG
雷峰网
雷峰网
W
WeLiveSecurity
P
Proofpoint News Feed
腾讯CDC
Cloudbric
Cloudbric
S
Secure Thoughts
C
Check Point Blog
博客园 - Franky
T
The Exploit Database - CXSecurity.com
T
Troy Hunt's Blog
GbyAI
GbyAI
Security Archives - TechRepublic
Security Archives - TechRepublic
Application and Cybersecurity Blog
Application and Cybersecurity Blog
月光博客
月光博客
C
Cyber Attacks, Cyber Crime and Cyber Security
I
Intezer
TaoSecurity Blog
TaoSecurity Blog
L
Lohrmann on Cybersecurity
V
Visual Studio Blog
F
Fortinet All Blogs
博客园 - 叶小钗
C
CXSECURITY Database RSS Feed - CXSecurity.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recorded Future
Recorded Future
C
Cisco Blogs
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
Y
Y Combinator Blog
Apple Machine Learning Research
Apple Machine Learning Research

博客园 - HotSky

Chrome启用CDP(chrome-devtools-protocol)进行远程操控 WPF 让ScrollViewer支持按住鼠标中键拖拽滚动内容 Nodejs使用 nodejs中写sql需要用in时的写法 C#城市最短路径 C#Animation Sqlite PDF附录A: 内容流操作码 WPF FPS类 生命模拟 C# Sql帮助类,可扩展 WPF WriteableBitmap通过GDI+绘制帮助类 Alpha混合 Bmp读写二值图 WPF支持任意快捷键+鼠标组合的绑定类 WPF阻止窗体被系统缩放,使用显示器DPI WPF DataGrid自动增长序号列 C#访问或修改私有类、函数、变量、属性 WPF一个简单的属性编辑控件
WPF 让ScrollViewer支持鼠标中键滚动缩放内容
HotSky · 2026-01-27 · via 博客园 - HotSky
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}");
}