使我的 GUI 可以通过键盘访问(Xp、Visual Studio、C++)

Posted

技术标签:

【中文标题】使我的 GUI 可以通过键盘访问(Xp、Visual Studio、C++)【英文标题】:Making my GUI accessible through keyboard (Xp, Visual Studio, C++) 【发布时间】:2009-09-09 11:19:12 【问题描述】:

我已经构建了一个带有按钮、按钮组、编辑、列表框...等的 GUI...但是现在我想知道如何使我的 gui 可以通过键盘访问,我的意思是,通过按 tab 来更改焦点按钮。有人知道如何做到这一点吗?我使用的是 Windows Xp,GUI 是使用 Visual Studio 2008 在 C++ 上编写的。

非常感谢

更新:

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;

我的 GUI 中有很多控件,我应该把 WS_TABSTOP 放在所有控件中吗?如果我有一组按钮...我应该将 WS_TABSTOP 放在每个按钮和组中吗?仅在单个按钮中?

例如,我将粘贴我创建的组:

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;

谢谢

【问题讨论】:

这些按钮是否存在于窗口或对话框中?你如何创建它们? 我在 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 上创建它们。在 WM_CREATE 上。 【参考方案1】:

如果您的 GUI 是作为标准模式对话框运行的,您应该可以免费获得控件之间的制表符和 Alt 键导航。

ie:设置了 WS_TABSTOP 样式的控件,您应该可以使用 Tab 键切换到,定义了快捷键的控件(例如:标题为“&Do Something”的按钮应该可以通过 Alt+D 访问 - 并且 D 应该下划线显示)。

如果您的窗口未作为标准模式对话框运行,要获得此行为,您的消息循环需要在分派每条消息之前调用 IsDialogMessage。

例如:

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))

    if (!IsDialogMessage(m_hWndYourWindow, &msg))
    
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    

【讨论】:

嗨,我的 GUI 不是模态的。我的代码中有一个类似的循环,但 IsDialogMessage 我放了 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 。加速器以这种方式工作,但我必须将 IsDialogMessage 放在哪里才能使制表键工作。谢谢 你应该可以使用类似“if (!TranslateAccelerator(...) && !IsDialogMessage(...))”的东西 当我这样做时,加速器停止工作,标签按钮也停止工作。 你是说如果你输入“if (!TransactionAccelerator)”你会得到加速器工作,如果你输入“if (!IsDialogMessage))”你会得到 tab 键工作,但你可以' t 让两者一起工作?此外,请确保您在要切换到的控件上设置了 WS_TABSTOP 样式。此外,尝试将调用顺序交换为“if (!IsDialogMessage(...) && ! TranslateAccelerator(...))”。也许一个正在排除另一个。如果您愿意,请发布您的消息循环的完整代码,我会看看。 如果我只使用翻译加速器。如果我只放 IsDialogMessage 选项卡不起作用。如果我把它们都放了(如果我交换订单)它们都不起作用。我会发布我的代码,但我认为问题可能出在控件上……也许我创建错了。

以上是关于使我的 GUI 可以通过键盘访问(Xp、Visual Studio、C++)的主要内容,如果未能解决你的问题,请参考以下文章

如何使我的键盘弹出窗口更加流畅,我的视图控制器以模态方式出现?

当触发 iOS Safari 中的虚拟键盘时,它会使我的 CSS 过渡闪烁。如何解决这个问题?

如何使我的 SpringBoot 应用程序可以通过我的公共 IP 地址访问?

windows 安装程序可以默认程序使用 XP 兼容模式吗?

键盘的事件被认为是鼠标在 GUI 上的点击

在 Qt 上为 Android 设计 GUI 的技术