Почему мое поле со списком (WinAPI) не выделяет/выбирает текст?

Мой ComboBox не выделяет/выбирает текст, когда я навожу указатель мыши на отображаемые параметры или нажимаю на него. Даже когда я нажимаю TAB на клавиатуре, при выборе элемента не отображается выделенный ComboBox.

Может ли кто-нибудь увидеть ошибку в приведенном ниже фрагменте кода?

PS: ComboBox виден в главном окне, а раскрывающийся список работает как положено.

#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);
}

Я изо всех сил пытался сделать эту работу.

Я даже пробовал искать код через

Реальные циклы сообщений намного сложнее, чем while (GetMessage(...), посмотрите WTL::CMessageLoop, чтобы увидеть более реалистичный пример.

user541686 31.08.2024 19:14

@user541686 user541686 Я не знаю, что «более реального» в цикле сообщений WTL. У него есть бесполезное if (bRet == -1) состояние, которое никогда не выполняется, и полностью отсутствует поддержка APC или других асинхронных примитивов. И буквально ничего из того, что предоставляет цикл сообщений WTL, не является полезным для этого конкретного фрагмента кода, поэтому я не уверен, почему вы продвигаете решение, более сложное, чем оно должно быть.

IInspectable 31.08.2024 22:32

@IInspectable: Вы полностью проигнорировали PreTranslateMessage, IsIdleMessage и OnIdle. Вы также читаете в моем комментарии то, чего я никогда не писал.

user541686 31.08.2024 22:59

@user541686 PreTranslateMessage — это просто очень многословный способ сказать: «Эй, позвольте мне вставить этот фрагмент кода между GetMessage и TranslateMessage». OnIdle не требуется для правильного функционирования программы. Кстати говоря: IsDialogMessage необходим для правильной навигации с помощью клавиатуры. «Реальный цикл сообщений» WTL оставляет желать лучшего. В любом случае, почему вы одержимы желанием снова продать свое слишком сложное решение гораздо более простой проблеме?

IInspectable 01.09.2024 00:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Второй параметр GetMessage должен быть NULL, иначе вы получите только сообщения главного окна, а не сообщения ComboBox.

while(GetMessageW(&message, NULL, 0, 0))
Когда GetMessage вернет -1? В данном случае: Никогда.
IInspectable 31.08.2024 14:52

Еще один вопрос, почему WS_TABSTOP не работает, если я добавляю еще один объект со стилем WS_TABSTOP. На TAB нажмите, чтобы изменить фокус на объекте.

djay 31.08.2024 18:47

@djay, это совершенно отдельная и не связанная с проблемой ComboBox проблема. Пожалуйста, опубликуйте это как новый вопрос.

Remy Lebeau 31.08.2024 19:14

Другие вопросы по теме