locked
How to move from control to control using arrow keys RRS feed

  • Question

  • Hi, 

    I have made an application in C Windows Api where I have a kind of grid of radio buttons and small edit controls. I want to be able to move between these controls using arrow keys.

    I have made the application able to move between controls by using the TAB key. The way I have done this is first to change the message loop like this:

    while( GetMessage(&msg, NULL, 0, 0)) {
        if(!IsDialogMessage(Hwnd,&msg)) 	{                                    
           TranslateMessage(&msg);      
           DispatchMessage(&msg);
        }
    }
    
     

    and then using WS_TABSTOP in the create window definitions. However, what I want to do is to move to and from the grid I mentioned by using the TAB key, but when being inside the grid, I will only move from control to control by using the arrow keys. Can anybody help me?

     Thanks in advance.

    -Keitel


     

    Tuesday, March 11, 2014 7:39 AM

Answers

  • >However, what I want to do is to move to and from the grid I mentioned by using the TAB key, but when being inside the grid, I will only move from control to control by using the arrow keys.

    I think the code you have - using IsDialogMessage should work. The key
    is to use the WS_GROUP style on the controls - see
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms644995(v=vs.85).aspx#ws_group

    Dave

    Tuesday, March 11, 2014 8:10 AM

All replies

  • >However, what I want to do is to move to and from the grid I mentioned by using the TAB key, but when being inside the grid, I will only move from control to control by using the arrow keys.

    I think the code you have - using IsDialogMessage should work. The key
    is to use the WS_GROUP style on the controls - see
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms644995(v=vs.85).aspx#ws_group

    Dave

    Tuesday, March 11, 2014 8:10 AM
  • Thank you for your answer. I've tried the WS_GROUP style as described in the article, but I wasn't able to make it work for the arrow keys.

    -Keitel

    Tuesday, March 11, 2014 11:40 AM
  • >Thank you for your answer. I've tried the WS_GROUP style as described in the article, but I wasn't able to make it work for the arrow keys.

    Clearly from the documentation, it ought to work, so maybe there's
    something specific in your application preventing it from working - or
    you're expecting it to do something it can't do (like move focus from
    an edit control)?

    If you use Spy++ to check the styles on controls on a dialog box where
    you know the keyboard operations work correctly, that should give you
    an example of what you need to do.

    Have you tried the technique in a simple test application so that you
    can check it in isolation from the rest of your code?

    Dave

    Tuesday, March 11, 2014 2:15 PM
  • Ok, maybe there is something I have misunderstood. I therefore give a stripped down version of the program:


    #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); HINSTANCE g_hinst; int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { HWND Hwnd; MSG msg ; int x; int y; WNDCLASS wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = TEXT( "DhruvaNada" ); wc.hInstance = hInstance ; wc.hbrBackground = CreateSolidBrush(RGB(66,50,166)); wc.lpfnWndProc = WndProc ; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClass(&wc); x = (GetSystemMetrics(SM_CXSCREEN)/2) - 512; y = (GetSystemMetrics(SM_CYSCREEN)) - 40; Hwnd = CreateWindow( wc.lpszClassName, TEXT("Testcontrols"), WS_OVERLAPPEDWINDOW | WS_VISIBLE | DT_CENTER, x, 0, 1024, y, 0, 0, hInstance, 0); ShowWindow(Hwnd, SW_MAXIMIZE); while( GetMessage(&msg, NULL, 0, 0)) { if(!IsDialogMessage(Hwnd,&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { static int screenheight; static int y2; static HWND Control[4][4]; static int xx; static int xo, x, y; switch(msg) { case WM_CREATE: y2=260; Control[0][0] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_GROUP | WS_TABSTOP | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 1, g_hinst, NULL); Control[0][1] = CreateWindow(TEXT("button"), TEXT("Blue"), WS_CHILD | WS_VISIBLE | BS_CENTER | BS_RADIOBUTTON, 0, 0, 0, 0, hwnd, (HMENU) 2 , g_hinst, NULL); Control[0][2] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 3, g_hinst, NULL); Control[0][3] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 4, g_hinst, NULL); Control[1][0] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_GROUP | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 5, g_hinst, NULL); Control[1][1] = CreateWindow(TEXT("button"), TEXT("Blue"), WS_CHILD | WS_VISIBLE | BS_CENTER | BS_RADIOBUTTON, 0, 0, 0, 0, hwnd, (HMENU) 6 , g_hinst, NULL); Control[1][2] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 7, g_hinst, NULL); Control[1][3] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 8, g_hinst, NULL); Control[2][0] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 9, g_hinst, NULL); Control[2][1] = CreateWindow(TEXT("button"), TEXT("Blue"), WS_CHILD | WS_VISIBLE | BS_CENTER | BS_RADIOBUTTON, 0, 0, 0, 0, hwnd, (HMENU) 10 , g_hinst, NULL); Control[2][2] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 11, g_hinst, NULL); Control[2][3] = CreateWindow(TEXT("edit") , NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd,(HMENU) 12, g_hinst, NULL); return 0 ;

    case WM_SIZE : xo = LOWORD(lParam)/2; xx = xo-10; MoveWindow(Control[0][0], xx, y2+35, 12, 12, TRUE); MoveWindow(Control[0][1], xx, y2+54, 12, 18, TRUE); MoveWindow(Control[0][2], xx, y2+76, 12, 18, TRUE); MoveWindow(Control[0][3], xx, y2+98, 12, 18, TRUE); xx += 20; MoveWindow(Control[1][0], xx, y2+35, 12, 12, TRUE); MoveWindow(Control[1][1], xx, y2+54, 12, 18, TRUE); MoveWindow(Control[1][2], xx, y2+76, 12, 18, TRUE); MoveWindow(Control[1][3], xx, y2+98, 12, 18, TRUE); xx += 20; MoveWindow(Control[2][0], xx, y2+35, 12, 12, TRUE); MoveWindow(Control[2][1], xx, y2+54, 12, 18, TRUE); MoveWindow(Control[2][2], xx, y2+76, 12, 18, TRUE); MoveWindow(Control[2][3], xx, y2+98, 12, 18, TRUE); return 0; case WM_DESTROY: { KillTimer (hwnd, 1); PostQuitMessage(0); return 0 ; } } return DefWindowProc(hwnd, msg, wParam, lParam); }

    Usually I will do the creation of controls in a loop. But this is just to keep the code simple. Maybe you or someone could give me an idea what is wrong.

    Thanks in advance.

    Keitel


    Tuesday, March 11, 2014 7:35 PM
  • >Ok, maybe there is something I have misunderstood. I therefore give a stripped down version of the program:

    As I mentioned...

    ".. or you're expecting it to do something it can't do (like move
    focus from an edit control)?"

    ... which seems to be what you have.

    The arrow keys are handled by the edit control that has focus, so you
    can't move to the next control in a group from an edit control. In a
    dialog you normally use WS_GROUP to group related radio buttons.

    If you change your example to have a group of radio buttons like this:

    Control[0][1] = CreateWindow(TEXT("button"), TEXT("Blue"), WS_CHILD |
    WS_VISIBLE |  BS_CENTER | BS_RADIOBUTTON,              0, 0, 0, 0, hwnd, (HMENU) 2 , g_hinst, NULL);
    Control[0][2] = CreateWindow(TEXT("button"), TEXT("Red"), WS_CHILD |
    WS_VISIBLE |  BS_CENTER | BS_RADIOBUTTON,              0, 0, 0, 0, hwnd, (HMENU) 2 , g_hinst, NULL);
    Control[0][3] = CreateWindow(TEXT("button"), TEXT("Green"), WS_CHILD |
    WS_VISIBLE |  BS_CENTER | BS_RADIOBUTTON,              0, 0, 0, 0, hwnd, (HMENU) 2 , g_hinst, NULL);

    Then the cursor keys will move focus between those controls.

    Dave

    Tuesday, March 11, 2014 9:56 PM
  • So, what you are saying is that it is impossible in Windows Api to make the program move between edit controls by using arrow keys? You can only do this by using the TAB key? Are you absolutely sure about this? I would just like to have it confirmed.

    Keitel

    Thursday, March 13, 2014 8:49 AM
  • >So, what you are saying is that it is impossible in Windows Api to make the program move between edit controls by using arrow keys?

    No, very little is "impossible" -  but you can't do it using
    IsDialogMessage on its own.

    You could hook the edit controls and provide your own handler for the
    cursor keys - but generally that would be silly because users expect
    to be able to use them to navigate inside the edit control itself. If
    your edit controls don't need to behave like edit controls, then maybe
    that's an option for you.

    Dave


    Ron Symonds www.rxs-enterprises.org/fp/wf-menu.aspx
    Thursday, March 13, 2014 10:03 AM
  • Could you explain a little more how to do what you are suggesting - how to provide my own handler for the cursor keys etc.

    Keitel

    Monday, March 17, 2014 11:15 AM
  • >Could you explain a little more how to do what you are suggesting - how to provide my own handler for the cursor keys etc.

    I don't recommend doing it - doing things that are contrary to the
    normal way controls work usually proves to annoy users in the long
    run.

    However, if you insist... you'd have to subclass the edit control and
    add WM_KEY* handlers to catch the cursor key press and then move the
    focus appropriately.

    Dave

    Monday, March 17, 2014 12:12 PM
  • You say sub class, but I am not working in C++, but in C:

    Keitel

    Sunday, March 23, 2014 2:26 PM
  • >You say sub class, but I am not working in C++, but in C:

    It was meant in the Windows sense:
    http://msdn.microsoft.com/en-us/library/windows/desktop/bb773183(v=vs.85).aspx

    Dave

    Sunday, March 23, 2014 8:33 PM
  • Ok, thank you for your help. I'll read the page and work on it from there.

    Keitel

    Tuesday, March 25, 2014 11:06 AM