Sifting through repeated key presses

This is a discussion on Sifting through repeated key presses within the Windows Programming forums, part of the Platform Specific Boards category; I've been exploring some keyboard input stuff lately, and found some functions in the FAQ to be of some use. ...

  1. #1
    Registered User
    Join Date
    Mar 2004
    Posts
    220

    Sifting through repeated key presses

    I've been exploring some keyboard input stuff lately, and found some functions in the FAQ to be of some use. But, I've ran into some problems that I don't want to run into in future implementations of these methods. My main focus is game programming, and this error is a big issue. The code which i'll paste below, grabs keypresses, and prints them out in a txt file(I use a file because I can c&p it btw), 10x more than I wanted the program to do. e.g it catches 50 keypresses, and not just one. Since i'm just starting out on this method of input for game programming, currently with my code I would make my character zoom across the screen like mad..very big issue as far as i'm concerned.

    So i'm asking for a way to capture key presses without it going mad like it does in this program. I'de like it to capture them at a good rate too. For instance, if a user presses a key twice, I want it to capture both of those keypresses, not just the first. I also don't want it to capture 50 keypresses on the first press, and 50 on the next...I haven't been able to find a solution for this yet, since it seems every keypress is about 50 of them depending on how fast your comp is, at least that's what i've come up with to explain it..and i'm not good enough of a coder to know about limits and such.

    I had tried coding it like this:
    a) capture first key press in a variable.
    b) capture second keypress in a temp variable.
    c) if first and second keypresses are equal only write the first keypress.
    d)else if the first and second keypresses are different, write both keypresses.

    But then I go back to my previous problem, what if the user presses the key twice? If I use that method, I would only capture the first keypress, and ignore the second...which obviously isn't good. It also makes me wonder how they would get past this problem in the first place...maybe there are some hidden functions in the winapi i'm not familiar with? That's what i'm getting out of it so far..

    But in any case, here's my code:
    PHP Code:
    //The catchKeyPress() function was taken from BMJ's code, and 
    //the KEY_DOWN and KEY_UP macros were taken from DIVX's 
    //code, I hope you don't mind guys :)
    #include <windows.h>
    #include <iostream>
    #include <fstream>

    #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
    #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

    bool catchKeyPress(char &Key);

    int main(int argcchar *argv[])
    {
        
    std::cout << "Keyboard Input Prog";
        
    std::ofstream loggingFile;
          
    loggingFile.open("log.txt"std::ios::app);
        
    char input;
        while(!
    KEY_DOWN(0x51))//0x51 = q
        
    {
            if(
    catchKeyPress(input) == false)
                
    loggingFile << input;  
        }        
        
    FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));  
        
    loggingFile.close(); 
        return 
    0;
    }    

    bool catchKeyPress(char &Key

        
    INPUT_RECORD Event
        
    DWORD NumberOfEventsEventsReadEventCounter

        
    GetNumberOfConsoleInputEvents(GetStdHandle(STD_INPUT_HANDLE), &NumberOfEvents); 

        if (
    NumberOfEvents == 0
            return 
    false
         
        for (
    EventCounter 0EventCounter NumberOfEventsEventCounter++) 
        { 
            
    PeekConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &Event1, &EventsRead); 
            if ((
    Event.EventType == KEY_EVENT) && ((Event.Event.KeyEvent.bKeyDown))) 
            { 
                
    ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &Event1, &EventsRead); 
                
    Key Event.Event.KeyEvent.wVirtualKeyCode
                if  (!(
    FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)))) 
                    exit(
    0); 
                return 
    true
            } 
            else 
                
    ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &Event1, &EventsRead); 
        } 

        return 
    false

    Sample output:
    Code:
    JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
    
    KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
    
    LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
    Since the code tags messed up the formatting/display, I had to condense it, the real output is much longer and doesn't have line breaks or spaces in it. But you can get the idea of what it's really doing i'm sure.

    I didn't expect the results of this program...but thenagain, i'm kind of new to the winapi. So this is kind of a learning experience for me ^_^
    Last edited by Tronic; 11-25-2004 at 02:23 PM.
    OS: Windows XP Pro CE
    IDE: VS .NET 2002
    Preferred Language: C++.

  2. #2
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Code:
            if(catchKeyPress(input) == false)
    It looks like catchKeyPress() returns false on failure. So you want to test for success instead:
    Code:
            if(catchKeyPress(input))

  3. #3
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    what if the user presses the key twice? If I use that method, I would only capture the first keypress, and ignore the second...which obviously isn't good. It also makes me wonder how they would get past this problem in the first place...maybe there are some hidden functions in the winapi i'm not familiar with?
    While I can't say whether it's the "best" way or not, the method that I usually use is:

    -Keep a boolean variable for each game key
    -On key-down, if the variable for the key is false, then set it to true and do the action; otherwise (if it's true), do nothing
    -On key-up, set the variable for the key to false.

    That way you won't get repeated keystrokes unless the key is released first. Also, it's nice because if you're capturing the key-up and key-down events using the WM_KEYDOWN and WM_KEYUP messages in your window procedure, then in other parts of the program you can simply check the state of the boolean variables to know whether the key is currently pressed or released. Also, you can add separate counter variables for each key, and each time you have a unique keystroke you increase the counter for that key, and rather than relying on checking the boolean variables you can just check if the counter for the key is greater than 0; if it is, then decrease it by one and perform the action.

    Etc. etc. etc... There are endless possibilities, when you put your imagination to work

    **EDIT**
    Ah, I see you're doing a console program. In that case you can ignore the last paragraph, but I believe the method of simply keeping a bunch of 'key-state' variables (i.e. an array of them, 1 element for each ASCII character code) still applies.
    Last edited by Hunter2; 11-25-2004 at 09:22 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 11-23-2007, 01:48 PM
  2. Virtual keys
    By Arkanos in forum Windows Programming
    Replies: 4
    Last Post: 12-12-2005, 10:00 AM
  3. Directional Keys - Useing in Console
    By RoD in forum C++ Programming
    Replies: 38
    Last Post: 10-06-2002, 05:42 PM
  4. FAQ: Directional Keys - Useing in Console
    By RoD in forum FAQ Board
    Replies: 38
    Last Post: 10-06-2002, 05:42 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21