Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Выделение нескольких элементов CTreeCtrl 
:(
    Опции темы
EvgenyTS
Дата 26.2.2009, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 26.11.2008

Репутация: нет
Всего: нет



Может подскажете как выделить несколько элементов в CTreeCtrl для последующего их использования?
PM MAIL   Вверх
Earnest
Дата 27.2.2009, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Tree View, в отличие от List View, не поддерживает выделение нескольких элементов. Т.е. поставить выделение-то можно (программно) - установить состояние TVS_SELECTED, но вот поддержка одновременного выделения и перебор - это задача программиста. Я делаю так: 1) завожу массив выделенных в текущий момент элементов и сама им управляю 2) ловлю TVN_SELCHANGED, где проверяю, нажат ли SHIFT / CTRL (чтобы множественное выделение делалось стандартным способом) и в зависимости от этого обновляю свою коллекцию выделенных элементо (при этом все старое выделение снимаю, а новое ставлю). 


--------------------
...
PM   Вверх
EvgenyTS
Дата 27.2.2009, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 26.11.2008

Репутация: нет
Всего: нет



если можешь кинь маленький примерчик. Мне нужно выделить только первые родительские узлы. Спасибо

Это сообщение отредактировал(а) EvgenyTS - 27.2.2009, 09:59
PM MAIL   Вверх
Earnest
Дата 27.2.2009, 15:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Код

// это в карту обработчиков
ON_NOTIFY_REFLECT (TVN_SELCHANGED,  OnSelChanged)

// ловим изменение выделения (поддержка множественного выделения)
void CLayerCtrl::OnSelChanged (NMHDR* pNMHDR, LRESULT* pResult) 
{
    *pResult=0;
    NMTREEVIEW* pnmtv = reinterpret_cast<NMTREEVIEW*>(pNMHDR);
    HTREEITEM hItem = pnmtv->itemNew.hItem;
    
    if (GetKeyState(VK_CONTROL) < 0)
      SelectItem (m_hStartItem = hItem, Toggle);
    else if (m_hStartItem && GetKeyState(VK_SHIFT) < 0)    // выделяем последовательность элементов
      SelectItems (m_hStartItem, hItem);
   else                                                                    // выделяем только текущий элемент
      SelectItems (m_hStartItem=hItem, hItem);
}

void CLayerCtrl::SelectItem (HTREEITEM hItem, int nSelect)
{
   if (nSelect == Toggle) 
      nSelect = ItemSelected (hItem) ? Unselect : Select;  

   if (nSelect == Select) 
   {
      Insert (m_Selection, hItem); // добавляем в m_Selection
    SetItemState (hItem, TVIS_SELECTED, TVIS_SELECTED);
        if (m_Selection.size() == 1) 
            CTreeCtrl::SelectItem (hItem); 
   }
   else
   {
      Erase (m_Selection, hItem); // удаляем из m_Selection
    SetItemState (hItem, 0, TVIS_SELECTED);
   }
}

// выделить последовательность между заданными элементами включительно
void CLayerCtrl::SelectItems (HTREEITEM hItemFrom, HTREEITEM hItemTo)
{
   // снимаем старое выделение
   // m_Selection - это отсортированный вектор HTREEITEM
   for (CSelection::iterator it = m_Selection.begin(); it != m_Selection.end(); ++it)
    SetItemState (*it, 0, TVIS_SELECTED);
   m_Selection.clear();

   // новое выделение: определяем, кто первый
   if (!hItemFrom) hItemFrom = hItemTo;
   if (hItemFrom != hItemTo)
   {
      RECT rFrom,rTo;
      if (!GetItemRect (hItemFrom, &rFrom, false))
         hItemFrom = hItemTo;
      else 
      {
         // hItemTo всегда должен быть видимым: это последний клик! 
         VERIFY (GetItemRect (hItemTo, &rTo, false));
         if (rFrom.top > rTo.top) std::swap (hItemFrom, hItemTo);
      }
   }
   
   // перебираем в порядке видимости и выделяем
   for (HTREEITEM hItem = hItemFrom; hItem!=0; hItem = GetNextVisibleItem (hItem))
   {
      SelectItem (hItem, Select);
      if (hItem == hItemTo) break;
   }
}

bool CLayerCtrl::ItemSelected(HTREEITEM hItem) const
{
   return std::binary_search (m_Selection.begin(), m_Selection.end(), hItem);
}




--------------------
...
PM   Вверх
EvgenyTS
Дата 27.2.2009, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 26.11.2008

Репутация: нет
Всего: нет



Спасибо. Разбираюсь...
вот элемент m_hStartItem. Что за он. Не могу найти объявление. Я подразумеваю что HTREEITEM. Но что он принимает?
PM MAIL   Вверх
Earnest
Дата 27.2.2009, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Это первый выделенный элемент. Запоминаем его,  когда первый раз нажимаем с SHIFT. По-моему, из кода это ясно.


--------------------
...
PM   Вверх
EvgenyTS
Дата 27.2.2009, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 61
Регистрация: 26.11.2008

Репутация: нет
Всего: нет



