Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как определить итем в CTreeCtrl, на котором нажали, Как определить итем в CTreeCtrl, на кото 
V
    Опции темы
andrey_s
Дата 11.10.2006, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте!
Как определить итем в CTreeCtrl, на котором нажали правую кнопку мыши.

Я думал нужно HTREEITEM hItem=m_Tree.GetSelectedItem(), но это не проходит.
Нужно как-то определить итем, на котором нажали правую кнопку,потом его выделить, а потом использовать GetSelectedItem().
Как?
PM MAIL   Вверх
Earnest
Дата 11.10.2006, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Лови либо WM_RBUTTONDOWN, либо уведомление NM_RCLICK. Вызывай HitTest, чтобы определить, какой итем кликнули, потом делай ему SelectItem.


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


Новичок



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

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



Спасибо за ответ.


Я пробовал так:
определял положение курсора:

Код

CPoint point;
GetCursorPos( &point );

вызывал функцию:

Код

HTREEITEM hItem=m_Tree.HitTest( point,&uFlags);


но почему-то она возвращает NULL. Какие флаги нужно указывать для этой функции? Или что-то я делал не так?

PM MAIL   Вверх
Earnest
Дата 12.10.2006, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Нужно предварительно перевести координаты курсора (экранные) в клиентские:
ScreenToClient()


--------------------
...
PM   Вверх
andrey_s
Дата 12.10.2006, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо, Earnest !
ScreenToClient() помогло!
Я, полазив по форумам, пытался сделать вот так:
Код

void CATreeCtrl::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
HTREEITEM hItem=pNMTreeView->itemNew.hItem ;
MessageBox (this->GetItemText(hItem));
*pResult = 0;
}

Но MessageBox выводил пустую строку. 
А вот по двойному клику левой кнопки работает нормально:
Код

void CATreeCtrl::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
{
    HTREEITEM hItem=this->GetSelectedItem();
    MessageBox (this->GetItemText(hItem));
    *pResult = 0;
}

В чём причина?
PM MAIL   Вверх
Earnest
Дата 13.10.2006, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



1) В моем MSDN написано, что на NM_RCLICK дереву приходит простой NMHDR, а вовсе не NMTREVIEW, так что скорее всего, а hItem у тебя лажа. Врочем, сам отладчиком посмотри. Нужно спрашивать позицию курсора и вызывать HitTest.

2) По правому клику, по-умолчанию, итем не получает фокус, а по левому - получает.


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


Новичок



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

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



Спасибо, Earnest, за ответы!
Вопрос решён. 
PM MAIL   Вверх
CityAC
Дата 4.4.2007, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Похожая ситуация, только нужно отследить итем, на крестик которого пользователь нажал левой кнопкой.
Выделять при этом итем не нужно, а нужно получить его текст.
Посоветовали TVN_ITEMEXPANDED.//СОБЫТИЕ РАЗВОРОТА УЗЛА
Код

void CprojDlg::OnTvnItemexpandedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    
    // TODO: Add your control notification handler code here
    *pResult = 0;
}

А как из него можно вытащить нужную инфу.
Или не парится а попробовать выше описанный метод?
--------------------
Вижу цель, не вижу припятствий.  
PM MAIL ICQ   Вверх
CityAC
Дата 4.4.2007, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Сделал вот так
Код

void CprojDlg::OnTvnItemexpandedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    CTreeCtrl* pTree = (CTreeCtrl*)GetDlgItem(IDC_TREE1);
    CPoint pt;
    GetCursorPos(&pt);
    ScreenToClient(&pt);
    HTREEITEM item = pTree->HitTest(pt);
    m_TreeCtrl.GetItemText(item);
    HelpFillTree(item);
    

    // TODO: Add your control notification handler code here
    *pResult = 0;
}




