Как составить программу редактирования

Привет, Хабр! Представляю вашему вниманию перевод статьи «Build Your Own Text Editor» автора Джереми Рутена.

Свой текстовый редактор!

Привет! Это вольный перевод о том, как написать свой никому не нужный текстовый редактор на C.

Итак, что сможет делать наш редактор?

  • Базовые функции редактора (писать, стирать, перемещать «каретку» и т.д.)
  • Искать по ключевому слову
  • Подсвечивать синтаксис

Еще чуть-чуть о реализации редактора:

  • Реализация редактора состоит из чуть больше, чем 1000 строк и одного файла
  • Не имеет зависимостей (кроме, конечно же, системных)

Всего туториал состоит из 184 шагов. Каждый шаг вы будете добавлять, изменять или удалять разные строки кода. На большинстве шагов вы сможете наблюдать за внесенными изменениями просто скомпилировав и запустив программу.

Я попробую объяснить каждый шаг на этом пути, иногда очень подробно. Не бойтесь пропускать теорию, потому что суть в самом написании кода и то, что вы вообще решились на это! Всё, что вы узнаете в процессе — это бонус, будет чему научится просто вводя изменения в код и наблюдая за результатами.

Настройки

Первый шаг, новый файл и всё всё всё с чистого листа…
Для начала убедитесь в том, что ваша среда корректно настроена для вашего ЯП (в нашем случае — для C), а так же вы хотя бы примерно понимаете, как компилировать и запускать вашу программу в этой среде.

К нашему счастью, редактор, который мы напишем не зависит от каких-либо внешних библиотек. Единственное, что нам понадобится, так это компилятор и стандартная библиотека языка C, с которой он и поставляется. Мы так же будем использовать make-скрипт для упрощения команд компиляции. Удостоверьтесь, что у вас есть как и компилятор для C, так и make.

Компилятор языка C

Так как C компилируемый язык, нам нужен, как не странно, компилятор, если у вас его нет, его обязательно нужно установить, как и make. Например, в Ubuntu, это можно сделать так:

sudo apt-get install gcc make

Функция main()

Итак, вот, с чего начинается наш путь! Создайте файл kilo.c и напишите в нем базовую main() функцию.

Шаг 1

int main() {
    return 0;
}

Для компиляции этого файла, достаточно ввести cc kilo.c -o kilo в ваш терминал. Если ошибок не последовало, в текущей директории появится исполняемый файл kilo. Что бы запустить программу, введите ./kilo. К сожалению, пока наша программа ничего не умеет, поэтому ничего нам не напечатает.

(не обязательно, что бы ваш редактор назывался так же, как и в статье, вы вполне можете назвать свой редактор «uber_mega_super_redaktor1337» другим эстетичным названием)

Упрощение компилирования с make

Каждый раз печатать что то вроде cc kilo.c -o kilo надоедает, поэтому мы и напишем make скрипт.

Создайте новый Makefile с подобным содержимым:

Шаг 2

kilo: kilo.c
    $(CC) kilo.c -o kilo -Wall -Wextra -pedantic -std=c99

Первая линия Makefile-а говорит нам о том, что мы хотим скомпилировать и то, что нам для этого потребуется. Вторая линия определяет команду, которую будет выполнять make скрипт. $(CC) обычно ссылается на команду cc.

Что это за магические слова появились?
Это флаги, а именно:

  1. -Wall — от английского «all Warnings», что говорит компилятору выводить почти все предупреждения, если ему что то не очень нравится.
  2. -Wextra и -pedantic просит компилятор выводить еще больше предупреждений, если такие имеются.
  3. -std=c99 показывает компилятору, какую версию стандарта языка C ему использовать при компилировании. Стандарт C99 немного упростит нам процесс написания кода.

Теперь, когда Makefile настроен, попробуйте написать команду make в ваш терминал для компиляции программы. Запустить её можно так же, как и всегда, ./kilo.

Продолжение следует…

