Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Alt+;鼠标滚轮变焦_C#_Wpf - Fatal编程技术网

C# Alt+;鼠标滚轮变焦

C# Alt+;鼠标滚轮变焦,c#,wpf,C#,Wpf,我有以下代码: private void scrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { if (Keyboard.IsKeyDown(Key.LeftAlt)) { e.Handled = true; //initiate zoooom! }

我有以下代码:

private void scrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (Keyboard.IsKeyDown(Key.LeftAlt))
            {
                e.Handled = true;

                //initiate zoooom!
            }                    
        }  
出于缩放的原因,我想实现alt+mousewheel,但我不想在scrollviewer上丢失常规的向上/向下鼠标滚轮。我只是想在放大时暂时禁用它。我尝试过在keyup和方法结束时取消处理,但仍然没有成功

上面的代码就像一个切换的东西。Alt+鼠标旋转可停止scrollviewer向上/向下滚动,但释放Alt后,scrollviewer仍被锁定。需要第二次按alt键才能释放物品。

问题 您遇到的问题是,在WPF应用程序中按Alt键会导致内置行为将焦点从当前项移动到当前项。要查看此行为,请按Alt,然后按空格,您将看到系统菜单弹出

要更清楚地看到它,请在窗口中添加一个按钮,其内容在您希望作为“访问密钥”的字符之前有一个下划线

请注意,我们基本上会钩住窗口的键向下事件来捕获所有键,然后我们会监听该键是否为系统键(可能包括F1、F2等功能键),如果是,我们会检查是否按下了Alt键

我们做第一次检查是为了稍微加快逻辑速度,而不是检查Alt键,除非我们首先知道它是一个系统键。否则,您在整个键盘上按的每一个键(例如在文本框中键入)都会涉及到检查Alt键和减慢速度

智能解决方案 为了达到您想要的效果,您确实需要能够检测用户是否处于您的“模式”或“焦点”,当用户开始按Alt时,他们处于您希望禁用访问键的模式

例如,确定此模式的一个简单方法是仅在滚动查看器聚焦时禁用Alt。然后,您的逻辑将更改为像这样有一个额外的检查

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.System && (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) 
        && e.OriginalSource == ScrollViewer) // <-- Added this check
        e.Handled = true;
}
代码隐藏

using System.Windows;
using System.Windows.Input;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.System && (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)))
                e.Handled = true;
        }
    }
}
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace WpfApp1
{

    public partial class MainWindow : Window
    {
        private bool mHasScrolledWithSystemKeyDown = false;
        private bool mSystemKeyIsDown = false;
        private IInputElement mLastFocusedControl;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            // If the system key is down...
            if (e.Key == Key.System)
                // Track it
                mSystemKeyIsDown = true;
        }

        private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            // If the system key is down while scrolling...
            if (mSystemKeyIsDown)
            {
                // If it is the first scroll since it being down...
                if (!mHasScrolledWithSystemKeyDown)
                    // Remember currently focused item
                    mLastFocusedControl = Keyboard.FocusedElement;

                // And flag as scrolled with system key down
                mHasScrolledWithSystemKeyDown = true;

                // Prevent scroll...
                e.Handled = true;

                // TODO: Zoom
            }
        }

        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            // On system key up...
            if (e.Key == Key.System)
            {
                // Track it
                mSystemKeyIsDown = false;

                // If we had scrolled with the system key down...
                if (mHasScrolledWithSystemKeyDown)
                    // Cause a small delay to allow this key up to process
                    Task.Delay(0).ContinueWith((t) => Dispatcher.Invoke(() =>
                    {
                        // Then focus the last control to "close" the system menu gracefully
                        mLastFocusedControl?.Focus();
                    }));

                // Flag the has scrolled to false to start again
                mHasScrolledWithSystemKeyDown = false;
            }
        }
    }
}
收盘时 请注意,如果您尝试在按下Alt后进行检测,然后取消该操作,请注意,如果使用任何消息泵命令(如简单地发送一个VM\u KEYUP命令)作为按住Alt的按钮,将无法正常工作,信息泵也有很多怪癖,你真的需要知道你在做什么,以免破坏其他东西。

问题 您遇到的问题是,在WPF应用程序中按Alt键会导致内置行为将焦点从当前项移动到当前项。要查看此行为,请按Alt,然后按空格,您将看到系统菜单弹出

