Код программы

We use cookies. Read the Privacy and Cookie Policy

Код программы

Теперь можно приступить к написанию кода. При запуске программы выполняется обработчик события Form_Load. При загрузке основной формы MainForm работает код, приведенный в листинге 7.9.

Листинг 7.9

ListViewHelper.SetGradient(listView);

string bs = Path.DirectorySeparatorChar.ToString();

// Устанавливаем начальную папку

this.path = bs + "My Documents" + bs;

// Заполняем список папок и файлов

fillList();

Сначала устанавливается внешний вид элемента listView с градиентной закраской фона. Затем устанавливается папка по умолчанию My Documents, которую программа открывает при загрузке. Метод fillList заполняет список ListView содержимым открываемой папки. Сам код метода приведен в листинге 7.10.

Листинг 7.10

/// <summary>

/// Заполнение ListView списком папок и файлов

/// </summary>

private void fillList() {

 Cursor.Current = Cursors.WaitCursor;

 // Заполняем ListView списком папок и файлов

 // в выбранной папке

 ListViewItem lvi;

 listView.BeginUpdate();

 listView.Items.Clear();

 // Если не корневая папка

 if (path.Length > 1) {

  // Добавляем папку "Вверх"

  lvi = new ListViewItem(UPDIR);

  lvi.ImageIndex = 0;

  listView.Items.Add(lvi);

 }

 // Добавляем папки

 string[] dirs = Directory.GetDirectories(path);

 ArrayList list = new ArrayList(dirs.Length);

 for(int i = 0; i < dirs.Length; i++)

  list.Add(dirs[i]);

 list.Sort(new SimpleComparer());

 foreach(string dir in list) {

  lvi = new ListViewItem(Path.GetFileName(dir));

  lvi.ImageIndex = 0;

  listView.Items.Add(lvi);

 }

 // Добавляем файлы

 string[] files = Directory.GetFiles(path);

 list = new ArrayList(files.Length);

 for(int i = 0; i < files.Length; i++)

  list.Add(files[i]);

 list.Sort(new SimpleComparer());

 foreach(string file in list) {

  lvi = new ListViewItem(Path.GetFileName(file));

  lvi.ImageIndex = 1;

  listView.Items.Add(lvi);

 }

 listView.EndUpdate();

 if (listView.Items.Count > 0) {

  // выделяем первый элемент

  listView.Items[0].Selected = true;

  listView.Items[0].Focused = true;

 }

 Cursor.Current = Cursors.Default;

}

Итак, посмотрим, что делает метод fillList. Перед заполнением элемента списком файлов надо очистить его содержимое от предыдущих записей при помощи метода Clear. После очистки списка надо проверить, является ли папка корневой. Если папка не корневая, то в список добавляется специальная папка «На один уровень выше». Затем в список добавляются все папки в отсортированном порядке.

После этого наступает очередь файлов. Они сортируются и заносятся в список. Наконец, первый элемент списка выделяется другим цветом. Заодно на первом элементе устанавливается фокус ввода. Навигация по папкам и файлам осуществляется с помощью кнопок и дополняется кнопкой Action. Код навигации приведен в листинге 7.11.

Листинг 7.11

/// <summary>

/// Навигация по папкам и файлам

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void listView_ItemActivate(object sender, System.EventArgs e) {

 Cursor.Current = Cursors.WaitCursor;

 ListViewItem lvi = listView.Items[listView.SelectedIndices[0]];

 bool isFolder = lvi.ImageIndex == 0;

 if (lvi.Text == UPDIR) {

  path = path.Substring(0,

   path.Substring(0,

   path.Length - 1).LastIndexOf(Path.DirectorySeparatorChar) + 1);

  fillList();

 } else if (isFolder) {

  path += lvi.Text + Path.DirectorySeparatorChar;

  fillList();

 } else

  ShellExecute.Start(path + lvi.Text);

 Cursor.Current = Cursors.Default;

}

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

Теперь разберем код для команд меню. Для команды Вырезать код приведен в листинге 7.12.

Листинг 7.12

