【问题标题】:Idenifying pressed HotKey with GetAsyncKeyState() only returns correct result if it's called once before [duplicate]使用 GetAsyncKeyState() 识别按下的热键仅在 [重复]
【发布时间】:2019-07-04 21:29:41
【问题描述】:

我对这个很困惑。我有一种方法可以检查是否按下了热键(使用RegisterHotkey)。 我在热键上调用GetAsyncKeyState(vKey),它的修饰符决定了哪个已注册的热键被这样调用。

    public bool IsPressed()
    {
         // Checks if the key and any (but not all) required modifiers are pressed
        // Int16.MinValue indicates that a key is pressed - 0 indicates it isn't - Keys.None cannot be used
        return GetAsyncKeyState(Key) == Int16.MinValue && (Modifier == ModifierKeys.None ||
            (Modifier == ModifierKeys.Shift && GetAsyncKeyState(Keys.ShiftKey) == Int16.MinValue) ||
            (Modifier == ModifierKeys.Alt && GetAsyncKeyState(Keys.Alt) == Int16.MinValue) ||
            (Modifier == ModifierKeys.Control && GetAsyncKeyState(Keys.ControlKey) == Int16.MinValue) ||
            (Modifier == ModifierKeys.Windows && (GetAsyncKeyState(Keys.LWin) == Int16.MinValue || GetAsyncKeyState(Keys.RWin) == Int16.MinValue))
            );
    }

以上返回false。所以我尝试单独添加语句以查看问题所在:

public bool IsPressed()
{

var keything =  GetAsyncKeyState(Key);

bool a = GetAsyncKeyState(Key) == Int16.MinValue && (Modifier == ModifierKeys.None);
bool b = (Modifier == ModifierKeys.Shift && GetAsyncKeyState(Keys.ShiftKey) == Int16.MinValue);
bool c = (Modifier == ModifierKeys.Alt && GetAsyncKeyState(Keys.Alt) == Int16.MinValue);
bool d = (Modifier == ModifierKeys.Control && GetAsyncKeyState(Keys.ControlKey) == Int16.MinValue);
bool e = (Modifier == ModifierKeys.Windows && (GetAsyncKeyState(Keys.LWin) == Int16.MinValue || GetAsyncKeyState(Keys.RWin) == Int16.MinValue));
bool f = GetAsyncKeyState(Key) == Int16.MinValue && (Modifier == ModifierKeys.None ||
    (Modifier == ModifierKeys.Shift && GetAsyncKeyState(Keys.ShiftKey) == Int16.MinValue) ||
    (Modifier == ModifierKeys.Alt && GetAsyncKeyState(Keys.Alt) == Int16.MinValue) ||
    (Modifier == ModifierKeys.Control && GetAsyncKeyState(Keys.ControlKey) == Int16.MinValue) ||
    (Modifier == ModifierKeys.Windows && (GetAsyncKeyState(Keys.LWin) == Int16.MinValue || GetAsyncKeyState(Keys.RWin) == Int16.MinValue))
    );


// Checks if the key and any (but not all) required modifiers are pressed
// Int16.MinValue indicates that a key is pressed - 0 indicates it isn't - Keys.None cannot be used
return GetAsyncKeyState(Key) == Int16.MinValue && (Modifier == ModifierKeys.None ||
    (Modifier == ModifierKeys.Shift && GetAsyncKeyState(Keys.ShiftKey) == Int16.MinValue) ||
    (Modifier == ModifierKeys.Alt && GetAsyncKeyState(Keys.Alt) == Int16.MinValue) ||
    (Modifier == ModifierKeys.Control && GetAsyncKeyState(Keys.ControlKey) == Int16.MinValue) ||
    (Modifier == ModifierKeys.Windows && (GetAsyncKeyState(Keys.LWin) == Int16.MinValue || GetAsyncKeyState(Keys.RWin) == Int16.MinValue))
    );
}

A 和 F 返回 true - 应该如此(F 也只是被返回的语句的副本)... 然而,让我没想到的是,方法本身也返回了true。

因此,在实际查询之前添加对 GetAsyncKeyState() 的调用会使其正常工作。 为什么会这样以及解决这个问题的最佳方法是什么(除了对函数的死调用)

【问题讨论】:

标签: c# winapi hotkeys


【解决方案1】:

而不是建议的 HotKey.IsPressed() 使用 GetAsyncKeyState() - 您可以改为从侦听器的 lParam 确定热键,如下所示:

热键类中的 IsPressed 如下所示:

public bool IsPressed(IntPtr lParam)
{
    uint param = (uint)lParam.ToInt64();
    var inputKey = (Keys)((param & 0xffff0000) >> 16);
    var inputModifier = (ModifierKeys)(param & 0x0000ffff);

    return inputKey == this.Key && inputModifier == this.Modifier;
}

或者使用它的一些变体,它不必在每次 IsPressed 调用时计算它。

【讨论】:

    猜你喜欢
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    相关资源
    最近更新 更多