Рассмотрим пример проектирования стандартного оконного приложения. Простейшая последовательность действий:
1) визуальное проектирование интерфейса (перенос на форму с Панели элементов необходимых визуальных и не визуальных элементов);
2) генерация заготовок методов обработки событий, связанных с элементами управления;
3) программирование методов обработки событий.

Постановка задачи

Создать текстовый редактор с обязательными функциями работы с файлами  «Открыть» и «Сохранить как», а также функциями редактирования текста. Выбор действий с файлами осуществлять через главное меню.

Реализация

Разместим на форме визуальный элемент textBox1 класса TextBox. Размер элемента сделайте чуть меньше размера формы, сместив его вниз от заголовка на 30-40 пикселей. Задайте свойство textBox1.MultiLine = true (для редактирования текста в несколько строк).

Перетащите с Панели элементов компонент menuStrip1 класса MenuStrip для создания меню.В левом верхнем углу рабочей области формы появится кнопка «Введите здесь» , а на панели невизульных компонентов отобразится элемент menuStrip1.

Для выбора имен файлов для их чтения и записи перетащим на эту же панель элементы openFileDialog1 (класс OpenFileDialog) и saveFileDialog1 (класс SaveFileDialog).

Кликнув по кнопке «Введите здесь», введите имя раздела меню «Файл» и добавьте ниже следующие пункты меню работы с файлами «Открыть», «Сохранить как» и «Выход». Ваша форма (вместе с панелью невизуальных элементов) будет выглядеть примерно так:
Примечание: для наглядности изменено свойство формы BackColor = Color.Peru. Первая группа действий закончена.

Вторая группа действий обеспечивает генерацию  заголовков методов обработки событий, связанных к кнопками меню. Для этого дважды нажмите каждую из трех позиций меню, а также событию Load формы Form1 на закладке «События» панели «Свойства» поставьте в соответствие метод Form1_Load (двойной клик справа от в строке Load).

Откроем форму в режиме Кода (файл Form1.cs):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ТекстовыйРедактор
{
   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
      }

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

      }

      private void сохранитьКакToolStripMenuItem_Click(object sender,      EventArgs e)
      {

      }

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

      }

      private void Form1_Load(object sender, EventArgs e)
      {

      }
   }
}

Перейдем к третьей группе действий — написанию кода для этих четырех методов.

Метод Form1_Load( ) используем для очистки поля компонента textBox1, для задания форматов файловых диалогов и имени файла — контрольного примера при его открытии:

private void Form1_Load(object sender, EventArgs e)
{
   textBox1.Clear();
   openFileDialog1.FileName = @"dataText2.txt";
   openFileDialog1.Filter =
            "Текстовые файлы (*.txt)|*.txt|All files (*.*)|*.*";
   saveFileDialog1.Filter =
            "Текстовые файлы (*.txt)|*.txt|All files (*.*)|*.*";
}

Комментарий. При загрузке формы мы задаем свойство FileName объекта openFileDialog1 указанием имени файла для открытия, а также задаем фильтры для диалогов открытия и сохранения файлов.  Сравните работу программы без использования этого метода.

В методе  открытьToolStripMenuItem_Click( ) используется  компонент openFileDialog1 для выбора имени файла для чтения. Если имя не выбрано (FileName = String.Empty), то работа метода завершается. Иначе создается новый экземпляр класса System.IO.StreamReader (var Читатель) с указанием имени файла и кодировки, данные из текстового файла переносятся в textBox1, объект Читатель закрывается. Добавлена обработка исключений,  которые могут возникнуть при открытии файла:

