On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru








 

Приложение. Создание и модификация шаблонов SDI- и MDI-приложений

Создание шаблона приложений

Сначала при помощи средства AppWizard создается шаблон однооконного или многооконного приложения. При этом генерируются следующие основные классы :

  • главный класс приложения (производный от базового класса CWinApp );
  • класс главного окна приложения (производный от базового класса CFrameWnd или CMDIFrameWnd в зависимости от типа приложения) ;
  • класс документа приложения (производный от базового CDocument );
  • класс окна просмотра документа (производный от базового CView );
  • класс дочернего MDI-окна (производный от базового класса CMDIChildWnd ) - только для mdi-приложения.

Редактирование документов (и обликов)

В классе документа следует определить элементы (простые переменные, переменные структурного типа, объекты различных классов и др.), отвечающие за хранение данных документа, считываемых и записываемых в файл.

Если в процессе работы с документом выделяется дополнительная память для хранения информации, то в деструкторе класса документа необходимо освободить всю дополнительную память, полученную в процессе работы.

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

  • объявить указатель pDoc на текущий документ и получить его при помощи метода GetDocument класса окна просмотра ;
  • изменить графическое изображение документа;
  • изменить содержимое документа, на который указывает pDoc;
  • установить флаг изменения документа, вызвав метод pDoc.SetModifiedFlag(TRUE);
  • для mdi-приложения вызвать метод pDoc.UpdateAllViews(this) для перерисовки всех обликов документа (кроме текущего ), на который указывает pDoc.

Для класса окна просмотра переопределить метод OnUpdate для того, чтобы выводить в этом методе только последние изменения, т.к. метод CView::OnUpdate базового класса просто вызывает метод OnDraw для перерисовки всего изображения.

Для восстановления всего изображения в окне просмотра после перекрытия окна необходимо изменить метод OnDraw класса окна просмотра документа, добавив вывод всего изображения .

Инициал изация нового документа

Для инициализации нового документа в методе OnNewDocument класса документа произвести

  • вызов метод CDocument::OnNewDocument базового класса для полной подготовки к работе с новым документом ;
  • инициализацию необходимых данных нового документа ;
  • выделение необходимой памяти для работы над документом .

Для очистки содержимого документа при инициализации нового документа в классе документа необходимо переопределить метод DeleteContents базового класса CDocument (этот метод вызывается методом CDocument::OnNewDocument - обработчиком открытия нового документа). Для этого в определении класса документа необходимо объявить виртуальный метод DeleteContents, а в реализации класса его определить. Работа метода DeleteContents должна заключаться в следующем :

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

Сохранение и восстановл ение документов

Чтобы приложение имело возможность сохранения документов в файле, нужно изменить метод Serialize класса документа. Метод Serialize вызывается всякий раз, когда надо сохранить документ в файле на диске или загрузить его из существующего файла. В методе Serialize необходимо определить, как он должен сохранять и восстанавливать документы приложения.

Использование стандартных диалогов выбора файлов

Для того, чтобы иметь возможность при открытии и сохранения документа на диске использовать стандартные диалоговые панели выбора файла с определенными программистом настройками, необходимо в приложении обработать командные сообщения с идентификаторами ID_FILE_OPEN, ID_FILE_SAVE, ID_FILE_SAVE_AS (следует отметить, что обработка этих сообщений должна происходить в разных классах приложения - см. ниже).

В класс документа необходимо добавить элемент BOOL status_new, принимающий значение TRUE, если пользователь работает с новым документом, и значение FALSE, если пользователь открыл документ, содержащийся в файле на диске. В методе OnNewDocument класса документа необходимо присвоить элементу status_new значение TRUE.

При помощи средства ClassWizard добавить в главный класс приложения (наследованный от класса CWinApp) обработчик командного сообщения с идентификатором ID_FILE_OPEN. Используемый ранее по умолчанию обработчик CWinApp::OnFileOpen этого сообщения убрать из списка обрабатываемых сообщений :

	BEGIN_MESSAGE_MAP(CApp, CWinApp)
		::
		ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
		::
	END_MESSAGE_MAP()

