Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.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# 注册已使用的热键_C#_Hook_Registerhotkey - Fatal编程技术网

C# 注册已使用的热键

C# 注册已使用的热键,c#,hook,registerhotkey,C#,Hook,Registerhotkey,背景: 我想全局收听热键序列(Ctrl+Alt+Left),因此我使用: [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); 这对于许多其他热键序列非常有效,例如Ctrl+Alt+PageUp,Ctrl+Alt+PageDown,等等。。。但是,Ctrl+Alt+Left会出现问题 问题: 在一台计算机上,它可以

背景:

我想全局收听热键序列(
Ctrl+Alt+Left
),因此我使用:

[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
这对于许多其他热键序列非常有效,例如
Ctrl+Alt+PageUp
Ctrl+Alt+PageDown
,等等。。。但是,
Ctrl+Alt+Left
会出现问题


问题:

在一台计算机上,它可以正常工作,就像任何其他热键序列一样,但在另一台计算机上,如果使用
Ctrl+Alt+Arrow
旋转屏幕,它无法注册热键(即返回零,并且不会回调窗口句柄)

MSDN表示:如果为热键指定的击键已被另一个热键注册,则RegisterHotKey失败

我希望能够注册热键序列,无论发生什么,如果需要,覆盖它。我当然希望屏幕保持不旋转,至少在我的程序运行期间

更改热键序列并不是一个真正的选项,因为其他计算机可能也有可能导致故障的其他热键序列


问题:

作为屏幕旋转热键的
Ctrl+Alt+Left
与作为保存热键的
Ctrl+S
之间有什么区别,两者导致一个失败,而另一个失败?(可能是因为一个是全局热键,第二个是上下文?)

是否可以完全覆盖热键?这是个好主意吗


最重要的是,我如何确保我的热键将被注册?

我刚刚将我的方法从热键改为挂钩。 我正在监听任何低级键盘按下事件,并在使用winAPI触发此类事件时获取修饰符的状态。然后我有关于当前按下序列的完整信息

要做到这一点需要很长很难看的代码,但最终很容易使用

/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class GlobalKeyboardHook
{
    #region Constant, Structure and Delegate Definitions

    /// <summary>
    /// defines the callback type for the hook
    /// </summary>
    public delegate int KeyboardHookProc(int code, int wParam, ref KeyboardHookStruct lParam);

    public struct KeyboardHookStruct
    {
        public int vkCode;
        public int scanCode;
        public int flags;
        public int time;
        public int dwExtraInfo;
    }

    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x100;
    private const int WM_KEYUP = 0x101;
    private const int WM_SYSKEYDOWN = 0x104;
    private const int WM_SYSKEYUP = 0x105;

    #endregion

    /// <summary>
    /// The collections of keys to watch for
    /// </summary>
    public List<Keys> HookedKeys = new List<Keys>();

    /// <summary>
    /// Handle to the hook, need this to unhook and call the next hook
    /// </summary>
    private IntPtr _hhook = IntPtr.Zero;

    /// <summary>
    /// Initializes a new instance of the <see cref="GlobalKeyboardHook"/> class and installs the keyboard hook.
    /// </summary>
    public GlobalKeyboardHook()
    {
        this.Hook();
    }

    /// <summary>
    /// Releases unmanaged resources and performs other cleanup operations before the
    /// <see cref="GlobalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
    /// </summary>
    ~GlobalKeyboardHook()
    {
        this.Unhook();
    }

    /// <summary>
    /// Installs the global hook
    /// </summary>
    public void Hook()
    {
        IntPtr hInstance = LoadLibrary("User32");
        this._hhook = SetWindowsHookEx(WH_KEYBOARD_LL, this.HookProc, hInstance, 0);
    }

    /// <summary>
    /// Uninstalls the global hook
    /// </summary>
    public void Unhook()
    {
        UnhookWindowsHookEx(this._hhook);
    }

    /// <summary>
    /// The callback for the keyboard hook
    /// </summary>
    /// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
    /// <param name="wParam">The event type</param>
    /// <param name="lParam">The keyhook event information</param>
    /// <returns></returns>
    private int HookProc(int code, int wParam, ref KeyboardHookStruct lParam)
    {
        if (code >= 0)
        {
            var key = (Keys) lParam.vkCode;

            if (this.HookedKeys.Contains(key))
            {
                var handler = this.KeyPressed;

                if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (handler != null))
                {
                    ModifierKeys mods = 0;

                    if (Keyboard.IsKeyDown(Keys.Control) || Keyboard.IsKeyDown(Keys.ControlKey) ||
                        Keyboard.IsKeyDown(Keys.LControlKey) || Keyboard.IsKeyDown(Keys.RControlKey))
                    {
                        mods |= ModifierKeys.Control;
                    }

                    if (Keyboard.IsKeyDown(Keys.Shift) || Keyboard.IsKeyDown(Keys.ShiftKey) ||
                        Keyboard.IsKeyDown(Keys.LShiftKey) || Keyboard.IsKeyDown(Keys.RShiftKey))
                    {
                        mods |= ModifierKeys.Shift;
                    }

                    if (Keyboard.IsKeyDown(Keys.LWin) || Keyboard.IsKeyDown(Keys.RWin))
                    {
                        mods |= ModifierKeys.Win;
                    }

                    if (Keyboard.IsKeyDown(Keys.Alt))
                    {
                        mods |= ModifierKeys.Alt;
                    }

                    handler(this, new KeyPressedEventArgs(mods, key));
                }
            }
        }

        return CallNextHookEx(this._hhook, code, wParam, ref lParam);
    }

    public event EventHandler<KeyPressedEventArgs> KeyPressed;

    #region DLL imports

    /// <summary>
    /// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
    /// </summary>
    /// <param name="idHook">The id of the event you want to hook</param>
    /// <param name="callback">The callback.</param>
    /// <param name="hInstance">The handle you want to attach the event to, can be null</param>
    /// <param name="threadId">The thread you want to attach the event to, can be null</param>
    /// <returns>a handle to the desired hook</returns>
    [DllImport("user32.dll")]
    private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance, uint threadId);

    /// <summary>
    /// Unhooks the windows hook.
    /// </summary>
    /// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
    /// <returns>True if successful, false otherwise</returns>
    [DllImport("user32.dll")]
    private static extern bool UnhookWindowsHookEx(IntPtr hInstance);

    /// <summary>
    /// Calls the next hook.
    /// </summary>
    /// <param name="idHook">The hook id</param>
    /// <param name="nCode">The hook code</param>
    /// <param name="wParam">The wparam.</param>
    /// <param name="lParam">The lparam.</param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    private static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref KeyboardHookStruct lParam);

    /// <summary>
    /// Loads the library.
    /// </summary>
    /// <param name="lpFileName">Name of the library</param>
    /// <returns>A handle to the library</returns>
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibrary(string lpFileName);

    #endregion
}

