Мой 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 user541686 Я не знаю, что «более реального» в цикле сообщений WTL. У него есть бесполезное if (bRet == -1)
состояние, которое никогда не выполняется, и полностью отсутствует поддержка APC или других асинхронных примитивов. И буквально ничего из того, что предоставляет цикл сообщений WTL, не является полезным для этого конкретного фрагмента кода, поэтому я не уверен, почему вы продвигаете решение, более сложное, чем оно должно быть.
@IInspectable: Вы полностью проигнорировали PreTranslateMessage
, IsIdleMessage
и OnIdle
. Вы также читаете в моем комментарии то, чего я никогда не писал.
@user541686 PreTranslateMessage
— это просто очень многословный способ сказать: «Эй, позвольте мне вставить этот фрагмент кода между GetMessage
и TranslateMessage
». OnIdle
не требуется для правильного функционирования программы. Кстати говоря: IsDialogMessage
необходим для правильной навигации с помощью клавиатуры. «Реальный цикл сообщений» WTL оставляет желать лучшего. В любом случае, почему вы одержимы желанием снова продать свое слишком сложное решение гораздо более простой проблеме?
Второй параметр GetMessage должен быть NULL, иначе вы получите только сообщения главного окна, а не сообщения ComboBox.
while(GetMessageW(&message, NULL, 0, 0))
Еще один вопрос, почему WS_TABSTOP не работает, если я добавляю еще один объект со стилем WS_TABSTOP. На TAB нажмите, чтобы изменить фокус на объекте.
@djay, это совершенно отдельная и не связанная с проблемой ComboBox проблема. Пожалуйста, опубликуйте это как новый вопрос.