2
votes

I'm trying to get a drop-down combo box (CBS_DROPDOWN or CBS_DROPDOWNLIST) to work. The problem is, anytime I open the combo box, the entire window "freezes" (it doesn't respond to anything, can't even close it, it ignores clicks). The only way to "unfreeze" it is to press the "esc" key.

While the window is "frozen" the combo box doesn't receive any messages, no mouse move, clicks etc.

This is the code I'm using to create the combo box:

case WM_CREATE:
    hComboBox = CreateWindow("COMBOBOX", nullptr,
        WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | CBS_DROPDOWNLIST,
        25, 25, 150, 280, hwnd, (HMENU)12345, GetModuleHandle(nullptr), nullptr);
    populate_cb();
    break;

The "populate_cb()" function simply adds some strings to the combo box and sets an initial element:

void populate_cb() {
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 1");
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 2");
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 3");
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 4");
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 5");
    SendMessage(hComboBox, CB_SETCURSEL, (WPARAM)2, 0);
}

However, the simple (CBS_SIMPLE) combo boxes work though.

Here is the full code:

#include <Windows.h>

HWND hComboBox;

void populate_cb() {
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 1");
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 2");
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 3");
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 4");
    SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)"Item 5");
    SendMessage(hComboBox, CB_SETCURSEL, (WPARAM)2, 0);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_CREATE:
        hComboBox = CreateWindow("COMBOBOX", nullptr,
            WS_OVERLAPPED | WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST,
            25, 25, 150, 280, hwnd, (HMENU)12345, GetModuleHandle(nullptr), nullptr);
        populate_cb();
        break;
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wcex;
    wcex.cbClsExtra = 0;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.cbWndExtra = 0;
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
    wcex.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
    wcex.hInstance = hInstance;
    wcex.lpfnWndProc = WndProc;
    wcex.lpszClassName = "WindowClass";
    wcex.lpszMenuName = nullptr;
    wcex.style = 0;

    if (!RegisterClassEx(&wcex)) {
        MessageBox(nullptr, "Window class registration failed!", "Error", MB_OK | MB_ICONERROR);
        return 1;
    }

    HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "WindowClass", "Window Title",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, nullptr,
        nullptr, hInstance, nullptr);

    if (!hwnd) {
        MessageBox(nullptr, "Window creation failed!", "Error", MB_OK | MB_ICONERROR);
        return 1;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    MSG msg;
    while (GetMessage(&msg, hwnd, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}
1
You're not responding to one of the combo box notifications by going into an infinite loop, are you?Mark Ransom
I'm not responding to any combo box notifications at all.Vlad
Please provide a minimal reproducible example. And while not a bug in itself, bitwise OR-ing the WS_OVERLAPPED window style indicates, that you decided against reading the documentation.IInspectable
need look under debugger - are thread wait to something or spin in infinite loop. callstack. all other windows also freeze ? message loop code not executed more ?RbMm
I'm going to guess you have passed the handle of your main window for the second argument of GetMessage(). You should usually pass nullptr except in certain circumstances.Jonathan Potter

1 Answers

8
votes
while (GetMessage(&msg, hwnd, 0, 0) > 0) 

pumps messages for the main window only. You need to service queued messages for all windows in the thread. Change this line to

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

As explained in the documentation for GetMessage passing NULL for the second argument retrieves messages for all windows owned by the thread.