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

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

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

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

Добавлен: 11.01.2024

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

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

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



Рис. 4.7. Простой RTF-редактор

В основе процедуры Запись () также лежит блок try.. .catch: выполнить noпытку (try) сохранения файла (saveFile) и при этом перехватить (catch) возможные недоразумения и сообщить о них пользователю в диалоговом окне MessageBox.

Выход из программы организован абсолютно так же, как и в программе из предыдущего примера. Вдобавок обработаны два события — пункт меню Выход и всевозможные закрытия программы традиционными способами Windows. Предусмотрен диалог с пользователем в случае имеющих место несохраненных данных.

Замечу, для закрытия приложения следует осторожно пользоваться методом Exit объекта Application (можно сказать, с оглядкой). Этот метод подготавливает приложение к закрытию. Да, метод Application.Exit() не вызывает события формы Сlosing. Но попробуйте проследить за поведением программы после команды Application.Exit с помощью отладчика (клавиша <F11>). Вы убедитесь, что после команды Application.Exit управление перейдет следующему оператору, затем — следующему, и так до конца процедуры. Если на пути встретится функция MessageBox, то программа выдаст это диалоговое окно, и это несмотря на то, что уже давно была команда Application.Exit. Аналогично ведет себя метод Сlose элемента Form (если вы работаете с проектом Windows Application), который вызывается таким образом: thislose(). Да, thislose вызывает событие формы Сlosing. Этот метод закрывает форму и освобождает все ресурсы. Но для освобождения ресурсов после команды thislose управление также пройдет все операторы процедуры. Таким образом, для немедленного выхода из процедуры следует комбинировать названные методы с return.

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

Пример 28. Печать текстового документа

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


Программа, представленная в данном разделе, имеет такие скромные возмож­ности: открыть в стандартном диалоге Windows текстовый файл, просмотреть его в окне программы (в текстовом поле) без возможности изменения текста (ReadOnly) и при желании пользователя вывести этот текст на принтер.

Таким образом, чтобы создать данную программу, следует в форму перенести следующие элементы управления: текстовое поле TextBox, меню MenuStrip с пунктами меню: Открыть, Печатать и Выход, а также элементы управления OpenFileDialog и PrintDocument. Текст программы представлен в листинге 4.7.

Листинг 4.7. Печать текстового документа

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

// просмотреть его в текстовом поле без возможности изменения текста

// (Readonly) и при желании пользователя вывести этот текст на принтер.

using System;

using System.Drawing;

using System.Windows.Forms;

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

namespace TXT_print

