Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Проблема с методом ShowDropDown() класса CComboBox, mfc

32K
22 сентября 2008 года
Denis1986
27 / / 25.08.2008
Я создаю ScrollBar для класса, наследованного от ListBox, вручную. При этом я располагаю окно скролла в неклиентской части окна ListBox.
ListBox является частью ComboBoxа. При первом вызове метода класса CComboBox ShowDropDown() всё отрисовывается нормально (то есть при создании окна ListBoxа). При последующих попытках сделать ListBox видимым с помощью вызова метода класса CComboBox ShowDropDown() видно, как ListBox плавно "выезжает" сверху вниз. При этом рисуется стандартный вертикальный скролл.

Вопрос: как сделать так, чтобы стандартный вертикальный скролл не отрисовывался при вызове метода класса CComboBox ShowDropDown()?

Если понадобится, могу выложить проект.
14
22 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
Вероятно, следует убрать у листбокса стиль WS_VSCROLL
32K
22 сентября 2008 года
Denis1986
27 / / 25.08.2008
Phodopus
Что самое интересное, у ListBox нет стиля WS_VSCROLL.
Я пробовал делать DWORD l_style = GetStyle(); а потом проверял значение l_style & WS_VSCROLL.
Для верности попробовал написать даже так:
Код:
void CSkinnedComboBox::ShowDropDown(BOOL bShowIt)
{
    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);
}

Но это ни на что не повлияло - при показе листбокса всё равно сначала рисуется стандартный вертикальный скролл.
14
22 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
Блин, давай проект, так гадать не могу..
32K
22 сентября 2008 года
Denis1986
27 / / 25.08.2008
В этом проекте есть ещё некоторые скинабельные контролы. Проблемный ComboBox находится в середине окна приложения.
14
23 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
Пока не сморел но родилось предположение что листбокс создается (со скроллбаром), отрисовывает себя в мембитмап, который и использует для плавного появления при дропдауне. То есть раньше, чем убираешь стиль WS_VSCROLL. Только догадка.
32K
23 сентября 2008 года
Denis1986
27 / / 25.08.2008
Phodopus
Цитата:
Пока не сморел но родилось предположение что листбокс создается (со скроллбаром), отрисовывает себя в мембитмап, который и использует для плавного появления при дропдауне. То есть раньше, чем убираешь стиль WS_VSCROLL. Только догадка.


Вряд ли стиль WS_VSCROLL вообще устанавливается. Я думаю, что mfc не настолько злобная технология, чтобы устанавливать стиль WS_VSCROLL, выполнять определённую отрисовку, а затем снова сбрасывать этот флаг :).
Ведь окно листбокса создаётся только при первом дропдауне. Затем оно только скрывается / показывается. А значит перед повторным дропдауном стиль WS_VSCROLL должен был бы быть установлен (если бы он был установлен при создании).
Мне кажется, что метод ShowDropDown() проверяет количество элементов в листбоксе, если это число больше, чем число отображаемых элементов, он предполагает, что должен быть скролл. Кстати, можно попробовать как-то обмануть функцию ShowDropDown(), например, сделать, чтобы листбокс на время выполнения этого метода возвращал какие-то специальные значения при запросе высоты окна/количества элементов... Попробую - напишу.

14
23 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
А это не MFC устанавливает, а винда. MFC просто обертка для виндового COMBOBOX. Заглянул в проект - там 2008 студия, а уменя 2005я, кучу ошибок выдает, дома попробую домучить.
32K
23 сентября 2008 года
Denis1986
27 / / 25.08.2008
Я нашёл одно из решений проблемы.
Я создал обработчик события WM_WINDOWPOSCHANGING для листбокса.

Код:
void CSkinnedListBox::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
    __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(), а потом показываю его "во всей красе".
Но это скорее хак, чем нормальное решение проблемы. Так что если кто-то знает другие способы избавиться от прорисовки стандартного скролла при дропдауне - пишите.
32K
24 сентября 2008 года
Denis1986
27 / / 25.08.2008
Нашёл альтернативное решение этой проблемы:
Код:
LRESULT CSkinnedListBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
          ...
          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);
}

Но первое решение в плане отрисовки смотрится несколько лучше (на мой взгляд) :)
Спасибо всем, кто попробовал мне помочь. Тему можно считать закрытой.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог