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

Обращаемся к операционной системе

Теперь, когда вы научились управлять формой дерева, мы продолжим развитие приложения. Используя клавишу Delete, удалите все ресурсы типа Bitmap. Удалите также глобальное объявление структуры TVINSERTSTRUCT. Теперь мы покажем, что можно обходиться и без ее помощи. Уберите весь учебный код, следующий после строки m_plmgList = new CImageList, и вставьте новый, так, чтобы функция приобрела вид:

void CLeftView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();
::SetWindowLongPtr(m_Tree.m_hWnd, GWL_STYLE, GetWindowLong(m_Tree.m_hWnd, GWL_STYLE)
|TVS_HASLINES I TVS_HASBUTTONSITVS_LINESATROOT|TVS_SHOWSELALWAYS);
//====== Создаем новый список изображений
m_pImgList = new CImageList;
//====== Связываем его с системным списком изображений
GetSvsImqList ();
//====== Получаем имена логических дисков
char s [1024];
DWORD size =::GetLogicalDriveStrings (1024, s);
if (Isize) // В случае отказа
return; // уходим молча
//=== Сканируем текст и вставляем новые узлы дерева
for (char *pName = s; *pNarae; pName += strlen(pName)+1)
Addltem (TVI_ROOT, pName);
}

Функция GetSysimgList, которую мы создадим чуть позже, получает от системы список системных значков и связывает его с деревом. Начать показ файлового дерева мы решили с демонстрации всех логических дисков, имеющихся в операционной системе в данный момент. API-функция GetLogicalDriveStrings заполняет строку текста, в которую она помещает перечень всех присутствующих в операционной системе логических дисков. Строка имеет особый формат: она состоит из нескольких подстрок, завершающихся нулем, например:

a:\0c:\0d:\00

Обратите внимание на то, что признаком конца перечня являются два нулевых байта. Первый завершает подстроку, а второй – всю строку. Используя эту особенность, мы создали цикл for (), в котором подстроки – имена логических дисков, сначала выявляются, а затем используются для вставки в дерево узлов, соответствующих логическим дискам. Функция Addltem, которую создадим позже, определяет индекс значка, соответствующего вставляемой сущности (диск, папка или файл), и создает в дереве новый узел с соответствующим ему изображением.

Теперь займемся созданием вспомогательных функций, которые понадобились при разработке функции OninitialUpdate. Введите в файл LeftView.cpp реализацию функции GetSysimgList, объявление которой уже существует в файле интерфейса LeftView.h класса CLef tview:

void CLeftView::GetSysImgList()
{
SHFILEINFO info;
// Попытка получить описатель системного списка значков
HIMAGELIST hlmg = (HIMAGELIST)
::SHGetFilelnfо("С:\\",0, Sinfo, sizeof (info), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
//=== Приписываем описатель системного списка
//=== изображений объекту CImageList
if (Ihlmg ||!m_pImgList › Attach(hlmg))
{
MessageBox(0,"He могу получить System Image List!");
return; }
//=== Связывание списка с элементом управления деревом
m_Tree.SetlmageList(m_pImgList, TVSIL_NORMAL);
}

Функция SHGetFilelnfo позволяет получить информацию о каком-либо объекте файловой системы. Последний параметр уточняет смысл вопроса. Определяем его с помощью битовых констант SHGFI_SYSICONINDEX и SHGFI_SMALLICON, которые означают, что мы интересуемся индексами значков в системном списке и нам нужны маленькие значки. Вы помните, что Windows поддерживает значки двух типов: большие (32x32) и маленькие (16x16). Результатом вызова функции будет описатель (handle) всего списка значков, который мы затем должны связать с элементом m_Tree. Но сначала требуется прикрепить (attach) Windows-описатель списка к объекту класса CimageList, адрес которого мы храним в переменной m_pImgList.

Понятие прикрепить описатель (attach a handle) вы будете встречать достаточно часто, программируя в рамках MFC, но значительно реже, чем разработчики, базирующиеся на платформе SDK (Software Development Kit), которые не пользуются классами MFC. Вместо этого они используют многочисленные структуры и прямо вызывают функции API из программы на языке С или C++. При этом им иногда приходится писать в 5-10 раз больше кода. Итак, понятие прикрепить описатель означает примерно следующее: дать объекту класса ту функциональность, которой обладает Windows-объект, обычно описываемый структурой и адресуемый с помощью описателя (handle).

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.