Мне нужно найти решение, поэтому я отвечу на свой вопрос. Советы от @Peyter помогли мне найти путь.
Во-первых, бесконечный l oop кажется мне абсолютно нормальным, я чувствую, что он работает более стабильно, чем Application.OnTime. Еще есть метод Чипа Пирсона, но я не нашел причины использовать его вместо бесконечного l oop (результат казался таким же).
Во-вторых, я тоже оставил Aplication.OnKey. . Я использовал решение с этого сайта . Это какая-то функция Windows и работает очень хорошо. Однако есть одна проблема. С этого момента нажатая клавиша будет означать для Excel как дополнительную, так и обычную деятельность. Например, когда я нажимаю стрелку вниз, я выбираю ячейку под ячейкой, в которой я нахожусь. Я хотел отключить обычное поведение для стрелок и букв, но не нашел подходящего способа сделать это. Поэтому я использовал уродливый;) В целом мои функции такие, как показано ниже.
Основной модуль:
Option Explicit
Sub RunGame()
Do While True
'
'
'Some game's stuff here
'
'
Call WasteTime(1)
IsKeyPressed
Loop
End Sub
Утилиты модуля:
Option Explicit
Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long
Private Const VK_DOWN = &H28 'DOWN ARROW key
Sub WasteTime(TimeToWaste As Single)
Dim i As Long
For i = 1 To TimeToWaste * 1000
VBA.DoEvents
Next
End Sub
Sub IsKeyPressed()
If GetAsyncKeyState(VK_DOWN) <> 0 Then
OnDownKey
End If
End Sub
Sub OnDownKey()
MsgBox "You pressed down key"
End Sub
Он работает . Пока не знаю куда поставить VBA.DoEvents
, но в l oop работает хорошо. Строка Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long
передает привет функции Windows, которая теперь будет работать для нас. Private Const VK_DOWN = &H28 'DOWN ARROW key
- это определение клавиши со стрелкой вниз, которая теперь будет называться VK_DOWN. IsKeyPressed()
проверяет, нажал ли пользователь какую-то клавишу. If GetAsyncKeyState(VK_DOWN) <> 0
проверяет, был ли нажат VK_DOWN. На удивление для меня эта Windows функция очень хорошо работает с VBA, никаких лагов нет!
Итак, что я сделал, чтобы заблокировать обычное поведение нажатия стрелок или букв? Я выбрал одну ячейку, в которой хотел бы остаться - в моем примере это AG1. Затем я использовал события рабочего листа (дважды щелкните лист слева в редакторе VBA, и вы его откроете). Я использовал там две функции:
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
[AG1].Select
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$AG$1" Then
Application.EnableEvents = False
[AG1].Clear
[AG1].Select
Application.EnableEvents = True
RunGame
End If
End Sub
Первая делает невозможным выход из AG1, потому что каждый раз, когда вы меняете выбор, VBA выбирает AG1 за вас.
Второй срабатывает. когда вы пытаетесь изменить значение ячейки. Подпрограмма очистит ячейку, выделит ее и запустит RunGame (). Зачем нужно последнее? Потому что, когда пользователь начинает что-то вводить, бесконечное l oop приостанавливается, а когда пользователь нажимает Enter, бесконечное l oop не продолжается. Я действительно не знаю, приостановлено это или закончено. Но, надеюсь, я обойдусь без буквенных клавиш, так что мне не о чем беспокоиться.