Файл: Справочник для опытных и как пособие для начинающих программистов. Компактдиск содержит исходные коды примеров из книги.doc

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.01.2024

Просмотров: 931

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


{ // здесь обрабатываем мгновенное событие первоначального

// нажатия клавиши

label2.Text = string.Empty;

// Если нажата клавиша

if (е.Alt == true) label2.Text += "Alt: Yes\n";
else label2.Text += "Alt: No\n";
// Если нажата клавиша

if (e.Shift == true) label2.Text += "Shift: Yes\n";
else label2.Text += "Shift: No\n";
// Если нажата клавиша

if (e.Control == true) label2.Text += "Ctrl: Yes\n";
else label2.Text += "Ctrl: No\n";
label2.Text += "Код клавиши: " + e.KeyCode + "\nKeyData: " + e.KeyData + "\nKeyValue: " + e.KeyValue;

}

private void Form1_KeyUp(object sender, KeyEventArgs e)

{

// Очистка меток при освобождении клавиши

Label1.Text = string.Empty; label2.Text = string.Empty;

}

}

}

}

В первую метку label1 записываем сведения о нажатой обычной (т. е. не мо­дифицирующей и не функциональной) клавише при обработке события Keypress. Во вторую метку из аргумента события е (е.Alt, е.shift и е.control) получаем сведения, была ли нажата какая-либо модифицирующая клавиша (либо их комби­нация). Обработчик события KeyUp очищает обе метки при освобождении клавиш.



Рис. 3.7. Фрагмент работы программы, определяющей нажатую клавишу

Убедиться в работоспособности программы можно, открыв решение Key.sln в папке Key.

Пример 21. Разрешаем вводить в текстовое поле только цифры

Обычно для диагностики вводимых числовых данных мы пользовались функ­цией TryParse. Эта функция возвращает true, если на ее вход подаются числовые данные, и false в противном случае. Покажем, как можно совершенно по-другому решить задачу контроля вводимых пользователем данных. Можно вообще не да­вать возможность пользователю вводить нечисловые данные. Обратите внима­ние, как происходит ввод числовых данных в программе Калькулятор системы Windows, здесь программа просто не даст возможности пользователю ввести нечи­словой символ. Продемонстрируем и мы такое решение на следующем примере.

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

Запустим систему Visual Studio 2010, в окне New Project выберем шаблон Win­dows Forms Application С#. На панели элементов Toolbox найдем текстовое поле TextBox и перетащим его в форму. Текст программы показан в листинге 3.7.

Листинг 3.7. Контроль вводимых пользователем числовых данных (вариант 1)

// Программа анализирует каждый символ, вводимый пользователем в текстовое

// поле формы. Если символ не является цифрой или Backspace, то текстовое поле

// получает запрет на ввод такого символа.

using System; *

using System.Windows.Forms;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace Numbers

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

this.Text = "Введите число"; textBoxl.Clear();

}

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)


{ // Разрешаем ввод только десятичных цифр и Backspace:

if (char.IsDigit(e.KeyChar) == true) return;

if (e.KeyChar == (char)Keys.Back) return;

e.Handled = true; // - запрет на ввод других вводимых символов

}

}

}

Как видно из программного кода, сразу после выполнения процедуры InitializeComponent задаем текст строки заголовка "Введите число" и очищаем текстовое поле TextBox1.clear(). Самое интересное начинается при обработке события нажатия клавиши в текстовом поле textBox1_KeyPress. Пустой обработ­чик этого события мы получаем, как и предыдущих программах, т. е. на вкладке конструктора формы в панели свойств Properties, щелкнув на символе молнии (Events), выбираем в списке всех возможных событий событие Keypress для тек­стового поля. Управляющая среда Visual Studio 2010 генерирует при этом пустую процедуру обработки данного события.

В этой процедуре можно легко определить, какую клавишу нажал пользова­тель, из аргумента события е. Символ, соответствующий нажатой клавише, cодержится в свойстве аргумента e.KeyChar. На вход функции IsDigital подаем это свойство (т. е. исследуемый символ), а на выходе получаем заключение, является ли исследуемый символ цифрой (true или false). Аргумент события е имеет заме­чательное свойство Handled, которое либо запрещает получение данного события текстовым полем (true), либо разрешает (false). Всякий раз при очередной работе процедуры textBox1_KeyPress изначально свойство е.Handled = false, т. е. по­лучение данного события текстовым полем разрешено. Последней строкой в про­цедуре запрещаем ввод символов в текстовое поле, но если пользователь вводит цифру или нажал клавишу <Backspace>, то этот запрет мы обходим с помощью оператора return. Таким образом, мы добиваемся игнорирования текстовым полем нецифровых символов.



Рис. 3.8. Контроль введенных данных