Ясно.
Вот создаю векстор HTREEITEM
vector<HTREEITEM>m_Selection;
при компил. пишет
error C2027: use of undefined type '_TREEITEM' Как правильно использовать?

Это сообщение отредактировал(а) EvgenyTS - 27.2.2009, 18:20
PM MAIL   Вверх
Earnest
Дата 28.2.2009, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Может, написал неправильно? И вообще, что за детский сад? smile 


--------------------
...
PM   Вверх
Tor887
Дата 14.11.2011, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 14.11.2011

Репутация: нет
Всего: нет



Цитата(Earnest @ 27.2.2009,  15:23)
Код

// это в карту обработчиков
ON_NOTIFY_REFLECT (TVN_SELCHANGED,  OnSelChanged)

// ловим изменение выделения (поддержка множественного выделения)
void CLayerCtrl::OnSelChanged (NMHDR* pNMHDR, LRESULT* pResult) 
{
    *pResult=0;
    NMTREEVIEW* pnmtv = reinterpret_cast<NMTREEVIEW*>(pNMHDR);
    HTREEITEM hItem = pnmtv->itemNew.hItem;
    
    if (GetKeyState(VK_CONTROL) < 0)
      SelectItem (m_hStartItem = hItem, Toggle);
    else if (m_hStartItem && GetKeyState(VK_SHIFT) < 0)    // выделяем последовательность элементов
      SelectItems (m_hStartItem, hItem);
   else                                                                    // выделяем только текущий элемент
      SelectItems (m_hStartItem=hItem, hItem);
}

void CLayerCtrl::SelectItem (HTREEITEM hItem, int nSelect)
{
   if (nSelect == Toggle) 
      nSelect = ItemSelected (hItem) ? Unselect : Select;  

   if (nSelect == Select) 
   {
      Insert (m_Selection, hItem); // добавляем в m_Selection
    SetItemState (hItem, TVIS_SELECTED, TVIS_SELECTED);
        if (m_Selection.size() == 1) 
            CTreeCtrl::SelectItem (hItem); 
   }
   else
   {
      Erase (m_Selection, hItem); // удаляем из m_Selection
    SetItemState (hItem, 0, TVIS_SELECTED);
   }
}

// выделить последовательность между заданными элементами включительно
void CLayerCtrl::SelectItems (HTREEITEM hItemFrom, HTREEITEM hItemTo)
{
   // снимаем старое выделение
   // m_Selection - это отсортированный вектор HTREEITEM
   for (CSelection::iterator it = m_Selection.begin(); it != m_Selection.end(); ++it)
    SetItemState (*it, 0, TVIS_SELECTED);
   m_Selection.clear();

   // новое выделение: определяем, кто первый
   if (!hItemFrom) hItemFrom = hItemTo;
   if (hItemFrom != hItemTo)
   {
      RECT rFrom,rTo;
      if (!GetItemRect (hItemFrom, &rFrom, false))
         hItemFrom = hItemTo;
      else 
      {
         // hItemTo всегда должен быть видимым: это последний клик! 
         VERIFY (GetItemRect (hItemTo, &rTo, false));
         if (rFrom.top > rTo.top) std::swap (hItemFrom, hItemTo);
      }
   }
   
   // перебираем в порядке видимости и выделяем
   for (HTREEITEM hItem = hItemFrom; hItem!=0; hItem = GetNextVisibleItem (hItem))
   {
      SelectItem (hItem, Select);
      if (hItem == hItemTo) break;
   }
}

bool CLayerCtrl::ItemSelected(HTREEITEM hItem) const
{
   return std::binary_search (m_Selection.begin(), m_Selection.end(), hItem);
}


Если смогу достучаться ,)

Проблемка: при ctrl вроде в список добавляется, а вот выделить не получается.. При этом пробовал вместо TVIS_SELECTED -> TVIS_BOLD - работает....
Хм, интересно, что с шифтом работает....    smile 


Это сообщение отредактировал(а) Tor887 - 14.11.2011, 12:38
PM MAIL   Вверх
Earnest
Дата 14.11.2011, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Не пойму в чем проблема


--------------------
...
PM   Вверх
Tor887
Дата 14.11.2011, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 14.11.2011

Репутация: нет
Всего: нет



В ф-ии SelectItem ()
Делаем SetItemState(hItem, TVIS_SELECTED, TVIS_SELECTED), при этом hItem - текуший, т.е. в случае нажатого ctrl-а уже после переключения, а прошлый уже отключился!
Я попробовал запоминать старый и здесь делать etItemState(hOldItem, TVIS_SELECTED, TVIS_SELECTED), но вылазят некоторые другие геморы...  smile 
Но помаленьку продвигаюсь, вроде... ,)
PM MAIL   Вверх
Tor887
Дата 15.11.2011, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 14.11.2011

Репутация: нет
Всего: нет



Вот еще какая штука: т.к. всё это сделано как реакция на изменение выделения - OnSelChanged - соответственно нельзя изменить состояние последнего выделенного элемента. Например выделили несколько элементов - не удастся снять выделение с последнего, потому что не вызывается OnSelChanged.
Пробовал решить эту проблему через OnNMClick, но там почему-то не работает фишка с вытаскиванием хендла на элемент..
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.1187 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.