How can I create a toolbar on pure WINAPI without icons? [migrated]

I need to create a toolbar with texts only (without icons).

I have tried to do that, but the toolbar has appeared without anything (only gray strip on the top part of my window).

The program is below.

It is assumed then `CreateButtons2` function should create the toolbar.

Buttons texts are in `ButtonsArray`.

Could you tell what I am doing wrong ?

#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
// ----------------------------------------
#include <vector>
#include <string>
#include <assert.h>
#include <winuser.h>

#pragma comment( lib, "comctl32" )
#include <commctrl.h>

void DebugOutput_c(const char* msg) {
    size_t convertedChars = 0;
    size_t newsize = strlen(msg) + 1;
    wchar_t* result_wstring = new wchar_t[newsize];
    mbstowcs_s(&convertedChars, result_wstring, newsize, msg, _TRUNCATE);

    OutputDebugStringW(result_wstring);
    delete[] result_wstring;
}

void DebugOutput_w(const std::wstring& msg) {
    OutputDebugStringW(msg.c_str());
}

void DebugOutput_s(const std::string s) {
    DebugOutput_c(s.c_str());
}

HINSTANCE g_hInst;                                
const WCHAR* szMainWindowTitle = L"--- TEST ---";
const WCHAR* szMainWindowClass = L"WinClass";
HWND g_hMainWindow = NULL;

LRESULT CALLBACK    WndProc_MainWin(HWND, UINT, WPARAM, LPARAM);

// ---------------------------------

struct ButtonDescription_STRUCT {
    std::wstring Caption;
    int ButtonID;
};

using ButtonDescriptions_ARRAY = std::vector<ButtonDescription_STRUCT>;

#define ID_BUTTON_1     1
#define ID_BUTTON_2     2

const ButtonDescriptions_ARRAY ButtonsArray = {
    {L"PLUS", ID_BUTTON_1},
    {L"MINUS", ID_BUTTON_2}
};

bool CreateButtons2(const ButtonDescriptions_ARRAY& ButtonsArray,
    HINSTANCE hInst, HWND hMainWindow) {

    bool ok = true;

    HWND hToolbar = CreateWindowW(TOOLBARCLASSNAME, NULL,
                                        TBSTYLE_WRAPABLE | WS_CHILD,
                                        0, 0, 0, 0,
                                        g_hMainWindow, NULL, hInst, NULL);
    DWORD ErrCode = GetLastError();
    assert(hToolbar != NULL);

    RECT rect;
    for (const ButtonDescription_STRUCT& b : ButtonsArray) {

        DebugOutput_w(L"Next = " + b.Caption + L"n");

        const int numButtons = 1;
        TBBUTTON tb{ 0 };
        tb.iBitmap = 0;
        tb.idCommand = b.ButtonID;
        tb.iString = (INT_PTR) b.Caption.c_str();
        tb.fsState = TBSTATE_ENABLED;
        tb.fsStyle = TBSTYLE_BUTTON | BTNS_SHOWTEXT; // BTNS_BUTTON;

        WPARAM wParam = 1;
        LPARAM lParam = (LPARAM)&tb;
        int iNew = SendMessageW(hToolbar, TB_ADDBUTTONSW, wParam, lParam);
        assert(iNew >= 0);

        DebugOutput_s("iNew = " + std::to_string(iNew) + "n");

    }

    ShowWindow(hToolbar, SW_SHOW);

    return ok;
}

ATOM RegisterClass_MainWin() {
    WNDCLASSEXW wcex;

    ZeroMemory(&wcex, sizeof(wcex));

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc_MainWin;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = g_hInst;
    
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    
    wcex.lpszClassName = szMainWindowClass;

    return RegisterClassExW(&wcex);
}



BOOL InitInstance(HINSTANCE hInstance) {
    g_hInst = hInstance;

    g_hMainWindow = CreateWindowW(szMainWindowClass, szMainWindowTitle, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

    if (!g_hMainWindow) {
        return FALSE;
    }

    return TRUE;
}

void ShowAndUpdateWin(HWND hWnd, int nCmdShow) {

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

}


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

    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(icex);
    icex.dwICC = ICC_BAR_CLASSES;
    BOOL res_init = InitCommonControlsEx(&icex);
    assert(res_init == TRUE);

    RegisterClass_MainWin();

    if (!InitInstance(g_hInst)) {
        return FALSE;
    }

    CreateButtons2(ButtonsArray, g_hInst, g_hMainWindow);

    ShowAndUpdateWin(g_hMainWindow, SW_NORMAL);

    MSG msg;

    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}


LRESULT CALLBACK WndProc_MainWin(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);

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