Интерфейс рассматриваемого приложения показан на рис. 3.8.

Убедиться в работоспособности программы можно, открыв соответствующее решение в папке NumbersOnly.

Пример 22. Разрешаем вводить в текстовое поле цифры, а также разделитель целой и дробной части числа

Мы совсем забыли, уважаемые читатели, что число, вводимое пользователем, может иметь дробную часть после точки или запятой. Причем выяснить, что имен­но установлено в вашей системе — точка или запятая в качестве разделителя целой и дробной частей числа, можно, например, запустив Калькулятор Windows. Здесь среди экранных кнопок увидим кнопку либо с десятичной точкой, либо с десятич­ной запятой. Очень легко поменять данную установку системы (обычно по умолча­нию в русифицированной версии Windows — запятая). Для этого следует в Панели управления выбрать значок Язык и региональные стандарты, затем на вкладке Региональные параметры щелкнуть на кнопке Настройка и на появившейся но­вой вкладке указать в качестве разделителя целой и дробной частей либо точку, либо запятую. Нам нужно добиться того, чтобы текстовое поле разрешало ввод только того разделителя, которое указано на вкладке Региональные параметры.

Для решения данной задачи запустим Visual Studio 2010, выберем проект шаб­лона Windows Forms Application С#. На панели элементов Toolbox найдем тек­стовое поле TextBox и перетащим его в форму. Текст программы представлен в листинге 3.8.

Листинг 3.8. Контроль вводимых пользователем числовых данных (вариант 2)

// Программа разрешает ввод в текстовое поле только цифровых символов,

// а также разделитель целой и дробной частей числа (т. е. точки или запятой)

using System;

using System.Windows.Forms;

// Другие директивы using удалены, поскольку они не используются вданной программе

namespace ТолькоЧисло_ТчкОrЗпт

{

public partial class Form1 : Form

{ // Разделитель целой и дробной частей числа может быть

// точкой "." или запятой "," в зависимости от

// установок в пункте Язык и региональные стандарты

// Панели управления ОС Windows:

System.Globalization.Culturelnfо Культ = System.Globalization.Culturelnfо.CurrentCulture;

string ТчкИлиЗпт;

public Form1()

{

InitializeComponent(); this.Text = "Введите число";

// Выясняем, что установлено на данном ПК в качестве

// разделителя целой и дробной частей: точка или запятая

ТчкИлиЗпт = Культ.NumberForirat.NumberDecimalSeparator;

}

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)

{

bool ТчкИлиЗптНАЙДЕНА = false;

// Разрешаю ввод десятичных цифр:

if (char.IsDigit(e.KeyChar) == true) return;

// Разрешаю ввод :

if (e.KeyChar == (char)Keys.Back) return;

// Поиск ТчкИлиЗпт в textBox, если IndexOf() == -1, то не найдена:

if (textBox1.Text.IndexOf(ТчкИлиЗпт) != -1)

ТчкИлиЗптНАЙДЕНА = true;

// Если ТчкИлиЗпт уже есть в textBox, то запрещаем вводить и ее,

// и любые другие символы:

if (ТчкИлиЗптНАЙДЕНА == true) { е.Handled = true; return; }

// Если ТчкИлиЗпт еще нет в textBox, то разрешаем ее ввод:

if (e.KeyChar.ToString() == ТчкИлиЗпт) return;

//В других случаях - запрет на ввод:

е.Handled = true;

}

}

}

Как видно из текста программы, вначале выясняем, что установлено в данной системе в качестве разделителя целой дробной части: точка или запятая. Этот раз­делитель записываем в строковую переменную ТчкИлиЗпт, которая видна из всех процедур данной программы, поскольку объявлена вне всех процедур. Далее, как и в предыдущем примере, в процедуре обработки события Keypress разрешаем ввод десятичных цифр и нажатие клавиши <Backspace> путем обхода с помощью return последнего оператора процедуры е.Handled = true, запрещающего ввод символа в текстовое поле.

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

На рис. 3.8 показан фрагмент работы программы.



Рис. 3.9. Кроме цифр программа разрешает ввод десятичной запятой

Убедиться в работоспособности программы можно, открыв соответствующее решение в папке ТолькоЧисло+ТчкОгЗпт.


Глава 4 Чтение, запись текстовых и бинарных файлов, текстовый редактор

Пример 23. Чтение/запись текстового файла в кодировке Unicode. Обработка исключений try...catch

Очень распространенной задачей является сохранение данных на диске в тек­стовом формате (не в двоичном). В этом случае сохраненные данные можно чи­тать, редактировать любым текстовым редактором, например Блокнотом или TextEdit. Читать текстовые данные также можно и в своей программе.

Казалось бы, это очень простая задача. Например, чтение текстового файла сво­дится буквально к нескольким строчкам:

// Создание экземпляра StreamReader для чтения из файла

System.IO.StreamReader Reader = new System.IO.StreamReader("C:WTextl.txt");

// Считывание содержимого текстового файла в строку

String Stroka = Reader.ReadToEndО;

Reader.Close();

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

Запустим среду Visual Studio 2010 и закажем новый проект шаблона Windows Forms Application С#. Далее в форму перенесем текстовое поле и две командные копки. Для текстового поля в окне Properties сразу укажем для свойства Multiline значение True, чтобы текстовое поле имело не одну строку, а столько, сколько по­местится в растянутом указателем мыши поле. Одна кнопка предназначена для открытия файла, а другая — для сохранения файла на машинном носителе. В листинге4.1 приведен текст данной программы.

Листинг 4.1. Чтение/запись текстового файла в кодировке Unicode

// Программа для чтения/записи текстового файла в кодировке Unicode

using System.Windows.Forms;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace TXT_Unicode

{

public partial class Form1 : Form

{

string filename = @"C:\Textl.txt";

public Form1()

{

InitializeComponent();

textBox1.Multiline = true; textBoxl.Clear();

textBox1.Tablndex =0; '

textBox1.Size = new System.Drawing.Size(268, 112);

button1.Text = "Открыть"; button1.Tablndex = 0;

button2.Text = "Сохранить";

base.Text = "Здесь кодировка Unicode";

}

private void button1_Click(object sender, System.EventArgs e)

{ // Щелчок на кнопке "Открыть".

// Русские буквы будут корректно читаться,


// если файл в кодировке UNICODE:

try

{

// Создание объекта StreamReader для чтения из файла:

var Читатель = new System.10.StreamReader(filename);

// Непосредственное чтение всего файла в текстовое поле:

textBox1.Text = Читатель.ReadToEnd();

Читатель.Close(); // закрытие файла

// Читать текстовый файл в кодировке UNICODE в массив строк

// можно также таким образом (без Open и Close):

// string[] МассивСтрок = System.IO.

// File.ReadAllLines(@"C:\Textl.txt");

}

catch (System.IO.FileNotFoundException Ситуация)

{ // Обработка исключительной ситуации:

MessageBox. Show (Ситуация.Message + “\nНет такого файла”,

"Ошибка", MessageBoxButtons.OK,

MessageBoxIcon.Exclamation);

}

catch (System.Exception Ситуация)

{

// Отчет о других ошибках:

MessageBox.Show(Ситуация.Message, "Ошибка",

MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

}

private void button2_Click(object sender, System.EventArgs e)

{ // Щелчок на кнопке Сохранить:

Try

{ // Создание объекта StreamWriter для записи в файл:

var Писатель = new System.10.StreamWriter(filename, false);

Писатель . Write (textBoxl. Text) ;

Писатель.Close();

// Сохранить текстовый файл можно также таким образом

// (без Close), причем, если файл уже существует,

// то он будет заменен:

// System.10.File.WriteAllText(@"С:\tmp.tmp", textBoxl.Text);

}

catch (System.Exception Ситуация)

{ // Отчет обо всех возможных ошибках:

MessageBox.Show(Ситуация.Message, "Ошибка",

MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

}

}

}

Несколько слов о блоках try, которые, как видно, используются в данном про­граммном коде. Логика использования try следующая: попытаться (try) выполнить некоторую задачу, например, прочитать файл. Если задача решена некоррект­но (например, файл не найден), то "перехватить" (catch) управление и обработать возникшую (исключительную, Exception) ситуацию. Как видно из текста программы, обработка исключительной ситуации свелась к информирова­нию пользователя о недоразумении.

При обработке события "щелчок на кнопке" Открыть организован ввод файла C:\Text1.txt. Обычно в этой ситуации пользуются элементом управления OpenFileDialog для выбора файла. Мы не стали использовать этот элемент управления для того, чтобы не "заговорить" проблему, а также свести к минимуму программный код.

Далее создаем объект (поток) Читатель для чтения из файла. Для большей выразительности операций с данным объектом мы назвали его русскими буквами Затем следует чтение файла filename методом ReadToEnd() в текстовое поле textBox1.Text и закрытие файла методом Сlose ().

При обработке события "щелчок на кнопке" Сохранить
организована запись файла на диск аналогично через объект Писатель. При создании объекта Писатель первым аргументом является filename, а второй аргумент false указывает, что данные следует не добавить (append) к содержимому файла (если он уже существует), а перезаписать (overwrite). Запись на диск производится с помощью метода write() из свойства Text элемента управления textBox1. На рис. 4.1 приведен фрагмент работы программы.



Рис. 4.1. Чтение/запись текстового файла в кодировке Unicode

Сделаем очень важное примечание. Запись текстового файла с помощью дан­ной программы будет происходить в формате (кодировке) Unicode, как и чтение из файла. То есть вы сможете читать эти файлы Блокнотом, редактировать их, но ка­ждый раз при сохранении файлов следить; чтобы кодировка была Unicode.

Однако по умолчанию в редакторах обычно используется кодировка ANSI. Ко­дировку ANSI с русскими буквами называют Windows 1251. Некоторые редакторы, например, RPad ("русский" Блокнот) вообще не работают с Unicode. Таким обра­зом, на сегодняшний день пока что записывать в кодировке Unicode — это как бы эксклюзив. Возможно, даже наверняка, в ближайшее время многое изменится в пользу Unicode, поскольку информационные технологии меняются очень быстро.

Если в Блокноте подготовить текстовый файл в обычной кодировке ANSI, то прочитать русские буквы данной программой не получится, хотя английские буквы отобразятся в текстовом поле без проблем. Почему? Дело в том, что приведенная в тексте данной программы технология описана в учебных пособиях по Visual С#, MSDN, на сайтах, подобных http://msdn.microsoft.com/library/rus/. Однако чаще это все англоязычные источники, а для английских текстов переход от одной кодировки к другой оказывается практически незаметным. Например, английские буквы кодировок Windows 1251, ASCII и Unicode совпадают, а с русскими буквами всегда возникают недоразумения. Об этом говорят программисты на различных форумах в Интернете.

Программистам эти недоразумения следует учитывать. Разрешению этого не­доразумения посвящена следующая программа.

Убедиться в работоспособности данной программы можно, открыв решение TXT_Unicode.sln в папке TXT_Unicode.

Пример 24. Чтение/запись текстового файла в кодировке
Windows 1251

В данном примере также на экранной форме имеем текстовое поле и две ко­мандных кнопки, назначение этих элементов управления аналогично предыдущему примеру. Однако чтение и запись текстового файла в этом примере происходит в кодировке Windows 1251 (ANSI). Поскольку структура данной программы анало­гична предыдущей, сразу обратимся к ее коду в листинге 4.2.

Листинг 4.2. Чтение/запись текстового файла в кодировке Windows 1251

// Программа для чтения/записи текстового файла в кодировке Windows 1251 using System;

using System.Windows.Forms;

// Другие директивы using удалены, поскольку они не используются в данной программе

namespace ТХТ_1251

{

public partial class Form1 : Form

{

string filename = @"C:\Text2.txt";

public Form1()

{

InitializeComponent();

textBox1.Multiline = true; textBox1.Clear();

textBox1.Size = new System.Drawing.Size(268, 112);

button1.Text = "Открыть"; button1.Tablndex = 0;

button2.Text = "Сохранить";

this.Text = "Здесь кодировка Windows 1251";

}

private void button1_Click(object sender, EventArgs e)

{ // Щелчок на кнопке Открыть

try

{ // Чтобы русские буквы читались бы корректно, объявляем

// объект Кодировка:

var Кодировка = System.Text.Encoding.GetEncoding(1251);

// Создание экземпляра StreamReader для чтения из файла

var Читатель = new System.IO.StreamReader(filename, Кодировка);

textBox1.Text = Читатель.ReadToEnd();

Читатель.Close();

// Читать текстовый файл в кодировке Windows 1251 в массив строк

// можно также таким образом (без Open и Close):

// string[] МассивСтрок = System.10.

// File.ReadAllLines(@"С:\Text2.txt", Кодировка);

}

catch (System.IO.FileNotFoundException Ситуация)

{ // Обработка исключительной ситуации:

MessageBox.Show(Ситуация.Message + "\пНет такого файла",

"Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

catch (Exception Ситуация)

{ // Отчет о других ошибках

MessageBox.Show(Ситуация.Message, "Ошибка",

MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

}

private void button2_Click(object sender, EventArgs e)

{ // Щелчок на кнопке Сохранить:

try

{

var Кодировка = System.Text.Encoding.GetEncoding(1251);

// Создание экземпляра StreamWriter для записи в файл:

var Писатель = new System.IO.StreamWriter(filename, false, Кодировка);

Писатель.Write(textBox1.Text);

Писатель.Close();

// Сохранить текстовый файл можно также таким образом (без Close)

// причем, если файл уже существует, то он будет заменен:

// System.IO.File.WriteAllText(@"С:\tmp.tmp",

// textBox1.Text, Кодировка);

}

catch (System.Exception Ситуация)

{ // Отчет обо всех возможных ошибках:

MessageBox.Show(Ситуация.Message, "Ошибка",

MessageBoxButtons.OK, MessageBox1con.Exclamation);

}

}

}

}

Этот текст программы отличается от предыдущего лишь тем, что здесь введен новый объект— Кодировка. Метод