Windows Management Instrumentation - инфраструктура управления операционной системой, страница 7

Запустите и убедитесь, что введение новых элементов не вызвало ошибок компиляции (появялись лишь предупреждения о неиспользуемых объектах), а список файлов получил строку с заголовками колонок. Теперь (в конструкторе класса) мы добавим делегатов, реагирующих на события файловой системы. Это можно сделать как с помощью инструментов (в режиме дизайна), так и вручную. Предпочитаю делать это вручную, так как становится более понятным смысл производимых изменений, но при этом требуется некоторая доля аккуратности. Ниже приведен код, который отражает смысл изменений.

Либо введите изменения вручную (как показано ниже), либо добейтесь того, чтобы в коде, который генерирует дизайнер (и прячет внутрь функции InitializeComponent), появились строки с такой же мнемоникой. Некоторые из приведенных строк он уже сделал (если вы пользовались дизайнером на первой стадии), поэтому внимательно следите за его кодом. Еще раз повторю, код генерирует дизайнер, его код спрятан. Если пользуетесь дизайнером, то берите отсюда лишь смысл изменений.

fileWatcher = new FileSystemWatcher();

fileWatcher.Filter = "";

fileWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite |

       NotifyFilters.Size | NotifyFilters.CreationTime;

fileWatcher.Renamed += new RenamedEventHandler (fileWatcher_Renamed);

fileWatcher.Changed += new FileSystemEventHandler (fileWatcher_Changed);

fileWatcher.Created += new FileSystemEventHandler (fileWatcher_Changed);

fileWatcher.Deleted += new FileSystemEventHandler (fileWatcher_Changed);

dirWatcher = new FileSystemWatcher();

dirWatcher.NotifyFilter = NotifyFilters.DirectoryName;

dirWatcher.IncludeSubdirectories = true;

dirWatcher.Renamed += new RenamedEventHandler (dirWatcher_Renamed);

dirWatcher.Created += new FileSystemEventHandler (dirWatcher_Changed);

dirWatcher.Deleted += new FileSystemEventHandler (dirWatcher_Changed);

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

private void fileWatcher_Renamed (object sender, RenamedEventArgs e)

{

}

Остальные обработчики похожи на этот, но следите за типом второго параметра (см. Help). Тела функций пока остаются пустыми. После введения изменений приложение должно работать так же, как и ранее.

Управление деревом файловой системы

Для того, чтобы заполнить дерево узлами, отражающими состояние объектов файловой системы, необходимо сначала правильно заполнить коллекцию (ImageList) из 12-ти картинок, о способе индексации которых мы договорились ранее. Я расчитываю, что с этой задачей вы уже справились, и можно начать заполнение с корневого узла "My Computer". Внутрь этого узла следует поместить множество узлов (объектов класса TreeNode), текст которых соответствует именам логических дисков, а иконки — их типам. Имена следует получить из перечня логических дисков. Перечень можно получить одним из трех способов. Используйте:

¨  классы WMI (ManagementObjectSearcher и ManagementObject),

¨  или класс Environment,

¨  или класс Directory.

При навигации по дереву всегда важно знать, заполнен-ли данный узел вложенными сущностями, или нет. Для этой цели удобно использовать свойство Tag, которое имеется в каждом объекте — потомке класса Control. Свойство Tag определено как object и, поэтому способно управлять объектом произвольного типа. Смысл этой переменной присваивает программист. Мы используем Tag каждого объекта класса TreeNode как флаг, указывающий на то, что множество узлов, вложенных в данный узел, уже не пусто.

Для заполнения дерева целесообразно ввести новый метод (назовем его FillTree). Добавьте вызов этого метода в конструктор, а в теле FillTree реализуйте алгоритм заполнения. Суть алгоритма обозначена ниже.

public void FillTree()

{

      // Эти константы подсмотрены в Help по API-функции  GetDriveType

  const int Removable = 2, LocalDisk = 3, Network = 4, CDROM = 5;

  string[] drives = // Получите список логических дисков

  UpdateStatusBar (Color.WhiteSmoke, "Refreshing file list...");

      //===== Тормозните перерисовку дерева (Напомним, что это объект tree)

      //===== Уничтожьте коллекцию узлов дерева

  //===== Создайте корневой узел "My Computer"

  //===== Установите в true  свойство Tag (для корневого узла)

      //===== Вставьте в дерево корневой узел

  foreach (string drive in drives)

  {

     int id = 0;   // Пока не определенный индекс изображения

     switch (Вызовите API-функцию и узнайте тип диска)

     {

     case LocalDisk:  id = 2;     break; // Об этом мы договорились ранее (должно быть у всех одинаково)

     case CDROM:     id = 4;     break;

     case Removable:  id = 6;     break;

     case Network:   id = 8;     break;

     }

     string name = drive.Substring (0, drive.Length - 1); // Убираем разделитель

     //===== Создайте новый узел

           //===== Вставьте его в коллекцию узлов, вложенных в корневой узел

     // AddItems (node);  // Заполнение коллекции вложенных узлов. Этот метод предстоит разработать

  }

      //===== Разрешите перерисовку дерева

  UpdateStatusBar (Color.WhiteSmoke, "Ready");

}

Здесь вызывается вспомогательный метод UpdateStatusBar. Его цель — генерировать событие типа UpdateStatus для того, чтобы клиентское приложение могло отреагировать и вывести в строку состояния главного окна посылаемое нами сообщение. Само событие UpdateStatus мы объявили ранее (см. общий блок переменных класса ExplorerControl). Вспомните, что каждому новому событию должен соответствовать какой-то делегатный тип, причем тип события должен быть идентичен типу его делегатов. Убедитесь, что в классе объявлен делегатный тип StatusHandler:

public delegate void StatusHandler (Color clr, string msg);

и ему соответствует событие, имеющее тот же тип:

public event StatusHandler UpdateStatus;

Теперь вставьте в класс ExplorerControl метод, который возбуждает событие и передает ему в качестве параметра цвет и текстовую строку, которая должна отобразиться в строке info главного окна.

private void UpdateStatusBar (Color clr, string s)

{