Асинхронный ввод/вывод
Под «Асинхронным вводом/выводом» в основном понимается возможность процесса выполнять ввод/вывод одновременно из многих источников. В частности асинхронным называют такой ввод/вывод, который производиться в том момент, когда входные данные доступны или выходные буферы свободны для принятия очередной порции данных. Это отличает асинхронных ввод/вывод от блокирующего, при котором операции… Читать ещё >
Асинхронный ввод/вывод (реферат, курсовая, диплом, контрольная)
Министерство образования и науки Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования
«Новгородский государственный университет имени Ярослава Мудрого»
Старорусский политехнический колледж (филиал)
Курсовая работа
по дисциплине «Системное программирование»
АСИНХРОННЫЙ ВВОД/ВЫВОД
Руководитель Шанаев И. Н Студентка группы 22 351
Михайлова А.Г.
Старая Русса
2014 г.
- ВВЕДЕНИЕ
- ФУНКЦИИ АСИНХРОННОГО ВВОДА/ВЫВОДА
- ПРОЦЕДУРЫ DELPHI
- СОЗДАНИЕ БЛОКНОТА НА DELPHI
- ЗАКЛЮЧЕНИЕ
- СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
- ПРИЛОЖЕНИЕ А
ВВЕДЕНИЕ
Под «Асинхронным вводом/выводом» в основном понимается возможность процесса выполнять ввод/вывод одновременно из многих источников. В частности асинхронным называют такой ввод/вывод, который производиться в том момент, когда входные данные доступны или выходные буферы свободны для принятия очередной порции данных. Это отличает асинхронных ввод/вывод от блокирующего, при котором операции чтения/записи пытаются выполняться, невзирая на доступность ресурсов, что типично приводит к блокировкам. Асинхронный ввод/вывод сам по себе несложен, обычно вопрос в том, чтобы одновременно контролировать много каналов, через которые должен выполняться ввод/вывод.
Ввод и вывод всегда выполнялись медленнее других операций. Эта низкая скорость вызвана следующими факторами:
— задержки вследствие поиска дорожки и сектора на устройствах произвольного доступа;
— задержки, вызванные относительно малой скоростью передачи данных между физическим устройством и системной памятью;
— задержки при передаче данных через сеть;
Операции ввода-вывода во многих случаях являются синхронными с потоками. Иными словами, весь поток должен был ждать, пока ввод-вывод не завершится.
Асинхронный ввод/вывод — принципиально новая возможность введена впервые в Win32 с появлением реальной многозадачности. Вызывая функции чтения и записи данных, вы на самом деле передаете исходные данные одному из потоков (threads) операционной системы, который и осуществляет фактические обязанности по работе с устройством. Время доступа всех периферийных устройств гораздо больше доступа к ОЗУ, и ваша программа, вызвавшая Read или write, будет дожидаться окончания операции ввода/вывода. Замедление работы программы налицо.
Асинхронный ввод/вывод не может осуществить ни одна из родных Delphi функций: ни функции FileRead/FileWrite, ни функции, доставшиеся нам от pascal BlockRead/BlockWrite, ни класс TFileStream. Асинхронный ввод/вывод можно осуществить только через API функции.
Рисунок 1. Схема асинхронного ввода/вывода
ФУНКЦИИ АСИНХРОННОГО ВВОДА/ВЫВОДА
Функция CreateFile. С помощью этой функции можно открыть на чтение или запись многие объекты: порты COM, дисковые устройства (для прямой работы с диском), пайпы и т. д.
HANDLE CreateFile (
LPCTSTR lpFileName, // имя файла
DWORD dwDesiredAccess, // тип доступа
DWORD dwShareMode, // параметры общего доступа
LPSECURITY_ATTRIBUTES lpSecurityAttributes,//атрибуты защиты
DWORD dwCreationDistribution, // создавать или открывать
DWORD dwFlagsAndAttributes, // дополнительные атрибуты
HANDLE hTemplateFile // нужен при создании файлов
ПРОЦЕДУРЫ DELPHI
Создание процедуры Delphi является оптимальным решением для разумного использования блока операторов. Нам не нужно каждый раз прописывать блок операторов, а просто написав его один раз, его нужно будет просто вызвать по имени, и он сделает всю работу.
Как будет выглядеть общая схема процедуры будет выглядеть таким образом:
delphi блокнот оператор Рисунок 2. Общая схема процедуры
Описание процедуры состоит из двух основных частей: заголовка и тела процедуры. Заголовок процедуры включает в себя зарезервированное слово procedure, имя процедуры и список формальных параметров. В списке формальных параметров нужно указывать тип этого параметра. Также допускается отсутствие формальных параметров. Имя процедуры — это уникальный идентификатор, по которому обращаются к процедуре. Нетрудно заметить, что процедурный блок по структуре похож на саму программу.
СОЗДАНИЕ БЛОКНОТА НА DELPHI
Наглядным примером асинхронного ввода/вывода является блокнот, рассмотрим его создание.
Первым делом мы должны построить базовый интерфейс пользователя приложения. Для этого добавьте в окно Designer Surface компоненты TMainMenu, TMemo, TActionList, TOpenDialog, TSaveDialog, TStatusBar (категория Win32) и компонент TToolbar.
Рисунок 3. Создание формы
Форме дайте имя MainForm.
После этого выберите компонент TMainMenu и создайте группы меню Файл, Правка и Формат. Не создавайте пока что никаких пунктов меню, поскольку для реализации команд меню будут использоваться действия.
Рисунок 4. Реализация команд Теперь выберите компонент ТМеmо и выполните следующие шаги:
Присвойте свойству Align значение alClient. чтобы компонент занял всю клиентскую область формы.
Удалите текст Memo1 из свойства Lines.
Присвойте свойству ScrollBars значение ssVertical. чтобы отобразить вертикальную линейку прокрутки и позволить пользователю без труда просматривать обширные текстовые файлы.
Меню File
Меню Файл должно содержать команды, которые позволят пользователю завершать работу приложения, создавать, загружать и сохранять файлы.
Рисунок 5. Всплывающее окно Пока мы не будем заниматься реализацией команд Параметры страницы иПечать.
Чтобы создать команды меню Файл, и дважды щелкните на TActionList, чтобы отобразить окно редактора Action List (Список действий).
Во-первых, нам необходимо создать команду Файл — Выход. Щелкните на кнопкеNew Action (Новое действие), чтобы создать новое действие, и выполните следующие шаги:
Присвойте свойству Caption нового действия значение Выход.
Сведите в свойстве Hint строку Выход из программы.
Присвойте действию имя ExitAction.
И, наконец, назначьте действие неименованному пункту меню в меню Файл.
Чтобы закрыть приложение, достаточно вызвать метод Close формы в обработчике события OnExecute действия:
Рисунок 6. Код программы
Загрузка документов Теперь необходимо реализовать команду Файл — Открыть, чтобы пользователь мог открывать существующие файлы. Во-первых, необходимо объявить приватную переменную, которая будет хранить имя файла открытого документа.
Эта переменная необходима в команде Файл — Сохранить, а также в некоторых других местах, о чем будет сказано чуть позже.
Рисунок 7. Код программы Чтобы пользователь мог выбрать существующий документ, вы должны использовать компонент TOpenDialog. Измените свойство Filter, чтобы диалоговое окно показывало только файлы с простым текстом, имеющие расширение .txt.
Рисунок 9. Фильтр
Будет разумным всегда добавлять фильтр All File Types, поскольку пользователь может иметь документы с простым текстом, сохраненные с расширением, отличным от .txt.
Теперь добавьте новое действие в список действий и измените его настройки следующим образом:
В свойстве Caption нового действия введите Открыть.
В свойстве Hint введите Открыть существующий документ.
Присвойте действию имя OpenAction.
Назначьте свойству Shortcut комбинацию Ctrl+O.
Чтобы загрузить текстовый документ в компонент ТМеmо. вы должны сделать несколько вещей. Во-первых, вы должны вызвать метод Execute компонентаTOpenDialog, чтобы пользователь мог выбрать документ. Если пользователь щелкнул на кнопке ОК в диалоговом окне, имя выбранного файла будет записано в свойство FileName компонента TOpenDialog, и метод Execute вернет значениеTrue.
Когда метод Execute возвращает True, вы должны скопировать имя выбранного файла в переменную FOpenedFile. а затем вызвать метод LoadFromFile, чтобы загрузить выбранный текстовый документ в свойство Lines компонента ТМеmо. Опять-таки поместите этот код в обработчик события OnExecute действия.
Рисунок 10. Код программы
И последнее что потребуется сделать — это создать команду Открыть в меню Файли назначить действие OpenAction свойству Action нового меню.
Сохранение документов Большинство приложений имеют две разные команды, которые позволяют пользователю сохранить документ: Сохранить и Сохранить как. КомандаСохранить используется для сохранения изменений в существующем документе, а команда Сохранить как — для сохранения документа, который не существует на диске или для сохранения копии существующего документа под другим именем.
Для начала мы реализуем команду Файл — Сохранить как. Команда Сохранить какдолжна позволить выбрать каталог и имя файла для документа с помощью компонента TSaveDialog. Измените свойства TSaveDialog:
В поле свойства DefaultExt введите txt, чтобы в диалоговом окне к имени файла автоматически добавлялось расширение .txt.
Создайте такой же фильтр, как и для компонента TOpenDialog.
Раскройте группу Options и присвойте свойству ofOverwritePrompt значениеTrue.
После того как вы включите свойство ofOverwritePrompt в набор Options, компонент TSaveDialog автоматически сгенерирует предупреждающее сообщение, если пользователь попытается использовать имя файла, который уже используется.
Теперь откройте редактор Action List и создайте действие Сохранить как:
В поле свойства Caption введите Сохранить как…
Присвойте действию имя SaveAsAction.
В поле свойства Hint введите Сохранить активный документ под новым именем.
Наконец, поместите код в обработчик событий OnExecute, a затем назначьте это действие неименованному пункту в меню Файл.
Рисунок 11. Код программы Действие Сохранить должно выполнить две вещи: сохранить изменения, произведенные в активном документе, если документ существует, или отобразить диалоговое окно Сохранить как, если документ не существует.
Чтобы создать действие Сохранить, выполните следующие шаги:
Создайте новое действие в редакторе Action List.
В поле свойства Caption нового действия введите Сохранить.
В поле свойства Hint введите Сохранить активный документ.
Присвойте действию имя SaveAction.
Назначьте свойству Shortcut комбинацию Ctrl+S.
Ниже показан обработчик события OnExecute действия Сохранить:
Рисунок 12. Код программы Создание новых документов Команда Файл — Новый сама по себе очень простая, поскольку мы должны выполнить всего лишь следующие шаги:
Очистить переменную FOpenedFile, чтобы приложение знало, что активный документ не существует.
Удалить существующий текст из компонента Memo1, вызвав метод Clear.
Чтобы создать действие Новый, выполните перечисленные ниже шаги:
Создайте новое действие в редакторе Action List.
В поле свойства Caption введите Новый.
В поле свойства Hint введите Создать новый документ.
Присвойте действию имя NewAction.
Назначьте свойству ShortCut комбинацию Ctrl+N.
Добавьте код в обработчик события OnExecute.
Рисунок 13. Код программы Назначьте действие NewAction неименованному пункту в меню Файл.
Защита данных пользователя Теперь, когда работа над меню File завершена, необходимо написать еще несколько строк кода, который будет защищать содержимое активного документа.
Рисунок 14. Окно программы
Грамотно спроектированное приложение должно проверять, изменял ли пользователь содержимое активного документа, и спрашивать пользователя о том, желает ли он сохранить документ, прежде чем разрешать пользователю:
Создавать новый документ.
Открывать существующий документ.
Закрывать все приложение.
Например, если в редакторе Блокнот вы введете некоторый текст, а затем попытаетесь закрыть редактор, то он автоматически уведомит о том, что вы не сохранили самый последний вариант изменений в документе, и позволит либо сохранить их, либо отменить изменения в активном документе.
Реализовать описанное поведение лучше всего, если создать функцию, которая будет проверять, изменял ли пользователь текст в редакторе, и спрашивать пользователя, желает ли он отменить либо сохранить изменения.
Рисунок 15. Код программы
Если текст, отображенный в редакторе, не был изменен, функция возвращаетTrue, в результате чего мы можем либо закрыть все приложение, либо заменить текст в редакторе пустым или существующим документом. Если текст в редакторе был изменен, вызывается функция MessageDlg, чтобы пользователь мог сохранить или отменить текст, отображенный в редакторе. Если пользователь щелкает на кнопке Yes (Да), функция сначала инициирует действие Сохранить для сохранения документа и возвращает True, чтобы уведомить о том, что теперь документ можно закрыть. Если пользователь щелкает на кнопке No (Нет), функция возвращает True, поскольку пользователь желает отменить изменения. Наконец, если пользователь щелкает на кнопке Cancel (Отмена), функция возвращает False, чтобы уведомить о том, что нельзя ни закрывать приложение, ни заменять активный документ другим.
Теперь необходимо вызвать функцию CloseCurrentDocument в действияхНовый и Открыть, чтобы спросить пользователя о дальнейших действиях, если в текст были внесены изменения.
Рисунок 16. Код программы
Последнее, что потребуется делать — это написать обработчик для событияOnCloseQuery формы.
Это событие возникает тогда, когда пользователь пытается закрыть форму. Параметр CanClose события OnCloseQuery позволяет определить, может ли форма быть закрыта или нет.
Обработчик события OnCloseQuery на самом деле очень прост. Мы должны всего лишь присвоить результат выполнения функции CloseCurrentDocumentпараметру CanClose. Таким образом, если функция CloseCurrentDocumentвернет значение True, пользователь сможет закрыть приложение. Закрытие формы будет остановлено только лишь в том случае, если текст в редакторе будет изменен, а пользователь щелкнет на кнопке Cancel (Отмена) в диалоговом окне MessageDlg.
Рисунок 17. Код программы Меню Edit
Все команды меню Edit будем создавать вручную.
Отмена Для начали создадим действие Отменить:
Создайте новое действие.
В поле свойства Caption введите Отменить.
В поле свойства Hint введите Отменить последнее действие.
Присвойте действию имя UndoAction.
Назначьте свойству Shortcut комбинацию Сtrl+Z.
Чтобы отменить действия в редакторе, вы должны вызвать метод Undo. Чтобы узнать, можете ли вы отменить какое-либо действие, необходимо вызвать метод CanUndo. Но лучше всего вызвать метод CanUndo в событииOnUpdate действия, чтобы запретить действие в случае невозможности выполнения отмены.
Рисунок 18. Код программы Назначьте действие UndoAction неименованному пункту в меню Правка.
Вырезание и копирование в буфер обмена Действия Вырезать и Копировать подобны друг другу. ДействиеКопировать копирует выделенный текст в буфер обмена, а действие Вырезать сначала копирует выделенный текст в буфер обмена, а затем удаляет текст из редактора.
Поскольку действия Вырезать и Копировать имеют один обработчик события OnUpdate, давайте сначала создадим оба действия, а затем напишем необходимые обработчики событий.
Чтобы создать действие Вырезать, выполните следующие шаги:
Создайте новое действие в редакторе Action List.
В поле свойства Caption нового действия введите Вырезать.
В поле свойства Hint введите Вырезать выделенный фрагмент в буфер обмена.
Присвойте действию имя CutAction.
Назначьте свойству Shortcut комбинацию Ctrl+X.
Чтобы создать действие Копировать, выполните перечисленные ниже шаги:
Создайте новое действие в редакторе Action List.
В поле свойства Caption нового действия введите Копировать.
В поле свойства Hint введите Копировать выделенный фрагмент в буфер обмена.
Присвойте действию имя CopyAction.
Назначьте свойству Shortcut комбинацию Ctrl+C.
Реализовать оба обработчика события OnExecute не составляет особого труда. Чтобы скопировать текст из редактора в буфер обмена, вы должны вызвать метод CopyToClipboard. Чтобы вырезать текст в буфер обмена, вызовите метод CutToClipboard редактора.
Рисунок 19. Код программы Код в обработчике события OnUpdate должен запрещать действие, если в редакторе не будет выделен текст. Для определения, сколько символов было выделено пользователем, можно использовать свойство SelLength редактора. Если значение этого свойства будет равно 0, это значит, что в редакторе нет выделенных символов, и действие должно быть запрещено.
Теперь запишем следующий обработчик события OnUpdate для действия вырезать и назначим его событию OnUpdate действия Копировать:
Рисунок 20. Код программы
Назначьте действия CutAction и CopyAction неименованным пунктам в менюПравка.
Вставка в буфер обмена Во время действия Вставить содержимое буфера обмена вставляется в редактор. Чтобы ваш редактор был по-настоящему профессиональным, вы должны позволить пользователю выбирать команду Вставить только тогда, когда в буфере обмена будет содержаться хоть какой-нибудь текст. Чтобы узнать, какой формат имеют данные, хранящиеся в буфере обмена, вызовите метод HasFormat.
Чтобы узнать, содержит ли буфер обмена простой текст, который может быть вставлен в редактор, вызовите метод HasFormat и передайте в качестве параметра константу CF_TEXT. Чтобы использовать глобальный объектClipboard, необходимо добавить модуль Clipbrd в список uses.
Для создания действия Вставить потребуется выполнить следующие шаги:
Создайте новое действие.
В поле свойства Caption нового действия введите Вставить.
В поле свойства Hint введите Вставить текст из буфера обмена.
Присвойте действию имя PasteAction.
Назначьте свойству Вставить комбинацию Ctrl+V.
Рисунок 21. Код программы Назначьте действие PasteAction неименованному пункту в меню Правка.
Удаление Действие Удалить выполняет практически то же самое, что и действиеВырезать. Подобно Вырезать, действие Удалить удаляет выделенный текст из редактора. Различие между ними состоит в том, что действие Удалить не копирует текст в буфер обмена перед удалением текста из редактора.
Чтобы создать действие Delete, выполните следующие шаги:
Создайте новое действие.
В поле свойства Caption нового действия введите Удалить.
В поле свойства Hint введите Удалить выделенный фрагмент.
Присвойте действию имя DeleteAction.
Назначьте свойству Shortcut клавишу Del.
Для удаления текста из редактора без изменения содержимого буфера обмена применяется метод ClearSelection. Кроме этого, назначьте обработчик события OnUpdate действия Cut событию OnUpdate действия Delete, чтобы позволить пользователю удалять выделенный текст только в том случае, если этот текст существует.
Назначьте действие DeleteAction неименованному пункту в меню Правка.
Выделение всего документа Пожалуй, наиболее простым из всех действий является Выделить все, которое позволяет выделять все содержимое редактора. Чтобы создать действие Выделить все, выполните следующие шаги:
Создайте новое действие.
В поле свойства Caption нового действия введите Выделить все.
В поле свойства Hint введите Выделить весь документ.
Присвойте действию имя SelectAllAction.
Назначьте свойству Shortcut клавишу Ctrl+A.
Назначьте действие SelectAllAction неименованному пункту в меню Правка.
Чтобы выделить все содержимое компонента ТМеmо, необходимо вызвать метод SelectAll:
Рисунок 22. Код программы Поиск текста в Delphi
Чтобы реализовать команду Найти, сначала добавьте в окно Designer Surfaceкомпонент TFindDialog. Компонент TFindDialog заключает в себе обычное диалоговое окно Найти, с помощью которого пользователь может производить поиск строки текста. Строка, которую пользователь пытается найти, хранится в свойстве FindText.
Чтобы пользователь мог осуществлять поиск в тексте, потребуется создать действие Найти, отображающее диалоговое окно Найти, и написать обработчик для события OnFind диалогового окна для реализации поиска. Поскольку диалоговое окно Найти позволяет искать несколько экземпляров строки, мы должны объявить переменную Integer, в которой будет храниться последняя позиция поиска:
Рисунок 23. Код программы Теперь, чтобы создать действие Найти, выполните перечисленные ниже шаги:
В поле свойства Caption нового действия введите Найти.
В поле свойства Hint введите Найти указанный текст.
Присвойте действию имя FindAction.
Назначьте свойству Shortcut комбинацию Ctrl+F.
В обработчик события OnExecute действия поместите следующий код:
Рисунок 24. Код программы Код, отвечающий за выполнение поиска:
Рисунок 25. Код программы Первая строка (приведение параметра Sender к типу TFindDialog) необязательна, если в команде Правка — Найти вы намереваетесь использовать только этот метод. В данном случае мы должны выполнить приведение к типу по той причине, что это позволит повторно использовать этот метод в событии OnFind компонента TReplaceDialog.
В следующих двух строках создается временная копия всего документа и удаляется та часть документа, в которой пользователь уже выполнил поиск. Если мы не удалим эту часть, функция Pos, используемая для выполнения поиска, всегда будет возвращать первый экземпляр строки поиска.
Если функция Pos найдет экземпляр строки поиска, мы должны будем сохранить позицию найденного экземпляра в переменной FLastSearch, а затем выделить строку в редакторе. Для выделения строки в редакторе потребуется изменить свойства SelStart и SelLength. Свойство SelStartпоказывает позицию курсора, а свойство SelLength определяет количество выделенных символов.
Наконец, чтобы показать выделение, мы должны вызвать метод SetFocus для передачи редактору фокуса.
Назначьте действие FindAction неименованному пункту в меню Правка.
Замена текста В плане завершения работы над меню Правка необходимо создать действиеЗаменить, которое позволит производить поиск и замену строки. Чтобы реализовать действие Заменить, потребуется выполнить следующие шаги:
Добавить в окно Designer Surface компонент TReplaceDialog. Создать действие, которое будет отображать диалоговое окноЗаменить.
Реализовать обработчики для событий OnFind и OnReplace компонентаTReplaceDialog.
Для создание действия Заменить потребуется выполнить перечисленные ниже шаги:
В поле свойства Caption нового действия введите Заменить…. В поле свойства Hint введите Заменить найденный текст другим текстом. Присвойте действию имя ReplaceAction. Назначьте свойству Shortcut комбинацию Ctrl+H.
Присвойте свойству Tag значение 1 или любое другое значение, отличное от 0. Назначьте обработчик события OnExecute действия Найти событиюOnExecute.
Мы должны изменить свойство Tag с целью повторного использования обработчика события OnExecute действия Найти. После того как вы измените свойство Tag действия Заменить, вы можете изменить обработчик событияOnExecute действия Найти, чтобы отобразить оба диалоговых окна:
Рисунок 26. Код программы Наконец, мы должны реализовать обработчики для события OnFind. которое происходит при щелчке пользователем на кнопке Найти, и событияOnReplace, которое происходит при щелчке пользователем на кнопкахЗаменить или Заменить все.
На самом деле, писать обработчик для события OnFind не потребуется, поскольку можно воспользоваться существующим обработчиком событияOnFind компонента TFindDialog. Этот обработчик можно использовать по той причине, что вначале было выполнено приведение параметра Sender к компоненту TFindDialog, а также потому, что TReplaceDialog происходит от класса TFindDialog.
В обработчике события OnReplace необходимо проверить, существует ли выделенный текст в редакторе (SelText <> ''), и если он существует, то заменить его строкой из свойства ReplасеТехt.
Рисунок 27. Код программы Меню Формат в нашем примере приложения является наиболее простым меню. Оно состоит только из двух команд — Перенос по словам и Шрифт.
Рисунок 28. Всплывающее окно Команда Перенос по словам позволяет переносить текст по правому краю. Если установить галочку напротив этой команды, то вы сможете прокручивать содержимое редактора по вертикали. Если галочка не будет установлена, вы должны будете отображать обе линейки прокрутки, поскольку длинные строки не будут переноситься по правому краю.
Чтобы создать действие Перенос по словам, выполните следующие шаги:
Создайте новое действие и присвойте его свойству AutoCheck значениеTrue, чтобы команда автоматически принимала состояние Checked.
В поле свойства Caption введите Перенос по словам.
Присвойте свойству Checked значение True, поскольку свойствоПеренос по словам редактора имеет значение True по умолчанию.
Присвойте действию имя WordWrapAction.
Рисунок 29. Код программы Назначьте действие WordWrapAction неименованному пункту в менюФормат.
Чтобы создать команду Формат — Шрифт, сначала добавьте в окно Designer Surface компонент TFontDialog, а затем создайте новое действие. В полеCaption нового действия введите Шрифт, присвойте действию имяFontAction, a затем напишите следующий код в обработчике событияOnExecute:
Рисунок 30. Код программы Назначьте действие FontAction неименованному пункту в меню Формат.
Отображение подсказок и состояния Добавьте на форму компонент TStatusBar. Если свойству SimplePanelприсвоить значение True, то компонент TStatusBar сможет отображать только одну порцию информации, заданную свойством SimpleText. Однако если свойству SimplePanel присвоить значение False, мы сможем использовать свойство Panels для создания многопанельной строки состояния и отображения большего количества информации для пользователя. Выберите компонент строки состояния и щелкните на кнопке (…) рядом со свойством Panels, чтобы вывести на экран редактор коллекций Collection Editor.
Щелкните на кнопке Add New (Добавить новую), чтобы создать три панели строки состояния. Присвойте свойству Width первых двух панелей значение 75. чтобы зарезервировать большее пространство для вывода текста. Первая панель будет служить для отображения количества строк в документе и номера выбранной в данный момент отроки. Вторая панель будет использоваться для отображении идентификатора Modified (Изменено), если содержимое редактора будет изменяться, а последняя панель будет применяться для вывода подсказок.
Наилучшим местом для этого кода является событие OnIdle приложения, поэтому добавьте в окно Designer Surface компонент TApplicationEvents и в обработчик события OnIdle поместите следующий код:
Рисунок 31. Код программы
Чтобы отобразить подсказку в последней панели, подготовьте обработчик для события OnHint:
Рисунок 32. Код программы Панель инструментов Теперь нам осталось сделать всего две вещи: добавить глифы для наиболее часто используемых действий, а затем поместить эти действия в панель инструментов. Для начала добавьте в окно Designer Surface компонентTImageList, присвойте ему имя Normal, а затем добавьте глифы для действийNew, Open, Save, Undo, Cut, Copy, Paste, Delete и Find. После того как вы добавите эти изображения в компонент TImageList, назначьтекомпонентTImageList компонентам TActionList, TToolbar и TMainMenu, после чего откройте редактор Action List и назначьте глифы соответствующим действиям.
После того как вы назначите глифы действиям, выберите панель инструментов и щелкните на ней правой кнопкой мыши, чтобы вывести контекстное меню панели инструментов. Контекстное меню содержит команду New Button (Новая кнопка) для создания новой кнопки панели инструментов, а также команду New Separator (Новый разделитель) для создания разделителя, который позволит визуально распределить кнопки по группам. Все, что вам необходимо сделать сейчас — это добавить несколько кнопок в панель инструментов и назначить действие свойству Action каждой кнопки.
При желании можете также изменить следующие два свойства, чтобы придать панели инструментов более привлекательный вид: Присвойте свойству AutoSize значение True, чтобы удалить пустое пространство в панели инструментов. Присвойте свойству ShowCaptions значение True, чтобы отобразить заголовки кнопок (если вы сделаете это, то должны будете удалить символы ам-персанда и точки из заголовков кнопок).
Рисунок 33. Готовая программа
ЗАКЛЮЧЕНИЕ
В заключении материала об асинхронном вводе-выводе следует отметить сложность реализации такого способа ввода-вывода. Для многих приложений, работающих с несколькими устройствами и/или сетевыми соединениями синхронная модель неудобна. Работа в режиме опроса тоже не всегда приемлема.
Решение этих проблем известно давно и называется асинхронный ввод/вывод. В этом режиме системные вызовы ввода/вывода возвращают управление сразу после формирования запроса к драйверу устройства, как правило, даже до того, как данные будут скопированы в системный буфер.
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1.Практикум по дисциплине «Информатика и программирование». Князева М. Д. 2010 г.
2.Программирование на Delphi 7 Князева М. Д. 2010 г.
3. Основы программирования в Delphi XE (+CD) Никита Культин 2011 г.
4.Основы алгоритмизации и программирования Семакин И. Г., Шестаков А. П. 2012 г.
5. Внутренний мир Borland Delphi Иван Хладни 2006 г.
ПРИЛОЖЕНИЕ А
unit note;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, StdCtrls, Printers, clipbrd, OleCtrls, vcspell3, ExtCtrls;
type
TForm1 = class (TForm)
Memo1: TMemo;
MainMenu1: TMainMenu;
File1: TMenuItem;
Exit1: TMenuItem;
New1: TMenuItem;
Edit1: TMenuItem;
Paste1: TMenuItem;
Copy1: TMenuItem;
Cut1: TMenuItem;
N5: TMenuItem;
Undo1: TMenuItem;
Text1: TMenuItem;
AlignLeft1: TMenuItem;
AlignRight1: TMenuItem;
AlignCenter1: TMenuItem;
N3: TMenuItem;
WordWrap1: TMenuItem;
N6: TMenuItem;
SelectAll1: TMenuItem;
N1: TMenuItem;
Open1: TMenuItem;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
Save1: TMenuItem;
Option1: TMenuItem;
CountChars1: TMenuItem;
Font1: TMenuItem;
FontDialog1: TFontDialog;
PrinterSetupDialog1: TPrinterSetupDialog;
PopupMenu1: TPopupMenu;
Clear1: TMenuItem;
Print1: TMenuItem;
SaveAs1: TMenuItem;
ReadOnly1: TMenuItem;
Help1: TMenuItem;
About1: TMenuItem;
Cut2: TMenuItem;
Copy2: TMenuItem;
Paste2: TMenuItem;
SelectAll2: TMenuItem;
N2: TMenuItem;
N4: TMenuItem;
procedure FormCreate (Sender: TObject);
procedure New1Click (Sender: TObject);
procedure Undo1Click (Sender: TObject);
procedure Cut1Click (Sender: TObject);
procedure Copy1Click (Sender: TObject);
procedure Paste1Click (Sender: TObject);
procedure AlignLeft1Click (Sender: TObject);
procedure AlignRight1Click (Sender: TObject);
procedure AlignCenter1Click (Sender: TObject);
procedure WordWrap1Click (Sender: TObject);
procedure Exit1Click (Sender: TObject);
procedure Edit1Click (Sender: TObject);
procedure SelectAll1Click (Sender: TObject);
procedure Clear1Click (Sender: TObject);
procedure Memo1Change (Sender: TObject);
procedure FormResize (Sender: TObject);
procedure Open1Click (Sender: TObject);
procedure Save1Click (Sender: TObject);
procedure CountChars1Click (Sender: TObject);
procedure Font1Click (Sender: TObject);
procedure Print1Click (Sender: TObject);
procedure FormCloseQuery (Sender: TObject; var CanClose: Boolean);
procedure SaveAs1Click (Sender: TObject);
procedure ReadOnly1Click (Sender: TObject);
procedure About1Click (Sender: TObject);
procedure Cut2Click (Sender: TObject);
procedure Copy2Click (Sender: TObject);
procedure Paste2Click (Sender: TObject);
procedure SelectAll2Click (Sender: TObject);
procedure PopupMenu1Popup (Sender: TObject);
private
filename: string;
modified: bool;
public
function SaveChanges: Boolean;
function Save: Boolean;
function SaveAs: Boolean;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1. FormCreate (Sender: TObject);
begin
OpenDialog1.Filter := 'Text Document (*.txt)|*.txt';
OpenDialog1.InitialDir := GetCurrentDir ();
OpenDialog1.DefaultExt := '.txt';
SaveDialog1.Filter := 'Text Document (*.txt)|*.txt';
SaveDialog1.InitialDir := GetCurrentDir ();
SaveDialog1.DefaultExt := '.txt';
Memo1.ScrollBars := ssVertical;
Memo1.WordWrap := True;
Memo1.SelStart := 0;
WordWrap1.Checked := True;
AlignLeft1.Checked := True;
Form1.Caption := 'Notepad — '+'Untitled';
filename := 'Untitled';
end;
procedure TForm1. New1Click (Sender: TObject);
begin
Memo1.Text := '';
modified := False;
filename := 'Untitled';
Form1.Caption := 'Notepad — '+'Untitled';
end;
procedure TForm1. Undo1Click (Sender: TObject);
begin
SendMessage (Memo1.Handle, WM_UNDO, 0,0);
end;
procedure TForm1. Cut1Click (Sender: TObject);
begin
Memo1.CutToClipboard;
end;
procedure TForm1. Copy1Click (Sender: TObject);
begin
Memo1.CopyToClipboard;
end;
procedure TForm1. Paste1Click (Sender: TObject);
begin
Memo1.PasteFromClipboard;
end;
procedure TForm1. AlignLeft1Click (Sender: TObject);
begin
Memo1.Alignment := taLeftJustify;
AlignLeft1.Checked := True;
AlignRight1.Checked := False;
AlignCenter1.Checked := False;
end;
procedure TForm1. AlignRight1Click (Sender: TObject);
begin
Memo1.Alignment := taRightJustify;
AlignLeft1.Checked := False;
AlignRight1.Checked := True;
AlignCenter1.Checked := False;
end;
procedure TForm1. AlignCenter1Click (Sender: TObject);
begin
Memo1.Alignment := taCenter;
AlignLeft1.Checked := False;
AlignRight1.Checked := False;
AlignCenter1.Checked := True;
end;
procedure TForm1. WordWrap1Click (Sender: TObject);
begin
if Memo1. WordWrap then
begin
Memo1.WordWrap := False;
WordWrap1.Checked := False;
Memo1.ScrollBars := ssBoth;
end
else
begin
Memo1.WordWrap := True;
WordWrap1.Checked := True;
Memo1.ScrollBars := ssVertical;
end;
end;
procedure TForm1. Exit1Click (Sender: TObject);
begin
Close;
end;
procedure TForm1. Edit1Click (Sender: TObject);
var
sMemo: String;
begin
{if some text is selected in the memo,
enable the cut and copy commands}
if Memo1. SelLength > 0 then begin
Copy1.Enabled := True;
Cut1.Enabled := True;
end
else
begin
Copy1.Enabled := False;
Cut1.Enabled := False;
end;
{if the clipboard contains some text,
enable the Paste command}
if Clipboard. HasFormat (CF_TEXT) then
Paste1.Enabled := True
else
Paste1.Enabled := False;
sMemo := Memo1. Text;
If Length (Trim (sMemo)) > 0 then begin
Undo1.Enabled := True;
SelectAll1.Enabled := True;
end
else
begin
SelectAll1.Enabled := False;
Undo1.Enabled := False;
end;
end;
procedure TForm1. SelectAll1Click (Sender: TObject);
begin
Memo1.SelectAll;
end;
procedure TForm1. Clear1Click (Sender: TObject);
begin
Memo1.Text := '';
modified := False;
end;
procedure TForm1. Memo1Change (Sender: TObject);
begin
modified := True;
end;
procedure TForm1. FormResize (Sender: TObject);
begin
Memo1.Width := Form1. ClientWidth + 1;
Memo1.Height := Form1. ClientHeight + 1;
end;
procedure TForm1. Open1Click (Sender: TObject);
begin
If OpenDialog1. Execute Then begin
Form1.Caption := 'Notepad — '+OpenDialog1.FileName;
Memo1.Lines.LoadFromFile (OpenDialog1.Filename);
Memo1.SelStart := 0;
filename := OpenDialog1. FileName;
end;
end;
procedure TForm1. Save1Click (Sender: TObject);
begin
if modified then
Save;
end;
procedure TForm1. CountChars1Click (Sender: TObject);
var
text: String;
begin
Str (Memo1.GetTextLen, text);
MessageDlg ('Your Document Has ' + text + ' Characters',
mtInformation, [mbOK], 0);
end;
procedure TForm1. Font1Click (Sender: TObject);
begin
FontDialog1.Font := Memo1. Font;
if FontDialog1. Execute then begin
Memo1.Font := FontDialog1. Font;
end;
end;
procedure TForm1. Print1Click (Sender: TObject);
var
sMemo: String;
filename: TextFile;
x: Integer;
begin
sMemo := Memo1. Text;
If Length (Trim (sMemo)) = 0 Then
MessageDlg ('No Text To Print', mtError,[MBOK], 0);
If Length (Trim (sMemo)) <> 0 Then
if PrinterSetupDialog1. Execute then begin
AssignPrn (filename);
Rewrite (filename);
for x := 0 to Memo1.Lines.Count — 1 do
Writeln (filename, Memo1. Lines[x]);
CloseFile (filename);
end;
end;
procedure TForm1. FormCloseQuery (Sender: TObject; var CanClose: Boolean);
begin
if modified then
if SaveChanges then
CanClose := True
else
CanClose := False
else
CanClose := True;
end;
function TForm1. SaveChanges: Boolean;
var
code: Integer;
begin
SaveChanges := True;
code := MessageDlg (filename + ' has changed. Do you want to save the changes?',
mtInformation, mbYesNoCancel, 0);
if (code = IDYES) then
SaveChanges := Save;
if (code = IDCANCEL) then
SaveChanges := False;
end;
function TForm1. Save: Boolean;
begin
if filename = '' then
Save := SaveAs
else
begin
modified := False;
Memo1.Lines.SaveToFile (filename);
Save := True;
end;
end;
function TForm1. SaveAs: Boolean;
begin
SaveDialog1.FileName := filename;
if SaveDialog1. Execute then
begin
filename := SaveDialog1. FileName;
Memo1.Lines.SaveToFile (filename);
modified := False;
Form1.Caption := 'Notepad — '+SaveDialog1.filename;
SaveAs := True;
end
else
SaveAs := False;
end;
procedure TForm1. SaveAs1Click (Sender: TObject);
begin
SaveAs;
end;
procedure TForm1. ReadOnly1Click (Sender: TObject);
begin
Memo1.ReadOnly := NOT Memo1. ReadOnly;
ReadOnly1.Checked := NOT ReadOnly1. Checked
end;
procedure TForm1. About1Click (Sender: TObject);
begin
if (Application.MessageBox (' © Notepad Created By Andrew Carter, Copyright 2001', 'About Notepad?', MB_OK) = IDOK) then
begin
end;
end;
procedure TForm1. Cut2Click (Sender: TObject);
begin
Memo1.CutToClipboard;
end;
procedure TForm1. Copy2Click (Sender: TObject);
begin
Memo1.CopyToClipboard;
end;
procedure TForm1. Paste2Click (Sender: TObject);
begin
Memo1.PasteFromClipboard;
end;
procedure TForm1. SelectAll2Click (Sender: TObject);
begin
Memo1.SelectAll;
end;
procedure TForm1. PopupMenu1Popup (Sender: TObject);
var
sMemo: String;
begin
{if some text is selected in the memo,
enable the cut and copy commands}
if Memo1. SelLength > 0 then begin
Copy2.Enabled := True;
Cut2.Enabled := True;
end
else
begin
Copy2.Enabled := False;
Cut2.Enabled := False;
end;
{if the clipboard contains some text,
enable the Paste command}
if Clipboard. HasFormat (CF_TEXT) then
Paste2.Enabled := True
else
Paste2.Enabled := False;
sMemo := Memo1. Text;
If Length (Trim (sMemo)) > 0 then begin
SelectAll2.Enabled := True;
Clear1.Enabled := True;
end
else
begin
SelectAll2.Enabled := False;
Clear1.Enabled := False;
end;
end;