Только 
HTREEITEM item = pTree->HitTest(pt);
через раз возвращает не верные итемы.
Например щелкая на "Мои Документы",  возвращает вложенный в мои документы узел "Documents and Settings".
А например с диском G или H  - все корректно

В чем может быть проблема.
И как различить развернут узел или нет.

Еще, я заполняю дерево постепенно: нажал на узел заполнил  его детей первым уровнем иерархии. А как потом избежать повторного заполнения после того как свернул и снова развернул узел?

Это сообщение отредактировал(а) CityAC - 4.4.2007, 14:19
--------------------
Вижу цель, не вижу припятствий.  
PM MAIL ICQ   Вверх
Earnest
Дата 4.4.2007, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



В MSDN все написано:
Цитата

pnmtv
Pointer to an NMTREEVIEW structure. The itemNew member is a TVITEM structure that contains valid information about the parent item in the hItem, state, and lParam members. The action member indicates whether the list expanded or collapsed. For a list of possible values, see the description of the TVM_EXPAND message. 

Т.е. 
Код

LPNMTREEVIEW pnmtv = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
HTREEITEM hItem = pnmtv->itemNew->hItem;

Насчет состояния - смотри pnmtv->action, или можно тупо спросить GetItemState (hItem, TVIS_EXPANDED)

И убедись, что обработчик повешен на TVN_ITEMEXPANDED, а не на TVN_ITEMEXPANDING.


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


Бывалый
*


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

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



Код

void CprojDlg::OnTvnItemexpandingTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
    
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    
    CPoint pt;
    GetCursorPos(&pt);
    ScreenToClient(&pt);
    HTREEITEM item = m_TreeCtrl.HitTest(pt);    
    


Если определять итем по координатам курсора, то как раз обработчик нужно вешать на TVN_ITEMEXPANDING, 
т.е. нужно получить итем под курсором до того как ветка развернется, иначе, если ветка окажется большая и будет иметь место скроллинг, 
то после развертки ветки под курсором окажется другой итем. Что собственно и происходило у меня когда обрабатывалось TVN_ITEMEXPANDED.

если же так как Вы, уважаемая Earnest, предложили в пред. посте то помоему все равно на какой обработчик. у меня по крайней мере на TVN_ITEMEXPANDING работает. Но я в отличие от Вас могу не знать каких то нюансов.

А можно ли к вставляемому узлу добавить свою информацию.
В частности мне нужно к узлу добавить информацию что я его уже заполнял чтобы при следующем открытии не заполнять его повторно.

Это сообщение отредактировал(а) CityAC - 4.4.2007, 17:08
--------------------
Вижу цель, не вижу припятствий.  
PM MAIL ICQ   Вверх
Earnest
Дата 4.4.2007, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



А просто спросить, есть ли у узла дети - не достаточно (ItemHasChildren)?
Но если нужна своя информация - то есть lParam в каждом итеме, он для того и предназначен.
Цитата(CityAC @  4.4.2007,  18:02 Найти цитируемый пост)
то помоему все равно на какой обработчик

Это зависит от задачи. Если требуется предваряющее действие, да еще и с возможностью отказаться - то OnExpanding, если post-обработка - то OnExpanded (скажем, заменить картинку). Во всяком случае, во время OnExpanded ты можешь точно спросить item, раскрыт ли он, и получишь правильный ответ.
А если ты их заполняешь - то пожалуй, да, нужно на OnExpanding.
Только у меня вызывает сомнение сам факт заполнения при раскрытии. Зачем?



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


Бывалый
*


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

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



Цитата

Только у меня вызывает сомнение сам факт заполнения при раскрытии. Зачем?


А когда в таком случае заполнять узел детьми?

--------------------
Вижу цель, не вижу припятствий.  
PM MAIL ICQ   Вверх
Earnest
Дата 4.4.2007, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



А сразу никак? При создании. Или при каком-то событии, когда узнаешь, что дерево нужно перестроить.
Если элементов немного (сотня-две) это довольно быстро делается. Только до и после поставь скобки SetRedraw(FALSE\TRUE), чтобы в процессе добавления итемов не моргало.


