Проблема с методом ShowDropDown() класса CComboBox, mfc
ListBox является частью ComboBoxа. При первом вызове метода класса CComboBox ShowDropDown() всё отрисовывается нормально (то есть при создании окна ListBoxа). При последующих попытках сделать ListBox видимым с помощью вызова метода класса CComboBox ShowDropDown() видно, как ListBox плавно "выезжает" сверху вниз. При этом рисуется стандартный вертикальный скролл.
Вопрос: как сделать так, чтобы стандартный вертикальный скролл не отрисовывался при вызове метода класса CComboBox ShowDropDown()?
Если понадобится, могу выложить проект.
Что самое интересное, у ListBox нет стиля WS_VSCROLL.
Я пробовал делать DWORD l_style = GetStyle(); а потом проверял значение l_style & WS_VSCROLL.
Для верности попробовал написать даже так:
{
if (m_my_list_box.GetSafeHwnd() != NULL)
m_my_list_box.ModifyStyle(WM_VSCROLL, 0, SWP_NOREDRAW);
__super::ShowDropDown(bShowIt);
if (m_my_list_box.GetSafeHwnd() != NULL)
m_my_list_box.ModifyStyle(WM_VSCROLL, 0, SWP_NOREDRAW);
m_my_list_box.HandleShowDropDown(bShowIt);
}
Но это ни на что не повлияло - при показе листбокса всё равно сначала рисуется стандартный вертикальный скролл.
Вряд ли стиль WS_VSCROLL вообще устанавливается. Я думаю, что mfc не настолько злобная технология, чтобы устанавливать стиль WS_VSCROLL, выполнять определённую отрисовку, а затем снова сбрасывать этот флаг :).
Ведь окно листбокса создаётся только при первом дропдауне. Затем оно только скрывается / показывается. А значит перед повторным дропдауном стиль WS_VSCROLL должен был бы быть установлен (если бы он был установлен при создании).
Мне кажется, что метод ShowDropDown() проверяет количество элементов в листбоксе, если это число больше, чем число отображаемых элементов, он предполагает, что должен быть скролл. Кстати, можно попробовать как-то обмануть функцию ShowDropDown(), например, сделать, чтобы листбокс на время выполнения этого метода возвращал какие-то специальные значения при запросе высоты окна/количества элементов... Попробую - напишу.
Я создал обработчик события WM_WINDOWPOSCHANGING для листбокса.
{
__super::OnWindowPosChanging(lpwndpos);
if (m_hide_flag)
lpwndpos -> flags |= SWP_HIDEWINDOW;
}
void CSkinnedComboBox::ShowDropDown(BOOL bShowIt)
{
m_my_list_box.SetHideFlag(true); //m_hide_flag = true
__super::ShowDropDown(bShowIt);
m_my_list_box.SetHideFlag(false); //m_hide_flag = false
if (m_my_list_box.GetSafeHwnd() != NULL && !m_my_list_box.IsWindowVisible())
m_my_list_box.ShowWindow(SW_SHOW);
m_my_list_box.HandleShowDropDown(bShowIt);
}
То есть я скрываю окно листбокса на время выполнения метода ShowDropDown(), а потом показываю его "во всей красе".
Но это скорее хак, чем нормальное решение проблемы. Так что если кто-то знает другие способы избавиться от прорисовки стандартного скролла при дропдауне - пишите.
{
...
if ((message == WM_PRINT || message == WM_PRINTCLIENT) && m_hide_flag)
return 1;
return __super::WindowProc(message, wParam, lParam);
}
void CSkinnedComboBox::ShowDropDown(BOOL bShowIt)
{
m_my_list_box.SetHideFlag(true); //m_hide_flag = true
__super::ShowDropDown(bShowIt);
m_my_list_box.SetHideFlag(false); //m_hide_flag = false
m_my_list_box.HandleShowDropDown(bShowIt);
}
Но первое решение в плане отрисовки смотрится несколько лучше (на мой взгляд) :)
Спасибо всем, кто попробовал мне помочь. Тему можно считать закрытой.