private void cutMenuItem_Click(object sender, System.EventArgs e) {

 ListViewItem lvi =

  listView.Items[listView.SelectedIndices[0]];

 clipboardFileName = this.path + lvi.Text;

 clipboardAction = ClipboardAction.Cut;

}

Путь к текущему выбранному файлу сопоставляется с производимым действием. Код, выполняющийся после выбора команды Копировать, приведен в листинге 7.13.

Листинг 7.13

private void copyMenuItem_Click(object sender, System.EventArgs e) {

 ListViewItem lvi = listView.Items[listView.SelectedIndices[0]];

 clipboardFileName = path + lvi.Text;

 clipboardAction = ClipboardAction.Copy;

}

Для команды меню Вставить код немного усложняется. Он приведен в листинге 7.14.

Листинг 7.14

private void pasteMenuItem_Click(object sender, System.EventArgs e) {

 // Если файл существует

 string dest = path + Path.GetFileName(clipboardFileName);

 if (File.Exists(dest)) {

  if (MessageBox.Show("Файл уже существует, перезаписать?", this.Text,

   MessageBoxButtons.YesNo, MessageBoxIcon.Question,

   MessageBoxDefaultButton.Button2) == DialogResult.Yes)

   File.Delete(dest);

  else return;

 }

 // Перемещаем или копируем

 string s = path.Substring(0, path.Length - 1);

 switch(clipboardAction) {

 case ClipboardAction.Cut:

  File.Move(clipboardFileName, dest);

  break;

 case ClipboardAction.Copy:

  File.Copy(clipboardFileName, dest, false);

  break;

 }

 clipboardAction = ClipboardAction.None;

 clipboardFileName = string.Empty;

 fillList();

}

Перед тем как вставить файл в другую папку, нужно удостовериться, что в ней нет файла с таким именем. Если же такой файл существует, то надо предупредить пользователя и узнать, что он хочет сделать. Код для команды Вставить ярлык приведен в листинге 7.15.

Листинг 7.15

private void pasteShortcutMenuItem_Click(object sender, System.EventArgs e) {

 int i = 2;

 string s = string.Empty;

 string dest;

 while(true) {

  dest = path + "Shortcut" + s + " to " +

   Path.GetFileName(Path.GetFileNameWithoutExtension(clipboardFileName) +

   ".lnk");

  if (!File.Exists(dest)) break;

  s = " (" + i.ToString() + ")";

  i++;

 }

 StreamWriter sw = new StreamWriter(dest);

 s = clipboardFileName;

 if(s.IndexOf(" ") > 0)

  s = """ + s + """;

 s = s. Length.ToString() + "#" + s;

 sw.WriteLine(s);

 sw.Close();

 fillList();

}

В этом коде создается уникальное имя ярлыка, которое затем записывается в виде файла с добавлением. К имени ярлыка добавляется расширение .LNK.

Код для команды Переименовать приведен в листинге 7.16.

Листинг 7.16

private void renameMenuItem_Click(object sender, System.EventArgs e) {

 Cursor.Current = Cursors.WaitCursor;

 istViewItem lvi = listView.Items[listView.SelectedIndices[0]];

 bool isFolder = lvi.ImageIndex = 0;

 string s;

 if (isFolder)

  s = "папку";

 else s = "файл";

 NameForm nameForm =

  new NameForm(this, "Переименовать " + s, lvi.Text,

   new SetNameDelegate(SetRename));

 if (nameForm.ShowDialog() = DialogResult.OK) fillList();

 listView.Focus();

}

Сначала обрабатывается текущий выделенный элемент. Если пользователь выделил папку, то для формы nameForm задается соответствующий заголовок Переименовать папку. Также из этой формы передается в основную форму новое имя папки или файла с помощью метода Set Rename, как это показано в листинге 7.17.

Листинг 7.17

/// <summary>

/// Метод для переименования папки или файла

/// </summary>

/// <param name="name">Имя папки или файла</param>

public void SetRename(string name) {

 ListViewItem lvi = listView.Items[listView.SelectedIndices[0]];

 bool isFolder = lvi.ImageIndex == 0;

 string itemName = path + lvi.Text;

 string destName =

  Path.GetDirectoryName(itemName) +

  Path.DirectorySeparatorChar.ToString() + name;

 if (isFolder)

  Directory.Move(itemName, destName);

 else

  File.Move(itemName, destName);

}

После того как будет получена информация о выделенном элементе, он переименовывается. Для реализации команды Удалить используется код, приведенный в листинге 7.18.

Листинг 7.18

private void deleteMenuItem_Click(object sender,

 System.EventArgs e) {

 ListViewItem lvi = listView.Items[listView.SelectedIndices[0]];

 bool isFolder = lvi.ImageIndex == 0;

 string s = "Are you sure you want to delete " + lvi.Text;

 if (isFolder)

  s += " and all its content";

 s += "?";

 if (MessageBox.Show(s, this.Text, MessageBoxButtons.YesNo,

  MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) ==

  DialogResult.Yes) {

 if (isFolder)

  Directory.Delete(path + lvi.Text, true);

 else

  File.Delete(path + lvi.Text);

 fillList();

}

Перед удалением папки или файла запрашивается подтверждение действий пользователя. Для создания новой папки используется следующий код, приведенный в листинге 7.19.

Листинг 7.19

private void newFolderMenuItem_Click(object sender, System.EventArgs e) {

 Cursor.Current = Cursors.WaitCursor;

 ListViewItem lvi = listView.Items[listView.SelectedIndices[0]];

 NameForm nameForm = new NameForm(this, "Новая папка", "",

  new SetNameDelegate(SetNewName));

 if (nameForm.ShowDialog() == DialogResult.OK) fillList();

 listView.Focus();

}

В результате действия этой функции отображается форма NameForm с заголовком Новая папка. Эта форма также передает информацию в главную форму при помощи метода SetNewName, который приведен в листинге 7.20.

Листинг 7.20

/// <summary>

/// Устанавливает новое имя для папки

/// </summary>

/// <param name="name">Имя для папки</name>

public void SetNewName(string name) {

 Directory.CreateDirectory(path + name);

}

Метод создает папку с заданным именем. Как видно, код его чрезвычайно прост.

Код для выполнения команды Свойства приведен в листинге 7.21.

Листинг 7.21

private void propertiesMenuItem_Click(object sender, System.EventArgs e) {

 Cursor.Current = Cursors.WaitCursor;

 ListViewItem lvi = listView.Items[listView.SelectedIndices[0]];

 FileInfo fi = new FileInfo(path + lvi.Text);

 PropertiesForm propertiesForm =

  new PropertiesForm(this, fi, new SetNameDelegate(SetRename),

  new SetAttributesDelegate(SetAttributes));

 if (propertiesForm.ShowDialog() == DialogResult.OK) fillList();

 listView.Focus();

}

Этот код вызывает форму PropertiesForm, которая отображает атрибуты выбранного файла или папки. Также в этой форме пользователь может изменять атрибуты файла при помощи метода SetAttributes, код которого приведен в листинге 7.22.

Листинг 7.22

public void SetAttributes(FileAttributes fileAttributes) {

 ListViewItem lvi = listView.Items[listView.SelectedIndices[0]];

 bool isFolder = lvi.ImageIndex = 0;

 if (isFolder) {

  DirectoryInfo di = new DirectoryInfo(path + lvi.Text);

  di.Attributes = fileAttributes;

 } else {

  FileInfo fi = new FileInfo(path + lvi.Text);

  fi.Attributes = fileAttributes;

 }

}

Для создания градиентной заливки соответствующего элемента интерфейса применяется метод, код которого приведен в листинге 7.23.

Листинг 7.23

public static void SetGradient(System.Windows.Forms.ListView listView) {

 // Новый вариант

 // Для .NET Compact Framework 2.0

 SendMessage(listView.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE,

  LVS_EX_GRADIENT);

 listView.Refresh();

}

Итак, основные трудности реализации программы рассмотрены. Кроме того, в примере присутствуют вызовы функций Windows API для работы с табличным списком ListView. Эти примеры рассматривались в главе 4, поэтому не стоит повторять их разбор. На самом деле эту программу можно улучшать до бесконечности, добавляя новые функциональные возможности. Надеюсь, у вас это получится. Буду рад, если вы пришлете свои варианты примеров, которые, на ваш взгляд, украсят программу.