static class Keyboard
{
    [Flags]
    private enum KeyStates
    {
        None = 0,
        Down = 1,
        Toggled = 2
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern short GetKeyState(int keyCode);

    private static KeyStates GetKeyState(Keys key)
    {
        KeyStates state = KeyStates.None;

        short retVal = GetKeyState((int)key);

        //If the high-order bit is 1, the key is down
        //otherwise, it is up.
        if ((retVal & 0x8000) == 0x8000)
            state |= KeyStates.Down;

        //If the low-order bit is 1, the key is toggled.
        if ((retVal & 1) == 1)
            state |= KeyStates.Toggled;

        return state;
    }

    public static bool IsKeyDown(Keys key)
    {
        return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
    }

    public static bool IsKeyToggled(Keys key)
    {
        return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
    }
}

/// <summary>
/// Event Args for the event that is fired after the hot key has been pressed.
/// </summary>
class KeyPressedEventArgs : EventArgs
{
    internal KeyPressedEventArgs(ModifierKeys modifier, Keys key)
    {
        this.Modifier = modifier;
        this.Key = key;

        this.Ctrl = (modifier & ModifierKeys.Control) != 0;
        this.Shift = (modifier & ModifierKeys.Shift) != 0;
        this.Win = (modifier & ModifierKeys.Win) != 0;
        this.Alt = (modifier & ModifierKeys.Alt) != 0;
    }

