Thread: GetAsyncKeyState(VK_CONTROL)

  1. #1
    Registered User Bajanine's Avatar
    Join Date
    Dec 2001
    Location
    The most peaks over 10,000 feet!
    Posts
    396

    GetAsyncKeyState(VK_CONTROL)

    I am trying to implement a multiple selection function but I seem to have some unintended ‘features’ .
    First, what I would like to implement is to allow selection of multiple members by this combination:
    press ‘ctrl’ key - left click with mouse – release ‘ctrl’ key
    this selects everything inline and to the right of the cursor as you can see in the attached picture.
    Now the problem, if I were to left click with the mouse in the same spot again my program acts as if the ‘ctrl’ key is depressed. Is this from a keyup message from my previous selection? If so how do I get rid of it?
    Second, if I press
    ‘ctrl’ – release ‘ctrl’ – and then left click
    my program seems to behave the way I intend but with the wrong combination of keys.
    Here is a snippet of code that I am working with:
    Code:
         
    case WM_LBUTTONDOWN:         
    {             //…misc code…             
    if(GetAsyncKeyState(VK_CONTROL))             
    {                 
        RayTestHorizontal(head, LeftClick);// multi-select inline and right of cursor.             
    }             
    else                 
        FindMember(LeftClick); // just selects one member.
    Thanks in advance for any pointers to help me out.
    Last edited by Bajanine; 11-23-2007 at 12:05 PM. Reason: edited to make code easier to read
    Favorite Quote:

    >For that reason someone invented C++.
    BLASPHEMY! Begone from my C board, you foul lover of objects, before the gods of C cast you into the void as punishment for your weakness! There is no penance for saying such things in my presence. You are henceforth excommunicated. Never return to this house, filthy heretic!



  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    A while ago I used GetAsyncKeyState() as part of codeform's clipboard extensions. I had huge problems with it. Windows 98 and Windows XP (the only versions I had access to) had completely different support for this function. Sometimes, something would work on one system, but not the other. I had particular trouble with modifier keys like shift and alt and control. I can't remember the exact details, but don't expect anything to work as it should.

    And I was only worrying about detecting when keys were down. Something like this.
    Code:
    /*! \mainpage
        Returns true if a given key is held down.
    
        Usage: asyncdown [left|right|either|both] [shift|ctrl|alt|win]
    
        left:   Return true if the left key is held down
        right:  Return true if the right key is held down
        either: Return true if either key is held down
        both:   Return true if both left and right keys are held down
    */
    
    #include <string.h>
    #include <windows.h>
    
    #define KEYDOWN(key) (GetAsyncKeyState(key) & 0x8000 ? 1 : 0)
    
    enum which_t {
        WHICH_LEFT,
        WHICH_RIGHT,
        WHICH_EITHER,
        WHICHES,
        WHICH_BOTH  /* Special case -- left and right */
    };
    
    char *whiches[] = {
        "left",
        "right",
        "either",
        "both"
    };
    
    enum type_t {
        TYPE_SHIFT,
        TYPE_CTRL,
        TYPE_ALT,
        TYPE_WIN,
        TYPES
    };
    
    struct data_t {
        char *name;
        int vk[WHICHES];
    } data[] = {
        {"shift", {VK_LSHIFT, VK_RSHIFT, VK_SHIFT}},
        {"ctrl", {VK_LCONTROL, VK_RCONTROL, VK_CONTROL}},
        {"alt", {VK_LMENU, VK_RMENU, VK_MENU}},
        {"win", {VK_LWIN, VK_RWIN, 0}},
    };
    
    int main(int argc, char *argv[]) {
        int x;
        enum type_t type = TYPE_SHIFT, t;
        enum which_t which = WHICH_EITHER, w;
    
        for(x = 1; x < argc; x ++) {
            for(t = 0; t < TYPES; t ++) {
                if(!strcmp(argv[x], data[t].name)) type = t;
            }
    
            for(w = 0; w < WHICHES; w ++) {
                if(!strcmp(argv[x], whiches[w])) which = w;
            }
        }
    
        if(which == WHICH_BOTH) {
            return KEYDOWN(data[type].vk[WHICH_LEFT])
                && KEYDOWN(data[type].vk[WHICH_RIGHT]);
        }
    
        return KEYDOWN(data[type].vk[which]);
    }
    Oh yes, I think there were troubles with VK_CONTROL. Try VK_LCONTROL or VK_RCONTROL. It might work.

    Just keep experimenting.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    This is one of the most misunderstood functions - and all because the MSDN documentation is confusing (and they've never fixed it). The exact same thing happened to me the first time I used it. Here's an archived GDI article that gives a better explanation...

    Scroll down to "Check the Keyboard State"

    http://msdn.microsoft.com/archive/de...n_dos2win2.asp

    gg

  4. #4
    Registered User Bajanine's Avatar
    Join Date
    Dec 2001
    Location
    The most peaks over 10,000 feet!
    Posts
    396
    Thanks for the input, I'll tinker with it some more.
    Favorite Quote:

    >For that reason someone invented C++.
    BLASPHEMY! Begone from my C board, you foul lover of objects, before the gods of C cast you into the void as punishment for your weakness! There is no penance for saying such things in my presence. You are henceforth excommunicated. Never return to this house, filthy heretic!



  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Sorry - I linked the wrong article

    http://msdn.microsoft.com/archive/de...dn_dos2win.asp

    Basicallly, you want to check the most significant bit only - as in dwks's code.

    >> #define KEYDOWN(key) (GetAsyncKeyState(key) & 0x8000 ? 1 : 0)

    gg

  6. #6
    Registered User Bajanine's Avatar
    Join Date
    Dec 2001
    Location
    The most peaks over 10,000 feet!
    Posts
    396
    Thanks for your help I actually found this:
    http://cboard.cprogramming.com/showt...yState+control
    and added this to my code and it works:
    Code:
    if((GetAsyncKeyState(VK_CONTROL) & 0x8000) == 0)  // 0x8000 = 32768
    			{
    				FindMember(LeftClick); // Select one member.
    			}
    			else
    			{
    				RayTestHorizontal(head, LeftClick); // Select multiple members.
    			}
    From limits.h I determined that SHRT_MAX is 32767 and 0x8000 is 1 greater than SHRT_MAX.

    But I still am not quite grasping this. is setting this to one over the max value of the type the same as setting the most significant bit?

    Would someone please clarify this for me, I have done quite a bit of searching but everything I have read isn't sinking in! I hate using code that I have absolutely no understanding of. I think doing that comes back to haunt you latter.

    Lost at c
    Favorite Quote:

    >For that reason someone invented C++.
    BLASPHEMY! Begone from my C board, you foul lover of objects, before the gods of C cast you into the void as punishment for your weakness! There is no penance for saying such things in my presence. You are henceforth excommunicated. Never return to this house, filthy heretic!



  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    A SHORT is 16 bits.
    A SHORT with the most significant bit set is 1000000000000000.
    In hex, that's 0x8000.
    SHRT_MAX is the maximum signed value.

    SHRT_MAX isn't really related to using GetAsyncKeyState(). On the topic of signed vs. unsigned values - signed values are typically represented in binary using two's-compliment: http://en.wikipedia.org/wiki/Two's_complement

    gg
    Last edited by Codeplug; 11-25-2007 at 10:56 AM. Reason: mo info

  8. #8
    Registered User Bajanine's Avatar
    Join Date
    Dec 2001
    Location
    The most peaks over 10,000 feet!
    Posts
    396
    Thanks for the link Codeplug!
    Favorite Quote:

    >For that reason someone invented C++.
    BLASPHEMY! Begone from my C board, you foul lover of objects, before the gods of C cast you into the void as punishment for your weakness! There is no penance for saying such things in my presence. You are henceforth excommunicated. Never return to this house, filthy heretic!



Popular pages Recent additions subscribe to a feed