--------------------
...
PM   Вверх
CityAC
Дата 4.4.2007, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Я изучаю дерево пытаясь создать проводник. Можешь представить сколько у меня узлов нужно загрузить при создании.
Я отказался от идеи загрузки при создании после того как просидел 1 минуту пока отработали все рекурсии.

У меня корявый код, но он работает.
можно прислать на разбор?
--------------------
Вижу цель, не вижу припятствий.  
PM MAIL ICQ   Вверх
Earnest
Дата 4.4.2007, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Наверное все же основное время занимает прохождение по файловой системе (а то и по удаленным компам)...
Я бы отделила построение дерева файлов от заполнения дерева-контрола. Скажем, построение файлового дерева засунуть в поток, построение удаленных веток действительно отложить on-demand, пока не понадобятся, а контрол обновлять, ну скажем по таймеру, пока изменения не прекратяться.
Это и с точки зрения дизайна лучше: разные задачи - разный код, и гибче.

Цитата(CityAC @  4.4.2007,  23:33 Найти цитируемый пост)
можно прислать на разбор? 

Нет, извини, код твой смотреть не буду, это слишком много времени съест. Но если есть желание, почему бы не выложить, может народ что посоветует.



--------------------
...
PM   Вверх
CityAC
Дата 11.4.2007, 01:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Есть ли возможность в узле дерева хранить полный путь к нему?
--------------------
Вижу цель, не вижу припятствий.  
PM MAIL ICQ   Вверх
Earnest
Дата 11.4.2007, 07:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



О каком дереве ты говоришь? Если о TreeCtrl, то это никому не нужно - путь легко восстанавливается посхождением вверх - по парентам. Если о собственной структуре - то же самое. Типичный узел дерева кроме ссылок на  потомков обычно хранит ссылку на парента, по которым и можно восстановить весь путь.
Хранение всего пути в каждом узле явно избыточно и мешает гибкости. Например, при перемещении узла по дереву ...


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


Бывалый
*


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

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



Цитата

О каком дереве ты говоришь? Если о TreeCtrl, то это никому не нужно - путь легко восстанавливается посхождением вверх - по парентам

Да я так и реализовывал, но думал что есть возможность хранить весь путь
--------------------
Вижу цель, не вижу припятствий.  
PM MAIL ICQ   Вверх
Greeen
Дата 11.4.2007, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Возможность есть, но нет необходимости. Если все же уж очень приспичит то SetItemData(HTREEITEM hItem, DWORD_PTR dwData); Передашь указатель на сроку с полным путем.


--------------------
Подпись больше не нужна
PM MAIL ICQ Skype   Вверх
Earnest
Дата 11.4.2007, 21:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Только эти указатели кто-то менеджить должен (создавать, хранить, уничтожать) - дерево за тебя это делать не будет.


--------------------
...
PM   Вверх
CityAC
Дата 12.4.2007, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Всем спасибо!!!
Более менее разобрался
Хранить полное имя действительно нет необходимости
получал имя узла так
Код

CString CprojDlg::MyGetPathName(HTREEITEM parItem)
{
    CString rootItemName = m_TreeCtrl.GetItemText( m_TreeCtrl.GetRootItem());
    m_fullName="";
    while(m_TreeCtrl.GetItemText(parItem)!=rootItemName)
    {
        m_fullName = m_TreeCtrl.GetItemText(parItem) +"\\" + m_fullName  ;
        if(!(parItem = m_TreeCtrl.GetParentItem (parItem)))
            return m_fullName;
    }
    if(m_fullName.Right(1)!="\\" && m_fullName!="")
                m_fullName+="\\";
    return m_fullName;
}


--------------------
Вижу цель, не вижу припятствий.  
PM MAIL ICQ   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




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


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

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