Реакция на уведомляющие сообщения 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.
