Книга: Программирование КПК и смартфонов на .NET Compact Framework
Код программы
Разделы на этой странице:
Код программы
Теперь можно приступить к написанию кода. При запуске программы выполняется обработчик события 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, поэтому не стоит повторять их разбор. На самом деле эту программу можно улучшать до бесконечности, добавляя новые функциональные возможности. Надеюсь, у вас это получится. Буду рад, если вы пришлете свои варианты примеров, которые, на ваш взгляд, украсят программу.
- Текстовые форматы и кодировки, или Почему иногда вместо текста я вижу абракадабру?
- 1.6.14. Правило генерации: избегайте кодирования вручную; если есть возможность, пишите программы для создания программ
- 2.1.5. Коды завершения программы
- Листинг 5.4. Код программы нахождения простых чисел, предназначенный для выполнения фоновым потоком
- 12.1. Программы с открытым кодом
- 5.11. ПРИМЕР ПРИМЕНЕНИЯ ПРОЕКТНОЙ ПРОЦЕДУРЫ ДЛЯ КОДИРОВАНИЯ ПРОГРАММЫ ПЕЧАТИ КАЛЕНДАРЯ НА ПРИНТЕРЕ
- Листинг 5.4. Код программы нахождения простых чисел, предназначенный для выполнения фоновым потоком
- Код C# для оставшейся части программы
- Внутреннее представление программы и генерация кода
- 8.2. Языки программирования Виды программирований
- Переработка
- 1.4. Динамические аспекты Ruby