На этом шаге мы рассмотрим еще один текстовый редактор.
Перед Анастасией Цокол, студенткой 4 курса факультета математики и информационных технологий Курганского государственного университета (декабрь 2005 г.) была поставлена следующая задача: разработать приложение, содержащее любой текст (предусмотреть загрузку текста из файла). Текст должен иметь возможность редактирования с помощью стандартных диалоговых панелей "Поиск" и "Замена" (реализовать все возможности: "Найти", "Найти далее", "Заменить", "Заменить всё").
Задача решена с использованием MDI-приложения.
Так как необходимо предусмотреть загрузку текста из файла и его редактирование, следовательно, было создано меню с пунктами File (Open, Exit) и Edit (Find, Find Next, Replace).
Так же, для удобства пользователя, была создана панель инструментов с соответствующими кнопками Open, Exit, Find, FindReplace, Replace (любую кнопку можно создать, используя Resource Workshop, размеры и изображения определяются по желанию).
При запуске программы открывается окно, на котором "активны" только две кнопки Open и Exit, так как текст для редактирования ещё не открыт.
При выборе подпункта Open или при нажатии на соответствующую кнопку, с помощью функции cmFileOpen() создается новое окно, являющееся дочерним по отношению к окну-клиенту, созданному в функции InitMainWindow() (более подробное описание можно посмотреть на 45 шаге).
После того, как какой-либо текст был загружен из файла, становятся "активными" кнопки Find и Replace и, следовательно, можно приступать к редактированию текста.
При выборе команды "Find" появляется диалоговое окно. В строку редактирования данного окна вводится искомое слово или искомый символ. При нажатии на кнопку "Найти", в документе будет выделен данный фрагмент в соответствии с текущим положением курсора. Если запрашиваемый текст не найден, выдаётся сообщение "Фрагмент … не найден". Нажатие на кнопку диалогового окна "Найти далее" соответствует нажатию кнопки "Найти далее" главного окна (положение курсора в тексте можно менять и при открытом диалоговом окне).
При выборе команды Replace так же появляется диалоговое окно, но уже с двумя строками редактирования: в первой вводится текст, который необходимо заменить, а во второй - чем его заменить. При нажатии на определенные кнопки данного диалогового окна, выполняются соответствующие операции, которые достаточно понятны и не требуют подробного описания. Если заменяемый текст не найден (в зависимости от положения курсора), так же выдается соответствующее сообщение.
Find и Replace - это стандартные диалоговые окна Windows (см. шаг 28).
Так же была создана строка сообщения для отображения подсказки при подведении (режим EnterHints) курсора к определенной кнопке на панели инструментов или к соответствующему подпункту меню.
Текст приложения:
#include <owl\applicat.h> #include <owl\decmdifr.h> #include <owl\editfile.h> #include <owl\mdi.h> #include <owl\controlb.h> #include <owl\statusba.h> #include <owl\buttonga.h> #include "pr73_1.rc" //Класс приложения. class TMDIApp: public TApplication { public: TMDIApp():TApplication(){} void InitMainWindow(); protected: TMDIClient *clienTWndw; TControlBar *controlBar; TMDIChild *childWnd; void CmFileOpen(); DECLARE_RESPONSE_TABLE (TMDIApp); }; DEFINE_RESPONSE_TABLE1(TMDIApp, TApplication) EV_COMMAND (CM_FILEOPEN, CmFileOpen), END_RESPONSE_TABLE; // TMDIApp::InitMainWindow() // Эта функция создает главное окно приложения, // окно-клиент, панель инструментов и // строку сообщения. void TMDIApp::InitMainWindow() { // Создать окно-клиент. clienTWndw = new TMDIClient; // Создать окно обрамления. TDecoratedMDIFrame *frameWnd = new TDecoratedMDIFrame ("Пример текстового редактора", MENU_1, *clienTWndw, TRUE); // Определить размеры и расположение окна обрамления. frameWnd->Attr.X = 50; frameWnd->Attr.Y = 50; frameWnd->Attr.W=GetSystemMetrics(SM_CXSCREEN)/3; frameWnd->Attr.H=GetSystemMetrics(SM_CXSCREEN)/3; // Создать инструментальную линейку. controlBar = new TControlBar (frameWnd,TControlBar::Vertical); controlBar->Insert(*new TButtonGadget(ID_OPEN, CM_FILEOPEN)); controlBar->Insert(*new TSeparatorGadget (10)); controlBar->Insert(*new TButtonGadget(ID_EXIT, CM_EXIT)); controlBar->Insert(*new TSeparatorGadget (30)); controlBar->Insert(*new TButtonGadget(ID_FIND, CM_EDITFIND)); controlBar->Insert(*new TSeparatorGadget (10)); controlBar->Insert(*new TButtonGadget(ID_FINDREPLACE, CM_EDITFINDNEXT)); controlBar->Insert(*new TSeparatorGadget (10)); controlBar->Insert(*new TButtonGadget(ID_REPLACE, CM_EDITREPLACE)); // Вставить панель инструментов в окно обрамления. frameWnd->Insert(*controlBar, TDecoratedFrame::Right); // Установить режим подсказки, чтобы сразу // показывать подсказку. controlBar->SetHintMode(TGadgetWindow::EnterHints); // Создать строку сообщения. TMessageBar *msgbar=new TMessageBar(0); //Вставить строку сообщения в окно обрамления. frameWnd->Insert(*msgbar, TDecoratedFrame::Bottom); EnableCtl3d (TRUE); // Установить значение указателя MainWindow приложения. SetMainWindow(frameWnd); }; void TMDIApp::CmFileOpen() { // Создать объект TData диалогового окна. TOpenSaveDialog::TData fileData (OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, "Все файлы (*.*) | *.* |Текстовые файлы (*.txt) | *.txt |", 0, 0, " * "); // Задать имя файла как пустую строку. strcpy(fileData.FileName, ""); // Создать диалоговое окно Open. TFileOpenDialog *dialog = new TFileOpenDialog (MainWindow, fileData); // Выполнить диалоговое окно Open. int result = dialog->Execute(); // Если пользователь выходит по кнопке ОК... if (result == IDOK) // Создать новый управляющий элемент редактирования файла. {TEditFile *editFile =new TEditFile (0, 0, 0, 0, 0, 0, 0, fileData.FileName); // Создать новое дочернее окно для файла. childWnd = new TMDIChild (*clienTWndw, "", editFile); // Отобразить новое дочернее окно. childWnd->Create(); } }; int OwlMain(int,char *[]) { return TMDIApp().Run(); }
Файл ресурсов:
#ifndef WORKSHOP_INVOKED #include "windows.h" #endif #include <owl\mdi.rh> #include <owl\editfile.rh> #define MENU_1 100 #define ID_MDIEDIT 101 #define ID_DOCUMENT 102 #define ID_OPEN CM_FILEOPEN #define ID_EXIT CM_EXIT #define ID_FIND CM_EDITFIND #define ID_FINDREPLACE CM_EDITFINDNEXT #define ID_REPLACE CM_EDITREPLACE #ifdef RC_INVOKED #include <owl\except.rc> #include <owl\statusba.rc> MENU_1 MENU { POPUP "&File" { MENUITEM "&Open", CM_FILEOPEN MENUITEM SEPARATOR MENUITEM "E&xit", CM_EXIT } POPUP "&Edit" { MENUITEM "&Find...", CM_EDITFIND MENUITEM "Find &Next", CM_EDITFINDNEXT MENUITEM "&Replace...", CM_EDITREPLACE } } STRINGTABLE { CM_FILEOPEN, "Открыть" CM_EXIT, "Выход" CM_EDITFIND, "Найти" CM_EDITFINDNEXT, "Найти далее" CM_EDITREPLACE, "Заменить" IDS_FILECHANGED, "Файл был изменён. \n\nСохранить изменения?" IDS_CANNOTFIND, "Фрагмент не найден \042%s\042" } ID_OPEN BITMAP "open1.bmp" ID_EXIT BITMAP "exit1.bmp" ID_FIND BITMAP "find1.bmp" ID_FINDREPLACE BITMAP "findnx1.bmp" ID_REPLACE BITMAP "replace1.bmp" #endif
Результат работы приложения изображен на рисунке 1:
Рис.1. Результат работы приложения
На следующем шаге мы рассмотрим простейший калькулятор.