Thread: WM_KEYDOWN and GetAsyncKeyState() for parent window

  1. #1
    Grey Wizard C_Sparky's Avatar
    Join Date
    Sep 2009
    Posts
    50

    WM_KEYDOWN and GetAsyncKeyState() for parent window

    I have an application which displays files in a listview, and has several buttons to press for various functions.

    I wish to capture the F5 key and the backspace key for the entire parent window, even when a child control has the focus. I can catch the two keys when the parent window has the focus and it works fine, but if a child window has the focus the main window procedure catches no such message.

    I'm wondering which solution would be more efficient on memory and processing:
    1) Subclassing all the child controls to catch the WM_KEYDOWN message
    2) Creating a separate thread which loops GetAsyncKeyState() and see's the key press no matter what control has the focus.

    Another alternative would be using a global keyboard hook, but that seems to be overdoing it, I know many anti-malware programs are set off by such actions.

    Implementing solution 2 would be much easier, but I'm not sure if it would be frowned upon that I chose that over subclassing.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Have you tried building an accelerator table with these keys you want and directing it to your main window with TranslateAccelerator() in your message dispatcher?

  3. #3
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Just check the MSG structure after TranslateMessage but before you foist it off on DispatchMessage

  4. #4
    Grey Wizard C_Sparky's Avatar
    Join Date
    Sep 2009
    Posts
    50
    Quote Originally Posted by CommonTater View Post
    Have you tried building an accelerator table with these keys you want and directing it to your main window with TranslateAccelerator() in your message dispatcher?
    I'm not familiar with using accelerator tables. However I just tried to implement one and have failed to make it work properly.

    I'm following the procedure here: Using Keyboard Accelerators (Windows)

    I've tried both loading the table from a resource and creating it at runtime, trying the F5 or F6 key. My message dispatcher is checking for keys with TranslateAccelerator(), and the callback is checking for the ID in WM_COMMAND under the low order word in wParam. I'm using Windows 7 Pro.

    Maybe could you give me an example how you would use it?

    And adeyblue: If you could be more specific about what I would be checking and doing with the result. Thanks.

  5. #5
    Grey Wizard C_Sparky's Avatar
    Join Date
    Sep 2009
    Posts
    50
    For those wondering what the solution is:

    Create a new function to call during the message loop:
    Code:
    int process_keydown(HWND hwnd, MSG* msg)
    {
        if(msg->message == WM_KEYDOWN)
        {
            switch(msg->wParam)
            {
                case VK_F5:
                    /* Do your stuff here */
                    return 1;
    
                case VK_BACK:
                    /* ... */
                    return 1;
            }
        }
    
        return 0;
    }
    And in the message loop:

    Code:
    while(GetMessage(&msg, NULL, 0, 0))
    {
         if(!process_keydown(hwnd, &msg)) // check for any WM_KEYDOWN message
         {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
         }
    }

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Usually accelerator tables are processed like this...

    Code:
    while(GetMessage(&msg, NULL, 0, 0))
         {  if (!TranslateAccelerator(win,KeyBrd,&msg))
              if (!IsDialogMessage(win,&msg))
                { TranslateMessage(&msg); 
                  DispatchMessage(&msg); }
    You create them in your resources like this...
    Code:
    HOTKEYS ACCELERATORS
    {
      80, 1000, VIRTKEY
      VK_SPACE, 1001, VIRTKEY
      83, 1002, VIRTKEY
      VK_PRIOR, 1003, VIRTKEY
      VK_NEXT, 1004, VIRTKEY
      VK_LEFT, 1005, VIRTKEY
      VK_RIGHT, 1006, VIRTKEY
      VK_UP, 1007, VIRTKEY
      VK_DOWN, 1008, VIRTKEY
      49, 1009, VIRTKEY
      50, 1010, VIRTKEY
      51, 1011, VIRTKEY
      52, 1012, VIRTKEY
      VK_RETURN, 1013, VIRTKEY
      84, 1014, VIRTKEY
      88, 1015, VIRTKEY
    }
    That is ... KEY, CMD, FLAGS...

    Of course you have to load the accelerator table on startup...
    Code:
    HACCEL KeyBrd;  
    
    // start accelerators
    KeyBrd = LoadAccelerators(PgmInst,"HOTKEYS");
    From there... it should work...

    From the example... Pressing the Space bar should result in a WM_COMMAND message with 1001 in the low word of WPARAM, sent to the window specified in TranslateAccelerators().
    Last edited by CommonTater; 01-03-2011 at 04:27 AM.

Popular pages Recent additions subscribe to a feed