RegisterHotKey第二次就无效了

yzy8788 2015-08-26 05:31:53
只能使用一次,第二次又需要重新激活一下窗口才能用,完整的代码如下

private const int WM_HOTKEY = 0x312; //窗口消息-热键
private const int HOT_KEY_ID = 8451476;

[DllImport("user32.dll")]
public static extern UInt32 RegisterHotKey(IntPtr hWnd, UInt32 id, UInt32 fsModifiers, UInt32 vk);
[DllImport("user32.dll")]
private static extern int UnregisterHotKey(IntPtr hwnd, int id);

public Form_AutoInputAlipayPwd()
{
InitializeComponent();
}

private void Form_AutoInputAlipayPwd_Activated(object sender, EventArgs e)
{
RegisterHotKey(Handle, HOT_KEY_ID, 1 | 2, (UInt32)Keys.M); //注册热键,Alt=1、Ctrl=2
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == HOT_KEY_ID)
{
SendKeys.Send("abcdefghijklmnopqrstuvwxyz");
}
}

private void Form_AutoInputAlipayPwd_FormClosing(object sender, FormClosingEventArgs e)
{
UnregisterHotKey(Handle, HOT_KEY_ID); //销毁热键
}
...全文
511 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
crystal_lz 2015-08-27
  • 打赏
  • 举报
回复
引用 5 楼 yzy8788 的回复:
[quote=引用 1 楼 crystal_lz 的回复:] 你为什么要在Activated里面去注册热键? RegisterHotKey是注册全局热键 系统级别的热键 如果你只是想要你的窗体在激活的时候 用的热键 直接处理 键盘事件就行了 全局热键只能注册一次的。。。 就像qq的截图程序 ctrl + alt + a 就能启动 无论QQ是否是活动窗口 就算是QQ最小化也能使用 当用户按下 ctrl + alt + a 的时候 系统会想注册这个热键的窗口发送 WM_HOTKEY消息 然后程序去处理这个消息即可
我感觉不管放在什么地方注册,只要注册成功了,我不销毁的话,应该这个热键还是有效的啊[/quote] 窗体加载 或者 构造函数里面 注册一次就好了 在调用 RegisterHotKey 只要是注册成功了的 在没有 调用UnregisterHotKey 之前 热键都是有效的
yzy8788 2015-08-27
  • 打赏
  • 举报
回复
引用 1 楼 crystal_lz 的回复:
你为什么要在Activated里面去注册热键? RegisterHotKey是注册全局热键 系统级别的热键 如果你只是想要你的窗体在激活的时候 用的热键 直接处理 键盘事件就行了 全局热键只能注册一次的。。。 就像qq的截图程序 ctrl + alt + a 就能启动 无论QQ是否是活动窗口 就算是QQ最小化也能使用 当用户按下 ctrl + alt + a 的时候 系统会想注册这个热键的窗口发送 WM_HOTKEY消息 然后程序去处理这个消息即可
我现在是想要全局热键,那我应该放在什么地方注册比较好呢?
yzy8788 2015-08-27
  • 打赏
  • 举报
回复
引用 1 楼 crystal_lz 的回复:
你为什么要在Activated里面去注册热键? RegisterHotKey是注册全局热键 系统级别的热键 如果你只是想要你的窗体在激活的时候 用的热键 直接处理 键盘事件就行了 全局热键只能注册一次的。。。 就像qq的截图程序 ctrl + alt + a 就能启动 无论QQ是否是活动窗口 就算是QQ最小化也能使用 当用户按下 ctrl + alt + a 的时候 系统会想注册这个热键的窗口发送 WM_HOTKEY消息 然后程序去处理这个消息即可
我感觉不管放在什么地方注册,只要注册成功了,我不销毁的话,应该这个热键还是有效的啊
crystal_lz 2015-08-27
  • 打赏
  • 举报
回复
引用 10 楼 crystal_lz 的回复:
传送门我写过的一篇 全局热键的文章

public partial class Form1 : Form
{
    public Form1() {
        InitializeComponent();
    }

    private const int ID_HOTKEY_STATE = 0x01;
    private const int ID_HOTKEY_TEST = 0x02;//第二个热键

