Глава 5. Вывод текстовой информации
Параграф 1. Вывод текстовой информации в контрол LabelДля вывода текстовой информации наиболее часто применяются контролы Label и TextBox, которые мы уже использовали в параграфе "Простейший Windows Application проект". Контрол TLabel предназначен для вывода однострочной текстовой информаци и имеет стандартный набор свойств и методов, большинство из которых прозрачны или описаны в предыдущих параграфах. Отметим, что в контрол можно помещать не только текст, но, чего нет в Delphi и Borland C++ Builder, и рисунки, аналогично, как это мы делалали для кнопок - он имеет такойже набор свойств(Image, ImageAlign, ImageList). Интересным является свойство UseMnemonic, позволяющее определить, как будет интерпретироваться символ амперсанда (&), размещенный в свойстве Text. Если установлено значение True, то амперсанд из текста удаляется, а символ, перед которым он расположен, подчеркивается. Эта возможность применяется для определения клавиш быстрого доступа для выбора именно контрола Label - пользователь может комбинацией клавиш <А1t>+<подчеркнутая клавиша в метке> устанавливать фокус на контрол, а затем, используя клавишу Tab, на контрол, следующий по таб номеру за контролом Label. Например, если в форме расположено несколько контролов, среди которых имеется текстовое поле, в которое необходимо перейти нажатием клавиши быстрого доступа, то достаточно установить свойства Tabindex метки и текстового поля так, чтобы для метки это значение было на единицу меньшее, чем у текстового поля. Теперь, в программе, Вы можете выбрать клавишами быстрого доступа метку и, далее, нажать клавишу Tab - будет выбрано текстовое поле для ввода информации. Вывод текста в контрол не вызывает трудностей, для этого контрол имеет свойство Text: label1.Text="My Text"; Параграф 2. Вывод текстовой информации в контрол TextBox2.1. Основные свойства TextBoxКонтрол TextBox мы пока использовали для ввода и вывода однострочного текста, однако он болле предназначен именно для ввода и вывода многострочного текста. Для этого у него есть свойство Multiline, которое должно быть установлено в True. Cвойства AcceptsTab и AcceptsReturn определяют действие при нажатии клавиш Tab и Enter, при False (по умолчанию) и при нажатии Tab или Enter осуществляется переход фокуса к следующему по TabIndex контролу, при True - клавиши выполняют основное свое назначение - вставка разрыва табуляции и перевод строки соответственно. Cвойство AutoSize определяет, нужно ли автоматически изменять размеры конрола, чтобы в нем можно было разместить его содержимое. Свойство CharacterCasing определяет регистр в котором будут отображаться техт в контроле. Свойство HideSelection целесообразно установить в False - в противном случае выделенный программно текст не будет отображаться. Свойство Locked определяет может ли пользователь изменять свойства TextBox программно. Свойство ScrollBars показывает положение полос прокрутки - при Both полоса прокрутки появляется при выходе текста за соответствующую границу. Свойство PasswordChar (работает только при Multiline=false) не дает возможности просматривать вводимые символы, заменяя их на привычные для ввода пароля звездочки или другой символ, указанный в этом поле. Свойство WordWrap при True разрешает перенос текста на новую строку при ширене строки текста более ширины окна. 2.2. Программный вывод текста в TextBoxСоздадим проект решения для вывода текстовой информации с контролом TrxtBox, показанный на Рис.1.
Рис.1. Проект решения для вывода текстовой информации Создание кнопочной панели, меню и панели статуса уже рассмотрены в предыдущих параграфах раздела, поэтому здесь приводятся лиш коды обработчиков событий для кнопок. У кнопок установлено свойство Tag соответственно в 1, 2 и 3 и события MouseHover и MouseLeave для всех кнопок замкнуты на toolStripButton1_MouseHover и toolStripButton1_MouseLeave. Для вывода подсказок использован контрол toolStrip, а для вывода подсказок в панель статуса StatusStrip и соответствующий код (все тонкости описаны в предыдущих параграфах). private void toolStripButton1_MouseHover(object sender, EventArgs e) { int i = Convert.ToInt32((sender as ToolStripButton).Tag); switch (i) { case 1: toolStripStatusLabel1.Text = "Output Text"; break; case 2: toolStripStatusLabel1.Text = "Delete String"; break; case 3: toolStripStatusLabel1.Text = "Close Form"; break; } } private void toolStripButton1_MouseLeave(object sender, EventArgs e) { toolStripStatusLabel1.Text = ""; } Прежде чем выводить текст программно, нажмем кнопочку с тремя точками в свойстве Lines (вызов String Coleection Editor) и выведем несколько строк текста с клавиатуры. После нажатия кнопочки OK видим, что текст появился в окне контрола и в свойстве Text. Это говорит о том, что текст можно выводить как в свойство Text, так и использовать свойство Lines (String[] Array). Обратим внимание, что в свойстве Text присутствуют два нечитаемых символа - это \r и \n - перевод строки и возврат каретки. К сожалению, из за этого, придется при редактировани текста учитывать наличие этих символов. У свойства Lines нет методов Add и Delete для строк, что также создает дополнительные трудности при редактировании текста. Перед началом манипулирования с текстом определим статическую переменную viNom в декларационной части кода: public partial class Form1 : Form { private static int viNom=0; ..... Следующие коды обработчиков событий нажатия для кнопок показывают возможности редактирования многострочного текста. Раскоментируйте интересующий Вас способ. toolStripButton1_Click(object sender, EventArgs e) { ////Вывод текста в одну строку //textBox1.Text+=" Text "+(Convert.ToInt32(viNom)).ToString(); viNom++; ////Первый способ вывода многострочного текста //textBox1.Text+="Строка "+(Convert.ToInt32(viNom)).ToString()+"\r\n"; //viNom++; //textBox1.Text += "Строка " + (Convert.ToInt32(viNom)).ToString() + "\r\n"; ////Второй способ вывода многострочного текста //textBox1.AppendText("Строка "Convert.ToString(viNom)+"\r\n"); //viNom++; //textBox1.AppendText("Строка " + Convert.ToString(viNom) + "\r\n"); ////Третий способ вывода многострочного текста //textBox1.Text = "Строка 1" + System.Environment.NewLine + "Строка 2"; ////Четвертый способ вывода многострочного текста //(требует подключения using System.IO) //System.IO.StringWriter writer = new System.IO.StringWriter(); //writer.WriteLine("Строка 1"); //writer.WriteLine("Строка 2"); //textBox1.Text += writer.ToString(); ////Пятый способ вывода многострочного текста //textBox1.Lines = new string[]{"Строка 1", "Строка 2"}; //Добавляем строку к любому методу //textBox1.AppendText(Environment.NewLine+"Строка 3"); } private void toolStripButton2_Click(object sender, EventArgs e) { string sLine; String sSearchString; try { sSearchString=textBox1.Lines[0].ToString(); } catch { //Удалять нечего return; } //Отобразим в заголовке окна удаляемый текст this.Text=sSearchString; //Можно удалить все //textBox1.SelectAll(); //textBox1.Cut(); //Если знаем, что удалять будем именно первую строку textBox1.SelectionStart = 0; //Длина +2 - запас на \r\n textBox1.SelectionLength=sSearchString.Length+2; if(textBox1.SelectionLength > 0) { MessageBox.Show(this, "Есть выделенный текст он = "+textBox1.SelectedText); //И далее просто удалить textBox1.Cut(); } //Если удалить надо по содержимому sSearchString="Строка 2"; int index=-1; for(int i=0;i < textBox1.Text.Length-sSearchString.Length;i++) { index = textBox1.Text.IndexOf(sSearchString,i,sSearchString.Length); if(index != -1) break; } if(index != -1) { //Можно выделить и так textBox1.Select(index,index+sSearchString.Length+2); textBox1.Cut(); } } private void toolStripButton3_Click(object sender, EventArgs e) { Application.Exit(); } Нажимаем F5 и можем добавлять и удалять строки в TextBox.
Рис.2. Демонстрация добавления и удаления строк Удалять строки можно и так (ровно как добавлять и вставлять): if(textBox1.Lines.Length > 0) { string[] vsS = textBox1.Lines; string[] vsS1 =new string[vsS.Length-1]; textBox1.Text = ""; //Удаляем нулевую строку for(int i=0; i < vsS.Length-1; i++) { vsS1[i]=vsS[i+1]; } textBox1.Lines = vsS1; } else { //Удалять нечего return; } Параграф 3. Ввод/Вывод текстовой информации в контрол TextBox из/в файл(а)3.1. Классы для работы с текстовыми файламиДля работы с текстовыми файлами удобно использовать потоки и класс потоков, наследника класса Stream - Класс FileStream. Класс FileStream используется для чтения и записи файлов. Его можно использовать для чтения и записи байтов, символов, строк и других типов данных. Класс FileStream поддерживает синхронное и асинхронное открытие файлов, синхронные операции чтения и записи (методы Read и Write), а также асинхронные операции чтения и записи (методы BeginRead и BeginWrite). Асинхронные операции завершаются вызовом методов EndRead и EndWrite соответственно. Режим по умолчанию - синхронный. Для проверки режима используемтсясвойство класса IsAsync. Для асинхронных операций необходим объект WaitHandle. Метод Seek используется для произвольного доступа к файлам. Свойство Position позволяет нам узнать или установить текущую позицию в потоке. Методы Lock и Unlock служат для предотвращения доступа ко всему файлу или к его части, а также для отмены ранее установленного запрета доступа. Свойство Length возвращает длину потока в байтах, а метод SetLength служит для задания длины потока. Методы ReadByte и WriteByte используются для чтения и записи одного байта. Для других примитивных типов необходимы классы BinaryReader и BinaryWriter соответственно. Удобно использовать для работы с текстовыми файлами в дополнение к классу FileStream классы TextReader, TextWriter StreamReader, StreamWriter, StringReader и StringWriter. Класс TextReader используется для чтения последовательности символов из ассоциированного потока. Этот класс служит основой для двух других классов: StreamReader и StringReader. Класс TextReader содержит следующие методы:
Класс TextWriter служит для записи последовательности символов в поток. Класс StreamReader применяется для чтения последовательности символов из файла или другого потока. Его можно использовать для чтения текстового файла построчно и как одну строку. Класс StringReader позволяет выполнить чтение символов из строк. StreamReader и StringReader для чтения строки из текстового файла и чтения символов из этой строки как из потока: Класс StreamWriter применяется для вывода последовательности символов в той или иной кодировке. По умолчанию используется экземпляр класса UTF8Encoding для записи символов в кодировке Unicode UTF-8. Существует несколько перегруженных конструкторов, позволяющих указать поток, кодировку по умолчанию, задать кодировку, размер буфера и тип операции: требуется перезаписать существующий файл или информация должна быть к нему добавлена. Свойство Flush служит для указания, следует ли записывать содержимое буфера в поток после каждого вызова методов Write и WriteLine. Класс StringWriter используется для записи строки, которая хранится в классе StringBuilder, реализованном в пространстве имен System.Text. 3.2. Ввод/Вывод текстовой информацииПокажем возможные способы использования перечисленных классов для ввода и вывода информации в TextBox. Используем для реализации проект решения из предыдущего параграфа. Для чего уберем имеющийся код из обработчиков toolStripButton1_Click и toolStripButton2_Click. При желании можем изменить тексты подсказок и картинки для button1 и button2 и заглавие проекта. В обработчики нажатия кнопок toolStripButton2_Click и toolStripButton2_Click запишем следующий код: // ЗАПИСЬ В ФАЙЛ СОДЕРЖИМОГО textBox1 private void toolStripButton1_Click(object sender, EventArgs e) { //Создаем поток для записи в файл и загружаем в него файл //при отсутствии файла он будет создан FileStream filestream = new FileStream("a.txt",FileMode.OpenOrCreate,FileAccess.Write); //Очищаем поток filestream.SetLength(0); //StreamWriter создаем для потока filestream StreamWriter streamwriter = new StreamWriter(filestream); //Записываем текст, введенный в textBox1 в файл streamwriter.Write(textBox1.Text); //Освобождаем ресурсы streamwriter.Flush(); streamwriter.Close(); filestream.Close(); } //ЧТЕНИЕ СОДЕРЖИМОГО ФАЙЛА И ВЫВОД В textBox1 private void button2_Click(object sender, EventArgs e) { string sFileText; FileStream filestream = new FileStream("a.txt", FileMode.OpenOrCreate,FileAccess.Read); //StreamReader создаем для потока filestream StreamReader streamreader = new StreamReader(filestream); //Буфер для прочитанной информации char[] chBuf = new char[filestream.Length]; //Чтения файла в буфер начиная с позиции 0 streamreader.ReadBlock(chBuf,0,(int)filestream.Length); sFileText = new string(chBuf); textBox1.Text+=sFileText; //Освобождаем ресурсы filestream.Close(); streamreader.Close(); } Проверим в заголовке наличие кода using System.IO; : После выполнения программы введенный в контрол TextBox текст будет записан в файл по нажатию toolStripButton1_Click и добавлен к введенному из файла по нажатию toolStripButton2_Click. Следующий код (изменим обработчик для кнопки 2) позволяет вывести текст по линиям. На этом принципе может быть также основан вывод конкретной строки текста. private void toolStripButton2_Click(object sender, EventArgs e) { string sStringText; string sFileName="a.txt"; TextReader textreader = new StreamReader(sFileName); bool fF=false; textBox1.Text=""; while(textreader.Peek() > -1) { sStringText=textreader.ReadLine(); if(fF) textBox1.Text+="\r\n"+sStringText; else textBox1.Text+=sStringText; fF=true; } textreader.Close(); } Когда необходимо чтение всего текста, то код можно упростить. private void toolStripButton2_Click(object sender, EventArgs e) { string sStringText; string sFileName="a.txt"; TextReader textreader = new StreamReader(sFileName); textBox1.Text=""; sStringText=textreader.ReadToEnd(); textBox1.Text+=sStringText; textreader.Close(); } Изменим теперь обработчик для кнопки 1 private void toolStripButton1_Click(object sender, EventArgs e) { string sFileName="a.txt"; StreamWriter streamwriter = new StreamWriter(sFileName); //Первая строка streamwriter.WriteLine("My Strings!!"); //Вторая строка streamwriter.WriteLine(textBox1.Text); streamwriter.Close(); } Теперь при запуске прграммы мы можем ввести какой либо текст в TextBox и, далее, после нажатия последовательно кнопок 1 и 2 его вывести c заголовком ("My Strings!!"). Этот код показывает как можно добавлять строки в текстовый файл. Добавим в заголовок решения строку: //Эта уже добавлена using System.IO; using System.Text; Изменим текст обработчика кнопки 1 для вывода чисел в текстовый файл: private void toolStripButton1_Click(object sender, EventArgs e) { Int64 viI; try { //Открываем файл при true - добавление при false - поток очищается StreamWriter streamwriter = new StreamWriter ("a.txt", false, Encoding.ASCII); for(viI=0; viI < 10; viI++) { //Вывод на одной линии streamwriter.Write(viI); //Вывод каждой цифра на новой линии streamwriter.WriteLine(viI); } streamwriter.Close(); } catch { } Результат после последовательного нажатия кнопок 1 и 2: 00 11 22 33 44 55 66 77 88 99 Параграф 4. Вывод текстовой информации в контрол RichTextBox4.1. Основные свойства RichTextBoxВначале изменим предыдущее решение удалив коды обработчиков событий нажатия Button1 и Button2, удалим контрол TextBox и на его место поместим контрол RichTextBox. Рассмотрим его свойство на страничке Properties. Большинство свойст аналогичны описанным ранее для уже рассмотренных контролов. Рассмотрим те свойства, которых не было у уже использованных нами контролов. Свойство AcceptButton позволяет закрепить кнопку, клик которой будет выполняться при нажатии Enter когда RichTextBox в фокусе (например после ввода). WordSelection если свойство true, пользователь может, двойным щелчком на любой части слова в контроле сделать его выделенным. BulletIndent и SelectionBullet - BulletIndent определяет отступ в пикселях текста перечислений (пунктов списка) от иконки соответствующей пункту списка при значении свойства SelectionBullet=true. Пример из Help С#: private void toolStripButton1_Click(object sender, EventArgs e) { // Очистить все richTextBox1.Clear(); richTextBox1.SelectionBullet = true; // Устанавливаем отступ в пикселях для пунктов списков richTextBox1.BulletIndent = 50; richTextBox1.SelectionFont = new Font("Arial", 16); //Выводим текст на который не влияет установленный //отступ (SelectionBullet=false) richTextBox1.SelectedText = "Ниже список\n"; richTextBox1.SelectionFont = new Font("Arial", 12); //Далее список richTextBox1.SelectionBullet = true; richTextBox1.SelectionColor = Color.Red; richTextBox1.SelectedText = "Яблоко" + "\n"; richTextBox1.SelectionFont = new Font("Arial", 12); richTextBox1.SelectionColor = Color.Orange; richTextBox1.SelectedText = "Апельсин" + "\n"; richTextBox1.SelectionFont = new Font("Arial", 12); richTextBox1.SelectionColor = Color.Purple; richTextBox1.SelectedText = "Виноград" + "\n"; richTextBox1.SelectionBullet = false; richTextBox1.SelectionFont = new Font("Verdana", 10); richTextBox1.SelectedText = "Список закончился\n"; } Результат вывода:
Рис.3. Свойства SelectionBullet и BulletIndent. Свойство DetectUrls позволяет распозновать и выделять интернетовские ссылки и запускать браузер по этой ссылке при наличии в решении кода обработчика события LinkClicked следующего вида (Рис.4.): private void toolStripButton3_Click(object sender, EventArgs e) { richTextBox1.Text = "Мой сайт http:\\wladm.narod.ru"; } private void richTextBox1_LinkClicked(object sender, LinkClickedEventArgs e) { System.Diagnostics.Process.Start(e.LinkText); }
Рис.4. Использование свойства DetectUrls Свойство ZoomFactor позволяет одновременно изменять масштаб вывода текста в RichTextBox в пределах значений 0.64 - 64.0. Свойство Ime Mode задает или возвращает состояние IME (Input Method Editor - IME - редактор способа ввода). Вместе со свойством RightToLeft определяют направление текста и способ его редактирования (свойства не актуальны для европейских языков, в том числе и для русского) - более необходимы при вводах иероглифических текстов на китайском, арабском, корейском и японском языках (при соответствующих Windows). Значение по умолчанию NoControl. Все остальные свойства richTextBox повторяют свойства TextBox. 4.2. Программный вывод текста в RichTextBoxВ начале параграфа мы поместили контрол RichTextBox на форму. Все свойства контрола пока оставим принятые по умолчанию. Свойства остальных контролов оставим без изменения - проект решения выглядит аналогично показанному на Рис.1. При удалении контрола требуется только удалить коды обработчиков нажатия кнопок 1 и 2. Так как свойство Lines у RichTextBox и TextBox, то следует предположить, что ввод и вывод информации в контрол ничем не отличимы в обоих контролах - достаточно заменить имена, как показано далее в обработчиках toolStripButton1_Click и toolStripButton2_Click. private void toolStripButton1_Click(object sender, EventArgs e) { //int viNom = 0; //Вывод текста в одну строку //richTextBox1.Text += " Text " + (Convert.ToInt32(viNom)).ToString(); //viNom++; ////Первый способ вывода многострочного текста //richTextBox1.Text+="Строка "+(Convert.ToInt32(viNom)).ToString()+"\r\n"; //viNom++; //richTextBox1.Text += "Строка " + (Convert.ToInt32(viNom)).ToString() + "\r\n"; ////Второй способ вывода многострочного текста //richTextBox1.AppendText("Строка "Convert.ToString(viNom)+"\r\n"); //viNom++; //richTextBox1.AppendText("Строка " + Convert.ToString(viNom) + "\r\n"); ////Третий способ вывода многострочного текста //richTextBox1.Text = "Строка 1" + System.Environment.NewLine + "Строка 2"; ////Четвертый способ вывода многострочного текста //(требует подключения using System.IO) //System.IO.StringWriter writer = new System.IO.StringWriter(); //writer.WriteLine("Строка 1"); //writer.WriteLine("Строка 2"); //richTextBox1.Text += writer.ToString(); ////Пятый способ вывода многострочного текста //richTextBox1.Lines = new string[]{"Строка 1", "Строка 2"}; //Добавляем строку к любому методу //richTextBox1.AppendText(Environment.NewLine+"Строка 3"); } private void toolStripButton2_Click(object sender, EventArgs e) { string sLine; String sSearchString; try { sSearchString=richTextBox1.Lines[0].ToString(); } catch { //Удалять нечего return; } //Отобразим в заголовке окна удаляемый текст this.Text=sSearchString; //Можно удалить все //richTextBox1.SelectAll(); //richTextBox1.Cut(); //Если знаем, что удалять будем именно первую строку richTextBox1.SelectionStart = 0; //Длина +2 - запас на \r\n richTextBox1.SelectionLength=sSearchString.Length+2; if(richTextBox1.SelectionLength > 0) { MessageBox.Show(this, "Есть выделенный текст он = "+richTextBox1.SelectedText); //И далее просто удалить richTextBox1.Cut(); } //Если удалить надо по содержимому sSearchString="Строка 5"; int index=-1; for(int i=0;i < richTextBox1.Text.Length-sSearchString.Length;i++) { index = richTextBox1.Text.IndexOf(sSearchString,i,sSearchString.Length); if(index != -1) break; } if(index != -1) { //Можно выделить и так richTextBox1.Select(index,index+sSearchString.Length+2); richTextBox1.Cut(); } } Коды обсолютно одинаковы и работают аналогично (Рис.2.). Все отличие контролов в формате текста .rtf и .txt. RichTextBox, как мы это видели при описании свойств контрола, позволяет менять шрифты, и характеристики шрифтов, отступы, использовать интернет ссылки и т.п. Но прежде чем перейти к рассмотрению всех этих возможностей приведем еще один код (подходит и для работы с TextBox), который позволяет удалять строки несколько иначе и показывает, что с RichTextBox это, в отношении хранения информации - такойже массив как и string[]: private void toolStripButton2_Click(object sender, EventArgs e) { string sText; try { sText = richTextBox1.Lines[0]; } catch { //Удалять нечего return; } //sText.Length+1 - для учета перехода на новую строку richTextBox1.Select(richTextBox1.Find(sText),sText.Length+1); //Если HideSelection=true то позволяет увидеть выделенное программно richTextBox1.Focus(); //Удаляем строку richTextBox1.Cut(); string[] sTextLines = richTextBox1.Lines; //Сохраняем строки в массиве for(int i = 0; i < sTextLines.Length; i++) { string sTextLine = sTextLines[i]; sTextLines[i] = sTextLine; } //убираем все строки richTextBox1.Clear(); //Внови помещаем сохраненные в sTextLines строки в RichTextBox richTextBox1.Lines = sTextLines; } 4.3. Использование шрифтов в RichTextBoxИзменим обработчик для кнопки 1 так, чтобы выводимые строки меняли свой шрифт при выводе очередной строки. private void toolStripButton1_Click(object sender, EventArgs e) { richTextBox1.Clear(); string sText1,sText2,sText3,sText4,sText5; for(int i=1; i <= 5; i++) { richTextBox1.Text+="Cтрока "+(Convert.ToInt32(i)).ToString()+ System.Environment.NewLine ; } //Копии введенных строк sText1="Cтрока "+(Convert.ToInt32(1)).ToString(); sText2="Cтрока "+(Convert.ToInt32(2)).ToString(); sText3="Cтрока "+(Convert.ToInt32(3)).ToString(); sText4="Cтрока "+(Convert.ToInt32(4)).ToString(); sText5="Cтрока "+(Convert.ToInt32(5)).ToString(); richTextBox1.Select(richTextBox1.Find(sText1),sText1.Length); richTextBox1.SelectionFont = new Font("Arial", 10,System.Drawing.FontStyle.Regular); richTextBox1.SelectionColor = Color.Red; richTextBox1.Select(richTextBox1.Find(sText2),sText2.Length); richTextBox1.SelectionFont = new Font("Arial", 12,System.Drawing.FontStyle.Underline); richTextBox1.SelectionColor = Color.Blue; richTextBox1.Select(richTextBox1.Find(sText3),sText3.Length); richTextBox1.SelectionFont = new Font("Arial", 14,System.Drawing.FontStyle.Bold); richTextBox1.SelectionColor = Color.Aqua; richTextBox1.Select(richTextBox1.Find(sText4),sText4.Length); richTextBox1.SelectionFont = new Font("Arial", 16,System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic); richTextBox1.SelectionColor = Color.Cyan; richTextBox1.Select(richTextBox1.Find(sText5),sText5.Length); richTextBox1.SelectionFont = new Font("Arial", 18, System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic | System.Drawing.FontStyle.Strikeout); richTextBox1.SelectionColor = Color.Brown; //Убираем выделение richTextBox1.SelectionStart=0; richTextBox1.SelectionLength=0; } Результат выполнения кода представлен на Рис.4.
Рис.5. Задание параметров шрифтов для строк Обратм внимание, что любая попытка добавить текcт обычным образом приведет у тому, что весь текст отобразится шрифтом, установленным в свойстве Font RichTextEdit. В приведенном выше коде показно как добавить составляющую в стиль шрифта. Но соствляющие можно также и убирать. Добавим в конец предыдущего кода фрагмент: FontStyle fs; //Вновь выделяем строку richTextBox1.Select(richTextBox1.Find(sText5),sText5.Length); //Запоминаем стиль шрифта fs=richTextBox1.SelectionFont.Style; //Убираем зачеркивание fs = fs & ~System.Drawing.FontStyle.Strikeout; richTextBox1.SelectionFont = new Font("Arial", 18,fs); richTextBox1.SelectionStart=0; richTextBox1.SelectionLength=0; Результат - перечеркивания в пятой строке исчезло. 4.4. Работа со строками в RichTextBoxВ предыдущем решении мы получили пятистрочный текст, который хорошо подходит для показа того, как можно менять местами, добавлять и удалять строки. Будем добавлять в обработчик нажатия кнопки 1 дополнительные фрагменты, на которых и рассмотрим работу со строками. Отметим сразу, что привычных для программистов методов, напрямую добавляющих, удаляющих или вставляющех строки в C# для RichEditBox, ровно как и для TextBox, нет. Как результат приходится работать через Clipboard. (Наличие метода Insert у свойства Text пусть никого не обольщает, его малая результативность будет показана чуть ниже). Изменим код в обработчике toolStripButton1_Click: private void toolStripButton3_Click(object sender, EventArgs e) { int viNom = 0; richTextBox1.Lines = new string[] { "Строка 1", "Строка 2","Строка 3","Строка 4","Строка 5"}; //Выделяем строку 5 richTextBox1.Select(richTextBox1.Find("Строка 5"), richTextBox1.Lines[4].Length); //Копируем выделенное в буфер richTextBox1.Copy(); //Ищем начало строки viNom = richTextBox1.Find("Строка 2"); //Создаем DataObject тождественный объекту в буфере DataObject dataobject = (DataObject)Clipboard.GetDataObject(); //Выделяем строку richTextBox1.SelectionStart = viNom; richTextBox1.SelectionLength = 0; //Вставляем перед ней строку из буфера richTextBox1.SelectedRtf = (String)dataobject.GetData(DataFormats.Rtf); } Результат видим на Рис.6.(слева). Если вместо строчки кода richTextBox1.SelectionLength=0; вставить richTextBox1.SelectionLength=richTextBox1.Lines[1].Length; Или вообще ее убрать, то строка 5 заместит строку 2 (Рис.6. справа).
Рис.6. Манипулирование строками в RichTextBox Теперь о методе Insert. Рассмотрим фрагмент кода, который добавим в конец фрагмента кода, где мы экспирементировали со шрифтами: string[] srgText = new string[richTextBox1.Lines.Length]; srgText = richTextBox1.Lines; richTextBox1.Clear(); for (int i = 0; i < srgText.Length; i++) { richTextBox1.Text = richTextBox1.Text.Insert(0, srgText[i] + "\r\n"); } Все хорошо (Рис.7.) - строки поменяльсь местами и вставлена строка в нулевую позицию, но все форматирование исчезло. Причина - Text и отформатированный текст не одно и тоже. Текст хранится в свойстве Lines по строчно и в свойстве текст одной строкой, а отформатированный и отображаемый текст в формате Rtf в свойстве SelectedRtf.
Рис.7. Манипулирование строками в RichTextBox Нетрудно посмотреть причину этого - достаточно добавить перед последнем вставленным фрагментом и в конце его код: System.Diagnostics.Debug.WriteLine(richTextBox1.Rtf); и посмотреть результат в окне отладчика и сравнить коды (меню View/Output). Зная формат нетрудно найти все, что было введено при форматировании и потерялось при присвоении. Можно попробовать осуществить манипуляцию строками через посредника, например richTextBox2. System.Windows.Forms.RichTextBox richTextBox2; richTextBox2 = new System.Windows.Forms.RichTextBox(); richTextBox2.Clear(); string sText1=richTextBox1.Lines[1]; richTextBox1.Select(richTextBox1.Find(sText1),sText1.Length); richTextBox2.Font=richTextBox1.SelectionFont; richTextBox2.Text=sText1; richTextBox1.Text= richTextBox1.Text.Insert(0,richTextBox2.Text); Однако и это ничего хорошего не дает - при присвоении теряются форматы всех строк кроме первой, который становится форматом всего текста. 4.5. Файловый ввод/вывод RichTextBoxРассмотрим фрагмент кода, который, как и прежде, поместим в конец кода обработчика toolStripButton3_Click: richTextBox1.SaveFile("a.rtf",RichTextBoxStreamType.RichText); richTextBox1.Clear(); richTextBox1.LoadFile("a.rtf",RichTextBoxStreamType.RichText); При запуске текст пишется из контрола в файл и читается из него в контрол благодаря наличию методов SaveFile и LoadFile. Причем формат тексты сохраняется. Как и большинства функций C# функции SaveFile и LoadFile перегружаемые и можно напрямую указать формат текста, например: richTextBox1.SaveFile("a.rtf",RichTextBoxStreamType.RichText); richTextBox1.LoadFile("a.rtf",RichTextBoxStreamType.RichText); Молчанов Владислав 15.07.2004г. Адаптировано к VS 2005 11.11.2006г. Еcли Вы пришли с поискового сервера - посетите мою главную страничкуНа главной странице Вы найдете программы комплекса Veles - программы для автолюбителей, программы из раздела графика - программы для работы с фото, сделанными цифровым фотоаппаратом, программу Bricks - игрушку для детей и взрослых, программу записную книжку, программу TellMe - говорящий Русско-Английский разговорник - программу для тех, кто собирается погостить за бугром или повысить свои знания в английском, теоретический материал по программированию в среде Borland C++ Builder, C# (Windows приложения и ASP.Net Web сайты). |