VBA GetAsyncKeyState в PowerPoint захватывает один и тот же ключ несколько раз - PullRequest
0 голосов
/ 02 октября 2018

Я пытаюсь использовать GetAsyncKeyState для захвата произвольной двухтактной альфа-последовательности клавиш в PowerPoint, например, «AA», «AB», «DZ».Однако я обнаружил, что первое нажатие клавиши фиксируется как первое и второе.

Для простоты приведенный ниже код пытается захватить только последовательность «AA».Я ожидаю, что код завершится после того, как «A» будет нажата дважды.Тем не менее, он завершается, как только один раз нажимается «A».

Option Explicit

Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" _
    (ByVal vKey As Long) As Integer

Private Const VK_A = &H41 'A key


Sub CaptureAA()

    ' Capture first 'A' keystroke
    Do While True
        If GetAsyncKeyState(VK_A) Then
            Debug.Print "First A captured"
            Exit Do
        End If
        DoEvents
    Loop

    ' Capture second 'A' keystroke
    Do While True
        If GetAsyncKeyState(VK_A) Then
            Debug.Print "Second A captured"
            Exit Do
        End If
        DoEvents
    Loop

End Sub

Я предполагаю, что мне нужно как-то отменить нажатие клавиши после первого GetAsyncKeyState, но я не уверен, правильно ли этоили как это сделать.

1 Ответ

0 голосов
/ 02 октября 2018

Когда вы проверяете его, вы возвращаете возвращаемое значение в Boolean, так что вы собираетесь взять бит "недавно нажатый" в дополнение к состоянию клавиши.С документация для API:

Хотя младший бит возвращаемого значения указывает, была ли клавиша нажата с момента последнего запроса, из-за упреждающей многозадачностиВ отличие от Windows, другое приложение может вызвать GetAsyncKeyState и получить бит «недавно нажатый» вместо вашего приложения.Поведение наименее значимого бита возвращаемого значения сохраняется строго для совместимости с 16-разрядными приложениями Windows (которые не являются приоритетными) и на него не следует полагаться.

Тем не менее, этоскорее всего никогда не будет надежно работать.Если вы хотите сделать это надежно, вам, вероятно, потребуется создать подкласс окна хоста.Каждый раз, когда вы звоните DoEvents в вашем цикле, вы рискуете потерять нажатия клавиш.

Вам также необходимо учитывать случай, когда пользователь набирает A {Any} A .Единственная вещь, которую вы действительно можете сделать с внешним циклом, пытающимся шпионить за «реальным» насосом сообщений, - это определить, не были ли они дважды в быстрой последовательности.Чтобы исключить любую другую клавишу, нажимаемую в это время, вам нужно отслеживать все события клавиатуры.

...