    private void Form1_Load(object sender, EventArgs e) {
        if (!Win32.RegisterHotKey(this.Handle, ID_HOTKEY_STATE,
            Win32.MOD_CONTROL | Win32.MOD_ALT, (uint)Keys.H)) {
            MessageBox.Show("热键注册失败");
        }
        if (!Win32.RegisterHotKey(this.Handle, ID_HOTKEY_TEST,
            Win32.MOD_CONTROL | Win32.MOD_ALT, (uint)Keys.J)) {
            MessageBox.Show("热键注册失败");
        }
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
        Win32.UnregisterHotKey(this.Handle, ID_HOTKEY_STATE);
        Win32.UnregisterHotKey(this.Handle, ID_HOTKEY_TEST);
    }
    //重写消息处理函数
    protected override void WndProc(ref Message m) {
        switch ((uint)m.Msg) {
            case Win32.WM_HOTKEY://如果注册成功 按下热键的时候会收到消息
                switch (m.WParam.ToInt32()) {//wParam中是热键的注册ID
                    case ID_HOTKEY_STATE:
                        if (this.WindowState == FormWindowState.Minimized) {
                            this.WindowState = FormWindowState.Normal;
                        }
                        this.Activate();
                        break;
                    case ID_HOTKEY_TEST:
                        MessageBox.Show("第二个热键被点下");
                        break;
                }
                break;
        }
        base.WndProc(ref m);
    }
}
剔除了 api 申明部分的代码
crystal_lz 2015-08-27
  • 打赏
  • 举报
回复
传送门我写过的一篇 全局热键的文章
Poopaye 2015-08-27
  • 打赏
  • 举报
回复
你贴出的代码里并没有处理这些key 但我怀疑是否你指处理了部分,导致剩余的消息始终没有被清除?
yzy8788 2015-08-27
  • 打赏
  • 举报
回复
刚测试了一下,在app.config里面新增
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
也不行,新增这个后,电脑里面的千牛和QQ尽然来回乱七八糟跳,跳的都无法操作电脑了。我已经看过了千牛和QQ里面的相同热键已经被我关闭了。 然后改成
<appSettings>
<add key="SendKeys" value="JournalHook"/>
</appSettings>
就和现状一样:只能使用一次。 我断点了一下,每次都会执行热键,看来问题就出在SendKeys上面了。坛子里有相关帖子《SendKeys.Send() 不稳定》http://bbs.csdn.net/topics/370169013
yzy8788 2015-08-27
  • 打赏
  • 举报
回复
引用 6 楼 crystal_lz 的回复:
[quote=引用 5 楼 yzy8788 的回复:] [quote=引用 1 楼 crystal_lz 的回复:] 你为什么要在Activated里面去注册热键? RegisterHotKey是注册全局热键 系统级别的热键 如果你只是想要你的窗体在激活的时候 用的热键 直接处理 键盘事件就行了 全局热键只能注册一次的。。。 就像qq的截图程序 ctrl + alt + a 就能启动 无论QQ是否是活动窗口 就算是QQ最小化也能使用 当用户按下 ctrl + alt + a 的时候 系统会想注册这个热键的窗口发送 WM_HOTKEY消息 然后程序去处理这个消息即可
我感觉不管放在什么地方注册,只要注册成功了,我不销毁的话,应该这个热键还是有效的啊[/quote] 窗体加载 或者 构造函数里面 注册一次就好了 在调用 RegisterHotKey 只要是注册成功了的 在没有 调用UnregisterHotKey 之前 热键都是有效的[/quote] 我也是这样想的,但是为什么我注册后,只能使用一次,第二次就无效了,必须重新激活一下窗体才能继续使用,挺奇怪的。 我来试试 @shingoscar 这位仁兄的办法行不行,也许是SendKeys问题
Poopaye 2015-08-26
  • 打赏
  • 举报
回复
Poopaye 2015-08-26
  • 打赏
  • 举报
回复
问题应该在SendKeys上 MSDN:
引用
The SendKeys class has been updated for the .NET Framework 3.0 to enable its use in applications that run on Windows Vista. The enhanced security of Windows Vista (known as User Account Control or UAC) prevents the previous implementation from working as expected. The SendKeys class is susceptible to timing issues, which some developers have had to work around. The updated implementation is still susceptible to timing issues, but is slightly faster and may require changes to the workarounds. The SendKeys class tries to use the previous implementation first, and if that fails, uses the new implementation. As a result, the SendKeys class may behave differently on different operating systems. Additionally, when the SendKeys class uses the new implementation, the SendWait method will not wait for messages to be processed when they are sent to another process. If your application relies on consistent behavior regardless of the operating system, you can force the SendKeys class to use the new implementation by adding the following application setting to your app.config file. <appSettings> <add key="SendKeys" value="SendInput"/> </appSettings> To force the SendKeys class to use the previous implementation, use the value "JournalHook" instead.
crystal_lz 2015-08-26
  • 打赏
  • 举报
回复
你为什么要在Activated里面去注册热键? RegisterHotKey是注册全局热键 系统级别的热键 如果你只是想要你的窗体在激活的时候 用的热键 直接处理 键盘事件就行了 全局热键只能注册一次的。。。 就像qq的截图程序 ctrl + alt + a 就能启动 无论QQ是否是活动窗口 就算是QQ最小化也能使用 当用户按下 ctrl + alt + a 的时候 系统会想注册这个热键的窗口发送 WM_HOTKEY消息 然后程序去处理这个消息即可

111,088

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