    public ModifierKeys Modifier { get; private set; }
    public Keys Key { get; private set; }
    public readonly bool Ctrl;
    public readonly bool Shift;
    public readonly bool Win;
    public readonly bool Alt;
}

/// <summary>
/// The enumeration of possible modifiers.
/// </summary>
[Flags]
public enum ModifierKeys : uint
{
    Alt = 1,
    Control = 2,
    Shift = 4,
    Win = 8
}
//
///管理全局低级键盘挂钩的类
/// 
类GlobalKeyboardHook
{
#区域常量、结构和委托定义
/// 
///定义钩子的回调类型
/// 
公共委托int KeyboardHookProc(int代码、int wParam、ref KeyboardHookStruct lParam);
公共结构KeyboardHookStruct
{
公共int-vkCode;
公共int扫描码;
公共国旗;
公共整数时间;
公共信息;
}
专用常量int WH_键盘LL=13;
私有常量int WM_KEYDOWN=0x100;
私有常量int WM_KEYUP=0x101;
私有常量int WM_SYSKEYDOWN=0x104;
私有常量int WM_SYSKEYUP=0x105;
#端区
/// 
///要监视的密钥集合
/// 
public List HookedKeys=新列表();
/// 
///钩子的句柄,需要这个来解开钩子并调用下一个钩子
/// 
私有IntPtr _hhook=IntPtr.Zero;
/// 
///初始化类的新实例并安装键盘挂钩。
/// 
公共GlobalKeyboardHook()
{
这个。Hook();
}
/// 
///释放非托管资源并在
///由垃圾回收回收并卸载键盘挂钩。
/// 
~GlobalKeyboardHook()
{
这个;
}
/// 
///安装全局钩子
/// 
公共空钩()
{
IntPtr hInstance=LoadLibrary(“User32”);
this.\u hhook=setWindowshookx(WH\u KEYBOARD\u LL,this.HookProc,hInstance,0);
}
/// 
///卸载全局钩子
/// 
公共空间取消挂钩()
{
解开钩子(这个.hhook);
}
/// 
///键盘挂钩的回调
/// 
///钩子代码,如果它不是>=0,函数不应该做任何事情
///事件类型
///keyhook事件信息
/// 
私有int-HookProc(int代码、int-wParam、ref-KeyboardHookStruct lParam)
{
如果(代码>=0)
{
var key=(Keys)lParam.vkCode;
if(this.HookedKeys.Contains(key))
{
var handler=this.KeyPressed;
if((wParam==WM| | wParam==WM|SYSKEYDOWN)&&(handler!=null))
{
ModifierKeys mods=0;
if(Keyboard.IsKeyDown(Keys.Control)| | Keyboard.IsKeyDown(Keys.ControlKey)||
键盘.IsKeyDown(Keys.LControlKey)| |键盘.IsKeyDown(Keys.RControlKey))
{
mods |=ModifierKeys.Control;
}
if(Keyboard.IsKeyDown(Keys.Shift)| Keyboard.IsKeyDown(Keys.ShiftKey)||
键盘.IsKeyDown(Keys.lshift键)| |键盘.IsKeyDown(Keys.rshift键))
{
mods |=ModifierKeys.Shift;
}
if(Keyboard.IsKeyDown(Keys.LWin)| | Keyboard.IsKeyDown(Keys.RWin))
{
mods |=ModifierKeys.Win;
}
if(Keyboard.IsKeyDown(Keys.Alt))
{
mods |=ModifierKeys.Alt;
}
处理程序(此,新键按EventTargets(mods,键));
}
}
}
返回CallNextHookEx(this.\uhhook,code,wParam,ref lParam);
}
按下公共事件处理程序键;
#区域DLL导入
/// 
///设置windows挂钩,执行所需事件,hInstance或threadId之一必须为非空
/// 
///要挂接的事件的id
///回调。
///要将事件附加到的句柄可以为null
///要将事件附加到的线程可以为null
///所需挂钩的把手
[DllImport(“user32.dll”)]
私有静态外部IntPtr SetWindowsHookEx(int idHook、KeyboardHookProc回调、IntPtr hInstance、uint threadId);
///