在 child window 中使用 winapi 在 c++ 中创建按钮不起作用

Creating a button in c++ with winapi in a child window doesn't work

我想用两个 child windows 创建一个 window。在 child windows 中应该是一个按钮,但它没有向我显示按钮,我也不知道为什么。这是我的代码:


#include "framework.h"
#include "projectnameTest.h"

wchar_t* convertCharArrayToLPCWSTR(const char* charArray)
{
    wchar_t* wString = new wchar_t[4096];
    MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
    return wString;
}

#define MAX_LOADSTRING 100

constexpr unsigned int bWindowOne = 110; 
constexpr unsigned int bWindowTwo = 111;


HINSTANCE hInst;                               
bool endloop = false;
HWND hWnd, hWndOne, hWndTwo;
HWND hButtonWindowOne, hButtonWindowTwo;


const char szWindowOneClass[] = "WindowOneClass";
const char szWindowOneTitel[] = "WindowOneTitel";

const char szWindowTwoClass[] = "WindowTwoClass";
const char szWindowTwoTitel[] = "WindowTwoTitel";

LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    WndOneProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK    WndTwoProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{

    WNDCLASSEXW wcex;
    const char szAppClass[] = "AppClass";
    const char szAppTitel[] = "AppTitel";

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = NULL;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = convertCharArrayToLPCWSTR(szAppClass);
    wcex.hIconSm = NULL;

    RegisterClassExW(&wcex);

    wcex.lpszClassName = convertCharArrayToLPCWSTR(szWindowOneClass);
    wcex.lpfnWndProc = WndOneProc;
    wcex.hIcon = NULL;

    RegisterClassExW(&wcex);

    wcex.lpszClassName = convertCharArrayToLPCWSTR(szWindowTwoClass);
    wcex.lpfnWndProc = WndTwoProc;
    
    RegisterClassExW(&wcex);
    
    hWnd = CreateWindowExW(NULL,
        convertCharArrayToLPCWSTR(szAppClass),
        convertCharArrayToLPCWSTR(szAppTitel),
        (WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU),
        200,
        150,
        500,
        500,
        NULL,
        NULL,
        hInstance,
        NULL);

    
    

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);


    MSG msg;

    while (false == endloop)
    {
        if (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

    }

    return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static PAINTSTRUCT ps;

    switch (message)
    {
    case WM_CREATE:
    {
        ::hWndOne = CreateWindowExW(NULL,
            convertCharArrayToLPCWSTR(szWindowOneClass),
            convertCharArrayToLPCWSTR(szWindowOneTitel),
            (WS_CHILD | WS_VISIBLE | WS_DLGFRAME),
            10,
            10,
            120,
            120,
            hWnd,
            NULL,
            ((LPCREATESTRUCT)lParam)->hInstance,
            NULL);
    
        ::hWndTwo = CreateWindowExW(NULL,
            convertCharArrayToLPCWSTR(szWindowTwoClass),
            convertCharArrayToLPCWSTR(szWindowTwoTitel),
            (WS_CHILD | WS_VISIBLE | WS_DLGFRAME),
            300,
            10,
            120,
            120,
            hWnd,
            NULL,
            ((LPCREATESTRUCT)lParam)->hInstance,
            NULL);

    }
    case WM_PAINT:
        {
            HDC hdc = BeginPaint(hWnd, &ps);
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        ::endloop = true;
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

LRESULT CALLBACK WndOneProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HDC hdc;
    static PAINTSTRUCT ps;

    switch (message)
    {
    case WM_CREATE:
    {
        ::hButtonWindowOne = CreateWindowExW(NULL, L"BUTTON", L"ButtonWindowOne", NULL, 10, 10, 40, 20, hWnd, (HMENU)bWindowOne, GetModuleHandle(NULL), NULL);

    }
    case WM_PAINT:
    {
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

LRESULT CALLBACK WndTwoProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HDC hdc;
    static PAINTSTRUCT ps;

    switch (message)
    {
    case WM_CREATE:
    {
        ::hButtonWindowOne = CreateWindowExW(NULL, L"BUTTON", L"ButtonWindowOne", NULL, 10, 10, 40, 20, hWnd, (HMENU)bWindowOne, GetModuleHandle(NULL), NULL);

    }
    case WM_PAINT:
    {
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

所以我已经尝试在主 window 中创建按钮并且成功了,但我不明白为什么它不在 child 中显示按钮windows,虽然几乎一模一样。谢谢你的帮助。

此代码还有其他问题,但要让按钮显示出来,您需要在创建按钮时提供 window 样式。子控件获得 WS_CHILD 样式,如果您希望它们可见,它们需要 WS_VISIBLE 例如将相关行更改为

hButtonWindowOne = CreateWindowExW(NULL, L"BUTTON", L"ButtonWindowOne", WS_CHILD | WS_VISIBLE, 10, 10, 40, 20, hWnd, (HMENU)bWindowOne, GetModuleHandle(NULL), NULL);