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。事实上,我以前在这篇文章中已经有过失误,但我对使用交互性表示怀疑。随车使用安全吗