c++ - Tab 键在子控件中不起作用

标签 c++ winapi

下面是我的窗口包含3组控件的winapi程序:

  1. 直接在窗口中创建的控件
  2. Group1 中的控件
  3. Group2 中的控件

当我按下 Tab 键时,它只在 set1 中遍历。 为什么我不能通过Tab键切换到group1和group2的子控件?

#include <Windows.h>

LRESULT __stdcall   WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message)
    {
    case WM_CTLCOLORSTATIC:
    {
        HDC hdcStatic = (HDC)wParam;
        SetTextColor(hdcStatic, RGB(0, 0, 255));
        SetBkMode(hdcStatic, TRANSPARENT);
        return (LRESULT)GetStockObject(NULL_BRUSH);
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
////////////////////////////////////////////////////////////////////////////
void CreateEdit(const HWND &parent, const int &x, const int &y, const int &id) {
    CreateWindow(L"EDIT", L"", WS_BORDER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, x, y, 200, 20, parent, (HMENU)id, NULL, NULL);
}
////////////////////////////////////////////////////////////////////////////
int __stdcall  wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR    lpCmdLine, _In_ int       nCmdShow)
{
    WNDCLASSEX wndclass{};

    wndclass.cbSize = sizeof(wndclass);
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.hInstance = hInstance;
    wndclass.hbrBackground = CreateSolidBrush(RGB(255, 128, 255));
    wndclass.lpszClassName = L"test";

    RegisterClassEx(&wndclass);

    HWND hWndMainWindow = CreateWindow(
        wndclass.lpszClassName,
        L"test",
        WS_EX_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE,
        100, 100, 500, 500,
        NULL, NULL, hInstance, NULL);

    ::ShowWindow(hWndMainWindow, SW_SHOW);
    ::UpdateWindow(hWndMainWindow);

    //Creating Controls~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    int x = 10, y = 20, id = 100;
    HWND    g1 = CreateWindow(L"button", L"Group1", WS_CHILD | WS_VISIBLE | BS_GROUPBOX | WS_TABSTOP | WS_GROUP, 0, 50, 220, 200, hWndMainWindow, (HMENU)++id, NULL, NULL);
    //Controls in Group1
    CreateEdit(g1, x, (y += 30), ++id);
    CreateEdit(g1, x, (y += 30), ++id);
    CreateEdit(g1, x, (y += 30), ++id);
    CreateEdit(g1, x, (y += 30), ++id);

    HWND    g2 = CreateWindow(L"button", L"Group2", WS_CHILD | WS_VISIBLE | BS_GROUPBOX | WS_TABSTOP | WS_GROUP, 260, 50, 220, 200, hWndMainWindow, (HMENU)++id, NULL, NULL);
    y = 20;
    //Controls in Group2
    CreateEdit(g2, x, (y += 30), ++id);
    CreateEdit(g2, x, (y += 30), ++id);
    CreateEdit(g2, x, (y += 30), ++id);
    CreateEdit(g2, x, (y += 30), ++id);

    //The controls that create  directly in the main window 
    y = 270;
    CreateWindow(L"static", L"Main Window Controls", WS_CHILD | WS_VISIBLE, x, y, 200, 30, hWndMainWindow, (HMENU)++id, NULL, NULL);

    CreateEdit(hWndMainWindow, x, (y += 30), ++id);
    CreateEdit(hWndMainWindow, x, (y += 30), ++id);
    CreateEdit(hWndMainWindow, x, (y += 30), ++id);
    CreateEdit(hWndMainWindow, x, (y += 30), ++id);
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    MSG msg;

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

    return (int)msg.wParam;
}

最佳答案

托管“Group1”和“Group2”的两个子窗口都需要用 WS_EX_CONTROLPARENT 样式标记为“控制父级”。这种风格意味着:

The window itself contains child windows that should take part in dialog box navigation. If this style is specified, the dialog manager recurses into children of this window when performing navigation operations such as handling the TAB key, an arrow key, or a keyboard mnemonic

按如下方式更改代码以创建这些窗口:

HWND    g1 = CreateWindowEx(WS_EX_CONTROLPARENT, L"button", L"Group1", WS_CHILD | WS_VISIBLE | BS_GROUPBOX | WS_TABSTOP | WS_GROUP, 0, 50, 220, 200, hWndMainWindow, (HMENU)++id, NULL, NULL);
HWND    g2 = CreateWindowEx(WS_EX_CONTROLPARENT, L"button", L"Group2", WS_CHILD | WS_VISIBLE | BS_GROUPBOX | WS_TABSTOP | WS_GROUP, 260, 50, 220, 200, hWndMainWindow, (HMENU)++id, NULL, NULL);

(顺便说一句,让您的窗口成为组框的子项似乎是错误的。它们不需要是 - 您可以将它们放在其中但使它们成为它的 sibling 而不是子项。组框是专门设计的以这种方式工作 - 我不知道它在 child 时使用控件的效果如何。)

关于c++ - Tab 键在子控件中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37318523/

相关文章:

带括号的 C++ 表达式

c++ - 在鼠标 Hook 中,滚轮增量始终为 0

c++ - 有没有办法消除构造函数选择的歧义?

c++ - 非限定或指针/引用类型的特征

c++ - std::bind 和 std::function 问题

C++ 编译错误(REPAST 库)

c - 环境变量和本地化

c# - 使用 IOCTL_DVD_* 控制代码从 C# 调用 DeviceIoControl

c - 如何指定Windows主参数nCmdShow

c# - 将外部应用程序移动到屏幕前面