views:

326

answers:

1

Hi guys,

I've built a GUI with button, groups of buttons, edits, listboxes... etc... but now I want to know how to make my gui accessible through keyboard, I mean, changing the focus by pressing tab button. Does anybody have any idea on how to do this? I'm using Windows Xp and the GUI is writen on C++ using Visual Studio 2008.

Thanks a lot

UPDATE:

INT APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

INITCOMMONCONTROLSEX ics;
ics.dwSize = sizeof(ics);
ics.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&ics);

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_PRUEBA, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
 return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDA_ACCEL_TABLE));

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
 if ((!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) && (!IsDialogMessage(msg.hwnd, &msg))) 
 //if ((!IsDialogMessage(msg.hwnd, &msg)) & (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg) )) 
    //if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
 {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
}

return (int) msg.wParam;

}

I have a lot of controls in my GUI, should I put WS_TABSTOP in all of them? What if I have a group of buttons... should I put WS_TABSTOP in every button and in the group? only in the individual buttons?

For example I'll paste a group I've created:

INT CrearControles(HWND hwnd, LPARAM lParam) {

HINSTANCE hInstance;
HFONT hfont;
HWND hctrl;
int i;

hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
hfont = (HFONT)GetStockObject( DEFAULT_GUI_FONT );

/* Insertar controles */    

hctrl = CreateWindowEx(
      0,
      "BUTTON",        /* Nombre de la clase */
      "Rol",       /* Texto del título */
      BS_GROUPBOX | WS_CHILD | WS_VISIBLE | WS_GROUP , /* Estilo */
      20, 15,           /* Posición */
      180, 100,          /* Tamaño */
      hwnd,            /* Ventana padre */
      (HMENU)GRUPO_ROL,/* Identificador del control */
      hInstance,       /* Instancia */
      NULL);           /* Sin datos de creación de ventana */ 
SendMessage(hctrl, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));

hctrl = CreateWindowEx(0, "BUTTON", "Receptor", BS_NOTIFY | BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 30, 35,      
      70, 25, hwnd, (HMENU)BOTON_RECEPTOR, hInstance, NULL);           
SendMessage(hctrl, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
SendDlgItemMessage(hwnd, BOTON_RECEPTOR, BM_SETCHECK, BST_CHECKED, 0);           
SetFocus(hctrl);

hctrl = CreateWindowEx(0, "BUTTON", "Emisor", BS_NOTIFY | BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 30, 65, 
      70, 25, hwnd, (HMENU)BOTON_EMISOR, hInstance, NULL);         
SendMessage(hctrl, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));


hctrl = CreateWindowEx(0, "STATIC", "Telefono", SS_SIMPLE | WS_CHILD | WS_VISIBLE, 150, 55, 100, 55, hwnd, (HMENU)LABEL_TELEFONO,
      hInstance, NULL);          
SendMessage(hctrl, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
SetFocus(hctrl); 

hctrl = CreateWindowEx(0, "EDIT", "", ES_READONLY | ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_NUMBER , 115, 68,
      80, 20, hwnd, (HMENU)EDIT_TELEFONO, hInstance, NULL); 
SendMessage(hctrl, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
SetFocus(hctrl);

return 1; }

Thx

+1  A: 

If you're GUI is running as a standard modal dialog you should get tabbing and Alt key navigation between controls for free.

ie: controls with the WS_TABSTOP style set you should be able to tab to, controls with short cut key defined (eg: a button with a caption of "&Do Something" should be accessible with Alt+D - and the D should be displayed underlined).

If your window is not running as standard modal dialog, to get this behaviour your message loop needs to call IsDialogMessage before dispatching each message.

eg:

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
 if (!IsDialogMessage(m_hWndYourWindow, &msg))
 {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
}
cantabilesoftware
deb
cantabilesoftware
When I do that the accelerators stop working, and neither do the tab button.
deb
cantabilesoftware
If I only put Translate accelerators work. If I only put IsDialogMessage tab doesn't work. If I put both of them (also if I swap the order) neither of them work. I'll post my code, but I think the problem could be on the controls... maybe I've created them wrongly.
deb
I think the first parameter to IsDialogMessage is wrong - it should be the handle to the top level window - not the window handle of the message being dispatched.
cantabilesoftware
Kudos 2 U! It was just like u said :) Thanks a lot
deb
Is it normal that to use the accelerators I have to push alt first and then the letter (they aren't pushed simutaneously) ? It happens when I have IsDialogMessage in the if... if not it works ok (pushing them simoultaneously).
deb
Hrm, I can't think of any reason why using IsDialogMessage would conflict with TranslateAccelerator. If they do I have no idea why and the only thing I can suggest is the same as before - try swapping the order of TranslateAccelerator/IsDialogMessage. Sorry can't help on that one.
cantabilesoftware