【问题标题】:C# WPF add KeyBinding events in XAMLC# WPF 在 XAML 中添加 KeyBinding 事件
【发布时间】:2016-06-09 09:52:42
【问题描述】:

我正在使用CefSharp 库提供的ChromiumWebBrowser 向我的C# 应用程序的用户显示一个网站。

我正在尝试添加功能以允许用户使用键盘快捷键“放大/缩小”,即CTRL +/CTRL -

我已设法使用“低级全局键盘挂钩/接收器”将KeyboardListener 添加到嵌入式浏览器:http://www.dylansweb.com/2014/10/low-level-global-keyboard-hook-sink-in-c-net/

目前,当浏览器“聚焦”并且用户在键盘上按下“+”时,我的应用程序将在浏览器上“放大”。我已经这样做了:

private void _listener_OnKeyPressed(object sender, KeyPressedArgs e)
{
    if(e.KeyPressed == Key.Add)
    {
        zoomInExecuted();
    }
}

我真正想要的只是在用户按住“CTRL”键,然后按“+”时允许放大。

我在我的 C# 中编写了以下方法(这是被调用的方法:

private void _listener_OnKeyPressed(object sender, KeyPressedArgs e)
{
    Debug.WriteLine("e: " + e.KeyPressed.ToString());

    if(e.KeyPressed == Key.LeftCtrl)
    {
        leftCtrlDown = true;
        Debug.WriteLine("LeftCtrl pressed, leftCtrlDown should be true: ", leftCtrlDown.ToString());
    }
    else
    {
        leftCtrlDown = false;
    } 

    if(e.KeyPressed == Key.RightCtrl)
    {
        rightCtrlDown = true;
        Debug.WriteLine("RightCtrl pressed, rightCtrlDown should be true: ", rightCtrlDown.ToString());
    }
    else
    {
        rightCtrlDown = false;
    }

    if((leftCtrlDown == true)) //&& (e.KeyPressed == Key.Add)) 
    {
        if (e.KeyPressed == Key.Add)
        {
            Debug.WriteLine("Ctrl & + pressed, 'zoomInExecuted()' should be called ");
            zoomInExecuted();
        }
    }else if((rightCtrlDown == true)) //&& (e.KeyPressed == Key.Add))
    {
        if (e.KeyPressed == Key.Add)
        {
            Debug.WriteLine("rightCtrl & + pressed, 'zoomInExecuted()' should be called ");
            zoomInExecuted();
        }
    }
}

我使用<Grid> 上的<KeyBinding> 标记调用此方法,其中浏览器显示在我的XAML 中:

<KeyBinding Modifiers="Ctrl" Key="LeftCtrl" Command="{Binding _listener_OnKeyPressed}"></KeyBinding>

但我遇到的问题是:虽然应用程序检测到何时按下“CTRL”键(调试被写入控制台),但似乎无法检测到第二次按下键(“+”键)。

我尝试添加第二个侦听器,它在第一个侦听器内调用,仅当 leftCtrlDownrightCtrlDown 布尔值为真时(即当用户按下任一 CTRL 键时),但应用程序仍然没有'似乎没有检测到第二个键的按下...

如何让我的应用“监听”另一个键的按下,同时它已经确认当前正在按下一个键?

编辑

我已经尝试按照答案中的建议进行操作,现在我的 XAML 中有:

<Window x:Class="..."
    ....
    xmlns:local="clr-namespace:Agent"
    ... >

    <Window.Resources>
        ...
    </Window.Resources>
    <Grid Name="grid">
        ...
        <Grid x:Name="grdBrowserHost" MinHeight="900" Height="Auto" MinWidth="1205" Width="Auto" Margin="5,0,0,0" DockPanel.Dock="Bottom" Grid.ColumnSpan="1" >
            <Grid.InputBindings>
                <KeyBinding Modifiers="Ctrl" Key="Add" Command="{Binding _listener_OnKeyPressed}"></KeyBinding>
            </Grid.InputBindings>
            ...
            <cefSharp:ChromiumWebBrowser Name="browser" ...>
                <KeyBinding Modifiers="Ctrl" Key="Add">
                    <KeyBinding.Command>
                        <local:Zoom Executed="zoomInExecuted" />
                    </KeyBinding.Command>
                </KeyBinding>
            </cefSharp:ChromiumWebBrowser.InputBindings>
        </Grid>
    </Grid>
    ...
</Window>

我添加的Zoom.cs类如下:

namespace Agent
{
    class Zoom : ICommand
    {
        public event EventHandler<object> Executed;

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            if (Executed != null)
                Executed(this, parameter);
        }