private void открытьToolStripMenuItem_Click(object sender, EventArgs e)
{
   openFileDialog1.ShowDialog();
   if (openFileDialog1.FileName == String.Empty) return;
   // Чтение текстового файла
   try
   {
      var Читатель = new System.IO.StreamReader(
      openFileDialog1.FileName, Encoding.GetEncoding(1251));
      textBox1.Text = Читатель.ReadToEnd();
      Читатель.Close();
   }
   catch (System.IO.FileNotFoundException Ситуация)
   {
      MessageBox.Show(Ситуация.Message + "nНет такого файла",
               "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
   }
   catch (Exception Ситуация)
   { // отчет о других ошибках
      MessageBox.Show(Ситуация.Message,
           "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
   }
}

Аналогично выполняется запись (сохранение) текстового файла:

private void сохранитьКакToolStripMenuItem_Click(object sender,EventArgs e)
{
   saveFileDialog1.FileName = openFileDialog1.FileName;
   if (saveFileDialog1.ShowDialog() == DialogResult.OK)
   {
      try
      {
         var Писатель = new System.IO.StreamWriter(
         saveFileDialog1.FileName, false,              
                             System.Text.Encoding.GetEncoding(1251));
         Писатель.Write(textBox1.Text);
         Писатель.Close(); 
     }
     catch (Exception Ситуация)
     { // отчет о других ошибках
          MessageBox.Show(Ситуация.Message,
              "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
     }
  }
}

Последний метод — закрытие формы — реализуется одним оператором:

private void выходToolStripMenuItem_Click(object sender, EventArgs e)
{
   this.Close();
}

Подготовим в блокноте текстовый файл Text2.txt и разместим его в подкаталоге data папки, где будет размещено ваше приложение.  Запустим программу на выполнение.   Добавьте в окне редактора несколько строк, сохраните файл с другим именем. Откройте новый файл и удалите часть текста в окне редактора.

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

ВЫВОД: В первом приближении поставленная задача решена. Данный пример приведен всего лишь для понимания:
во-первых,  алгоритма действий разработчика визуального приложения  «интерфейс, события-методы, реализация»;
во-вторых, удобства использования готовых компонентов (нам не пришлось программировать операции редактирования текста — стандартные события уже привязаны к компоненту textBox1);
в-третьих, целесообразности использования готовых компонентов (файловых диалогов) с точки зрения стандартизации интерфейса пользователя и программы.

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


NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.


Помощь проекту:

Предлагаем вашему вниманию серию англоязычных статей, опубликованную в блоге Джереми Рутена. В ней подробно разбирается процесс разработки собственного текстового редактора на языке C.

Проект занимает примерно тысячу строк кода и не использует никаких зависимостей. Для удобства и лучшего понимания весь процесс разбит на 184 шага. По прохождении каждого этапа вы сможете скомпилировать проект и увидеть все изменения. Исходный код каждого шага доступен на GitHub.

Статьи написаны простым, понятным даже начинающим программистам языком. Все термины либо объясняются в статье, либо снабжены ссылками на другие Интернет-ресурсы.

Реализация этого проекта однозначно будет вам полезна: во-первых, вы сможете освоить или подтянуть знания по языку C, а во-вторых, разберётесь в основных принципах работы текстовых редакторов.

Итак, вот список статей:

  1. Настройка.
  2. Переход в «сырой» режим.
  3. «Сырой» ввод и вывод.
  4. Отображение текста.
  5. Редактор текста.
  6. Поиск.
  7. Подсветка синтаксиса.
  8. Примечания.

Если вам хочется написать ещё какой-нибудь проект самостоятельно, советуем обратить внимание на серию статей, посвящённую созданию ОС на ассемблере и Rust.

Сделать собственный текстовый редактор гораздо проще, чем кажется. Сейчас мы соорудим такой, и вы сами в этом убедитесь.

В этой статье мы соберем текстовый редактор, который будет работать в браузере. В помощь нам три технологии:

  • JavaScript — язык, на котором всё будет работать. Это не лучший язык для полноценных приложений, но с ним вы сможете запрограммировать текстовый редактор прямо в браузере.
  • Contenteditable — возможность языка HTML делать какие-то части страницы редактируемыми. Обычно со страницы можно только читать, но благодаря этому свойству можно еще и писать.
  • Localstorage — особая область памяти, которая позволяет сохранить что-нибудь для конкретной страницы в браузере. Ваш браузер будет помнить, что вы ввели конкретно в этой странице. Это самая интересная часть.

Общая идея

У нас будет HTML-страница, на ней будет блок, похожий на лист бумаги. У него будет включен content editable, то есть внутри этого блока можно будет что-то писать. После каждого нажатия клавиши содержимое этого блока будет записываться во внутреннюю память браузера.

Вторая часть алгоритма — при загрузке страницы взять из памяти тот текст, что там был раньше, и показать его в нашей текстовой области. Страницу можно обновлять как угодно и даже выключать компьютер — текст всё равно останется в памяти.

Если записать алгоритм кратко, то он будет выглядеть так:

  1. Достаём из памяти тот текст, который там был
  2. Выводим его в нашу область для редактирования
  3. Постоянно смотрим, нажата ли какая-нибудь клавиша
  4. Если нажата — сразу записываем изменения в память.

Пункты 3 и 4 выполняются непрерывно до тех пор, пока вы не закроете страницу.

Готовим каркас

Пойдём уже привычным способом и создадим новый HTML-файл, в котором будут прописаны все нужные блоки. Мы так уже делали в статьях про генератор паролей и спортивный таймер.

<!DOCTYPE html>
<html>
<!-- служебная часть -->

<head>
  <!-- заголовок страницы -->
  <title>Текстовый редактор</title>
  <!-- настраиваем служебную информацию для браузеров -->
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- задаём CSS-стили прямо здесь же, чтобы всё было в одном файле -->
  <style type="text/css">
  </style>
  <!-- закрываем служебную часть страницы -->
</head>
<!-- началось содержимое страницы -->

<body>
  <!-- пишем скрипт, который будет постоянно сохранять наш текст -->
  <script>
  </script>
  <!-- закончилось содержимое страницы -->
</body>
<!-- конец всего HTML-документа -->

</html>

Сохраняем как html-файл, открываем его в браузере и видим пустой экран. Это нормально, сейчас будем наполнять.

Расставляем содержимое

Нам нужен только заголовок, который объяснит нам, где мы находимся, и большое пространство для ввода текста. За текстовое поле будет отвечать блок <div> со свойством contenteditable. Это свойство разрешает редактировать текст в блоке как угодно.

Разместим это в разделе <body>:

<!-- заголовок страницы -->
<h2>Текстовый редактор с автосохранением</h2>
<!-- большой блок для ввода текста: высота в половину, а ширина — во весь экран, назвывается "text_area", обведено рамкой толщиной в 1 пиксель, выравнивание текста — по левому краю -->
<div id="editor" contenteditable="true"
  style="height: 50%; width: 100%; border: solid; border-width: 1px; text-align: left">
</div>

Настраиваем стили

Стили задают внешний вид страницы и любых элементов на ней. Сделаем наш заголовок опрятнее:

/*задаём общие параметры для всей страницы: шрифт и отступы*/
body {
  text-align: center;
  margin: 10;
  font-family: Verdana, Arial, sans-serif;
  font-size: 16px;
}
/*закончили со стилями*/

Сохраняем, обновляем и смотрим на результат:

Пишем скрипт

Теперь нужно научить редактор сначала извлекать из памяти прошлый текст, а потом снова запоминать каждое нажатие клавиши. Всё будем делать через localStorage, как с ним работать — рассказываем в статье про список задач.

// если в нашем хранилище уже что-то есть…
if (localStorage.getItem('text_in_editor') !== null) {
  // …то отображаем его содержимое в нашем редакторе
  document.getElementById('editor').innerHTML = localStorage.getItem('text_in_editor');
}
// отслеживаем каждое нажатие клавиши и при каждом нажатии выполняем команду
document.addEventListener('keydown', function (e) {
  // записываем содержимое нашего редактора в хранилище
  localStorage.setItem('text_in_editor', document.getElementById('editor').innerHTML);
});

Кладём это в раздел <script> и смотрим, что получилось:

Общий код страницы

<!DOCTYPE html>
<html>
<!-- служебная часть -->

<head>
  <!-- заголовок страницы -->
  <title>Текстовый редактор</title>
  <!-- настраиваем служебную информацию для браузеров -->
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- задаём CSS-стили прямо здесь же, чтобы всё было в одном файле -->
  <style type="text/css">
    /*задаём общие параметры для всей страницы: шрифт и отступы*/
    body {
      text-align: center;
      margin: 10;
      font-family: Verdana, Arial, sans-serif;
      font-size: 16px;
    }

    /*закончили со стилями*/
  </style>
  <!-- закрываем служебную часть страницы -->
</head>
<!-- началось содержимое страницы -->

<body>
  <!-- началась видимая часть -->
  <!-- заголовок страницы -->
  <h2>Текстовый редактор с автосохранением</h2>
  <!-- большой блок для ввода текста: высота в половину, а ширина — во весь экран, назвывается "text_area", обведено рамкой толщиной в 1 пиксель, выравнивание текста — по левому краю -->
  <div id="editor" contenteditable="true"
    style="height: 50%; width: 100%; border: solid; border-width: 1px; text-align: left">
  </div>
  <!-- закончилась видимая часть -->
  <!-- пишем скрипт, который будет постоянно сохранять наш текст -->
  <script>
    // если в нашем хранилище уже что-то есть…
    if (localStorage.getItem('text_in_editor') !== null) {
      // …то отображаем его содержимое в нашем редакторе
      document.getElementById('editor').innerHTML = localStorage.getItem('text_in_editor');
    }
    // отслеживаем каждое нажатие клавиши и при каждом нажатии выполняем команду
    document.addEventListener('keydown', function (e) {
      // записываем содержимое нашего редактора в хранилище
      localStorage.setItem('text_in_editor', document.getElementById('editor').innerHTML);
    });
 // закончился скрипт
  </script>
  <!-- закончилось содержимое страницы -->
</body>
<!-- конец всего HTML-документа -->

</html>

В следующих сериях

Сделаем нашему редактору приличный внешний вид — чтобы был похож на лист бумаги с тенью.

Добавим возможность менять документы и создавать новые.

Добавим каждой заметке заголовок.

Подписывайтесь на наши соцсети, и как только выйдет новая версия, мы вам расскажем.

вот все необходимое.

Тема: Создание системы главного и контекстного меню в Delphi

Цели:
обучающая: закрепить знания о главном и контекстном меню; научиться создавать систему главного и контекстного меню
развивающая: развитие логического мышления, повышение познавательной активности
воспитательная: воспитание у учащихся постоянной потребности в самосовершенствовании и самообразовании, умения работать в коллективе
методическая: совершенствование приемов развивающего обучения путем применения различных видов опроса и закрепления

Разработка приложения «Редактор текстов»

На примере разработки приложения «Редактор текстов» рассмотрим использование на форме невизуальных и неоконных компонентов, а также порядок проектирования главного меню, всплывающего меню и панели инструментов.
Разрабатываемое приложение должно обеспечить:
• отображение существующего текстового файла в окне редактирования или создание нового файла;
• выполнение простейших операций по редактированию: вставка-удаление символов, копирование и перемещение фрагментов текста с использованием Системного буфера обмена (ClipBoard);
• сохранение результатов редактирования в том же или ином файле.
Рассмотрим последовательно этапы разработки приложения.

Первый этап – проектирование интерфейса. Главное окно приложения будет содержать следующие визуальные компоненты:
• главное меню, расположенное в верхней части окна;
• панель инструментов, расположенную сразу под строкой Главного меню;
• область для отображения и редактирования текстов, которая должна занимать всю оставшуюся часть главного интерфейсного окна;
• «всплывающее» меню, которое должно появляться при нажатии правой кнопки мыши в области редактирования.
Главное меню. Для организации выполнения перечисленных действий построим Главное меню приложения.
Разобьем функции приложения на две группы – «Файл» и «Редактировать». Эти две группы и представляют собой опции Главного меню.
В группу «Файл» войдут функции «Создать», «Открыть», «Сохранить», «Сохранить как…» и «Выход». Опция меню «Файл» должна объединять соответствующие пункты меню, представляющие собой команды, вызывающие выполнение перечисленных функций.
В группу «Редактировать» — функции «Врезать», «Копировать» и «Вставить».
Дизайнер меню. Компонент Главного меню располагается на странице «Стандартные» Палитры компонентов. Установим компонент на форме и вызовем Дизайнер меню. Это можно сделать либо через свойство Items компоненты Главного меню, либо с помощью контекстного меню, вызвав его на форме.
Каждый пункт меню вводится с помощью Дизайнера, а затем отображается в строке меню на форме. При вводе нового пункта на самом деле создается новый компонент и добавляется в список компонентов Инспектора объектов (хотя визуально на форму ничего не добавляется). В свойствах компонента обязательно заполняются поля Caption – название пункта, Name – имя компонента и, если необходимо, поля ShortCut – «горячая клавиша» для вызова функции с помощью клавиатуры и Bitmap – для добавления пиктограммы к заголовку пункта.
Для удобства восприятия команды меню визуально разбиваются на группы с помощью добавления в меню специальных пунктов-разделителей. Чтобы ввести такой пункт, достаточно в свойстве Caption установить знак «-» (дефис).
Панель инструментов. Следующий этап проектирования формы – размещения Панели инструментов. Панель инструментов предназначена для дублирования наиболее часто использующихся команд меню графическими кнопками, что обеспечивает более быстрый способ вызова функций.
Начиная с версии 3, в Delphi появился специальный компонент ToolBar (страница «Win32» Палитры компонентов), предоставляющий готовую панель инструментов со своими собственными кнопками. Компонент ToolBar инкапсулирует соответствующий стандартный элемент управления Windows.
Разместим компонент на форме и зададим значения некоторым свойствам (помимо свойства Name). Значение alTop свойства Algin определяет положение панели инструментов на форме — в верхней части, сразу под строкой Главного меню. Установка свойства Flat в true задает особый стиль изображения кнопок панели – без прорисовки контура (контур появляется только у кнопки, на которую указывает курсор).
Сначала размещенная на форме панель инструментов пуста. Добавление кнопок осуществляется с помощью всплывающего контекстного меню компонента: для добавления кнопки используется команда New Button, а для добавления разделителя – команда New Separator.
Компонент ToolBar содержит объекты класса TToolButton. Это внутренние объекты (аналогично объектам класса TMenuItem, которые являются внутренними для объекта MainMenu).
Далее для каждой кнопки задается рисунок – пиктограмма, соответствующая функциональному назначению кнопки. Определение рисунков для кнопок панели инструментов осуществляется с помощью невизуального компонента ImageList. Этот компонент не имеет своего места на форме и предназначен для создания коллекции рисунков, выбор которых происходит по индексу – номеру рисунка в коллекции.
Имя компонента заносится в свойство Image Панели инструментов и, таким образом, обеспечивается связь каждой отдельной кнопки панели с соответствующей картинкой.
Коллекция рисунков ImageList. Для создания коллекции рисунков на форму добавляется компонент ImageList ( страница «Win32» Палитры компонентов). Контекстное меню компонента позволяет вызвать Редактор ImageList, с помощью которого проводятся действия по добавлению и удалению рисунков коллекции.
Каждый добавленный рисунок получает в коллекции свой индекс и может быть в дальнейшем связан с некоторой кнопкой панели инструментов путем занесения значения индекса в свойство ImageIndex кнопки.
На примере кнопки Панели инструментов продемонстрируем использование пары свойств ShowHint и Hint для формирования «всплывающих» подсказок. Установка свойства ShowHint в True обеспечивает включение аппарата «всплывающей» подсказки для компонента, т.е. появление в специфическом «всплывающем» окне текста, заданного в свойстве Hint, при задержке курсора в области компонента.
Область для отображения и редактирования текстов. Для отображения и редактирования текстовых файлов разместим на форме компонент Memo класса TMemo. Установим значение Client в свойстве Algin компонента, обеспечив тем самым заполнение компонентом всей незанятой части главного интерфейсного окна.
Компонент Memo предназначен для ввода разделенных и не разделенных на строки текстов. При установке свойства WordWrap в True происходит дополнительное разбиение текстов на строки по ширине компонента.
Свойство ScrollBar позволяет установить на области компонента стандартные полосы «прокрутки» текстов: ssVertical – только вертикальная полоса, ccHorizontal – только горизонтальная полоса, ssBoth – обе полосы.
Компонент автоматически поддерживает стандартные функции редактирования – ввод, замену и удаление отдельных символов, а также выделение фрагментов текста.
Приведем фрагмент текстового описания формы для компонента Memo( имя компонента – EditMemo):

Delphi
1
2
3
4
5
6
7
8
9
Object EditMemo:Mеmo
    Left =0;
    Top=25;
    Width=493;
    Height=295;
    Algin=alClient;
    ScroollBar=ssVertical;
    TabOrder=1;
End;

Контекстное меню. Кроме Главного меню обычно ещё используется похожий на него компонент PopupMenu (страница «Стандартные»). Такое меню отображается при нажатии на правую кнопку мыши в области компонента, свойство PopupMenu которого указывает на данное меню. Это стандартный способ использования контекстного меню.
Разместим на форме неоконный компонент PopupMenu и добавим в меню опции из группы команд «Редактирование» Главного меню. Порядок проектирования контекстного меню полностью совпадает с порядком проектирования Главного меню и тоже предполагает использование Дизайнера меню.
Для привязки пунктов контекстного меню к компоненту Memo занесем свойство PopupMenu компонента имя контекстного меню.
Использование стандартных диалогов. Для организации работы с файлами (открытия файлов для редактирования и сохранения результатов) используются компоненты стандартных диалогов Windows, реализованные в среде. Разместим на форме приложения неоконные компоненты OpenDialog и SaveDialog (страница «Dialogs») и рассмотрим возможности их использования на примере компонента OpenDialog (SaveDialog работает похожим образом).
Использование диалоговых компонентов не обеспечивает автоматического открытия или сохранения файлов, но позволяет получить для дальнейшей обработки в программе имя выбранного пользователем файла.
Рассмотрим некоторые свойства компонентов, позволяющие управлять видом и характером действия диалогового окна.
Свойство FileName назначает имя файла по умолчанию (имя, которое будет отображаться в окне «Имя файла» при открытии диалогового окна) содержит имя выбранного пользователем файла.
Свойство DefaultExt позволяет указать расширение имени файла, которое будет добавляться по умолчанию в том случае, если в окне «Имя файла» имя будет указано без расширения.
Свойство Filter задает список файловых масок (файловых фильтров), из которого пользователь может выбирать для отображения в диалоговом окне только нужные типы файлов. Файловый фильтр представляет собой строку, состоящую из одной или более пар значений. Пара значений – это описание фильтра и сам фильтр. Каждая пара значений задает один фильтр. Пары значений и значения внутри одной пары разделяются символом «І». Например, следующая строка задает два фильтра для диалога:
MyOpenDialog.Filter:=’Текстовые файлы (*.txt) І *.txt І Все файлы (*.*)І *.* ’

Второй этап разработки приложения – разработка процедур обработки событий. Рассмотрим последовательно процедуры-обработчики для пунктов Главного меню (обработчики события OnClick для каждого компонента класса TMenuItem).
Пункт Главного меню Файл/Открыть предназначен для организации диалога выбора файла на редактирование. Метод OpenDialog.Execute открывает диалоговое окно, а после нажатия на кнопку «Открыть» в диалоговом окне возвращает значение True и заполняет свойство OpenDialog.FileName, помещая в него имя выбранного в окне диалога файла.
Метод LoadFromFile объекта TString, представляющего свойство Lines компонента EditMemo, позволяет одновременно организовать открытие и чтение файла в область редактирования. Если процесс загрузки файла закончился удачно, изменяется заголовок окна приложения (в него помещается имя открытого файла) и заполняется глобальная переменная CurrentFileName, служащая для хранения имени текущего файла. В случае возникновения ошибки при загрузке файла управление передается в блок обработки исключений и выдается диалоговое окно сообщения.
Приведем текст процедуры:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
Procedure TForm1.MFile_OpenClick(Sender:TObject);
Begin
    If OpenDialog.Execute then 
        Try 
        EditMemo.Lines.LoadFromFile(OpenDialog.FileName);
        Form1.Caption:=Form1.Caption + ‘ – ‘ + OpenDialog.FileName;
        CurrentFileName:=OpenDialog.FileName;
        Except
            On EFOpenError do
            MessageDlg (‘Ошибка при открытии файла’ , mtError,[mbOk],0);
        End;
End;

Пункт Главного меню Файл/Сохранить как… предназначен для сохранения результатов редактирования в файле, имя которому назначает пользователь. При организации процесса сохранения результатов необходимо учесть возможность существования файла с именем, указанным в окне диалога сохранения. В предлагаемой процедуре-обработчике используется стандартная функция FileExists для проверки существования файла и организуется запрос-диалог для принятия решения. Стандартная функция MessageDlg открывает диалоговое окно с тремя управляющими кнопками — [Yes], [No] и [Cancel] и возвращает константу – признак выполненного действия (нажатой кнопки).
В зависимости от принятого пользователем решения выполняется одна из трех последовательности действий: сохранение результатов редактирования с помощью применения метода SaveToFile, симметричного методу LoadFromFile; повторяется диалог назначения имени файла или происходит выход из процедуры-обработчика:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Procedure TForm1.MFile_SaveAsClick(Seder:TObject);
Label 1;
Var     btn: word;
    Fsave:Boolean;
Begin
    If  EditMemo.Text<>’ ‘then
    Begin
    1: if SaveDialog.Execute then
        if FileExists (SaveDialog.FileName) then
        begin
            btn:= MessageDlg(‘Файл существует. Перезаписать?’,
                 mtWarning, [mbYes, mbNo, mbCancel], 0);
            if btn= mrNo then goto 1;
            if btn=mrCancel then fsave:=false;
            if btn=mrYes then fsave:=true;
        end
        else fsave:=true;
        if fsave then
        try 
            EditMemo.Lines.SaveToFile(SaveDialog.FileName);
            CurrentFileName:=SaveDialog.FileName;
            Form1.Caption:=Progcaption +-+ SaveDialod.FileName;
        Except
        On EInOutError do
            MessageDlg(‘Ошибка записи в файл’, mtError, [mbOk], 0);
        End;
End;

Посредством пункта Главного меню Файл/Сохранить результаты редактирования сохраняются в текущем файле, если имя текущего файла не пусто, или происходит вызов процедуры-обработчика для пункта меню Файл/Сохранить как…:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Procedure TForm1.MFile_SaveClick(Sender:TObject);
Label 1;
Var     btn:word;
    Fsave: Boolean;
Begin
    If EditMame.Text<>’ ‘ then 
        If CurrentFileName = ‘ ‘ then MFile_SaveAs.Click
            Else
            Try
            EditMemo.Lines.SaveToFile(CurrentFileName);
            Except
            On EInOutError do
            MessageDlg(‘Ошибка записи в файл’, mtError, [mbOk], 0);
            End;
End;

Обработчики событий пунктов Главного меню из группы «Редактировать» построены на использовании методов работы с Системным буфером обмена. Рассмотрим эти методы, общие для компонентов, поддерживающих процессы редактирования.
Метод CopyToClipboard предназначен для копирования выделенного фрагмента текста в Системный буфер обмена.
Метод CutToClipboard предназначен для удаления из текста выделенного фрагмента и переноса его в Системный буфер обмена.
Метод PasteToClipboard предназначен для вставки текста, содержащегося в Системном буфере обмена, по месту текстового курсора.
Использование этих методов позволяет организовать процедуры редактирования, связанные не только с перемещением фрагментов текста внутри области редактирования, но и обеспечить взаимодействие разрабатываемого приложения с другими, поддерживающими обработку текстовой информации.
Процедуры-обработчики, реализованные для пунктов Главного меню, являются общими и подключаются к соответствующим кнопкам панели инструментов и соответствующим пунктам контекстного меню.



0



Понравилась статья? Поделить с друзьями:
  • Как найти давление газа задача
  • Как найти путь пройденный телом с ускорением
  • Как найти ранее удаленные файлы
  • Как воспользоваться услугой найди айфон
  • Как составить бюджет парка