Results 1 to 11 of 11

Thread: [RESOLVED] Removing Delay On KeyPress/KeyDown...

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Sep 2013
    Posts
    127

    Resolved [RESOLVED] Removing Delay On KeyPress/KeyDown...

    Using the keyboard to move a sprite: whether I use the KeyPress, KeyDown, or GetAsyncKeyState, I still get a delay. Sure, it moves, but between the vertical directions and the horizontal directions, there is a delay. It'll start, stop, then start and continue. How do I remove the STOP part.

    (I've checked my Keyboard settings in Control Panel... all is as fast as possible, so altering that won't help.)

  2. #2
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Removing Delay On KeyPress/KeyDown...

    It sounds like you're talking about the pause between pressing a key, and then before it starts repeating. There may be a way to change that. However, if it were me, I wouldn't use that pause at all. Both KeyDown and KeyPress are going to acknowledge that pause. And, it's my understanding that GetAsyncKeyState is going to acknowledge it as well.

    When I'm doing something like that, I look at the first KeyPress (or KeyDown) and then start monitoring keys with GetKeyState, not worrying about when the next key comes in. Using that approach, you'd have to use a timer, or possibly a continuous loop with Sleep (until the key is up), to monitor how long the key was down.

    Maybe That'll Help,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  3. #3
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Removing Delay On KeyPress/KeyDown...

    It was actually a bit more work than I thought, and this code needs more clean-up, but it'll get you going. It's just some code I quickly cobbled together:

    Just throw it into Form1, with no controls on the form, to test.

    Code:
    
    Option Explicit
    '
    Private Type POINTAPI
        X As Long
        Y As Long
    End Type
    Private Type msg
        hWnd As Long
        message As Long
        wParam As Long
        lParam As Long
        Time As Long
        pt As POINTAPI
    End Type
    Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
    Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
    Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" (lpMsg As msg, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
    '
    
    Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
        Const VK_E          As Long = &H45&
        If KeyCode = vbKeyE Then
            Do
                ClearKeyboardBuffer
                Debug.Print Int(Rnd * 9000) + 1000
                Sleep 10
                If GetKeyState(VK_E) >= 0 Then Exit Do
            Loop
        End If
    End Sub
    
    Public Sub ClearKeyboardBuffer()
        Const WM_KEYFIRST = 256
        Const WM_KEYLAST = 264
        Const PM_REMOVE = 1
        Dim msg As msg
        Dim rc As Long
        Do
            rc = PeekMessage(msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)
        Loop While rc <> 0
    End Sub
    
    
    Good Luck,
    Elroy

    EDIT1: This sample is all about the "e" key.

    EDIT2: Also, I just made it repeat every 10 milliseconds, with no pause. But that could be adjusted to whatever you need.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  4. #4

    Thread Starter
    Lively Member
    Join Date
    Sep 2013
    Posts
    127

    Re: Removing Delay On KeyPress/KeyDown...

    Thanks, Elroy, but that doesn't solve the issue I'm running into. A single key seems to perform smoothly, even using the three ways I mentioned in the original post. The problem arises when switching from one key to another. For instance, say you're moving a ball on the form to the right with the D key, then you want to move the ball up with the W key. When immediately switching from D to W, there is a hesitation before the ball moves. That's the problem... getting rid of the hesitation.

  5. #5
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Removing Delay On KeyPress/KeyDown...

    Hi mcoulter876,

    Just got back. Also, I'm throwing together a procedure to process multiple keys. I'll post it in a few.

    Best Regards,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #6
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Removing Delay On KeyPress/KeyDown...

    Here, try throwing this into a Form1 (no controls), and see if it's something similar to what you're trying to do.

    Code:
    
    Option Explicit
    '
    Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
    Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
    Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" (ByVal lpMsg As Long, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
    '
    
    Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
        ProcessDownKeys 50&, vbKeyE, vbKeyS, vbKeyD, vbKeyX
    End Sub
    
    Private Sub ProcessDownKeys(millisecDelay As Long, ParamArray vArgs() As Variant)
        ' This doesn't return until all the specified keys are released.
        ' The ParamArray should contain a mutually exclusive list of the KeyCodeConstants (vbKey...).
        ' Will error if no arguments are provided.
        ' For any/all keys specified, there should also be a function in this form named Do?Key where the ? is the key name.  If not found, an error will result.
        ' For the time being, this just works on the alphabet and numbers.  Other keys to come later.
        '
        Static l(6) As Long             ' Just a spoof for the lpMsg structure.  We don't need its contents.
        Dim i As Long
        Dim bDown() As Boolean
        Dim bSomeDown As Boolean
        '
        Do
            Do While PeekMessage(VarPtr(l(0)), 0&, 256&, 264&, 1&) <> 0: Loop       ' Clear keyboard buffer.
            bSomeDown = False
            ReDim bDown(UBound(vArgs))
            For i = 0 To UBound(vArgs)
                If GetKeyState(vArgs(i)) < 0& Then
                    bDown(i) = True
                    bSomeDown = True
                    CallByName Me, "Do" & Chr$(vArgs(i)) & "Key", VbMethod
                End If
            Next i
            If Not bSomeDown Then Exit Sub
            Debug.Print ' Just for testing.
            Sleep millisecDelay
        Loop
    End Sub
    
    Public Sub DoEKey()
        Debug.Print "E";
    End Sub
    
    Public Sub DoSKey()
        Debug.Print "S";
    End Sub
    
    Public Sub DoDKey()
        Debug.Print "D";
    End Sub
    
    Public Sub DoXKey()
        Debug.Print "X";
    End Sub
    
    Good Luck,
    Elroy

    EDIT1: Just looking at that code, I'm thinking I didn't handle key-code-combinations very well, but there's certainly no reason they couldn't be handled. Pretty much everything you'd need is listed in the KeyCodeConstants enumeration of the VBRUN library.

    EDIT2: Here, I enhanced the above code to handle the arrow keys as well. And then, made a sort of PacMan-like thing with it. The project is attached:
    Attached Files Attached Files
    Last edited by Elroy; Mar 11th, 2018 at 01:33 PM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  7. #7
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Removing Delay On KeyPress/KeyDown...

    Quote Originally Posted by mcoulter876 View Post
    ... The problem arises when switching from one key to another...
    Hmm, when Form.KeyPreview is enabled, then you can solve the problem without any APIs, by using this simple Class here:
    (name it cGameKeys):
    Code:
    Option Explicit
    
    Public Enum enmDirection
      kDirLeft = 1
      kDirUp = 2
      kDirRight = 4
      kDirDown = 8
    End Enum
    
    Event StateChange(ByVal Up As Boolean)
     
    Public State As enmDirection
    
    Public Sub ProcessKeyEvt(KeyCode As Integer, ByVal Up As Boolean)
      Dim D As enmDirection: D = State
      Select Case KeyCode
        Case 37, 65: D = IIf(Up, D And Not kDirLeft, D Or kDirLeft)
        Case 38, 87: D = IIf(Up, D And Not kDirUp, D Or kDirUp)
        Case 39, 68: D = IIf(Up, D And Not kDirRight, D Or kDirRight)
        Case 40, 83: D = IIf(Up, D And Not kDirDown, D Or kDirDown)
      End Select
      If D <> State Then State = D: RaiseEvent StateChange(Up)
    End Sub
    Now, to test this Class (which allows to move a little red Circle even diagonally by using either the "wasd" or the arrow-keys),
    you will have to add a simple Timer1-Control to a form and paste the following code into the Form:
    Code:
    Option Explicit
    
    Private WithEvents GK As cGameKeys, x, y
    
    Private Sub Form_Load()
      KeyPreview = True: ScaleMode = vbPixels: DrawWidth = 12
      x = ScaleWidth \ 2: y = ScaleHeight \ 2
      Set GK = New cGameKeys
      Timer1.Enabled = False: Timer1.Interval = 50
    End Sub
    
    Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
      GK.ProcessKeyEvt KeyCode, False
    End Sub
    
    Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
      GK.ProcessKeyEvt KeyCode, True
    End Sub
    
    Private Sub GK_StateChange(ByVal Up As Boolean)
      Debug.Print "Key-"; IIf(Up, "Up", "Down"), GK.State
      Timer1.Enabled = GK.State: If Not Up Then Timer1_Timer
    End Sub
    
    Private Sub Timer1_Timer()
     If GK.State And kDirLeft Then x = x - 1
     If GK.State And kDirUp Then y = y - 1
     If GK.State And kDirRight Then x = x + 1
     If GK.State And kDirDown Then y = y + 1
     If GK.State Then Cls: PSet (x, y), vbRed: Caption = x & ", " & y
    End Sub
    HTH

    Olaf
    Last edited by Schmidt; Mar 11th, 2018 at 09:10 PM.

  8. #8
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Removing Delay On KeyPress/KeyDown...

    mcoulter876,

    The take-home message is to forget about using the Windows key-repeat feature. You've got to (somehow) figure out when your keys-of-interest are down or up, and create your own repeat (possibly starting the moment it's detected that the key has been pressed).

    Basically, that's what both Olaf and I have done.

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  9. #9

    Thread Starter
    Lively Member
    Join Date
    Sep 2013
    Posts
    127

    Re: Removing Delay On KeyPress/KeyDown...

    Thanks to you both. I used Schmidt's code and it does what I need it to.

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Sep 2013
    Posts
    127

    Re: [RESOLVED] Removing Delay On KeyPress/KeyDown...

    Additionally, if there is a way to use Schmidt's code to include the diagonal directions using, for example, A and W to move Up-Left, that would also be helpful.

  11. #11
    The Idiot
    Join Date
    Dec 2014
    Posts
    3,001

    Re: [RESOLVED] Removing Delay On KeyPress/KeyDown...

    as im creating a game i need the keys to work without issues.
    its quite simple, when key down, it will set that key to true until key up. no need for a loop/timer or api.
    now, in the game loop, if the key is true it will move.
    other keys can only get pressed once, until the key is up, this to prevent repeats.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width