        public event EventHandler CanExecuteChanged;
    }
}

但由于某种原因,我在 XAML 中遇到了编译错误:

                                            <local:Zoom Executed="zoomInExecuted" />

上面写着:

命名空间“clr-namespace:Agent”中不存在名称“Zoom”。

虽然很明显。

【问题讨论】:

  • LeftCtrl 也是修饰符,不能使用 Ctrl + LeftCtrl 的快捷方式
  • 您是指在 XAML 中吗?我尝试将其更改为:&lt;KeyBinding Modifiers="Ctrl" Key="Add" Command="{Binding _listener_OnKeyPressed}"&gt;&lt;/KeyBinding&gt; 但我遇到了同样的问题...我的控制台显示当我按下它时按下了 CTRL,然后显示当我按下它时按下了 +,但是 zoomInExecuted() 函数没有'似乎没有被调用..
  • Zoom 可能需要公开。

标签: c# wpf xaml keyboard-shortcuts keypress


【解决方案1】:

这行不行:

<KeyBinding Modifiers="Ctrl" Key="LeftCtrl" Command="{Binding _listener_OnKeyPressed}"/>

KeyBinding.Command 需要一个实现ICommand 的对象,您将它绑定到一个方法。

ICommand 接口的基本实现如下所示:

class SimpleCommand : ICommand
{
    public event EventHandler<object> Executed;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        if (Executed != null)
            Executed(this, parameter);
    }

    public event EventHandler CanExecuteChanged;
}

你可以这样使用:

<Window.InputBindings>
    <KeyBinding Modifiers="Control" Key="Add">
       <KeyBinding.Command>
           <local:SimpleCommand Executed="SimpleCommand_OnExecuted"/>
       </KeyBinding.Command>
    </KeyBinding>
</Window.InputBindings>

在后面的代码中:

private void SimpleCommand_OnExecuted(object sender, object e)
{
    MessageBox.Show("SimpleCommand Executed");
}

通常您会使用Commanding 在代码中定义命令并在 XAML 中使用它。当您将该命令绑定到KeyBindingButtonMenuItem(或其他)时,您的实现的CanExecute 方法可用于禁用该命令(并因此禁用它绑定到的元素)。

【讨论】:

  • 感谢您的回答。我的代码“有效”,但前提是我希望键盘快捷键由一个键组成 - 即,如果我仅在按下键盘上的“+”时调用“缩放”方法,则 GUI 上显示的视图将放大- 我正在寻找的是一种仅在同时按下“CTRL”和“+”时才调用此事件的方法。我看不到您在答案中编写的代码如何解决这个问题?你能再给我解释一下吗?
  • 看看你的代码,看来我的类必须继承自ICommand?我不能这样做,因为我已经从Window 继承,因为我的应用程序提供了其他功能。我如何将ICommand 与现有代码一起使用?使用键盘时将ICommand 传递给我的应用程序与传递方法有何不同?
  • 什么?不!窗口不必从ICommand 继承。您的 Command 必须这样做。我已经提供了一个简单的实现(SimpleCommand)。您只需遵循该模式,而不是 SimpleCommand_OnExecuted,而是为每个 KeyBinding 提供自己的事件处理程序(例如 ZoomIn_OnExecuted
  • 您编写的class SimpleCommand : ICommand 代码块显示了什么?这就是让我认为我必须让我的类继承自ICommand 的原因...我是否需要编写一个实现ICommand 接口的类,然后从XAML 中的CTRL+ 按键调用它?我不知道应该在哪里/如何实现您在class SimpleCommand 中编写的代码?
  • 把它放在一个.cs文件中,引用xaml中的命名空间(xmlns:local=whatever)并使用它。
【解决方案2】:

问题是您只挂钩 WM_KEYDOWN 和 WM_SYSKEYDOWN 消息。您还需要挂钩 WM_KEYUP 和 WM_SYSKEYUP 消息。为了确定当前是否正在按下 CTRL 键,您必须在他们按下键时设置 leftCtrlDown = true,并在他们释放键时设置 leftCtrlDown = false。当他们按下除控制之外的任何键时,您的代码设置 leftCtrlDown = false 。这个逻辑是错误的。

查看链接的文章,您需要修改 HookCallback() 以监听 WM_KEYUP 和 WM_SYSKEYUP。然后,您将需要为按键添加另一个事件,或者在 KeyPressedArgs 中添加一个标志,以指示该事件是针对按键向上还是按键向下触发。无论哪种方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 2023-03-28
    • 2017-07-26
    • 1970-01-01
    相关资源
    最近更新 更多