Иллюстрированный самоучитель по Visual Studio .NET

Реакция на уведомляющие сообщения CTreeCTRL

Когда пользователь раскрывает узел дерева, то встроенный в класс CTreeView объект класса CTreeCTRL посылает родительскому окну (нашему представлению CLeftview) уведомляющее сообщение. Оно работает по схеме WM_NOTIFY, которую мы уже рассматривали. Наш класс CLeftview должен реагировать на это сообщение, сканировать раскрываемую папку или логический диск и изменять дерево, вставляя в раскрываемую ветвь новые объекты файловой системы, которые обнаружены внутри папки или диска. Для того чтобы ввести в класс способность реагировать на рассматриваемое сообщение, вы должны:

  1. Открыть окно Class View, установить фокус на имя класса CLeftView и перейти в окно Properties.
  2. В окне Properties нажать кнопку с подсказкой Messages, а затем кнопку Categorized.
  3. Нажать маркер (-) Common в верхнем левом углу прокручиваемого списка сообщений так, чтобы он изменился на (+). Тем самым вы скрываете часть списка с перечнем всех обычных сообщений Windows.
  4. В оставшейся части списка найти сообщение =TVN_ITEMEXPANDING и в выпадающем списке справа выбрать действие <Add>.
  5. Повторить действия пункта 4 для сообщений =TVN_ITEMEXPANDED и =TVN_ SELCHANGED.

Буква N в имени сообщения говорит о том, что сообщение является уведомляющим, а знак равенства перед ним означает, что оно принадлежит к особой группе отражаемых (reflected) сообщений. В версиях MFC (до 4.0), не было обработчиков отражаемых сообщений. Теперь к старому механизму обработки уведомляющих сообщений от дочерних (child) элементов добавился новый, который позволяет произвести обработку уведомляющего сообщения в классе самого элемента. Уведомляющее сообщение как бы отражается (reflects) назад в класс дочернего окна (элемента управления CTreeCTRL). Этот сценарий мог бы быть реализован и в классе, производном от CTreeCTRL, но нам нет смысла создавать такой класс, так как возможности класса CLef tview вполне достаточны для обработки обоих сообщений. Здесь важен лишь тот факт, что можно перехватить управление в те моменты, когда пользователь манипулирует с деревом.

Первое сообщение (=TVN_ITEMEXPANDING) поступает в момент нажатия маркера (+). Дерево в этот момент еще не раскрылось. Здесь мы должны притормозить процесс перерисовки дерева до того момента, пока не получена вся информация о содержимом раскрываемого узла.

Саму информацию мы будем добывать в теле функции, обрабатывающей второе сообщение (=TVN_ITEMEXPANDED). Оно приходит после того, как узел дерева раскрылся (но не обязательно перерисовался). Здесь мы должны реализовать два варианта развития событий: узел открывается впервые и узел открывается повторно.

Третье сообщение (=TVN_SELCHANGED) приходит в момент, когда пользователь нажал кнопку в пределах самого узла, то есть он выбрал (select) узел. Начнем с обработки первого сообщения. Измените тело функции Onltemexpanding так, чтобы оно имело вид:

void CLeftView::0nltemexpanding (NMHDR* pNMHDR, LRESULT* pResult)
{
//====== Преобразование типа указателя
NM_TREEVIEW* p = (NM_TREEVIEW*)pNMHDR;
//====== Если узел не раскрыт
if (!(p › itemNew.state & TVIS_EXPANDED))
//====== тормозим перерисовку
SetRedraw(FALSE); *pResult = 0;
}
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.