{

public partial class Form1 : Form

{

System.IO.StreamReader Читатель;

public Form1()

{

InitializeComponent();

base.Text = "Открытие текстового файла и его печать";

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

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

textBox1.ScrollBars = ScrollBars.Vertical;

textBox1.Readonly = true;

//До тех пор, пока файл не прочитан в текстовое поле,

//не должен быть виден пункт меню "Печать..."

печатьToolStripMenuItem.Visible = false;

openFileDialog1.FileName = null;

}

private void открытьToolStripMenuItem_Click(object sender, EventArgs e)

{ // Щелчок на пункте меню "Открыть":

openFileDialog1.Filter =

"Текстовые файлы (*.txt)|*.txt|All files (*.*)|*.*";

openFileDialog1.ShowDialog();

if (openFileDialog1.FileName == null) return;

try

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

Читатель = new System.IO.StreamReader(openFileDialogl.FileName,

System.Text.Encoding.GetEncodihg(1251));

// - здесь заказ кодовой страницы Win1251 для русских букв

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

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

печатьToolStripMenuItem.Visible = true;

}

catch (System.IO.FileNotFoundException Exc) '

{

MessageBox.Show(Exc.Message + "/nНет такого файла", "Ошибка",

MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

catch (Exception Exc)

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

MessageBox.Show(Exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

}

private void печатьToolStripMenuItem_Click(object sender, EventArgs e)

{ // Пункт меню "Печать"

try

{

Читатель = new System.IO.StreamReader(openFileDialog1.FileName,

System.Text.Encoding.GetEncoding(1251));

// - здесь заказ кодовой страницы Winl251 для русских букв

try { printDocumentl.Print(); }

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

}

catch (Exception ex) { MessageBox.Show(ex.Message); }

}

private void printDocument1_PrintPage(object sender, System.Drawing.

Printing.PnntPageEventArgs e)



{

Single linesPerPage = 0;

Single yPos = 0; int count = 0;

Single leftMargin = e.MarginBounds.Left;

Single topMargin = e.MarginBounds.Top;

String line = null;

Font printFont = new Font("Times New Roman", 12.0F);

// Вычисляем количество строк на одной странице

linesPerPage = е.MarginBounds.Height /

printFont.GetHeight(e.Graphics);

// Печатаем каждую строку файла

while (count < linesPerPage)

{

line = Читатель .ReadLine ();

if (line == null) break;

// выход из цикла

yPos = topMargin + count * printFont.GetHeight(e.Graphics);

// Печать строки

e.Graphics.DrawString(line, printFont, Brushes.Black,

leftMargin, yPos, new StringFormat());

count += 1;

}

// Печать следующей страницы, если есть еще строки файла

if (line != null) е.HasMorePages = true;

else e.HasMorePages = false;

}

private void выходToolStripMenuItem_Click(object sender, EventArgs e)

{ // Выход из программы

base.Close();

}

}

}

Здесь при обработке события загрузки формы Form1_Load запрещаем пользова­телю редактировать текстовое поле: Readonly = true. Также назначаем свойству печатьToolstripMenuitem.visible = false (пункт меню Печать), т.е. в начале работы программы пункт меню Печать пользователю не виден (поскольку пока распечатывать нечего, необходимо вначале открыть текстовый файл). Остальные присваивания при обработке события Form1_Load очевидны.

При обработке события "щелчок на пункте меню" Открыть вызываем стан­дартный диалог openFiieDialog и организуем чтение файла через создание потока StreamReader Эти процедуры мы уже рассматривали подробно в разделах о текстовых редакторах, поэтому оставим их без комментария. Замечу только, что nocле чтения файла в текстовое поле назначаем видимость пункту меню Печать печатьToolStripMenuItem.Visible = true, поскольку уже есть, что печатать на принтере (файл открыт).

Представляет интерес обработка события "щелчок на пункте меню" Печать. Этот пункт написан автором по технологии, приведенной в справочной системе С# (MSDN). Здесь во вложенных блоках try. . .finally. . .catch программа еще раз создает поток StreamReader, а затем запускает процесс печати докумнта printDocument1.Print. Если ничего более не программировать, только метод printDocument1.Print, то принтер распечатает лишь пустую страницу. Чтобы принтер распечатал текст, необходимо обработать событие PrintPage (см. текст программы), которое создает объект PrintDocument. То есть роль метода Print – это создать событие PrintPage.

Обратите внимание на обработку события PrintDocument1. PrintPage. Пример обработки этого события приведен в MSDN. Вначале перечислены объявления ременных, значения некоторых из них получаем из аргументов события
е, например, leftMargin — значение отступа от левого края, и т. д. Назначаем шрифт печати — Times New Roman, 12 пунктов.

Далее в цикле while программа читает каждую строку line из файла— Читатель .ReadLine (), а затем распечатывает ее командой (методом) Drawstring. Здесь используется графический объект Graphics, который получаем из аргумента события е.

В переменной count происходит счет строк. Если количество строк оказывавается большим, чем число строк на странице linesPerPage, то происходит выход из цикла, поскольку страница распечатана. Если есть еще страницы, а программа выясняет это, анализируя содержимое переменной line, если ее содержимое отличается от значения null (line ! = null), то аргументной переменной e.HasMorePage назначаем true, что инициирует опять событие PrintPage и подпрограмм PrintDocument1. Print начинает свою работу вновь. И так, пока не закончатся все страницы е.HasMorePages = False для печати на принтере.



Рис. 4.8. Фрагмент работы программы печати текстового файла

На рис. 4.8 показан интерфейс приложения. убедиться в работоспособности программы можно, открыв решение ТХT_print.sln в папке TXT_print.

Пример 29. Чтение/запись бинарных файлов с использованием потока данных

Обычно программа либо что-то читает с диска в оперативную память, либо что-то пишет на диск. Писать, читать можно либо в бинарный (двоичный) файл, либо в текстовый (литерный, строковый) файл. Разница между ними состоит в том, что текстовый файл можно прочитать текстовым редактором, например Блокнотом, а бинарный — нет. Название "бинарный" (двоичный) — условное, поскольку, по су­ти и текстовый, и бинарный файлы являются двоичными файлами.

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

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

Итак, в форме имеем три текстовых поля, куда пользователь может записать соответственно номер студента по порядку, фамилию студента и его средний балл успеваемости. Поэтому в форму из панели Toolbox перенесем три текстовых поля TextBox, три метки Label и две командных кнопки: Читать и Сохранить. Таким образом, получим пользовательский интерфейс, показанный на рис. 4.9. Текст про­граммы приведен в листинге 4.8.

Листинг 4.8. Чтение/запись бинарных файлов

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

using System;

using System. Windows . Forms ;

using System.IO; // - добавляем пространство имен для сокращения программного кода

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

namespace Read_Write_bin

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

base.Text = "Успеваемость студента"; label1.Text = "Номер n/n";

label2.Text = "Фамилия И.О."; label3.Text = "Средний балл";

textBox1.Clear(); textBox2.Clear(); textBox3.Clear();

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

}

private void button1_Click(object sender, EventArgs e)

{ // ЧТЕНИЕ БИНАРНОГО ФАЙЛА.

// Если такого файла нет

if (File.Exists(@"C:\student.usp") == false) return;

// Создание потока Читатель

var Читатель = new BinaryReader(File.OpenRead(@"C:\student.usp"));

try

{

int Номер_пп = Читатель.Readlnt32();

string ФИО = Читатель .ReadString ();

Single СредБалл = Читатель.ReadSingle();

textBox1.Text = Convert.ToString(Номер_пп);

textBox2.Text = Convert.ToString(ФИО);

textBox3.Text = Convert.ToString(СредБалл);

}

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

}

private void button2_Click(object sender, EventArgs e)

{ // ЗАПИСЬ БИНАРНОГО ФАЙЛА.

// Создаем поток Писатель для записи байтов в файл

BinaryWriter Писатель = new BinaryWriter(

File.Open(@"C:\student.usp", FileMode.Create));

try

{

int Номер_пп = Convert.ToInt32(textBoxl.Text);

string ФИО = Convert.ToString(textBox2.Text);

Single СредБалл = Convert.ToSingle(textBox3.Text);

Писатель.Write(Номер_пп);

Писатель.Write(ФИО);

Писатель.Write(СредБалл);

}

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

}

}

}

Как видно, сразу после выполнения процедуры InitializeComponent организована инициализация (присвоение начальных значений) элементам формы: текстовых полей, меток и кнопок. Запись файла на диск происходит при обработке события button2 .Сlick, т. е. щелчок мышью на кнопке Сохранить