Изменить заготовку метода OnFileOpen главного класса приложения следующим образом:

	void CApp::OnFileOpen()
	{
		// Создание стандартной панели выбора файла 
"Open"
		CFileDialog DlgOpen(TRUE,(LPCTSTR)"txt",NULL,
			OFN_HIDEREADONLY,(LPCSTR)" Text Files (*.txt) |*.txt||");

		// Отображение стандартной панели выбора файла 
"Open"
		if(DlgOpen.DoModal()==IDOK)
		{
			// Создание объекта класса документа, связанного с
			// файлом, и его окна просмотра.

			// OpenDocumentFile - метод класса CWinApp

			CDocument *pDoc =OpenDocumentFile(DlgOpen.GetPathName());

			// Чтение данных из файла и запись их 
			// в элементы класса документа.

			pDoc->OnOpenDocument(DlgOpen.GetPathName());
		}
	}

В классе документа переопределить метод OnOpenDocument базового класса CDocument. Для этого в определении класса документа необходимо объявить виртуальный метод OnOpenDocument, а в реализации класса документа необходимо его определить:

	BOOL CDoc::OnOpenDocument( const char* pszPathName)
	{
		// Вызов метода базового класса.
		// Он сначала вызывает метод DeleteContents для очистки документа,
		// а затем метод Serialize для чтения данных из файла

		if(!CDocument::
OnOpenDocument(pszPathName)) return FALSE;

		// Инициализация необходимых данных класса, выделение 
		// памяти аналогично методу 
OnNewDocument
		. . . . . . . 

		status_new=FALSE; // документ не новый

		return TRUE;
	}

При помощи средства ClassWizard добавить в класс документа обработчики командных сообщений с идентификаторами ID_FILE_SAVE и ID_FILE_SAVE_AS . Изменить заготовки методов-обработчиков следующим образом :

	void CDoc::OnFileSave()
	{
		if(status_new==TRUE) // если документ новый, то выбор имени файла

		{
			// Создание стандартной панели выбора файла 
"SaveAs"
			CFileDialog DlgSave(FALSE,(LPCSTR)"txt",GetTitle(),
				OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
				(LPCSTR)" Text Files (*.txt) |*.txt||");

			// Отображение стандартной панели выбора файла 
"SaveAs"
			if(DlgSave.DoModal()==IDOK)
			{
				SetPathName(DlgSave.GetPathName());

				// Вызов метода базового класса.
				// Он вызывает метод Serialize для записи данных

				CDocument::
OnSaveDocument(DlgSave.GetPathName());

				status_new=FALSE; // документ уже не новый

			}
		}
		else	// Вызов метода базового класса.

			CDocument::
OnSaveDocument(GetPathName());
	}
	void CDoc::OnFileSaveAs()
	{
		// Создание стандартной панели выбора файла 
"SaveAs"
		CFileDialog DlgSaveAs(FALSE,(LPCSTR)"txt",GetTitle(),
			OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
			(LPCSTR)" Text Files (*.txt) |*.txt||");

		// Отображение стандартной панели выбора файла 
"SaveAs"
		if(DlgSaveAs.DoModal()==IDOK)
		{
			SetPathName(DlgSaveAs.GetPathName());

			// Вызов метода базового класса.
			// Он вызывает метод Serialize для записи данных

			CDocument::
OnSaveDocument(DlgSaveAs.GetPathName());

			status_new=FALSE; // документ уже не новый

		}
	}

Запись и восстановление данных без помощи фрхивных файлов

Если программист не желает производить запись и восстановление документов при помощи архивных файлов и с использованием метода Serialize, то вместо использования в приложении методов CDocument::OnSaveDocument и CDocument::On OpenDocument базового класса документов он может использовать переопределения этих методов OnSaveDocument и On OpenDocument в своем классе документа .

В переопределенном уже ранее методе On OpenDocument класса документа (см. выше) вместо вызова по умолчанию метода базового класса CDocument::OnOpenDocument(pszPathName)) следует:

  • вызвать метод DeleteContents;
  • объявить объект file класса CFile или производного от него ;
  • открыть для объекта file файл с именем pszPathName (передается в метод в качестве параметра) в режиме "для чтения ";
  • считать данные из файла file и разместить их в элементах класса документа.

Изменить в методах OnFileSaveAs и OnFileSaveAs (см. выше) вызовы метода CDocument:: OnSaveDocument на вызовы OnSaveDocument. Затем переопределить метод On SaveDocument в классе документа приложения, для чего в определении класса документа необходимо объявить виртуальный метод On SaveDocument, а в реализации класса документа необходимо его определить. Причем в переопределенном методе On SaveDocument выполнить следующие действия :

  • объявить объект file класса CFile или производного от него ;
  • открыть для объекта file файл с именем pszPathName в режиме для "записи" ;
  • записать данные из элементов класса документа в файл file.
Назад       Содержание