Search code examples
cwindowsuser-interfacewinapicombobox

Why does my Combo Box (WinAPI) not highlight/select its text?


My ComboBox does not highlight/select text when I hover/click the mouse pointer over Options displayed. Even when I press TAB on the keyboard, the item selection does not show the ComboBox highlighted.

Can anyone see any error in the code snippet below?

PS: the ComboBox is visible in the main window and the Dropdown list is working as intended.

#include <windows.h>
#include <windowsx.h>
#include <CommCtrl.h>
#include <wingdi.h>
#include <WinUser.h>
#include <stdbool.h>

#define APP_CLASS_NAME_W        L"Test GUI Class"
#define APP_NAME_CAPTION_W      L"My Test GUI"
#define APP_DEFAULT_WIDTH       640
#define APP_DEFAULT_HEIGHT      480
#define APP_BACKGROUND_COLOR    (RGB(225, 229, 180))

enum e_TestGUIObjectIndices
{
    e_TEST_GUI_COMBOBOX     = 1
};

typedef struct s_TestGUIWindowsParams
{
    int X;
    int Y;
    int Width;
    int Height;
} t_TestGUIWindowsParams;

LRESULT CALLBACK TestGUI_Process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
{
    MSG message = {0};
    WNDCLASSW window_class = {0};
    HWND main_window = {0};
    t_TestGUIWindowsParams main_window_size = {0};
    ATOM result = 0;

    /* Initialization Main Window Class Structure */
    window_class.lpszClassName = APP_CLASS_NAME_W;
    window_class.style = CS_HREDRAW | CS_VREDRAW;
    window_class.hInstance = hInstance;
    window_class.hbrBackground = CreateSolidBrush(APP_BACKGROUND_COLOR);
    window_class.lpfnWndProc = TestGUI_Process;
    window_class.hCursor = LoadCursor(0, IDC_ARROW);
    window_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    window_class.lpszMenuName = NULL;
    window_class.cbClsExtra = 0;
    window_class.cbWndExtra = 0;

    result = RegisterClassW(&window_class);

    // Center aligned main window parameters
    main_window_size.X = (GetSystemMetrics(SM_CXSCREEN) >> 1)-(APP_DEFAULT_WIDTH >> 1);
    main_window_size.Y = (GetSystemMetrics(SM_CYSCREEN) >> 1)-(APP_DEFAULT_HEIGHT  >> 1);
    main_window_size.Width = APP_DEFAULT_WIDTH;
    main_window_size.Height = APP_DEFAULT_HEIGHT;

    /* Creation of Main Window */
    main_window = CreateWindowExW(WS_EX_COMPOSITED, window_class.lpszClassName,
                                APP_NAME_CAPTION_W, (WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_TABSTOP | WS_BORDER),
                                main_window_size.X, main_window_size.Y, main_window_size.Width, main_window_size.Height,
                                NULL, NULL, window_class.hInstance, NULL);
    
    if(main_window == NULL)
    {
        MessageBoxW(NULL, L"CreateWindowExW Failed", L"Anything", MB_OK | MB_ICONERROR);
        return 0;
    }

    EnableWindow(main_window, TRUE);

    ShowWindow(main_window, nCmdShow);
    UpdateWindow(main_window);
    
    while(GetMessageW(&message, main_window, 0, 0) > 0)
    {
        TranslateMessage(&message);
        DispatchMessageW(&message);
    }

    return(int)message.wParam;
}

LRESULT CALLBACK TestGUI_Process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static TITLEBARINFO main_window_titlebar = {0};
    static HWND main_window_combobox = {0};
    HINSTANCE main_window_instance = (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
    static const WCHAR item_text[3][7] = {  { L"Item 1\000" },
                                            { L"Item 2\000" },
                                            { L"Item 3\000" } };

    switch(message)
    {
        case WM_CREATE:
            main_window_titlebar.cbSize = sizeof(TITLEBARINFO);
            GetTitleBarInfo(hwnd, &main_window_titlebar);
            main_window_combobox = CreateWindowExW(0, WC_COMBOBOXW, L"",
                                WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
                                10, main_window_titlebar.rcTitleBar.bottom - main_window_titlebar.rcTitleBar.top + 25,
                                200, 500, // Position and size
                                hwnd, (HMENU)e_TEST_GUI_COMBOBOX, main_window_instance, NULL);
            UpdateWindow(hwnd);
            SendMessageW(main_window_combobox, CB_ADDSTRING, 0, (LPARAM)item_text[0]);
            SendMessageW(main_window_combobox, CB_ADDSTRING, 0, (LPARAM)item_text[1]);
            SendMessageW(main_window_combobox, CB_ADDSTRING, 0, (LPARAM)item_text[2]);
            SendMessageW(main_window_combobox, CB_SETCURSEL, (WPARAM)2, 0);
            break;
        
        case WM_GETMINMAXINFO:
            LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
            lpMMI->ptMinTrackSize.x = APP_DEFAULT_WIDTH;
            lpMMI->ptMinTrackSize.y = APP_DEFAULT_HEIGHT;
            break;
        
        case WM_SIZE:
            break;
        
        case WM_COMMAND: 
            switch(LOWORD(wParam))
            {
                case e_TEST_GUI_COMBOBOX:
                {
                    switch(HIWORD(wParam))
                    {                      
                        case CBN_SELCHANGE:
                            WCHAR get_string[12];
                            int index = SendMessageW(main_window_combobox, CB_GETCURSEL, 0, 0);
                            SendMessageW(main_window_combobox, CB_GETLBTEXT, (WPARAM)index, (LPARAM)get_string);
                            break;
                        
                        default:
                            break;
                    }
                }
                break;
            }
            break;
        
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }

    return DefWindowProcW(hwnd, message, wParam, lParam);
}

I have been struggling to make this work.

I have even tried searching code through ChatGPT and it gives me similar code with, of course, different variable names. The code snippet is the same. Even the example code from WinAPI documentation is similar.


Solution

  • The second parameter of GetMessage must be NULL, otherwise you only get the messages of the main window and not those of the ComboBox.

    while(GetMessageW(&message, NULL, 0, 0))