要更清楚地看到它,请在窗口中添加一个按钮,其内容在您希望作为“访问密钥”的字符之前有一个下划线

请注意,我们基本上会钩住窗口的键向下事件来捕获所有键,然后我们会监听该键是否为系统键(可能包括F1、F2等功能键),如果是,我们会检查是否按下了Alt键

我们做第一次检查是为了稍微加快逻辑速度,而不是检查Alt键,除非我们首先知道它是一个系统键。否则,您在整个键盘上按的每一个键(例如在文本框中键入)都会涉及到检查Alt键和减慢速度

智能解决方案 为了达到您想要的效果,您确实需要能够检测用户是否处于您的“模式”或“焦点”,当用户开始按Alt时,他们处于您希望禁用访问键的模式

例如,确定此模式的一个简单方法是仅在滚动查看器聚焦时禁用Alt。然后,您的逻辑将更改为像这样有一个额外的检查

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.System && (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) 
        && e.OriginalSource == ScrollViewer) // <-- Added this check
        e.Handled = true;
}
代码隐藏

using System.Windows;
using System.Windows.Input;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.System && (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)))
                e.Handled = true;
        }
    }
}
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace WpfApp1
{

    public partial class MainWindow : Window
    {
        private bool mHasScrolledWithSystemKeyDown = false;
        private bool mSystemKeyIsDown = false;
        private IInputElement mLastFocusedControl;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            // If the system key is down...
            if (e.Key == Key.System)
                // Track it
                mSystemKeyIsDown = true;
        }

        private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            // If the system key is down while scrolling...
            if (mSystemKeyIsDown)
            {
                // If it is the first scroll since it being down...
                if (!mHasScrolledWithSystemKeyDown)
                    // Remember currently focused item
                    mLastFocusedControl = Keyboard.FocusedElement;

                // And flag as scrolled with system key down
                mHasScrolledWithSystemKeyDown = true;

                // Prevent scroll...
                e.Handled = true;

                // TODO: Zoom
            }
        }

        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            // On system key up...
            if (e.Key == Key.System)
            {
                // Track it
                mSystemKeyIsDown = false;

                // If we had scrolled with the system key down...
                if (mHasScrolledWithSystemKeyDown)
                    // Cause a small delay to allow this key up to process
                    Task.Delay(0).ContinueWith((t) => Dispatcher.Invoke(() =>
                    {
                        // Then focus the last control to "close" the system menu gracefully
                        mLastFocusedControl?.Focus();
                    }));

                // Flag the has scrolled to false to start again
                mHasScrolledWithSystemKeyDown = false;
            }
        }
    }
}
收盘时
请注意,如果您尝试在按下Alt后进行检测,然后取消该操作,请注意,如果使用任何消息泵命令(如简单地发送一个VM\u KEYUP命令)作为按住Alt的按钮,将无法正常工作,消息泵也有很多怪癖,你真的需要知道你在做什么,以避免破坏其他东西。

你是否尝试过将mousescrollevent移动到viewmodel命令?然后使用LeftAlt键绑定命令,设置LeftAlt被按下的标志,并在mousescroll命令中查看标志值?我在中编写了一个WPF行为来完成此操作,听起来它对您很有用。它甚至支持指定一个修改键(比如
LeftAlt
)。@BradleyUffner嗨,我在这个项目中使用Caliburn。事实上,我以前在这篇文章中已经有过失误,但我对使用交互性表示怀疑。与Caliburn一起使用安全吗?我以前从未使用过Caliburn,但从我刚才的快速观察来看,我认为它不会损坏任何东西。如果Caliburn提供了自己的
行为
模式,我会尝试使我的代码适应它的使用方式。@BradleyUffner遗憾的是,你的答案在我的情况下不起作用。在项目中添加交互性会导致它无法正确编译,它说:
发现不同版本的“System.Windows.Interactivity”之间存在冲突无法解决该问题。
并且运行该程序会导致Caliburn在PresentationFramework.dll中引发解析异常。是否尝试将MouseSrollEvent移动到viewmodel命令?然后使用LeftAlt键绑定命令,设置LeftAlt被按下的标志,并在mousescroll命令中查看标志值?我在中编写了一个WPF行为来完成此操作,听起来它对您很有用。它甚至支持指定一个修改键(比如
LeftAlt
)。@BradleyUffner嗨,我在这个项目中使用Caliburn。事实上,我以前在这篇文章中已经有过失误,但我对使用交互性表示怀疑。随车使用安全吗