标题:如何实现快捷键功能
只看楼主
蚕头燕尾
Rank: 10Rank: 10Rank: 10
来 自:Gryffindo
等 级:贵宾
威 望:12
帖 子:734
专家分:1546
注 册:2013-3-24
结帖率:96.08%
已结贴  问题点数:20 回复次数:10 
如何实现快捷键功能
问题是基于C#代码的,不知道发在哪里,就放在这个版块了。

要求实现全局快捷键,而且是单键,不是组合键。比如Space、A-Z等等。

1.非全局的组合快捷键(实现方法参见:http://blog.

2.非全局单键(不知道怎么实现)

3.全局组合键(同样参见上链接)

4.全局单键(我的问题)

搜索更多相关主题的帖子: 如何 组合键 快捷键 而且 
2015-08-25 14:12
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
KeyDown是冒泡事件

授人以渔,不授人以鱼。
2015-08-25 14:49
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
下面的程序,不论在何处按键,都会在上面的TextBlock中显示按下的键名,哪怕光标在TextBox中亦如此。

WpfApplication1.zip (4.48 KB)

授人以渔,不授人以鱼。
2015-08-25 14:54
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
程序代码:
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas."
        xmlns:x="http://schemas."
        xmlns:d="http://schemas."
        xmlns:mc="http://schemas."
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        KeyDown="Window_KeyDown"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="139,87,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="194,175,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>

    </Grid>
</Window>


程序代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

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

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            textBlock.Text = e.Key.ToString();
        }
    }
}

授人以渔,不授人以鱼。
2015-08-25 14:57
蚕头燕尾
Rank: 10Rank: 10Rank: 10
来 自:Gryffindo
等 级:贵宾
威 望:12
帖 子:734
专家分:1546
注 册:2013-3-24
得分:0 
这段代码我看不太懂,我写的是winForm代码

我运行了一下程序,似乎并没有什么反应?

这是程序运行界面:

学习编程,为的是表达自己的思想,而不是被别人的思想所禁锢。要先明白自己想干嘛,而不要先问别人让你干嘛。               

                                                                                                                    Black Cat      Hello Tomorrow~
2015-08-25 22:16
蚕头燕尾
Rank: 10Rank: 10Rank: 10
来 自:Gryffindo
等 级:贵宾
威 望:12
帖 子:734
专家分:1546
注 册:2013-3-24
得分:0 
从你的叙述:不论在何处按键,都会在上面的TextBlock中显示按下的键名
我感觉有点鼠标追踪的意思(我听说钩子可以这样做,因为我C#刚接触,还未仔细看钩子是什么)

我听说钩子用来做全局快捷键挺方便,且暂不用这种办法。

我还是挺想知道这样做为什么不行的,下面是我的代码:
1.HotKey类的定义
程序代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Forms;  

namespace Hangman_Steven
{
    class HotKey
    {
        //如果函数执行成功,返回值不为0。  
        //如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。  
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool RegisterHotKey(
            IntPtr hWnd,                 //要定义热键的窗口的句柄  
            int id,                      //定义热键ID(不能与其它ID重复)            
            KeyModifiers fsModifiers,    //标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效  
            Keys vk                      //定义热键的内容  
            );

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool RegisterHotKey(
            IntPtr hWnd,
            int id,
            Keys vk
            );

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool UnregisterHotKey(
            IntPtr hWnd,                 //要取消热键的窗口的句柄  
            int id                       //要取消热键的ID  
            );

        //定义了辅助键的名称(将数字转变为字符以便于记忆,也可去除此枚举而直接使用数值)  
        [Flags()]
        public enum KeyModifiers
        {
            None = 0,
            Alt = 1,
            Ctrl = 2,
            Shift = 4,
            WindowsKey = 8
        }
    }
}



2.调用
HotKey.RegisterHotKey(Handle, 101, HotKey.KeyModifiers.Shift, Keys.A);//定义Shift+A


我幻想着可以这样调用
HotKey.RegisterHotKey(Handle, 101, Keys.A);


所以我在HotKey类的定义中重载了RegisterHotKey函数(具体见定义代码)。但是实践证明:
HotKey.RegisterHotKey(Handle, 101, Keys.A);

这样定义的快捷键并不起作用。

PS:快捷键功能定义函数(部分代码)
程序代码:

 /// 监视Windows消息,重载WndProc方法,用于实现热键响应 
        protected override void WndProc(ref Message m)
        {
            const int WM_HOTKEY = 0x0312;
            //按快捷键  
            switch (m.Msg)
            {
                case WM_HOTKEY:
                    switch (m.WParam.ToInt32())
                    {
                        case 101:
                            //这里写具体的函数内容
                            break;

学习编程,为的是表达自己的思想,而不是被别人的思想所禁锢。要先明白自己想干嘛,而不要先问别人让你干嘛。               

                                                                                                                    Black Cat      Hello Tomorrow~
2015-08-25 22:27
蚕头燕尾
Rank: 10Rank: 10Rank: 10
来 自:Gryffindo
等 级:贵宾
威 望:12
帖 子:734
专家分:1546
注 册:2013-3-24
得分:0 
我想知道为什么我的代码原来那样是对的,为什么不能那样重载声明,简而言之,就是:这一切是怎么回事?


学习编程,为的是表达自己的思想,而不是被别人的思想所禁锢。要先明白自己想干嘛,而不要先问别人让你干嘛。               

                                                                                                                    Black Cat      Hello Tomorrow~
2015-08-25 22:34
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
我写的是WPF

授人以渔,不授人以鱼。
2015-08-25 22:44
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
得分:0 
我上面2楼说了,在WPF中,KeyDown事件是冒泡的:事件首先在焦点控件内触发,被焦点控件处理过后,事件会向上冒泡,即由上层控件捕获,不管上层控件处理与否,都继续向上冒,直至最高层的容器即窗体(Window)。在这种机制中,捕获全局按键成为可能,只要由Window的KeyDown事件处理代码处理该键即可。

在WinForms中,用钩子的办法,需要首先由窗体捕获键盘按键事件,再决定是否向下传送,这里与WPF的方向相反。向下传送并不难,难在由最顶层控件捕获事件之后,要知道整个窗体的控件传递链路,才能向下传递到焦点控件中,这要你自己维护。要么你窗体直接拦截了事,不再向下传,但那不现实,因为有些按键是你不需要的,那必须仍由焦点控件去处理,而这个时候你传不下去了。

解决的办法:自己维护窗体的控件树!具体地说,是Windows消息处理的轮询必须是有顺序的,首先应由Form接收,依次向下。你原来的对,恐怕是因为控件少,当窗体空控件布局复杂时,就失效了。我是不写WinForms程序的,接下去就帮不了你啦。

[ 本帖最后由 TonyDeng 于 2015-8-25 23:03 编辑 ]

授人以渔,不授人以鱼。
2015-08-25 22:57
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:10 
c#的窗体不知道有没有keypriview属性,该属性为true,则只要焦点在窗体中任何一个控件里都可以捕获键盘事件并送到需要的控件里显示,如果焦点不在本窗体,则只有消息钩子了。

能编个毛线衣吗?
2015-08-26 08:45



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-456735-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.448456 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved