无论我尝试什么,我都无法在 KeyDown 上退出循环
No Matter What I Try, I Cannot Exit Loop On KeyDown
这真的让我感到沮丧。
基本上,这是我为 GTA IV 编写的脚本的一部分(完成后我可能会在我的网站上发布 mod),我需要在用户按下定义的键时退出此循环在游戏中。当然,我不能使用 KeyPreview
因为这是一个 class 库 (GTA IV 插件必须使用 .net.dll)。
这是我到目前为止尝试过的(显然不是完整的代码),正如许多网站上所建议的那样:
循环:
Sub CarFunctions()
Dim veh = Player.Character.CurrentVehicle
Do
Application.DoEvents()
If CancelLoop = True Then
Exit Do
End If
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
Wait(500)
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
Wait(500)
Loop
End Sub
KeyDown 事件:
Private Sub VehicleControls_KeyDown(sender As Object, e As GTA.KeyEventArgs) Handles Me.KeyDown
Try
Dim veh = Player.Character.CurrentVehicle
If e.Key = Keys.NumPad5 Then
CancelLoop = True
End If
Catch ex As Exception
Game.Console.Print(ex.ToString)
End Try
End Sub
据我所知,问题是程序在循环时没有检测到任何按键事件。我尝试使用多线程,但它在游戏中抛出异常,我无法使用调用方法。
提前致谢。
一般'exit control structure'关键词,如exit do,应该避免。
https://msdn.microsoft.com/en-us/library/eked04a7.aspx
Dim index As Integer = 0
Do
Debug.Write(index.ToString & " ")
index += 1
Loop Until index > 10
我认为循环 until 就是您要查找的内容。您可能必须使用 while 循环而不是 do while 来支持您的特定逻辑。这是我的尝试。
Sub CarFunctionsTask()
Task.Factory.StartNew(Sub()
Dim veh = Player.Character.CurrentVehicle
Do
If CancelLoop = False Then
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
Wait(500)
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
Wait(500)
End If
Loop Until CancelLoop
End Sub)
End Sub
我认为 codemonkeyliketab 接近答案,因为循环需要在后台线程上 运行 才能不阻止按键事件。我会推荐类似于他所做的事情,但使用调用上下文来执行 Native.Function.Call
行,如下所示:
Sub CarFunctions()
Dim veh = Player.Character.CurrentVehicle
Dim callingContext = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext
System.Threading.Tasks.Task.Factory.StartNew(
Sub()
While CancelLoop = False
Dim t As Task
t = System.Threading.Tasks.Task.Factory.StartNew(
Sub()
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
End Sub,
System.Threading.CancellationToken.None,
System.Threading.Tasks.TaskCreationOptions.None,
callingContext)
t.Wait()
Wait(500)
t = System.Threading.Tasks.Task.Factory.StartNew(
Sub()
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
End Sub,
System.Threading.CancellationToken.None,
System.Threading.Tasks.TaskCreationOptions.None,
callingContext)
t.Wait()
Wait(500)
End While
End Sub)
End Sub
在 Mike Guthrie 和 codemonkeyliketab 的帮助下,我通过在循环中使用 isKeyPressed()
设法解决了这个问题(但是不是很完美):
Do
If Me.isKeyPressed(Keys.Decimal) Then
Exit Do
End If
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
Wait(500)
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
Wait(500)
Loop
谢谢大家的回答。
这真的让我感到沮丧。
基本上,这是我为 GTA IV 编写的脚本的一部分(完成后我可能会在我的网站上发布 mod),我需要在用户按下定义的键时退出此循环在游戏中。当然,我不能使用 KeyPreview
因为这是一个 class 库 (GTA IV 插件必须使用 .net.dll)。
这是我到目前为止尝试过的(显然不是完整的代码),正如许多网站上所建议的那样:
循环:
Sub CarFunctions()
Dim veh = Player.Character.CurrentVehicle
Do
Application.DoEvents()
If CancelLoop = True Then
Exit Do
End If
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
Wait(500)
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
Wait(500)
Loop
End Sub
KeyDown 事件:
Private Sub VehicleControls_KeyDown(sender As Object, e As GTA.KeyEventArgs) Handles Me.KeyDown
Try
Dim veh = Player.Character.CurrentVehicle
If e.Key = Keys.NumPad5 Then
CancelLoop = True
End If
Catch ex As Exception
Game.Console.Print(ex.ToString)
End Try
End Sub
据我所知,问题是程序在循环时没有检测到任何按键事件。我尝试使用多线程,但它在游戏中抛出异常,我无法使用调用方法。
提前致谢。
一般'exit control structure'关键词,如exit do,应该避免。
https://msdn.microsoft.com/en-us/library/eked04a7.aspx
Dim index As Integer = 0
Do
Debug.Write(index.ToString & " ")
index += 1
Loop Until index > 10
我认为循环 until 就是您要查找的内容。您可能必须使用 while 循环而不是 do while 来支持您的特定逻辑。这是我的尝试。
Sub CarFunctionsTask()
Task.Factory.StartNew(Sub()
Dim veh = Player.Character.CurrentVehicle
Do
If CancelLoop = False Then
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
Wait(500)
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
Wait(500)
End If
Loop Until CancelLoop
End Sub)
End Sub
我认为 codemonkeyliketab 接近答案,因为循环需要在后台线程上 运行 才能不阻止按键事件。我会推荐类似于他所做的事情,但使用调用上下文来执行 Native.Function.Call
行,如下所示:
Sub CarFunctions()
Dim veh = Player.Character.CurrentVehicle
Dim callingContext = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext
System.Threading.Tasks.Task.Factory.StartNew(
Sub()
While CancelLoop = False
Dim t As Task
t = System.Threading.Tasks.Task.Factory.StartNew(
Sub()
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
End Sub,
System.Threading.CancellationToken.None,
System.Threading.Tasks.TaskCreationOptions.None,
callingContext)
t.Wait()
Wait(500)
t = System.Threading.Tasks.Task.Factory.StartNew(
Sub()
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
End Sub,
System.Threading.CancellationToken.None,
System.Threading.Tasks.TaskCreationOptions.None,
callingContext)
t.Wait()
Wait(500)
End While
End Sub)
End Sub
在 Mike Guthrie 和 codemonkeyliketab 的帮助下,我通过在循环中使用 isKeyPressed()
设法解决了这个问题(但是不是很完美):
Do
If Me.isKeyPressed(Keys.Decimal) Then
Exit Do
End If
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, True)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 1)
Wait(500)
Native.Function.Call("SET_VEH_INDICATORLIGHTS", veh, False)
Native.Function.Call("FORCE_CAR_LIGHTS", veh, 2)
Wait(500)
Loop
谢谢大家的回答。