Реакция на уведомляющие сообщения CTreeCTRL
Бит состояния TVIS_EXPANDED не равен нулю, когда узел уже раскрыт. Мы хотим выделить обратный случай, поэтому пользуемся операцией логического отрицания. Метод cwnd::SetRedraw позволяет установить флаг перерисовки. Если он снят, то система не будет перерисовывать содержимое окна. Вставьте изменения В тело функции обработки Onltemexpanded:
void CLeftView::OnItemexpanded (NMHDR* pNMHDR, LRESULT* pResult) { NMJTREEVIEW* p = (NMJTREEVIEW*)pNMHDR; //====== Создаем курсор ожидания CWaitCursor wait; //====== Признак раскрытия узла (а не его закрытия) if (p › itemNew.state & TVIS_EXPANDED) { // Описатели раскрываемого и 1-го вложенного узла HTREEITEM hCur = p › itemNew.hltem, h = m_Tree.GetChildItem(hCur); //====== Если имя вложенного узла пусто, //====== то ветвь еще не раскрывалась if (m_Tree.GetItemText(h) == "") { //====== Удаляем муляж m_Tree.DeleteItem(h); //====== Вычисляем полный путь CString s = GetPath(hCur) + "*.*"; //====== Наполнение раскрытой ветви CFileFind cff; BOOL bFound = cff.FindFile(s); while (bFound) { bFound = cff.FindNextFile(); if (cff.IsDirectory() &&!cff.IsDots()) AddItem(hCur, cff.GetFilePath ()); } } // ====== Разрешаем перерисовку SetRedraw(TRUE); } *pResult = 0; }
Здесь реализованы два варианта развития событий: узел открывается впервые и узел отрывается повторно. Признаком первого варианта является наличие пустого элемента с нулевым индексом изображения и пустой строкой текста внутри раскрываемой ветви. Мы удаляем такой элемент, определяем полный файловый путь раскрываемого узла (папки или диска), сканируем файловый адрес и наполняем дерево новыми элементами.
Алгоритм заполнения содержимого папки сходен с алгоритмом заполнения логического диска. Также воспользуемся пустым узлом для пометки папок, которые имеет смысл раскрывать, так как в них есть вложенные папки или файлы. Функция GetPath должна пройти вверх по иерархической структуре дерева и вычислить полный файловый путь узла, заданного параметром. Введите коды этой функции в файл LeftView.cpp:
CString CLeftView::GetPath (HTREEITEM hCur) { //====== Вычисляет полный файловый путь узла hCur CString s = ""; for (HTREEITEM h=hCur; h; h=m_Tree.GetParentItem(h)) s = m_Tree.GetItemText(h) + '\\' + s; return s; }
Размеры левого окна были заданы в момент создания стартовой заготовки и они, пожалуй, маловаты. Исправьте начальные размеры окна, которые задаются при вызове CreateView внутри функции CTreeFrame::OnCreateClient. Посмотрите справку по этой функции и задайте горизонтальный размер окна равным 200.
Запустите приложение и протестируйте работу дерева. Теперь его поведение должно соответствовать тем требованиям, которые были сформулированы в начале разработки проекта. В такие моменты полезно провести эксперименты, чтобы лучше уяснить смысл некоторых действий. Например, временно уберите битовый флаг SHGFI_SMALLICON при вызове SHGetFileinf о и посмотрите, как изменится вид узлов дерева. Затем временно исключите вызов функции SetRedraw в обработчике Onitemexpanding и пронаблюдайте поведение дерева при раскрытии папки, содержащей большое количество вложенных объектов, например winNT.