Программирование под Windows с использованием MFC
Основа архитектуры «документ\представление»
- Создание различных типов документов
- Шаблоны однодокументных приложений
- Шаблоны многодокументных приложений
- Место объекта-приложения в архитектуре "документ/представление"
- Роль фреймов в архитектуре "документ/представление"
- Создание каркаса приложения на базе архитектуры "документ/представление"
Каждое приложение, написанное для Windows, имеет одно главное окно, которое состоит из двух компонентов — фрейма и клиентской (рабочей) области. Оно может быть как стандартным окном Windows (например, при построении SDI- и MDI-приложений), так и обычным блоком диалога. В любом случае внутри главного окна приложение предоставляет пользователю всю необходимую для работы информацию, представляющую собой не только данные, т. е. текст, рисунки и т. п., но и элементы интерфейса — меню, полосы прокрутки, панели инструментов, строка состояния и т. д. Каждый из этих элементов (по крайней мере, для приложений, созданных с использованием библиотеки MFC) является объектом, в состав которого входят функции, определяющие его поведение, т. е. взаимодействие как с другими объектами, так и с данными. Любые действия пользователя во время выполнения приложения вызывают генерацию сообщений, содержащих в себе информацию о том, что конкретно сделал пользователь. Все объекты приложения обладают способностью реагировать на те или иные сообщения. Во многих случаях эта способность заложена в библиотеке MFC, а для других реализуются специальные обработчики. Повторю — все перечисленные свойства характерны (с той или иной степенью полноты) для каждого Windows-приложения.
Оставим в стороне приложения, базирующиеся на блоках диалога, и сосредоточимся на тех, которые в качестве своего главного окна имеют стандартное окно Windows. Основным для таких окон является объект, созданный на базе класса CFrameWnd (для SDI-приложений) или CMDlFmmeWnd (для
MDI-приложений). То, что делалось до сих пор, заключалось в создании некоторых необходимых оконных объектов и самостоятельной организации взаимодействия между ними. Мы полностью (более того — сознательно) игнорировали такое мощное средство, заложенное разработчиками в библиотеку MFC, как архитектура "документ/представление" (document/view).
Что же включают в себя эти понятия? В самом общем случае, под документом фирма Microsoft понимает те данные, с которыми работает приложение. Это может быть все что угодно, — "простой" текст, картинка и т. п. Отображение этих данных на экране осуществляется в так называемом фрейме документа. Разработчики библиотеки MFC создали для фреймов специальные классы окон — представления, которые отображают данные документа и управляют взаимодействием пользователя с ними. Другими словами, способ хранения данных в памяти или на диске никоим образом не влияет на их внешнее представление пользователю.
Рассматриваемая архитектура основывается на создании соответствующих фреймов документов, содержащих специальные окна — представления. Кроме того, фрейм осуществляет координацию взаимодействия между документами различных типов и их представлениями, направляя им команды и получая от них извещения. Маршруты, по которым осуществляется передача сообщений, подробно описаны нами в части 4 данного руководства.
Архитектура "документ/представление" разделяет между собой данные-документы и их изображения. Каждый документ представлен в виде объекта, который обеспечивает пространство для хранения данных в памяти и отвечает за такие операции, как запись и чтение документа с диска. Очевидно, что большая часть таких операций выполняется самим приложением, а не классами библиотеки MFC. Кроме того, для каждого используемого представления также создается отдельный объект, который представляет собой экранное окно, отвечающее за взаимодействие с пользователем и соответствующим объектом документа, печать и т. д. Совместную работу перечисленных объектов координирует фрейм, который в большинстве случаев является главным окном приложения.
Пример приложения:
Когда запускается приложение под Windows, пользователь взаимодействует с документами посредством их изображений во фреймах. Фреймы документов имеют два основных компонента: собственно фрейм и его содержимое. Для них библиотека MFC использует два различных класса. Класс фрейма управляет непосредственно фреймом, а класс представления — его содержимым. При этом окно представления является дочерним по отношению к фрейму, т. е. размещается в его рабочей области. Сам фрейм документа может быть окном SDI-приложения или дочерним окном MDI-приложения.
<>
Взаимосвязь между фреймом, документом и представлением
Работа с основными компонентами фрейма документа осуществляется также по-разному. За взаимодействие пользователя непосредственно с фреймом (изменение размеров, перемещение и т. д.) полностью отвечает сама система Windows. Управление же содержимым фрейма, т. е. представлениями, ложится на плечи разработчика.
Для координации создания и взаимодействия трех основных объектов рассматриваемой архитектуры в библиотеке MFC используются специальные классы шаблонов документов, которые создаются и управляются объектом "приложение".
Таким образом, архитектура "документ/представление" охватывает следующие основные классы:
- CWinApp — класс для создания единственного объекта — приложения;
- CFrameWnd — класс для создания главного окна однодокументного приложения и базовый для классов CMDIFrameWnd и CMDIChildWnd, которые отвечают за работу многодокументного приложения;
- CDocTemplate — базовый абстрактный класс для создания шаблонов документов; при работе с однодокументным приложением используется производный от него класс CSingleDocTemplate, а для многодокументных — класс CMultiDocTemplate,
- CDocument — класс для создания собственно документа;
- CView — базовый класс, который совместно со своими производными классами — CCtiiView, CEditView, CListView, CTreeView и CScrollView — отвечает за отображение данных документа и за взаимодействие с пользователем; для этих же целей можно использовать класс CSplitterWnd.
// MainFrm.h : interface of the CMainFrame class
#pragma once
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
public:
// Operations
public:
// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
// Generated message map functions
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
// mfc2Doc.h : interface of the Cmfc2Doc class
#pragma once
class Cmfc2Doc : public CDocument
{
protected: // create from serialization only
Cmfc2Doc();
DECLARE_DYNCREATE(Cmfc2Doc)
// Attributes
public:
// Operations
public:
// Overrides
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
// Implementation
public:
virtual ~Cmfc2Doc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
};
// mfc2View.h : interface of the Cmfc2View class
//
#pragma once
class Cmfc2View : public CView
{
protected: // create from serialization only
Cmfc2View();
DECLARE_DYNCREATE(Cmfc2View)
// Attributes
public:
Cmfc2Doc* GetDocument() const;
// Operations
public:
// Overrides
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
// Implementation
public:
virtual ~Cmfc2View();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in mfc2View.cpp
inline Cmfc2Doc* Cmfc2View::GetDocument() const
{ return reinterpret_cast<Cmfc2Doc*>(m_pDocument); }
#endif
// MainFrm.h : interface of the CMainFrame class
//
#pragma once
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
public:
// Operations
public:
// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
// Generated message map functions
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
// MainFrm.cpp : implementation of the CMainFrame class
#include "stdafx.h"
#include "mfc2.h"
#include "MainFrm.h"
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
// TODO: Delete these three lines if you don't want the toolbar to be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return TRUE;
}
// mfc2Doc.cpp : implementation of the Cmfc2Doc class
//
#include "stdafx.h"
#include "mfc2.h"
#include "mfc2Doc.h"
// Cmfc2Doc
IMPLEMENT_DYNCREATE(Cmfc2Doc, CDocument)
BEGIN_MESSAGE_MAP(Cmfc2Doc, CDocument)
END_MESSAGE_MAP()
// Cmfc2Doc construction/destruction
Cmfc2Doc::Cmfc2Doc()
{
// TODO: add one-time construction code here
}
Cmfc2Doc::~Cmfc2Doc()
{
}
BOOL Cmfc2Doc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
// Cmfc2Doc serialization
void Cmfc2Doc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{ // TODO: add storing code here
}
else
{ // TODO: add loading code here
}
}
// mfc2View.cpp : implementation of the Cmfc2View class
//
#include "stdafx.h"
#include "mfc2.h"
#include "mfc2Doc.h"
#include "mfc2View.h"
IMPLEMENT_DYNCREATE(Cmfc2View, CView)
BEGIN_MESSAGE_MAP(Cmfc2View, CView)
END_MESSAGE_MAP()
// Cmfc2View construction/destruction
Cmfc2View::Cmfc2View()
{// TODO: add construction code here
}
Cmfc2View::~Cmfc2View()
{ }
BOOL Cmfc2View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
// Cmfc2View drawing
void Cmfc2View::OnDraw(CDC* /*pDC*/)
{
Cmfc2Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
}
// mfc2.cpp : Defines the class behaviors for the application.
#include "stdafx.h"
#include "mfc2.h"
#include "MainFrm.h"
#include "mfc2Doc.h"
#include "mfc2View.h"
// Cmfc2App
BEGIN_MESSAGE_MAP(Cmfc2App, CWinApp)
ON_COMMAND(ID_APP_ABOUT, &Cmfc2App::OnAppAbout)
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
END_MESSAGE_MAP()
// Cmfc2App construction
Cmfc2App::Cmfc2App()
{ // TODO: add construction code here,
}
// The one and only Cmfc2App object
Cmfc2App theApp;
BOOL Cmfc2App::InitInstance()
{
CWinApp::InitInstance();
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(4); // Load standard INI file options (including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(Cmfc2Doc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(Cmfc2View));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// Enable DDE Execute open
EnableShellOpen();
RegisterShellFileTypes(TRUE);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line. Will return FALSE if
// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// call DragAcceptFiles only if there's a suffix
// In an SDI app, this should occur after ProcessShellCommand
// Enable drag/drop open
m_pMainWnd->DragAcceptFiles();
return TRUE;
}
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// App command to run the dialog
void Cmfc2App::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
Интерфейс многодокументного приложения:
Приложение может поддерживать произвольное число типов документов. Единственное, что для этого нужно сделать — это создать и "зарегистрировать" во время инициализации объекта-приложения (при выполнении функции Initlnstance) необходимое число шаблонов документов. Причем для каждого типа документа, с которым предполагается работа, используется свой шаблон. Например, если приложение поддерживает документы двух разных типов — табличные и текстовые, то оно должно создать для них два разных шаблона.
В библиотеке классов MFC для работы с шаблонами документов реализованы специальный класс — CDocTemplate и два производных от него — CSingleDocTemplate и CMultiDocTemplate. Рассмотрим возможности, которые в них заложены.
Создание различных типов документов
Базовым классом для создания шаблонов является CDocTemplate. Это абстрактный класс, в котором реализованы основные функциональные возможности для работы с шаблонами документов — организация и управление взаимодействием между классами трех типов:
- Классом документа, образованного из CDocument.
- Классом представления, который изображает данные документа. Можно создать этот класс на базе CView, CScrollView, CFormView, CEditView и т. д. (CEditView используется непосредственно для текстовых документов).
- Классом фрейма, который содержит представление. Для SDI-приложе-ний он создается на основе CFrameWnd, а для MDI-приложений — на базе CMDIChildWnd. Базовые классы можно использовать и непосредственно.
Место классов для создания шаблонов документов в иерархии библиотеки MFC
Рассмотрим основные компоненты класса CDocTemplate. Начнем, как обычно, с конструктора, который фиксирует типы документа, фрейма и представления, доступные для работы с данным шаблоном.
CDocTemplate::CDocTemplate (
UINT nIDResource,
CRuntimeClass *pDocClass,
CRuntimeClass *pFrameClass,
CRuntimeClass *pViewClass)
Создает объект класса. В качестве аргументов используются: nIDResource — идентификатор ресурсов (меню, командные клавиши и строка описания типа шаблона документа), используемых с этим типом документов; pDocClass— указатель на объект CRuntimeClass, отвечающий за данные документа; pFrameClass — указатель на объект CRuntimeClass, характеризующий фрейм документа; pViewClass— указатель на объект CRuntimeClass, отвечающий за представление документа. Эти объекты должны быть уже определены к моменту создания объекта "шаблон документа". Память под этот объект следует распределять динамически, а полученный указатель передать в качестве параметра в функцию CWinApp::AddDocTemplate.
virtual void CDocTemplate::AddDocument (CDocument *pDoc),
virtual void CDocTemplater:RemoveDocument (CDocument *pDoc)
Добавляет (удаляет) документ, на который указывает pDoc, в список документов, ассоциированных с этим шаблоном. В производных классах CSingleDocTemplate и CMultiDocTemplate эти функции переопределены.
virtual void CDocTemplate::LoadTemplate ()
Загружает ресурсы для данного шаблона документа. Обычно вызывается библиотекой MFC во время создания объекта и практически не требует прямого вызова. Исключение составляет случай, когда объект класса создается на глобальном уровне. В этом случае во время выполнения функции CWinApp:: AddDocTemplate необходим явный вызов LoadTemplate.
Ресурсами, используемыми документами этого типа, могут быть меню, командные клавиши и единственный строковый ресурс. Рассмотрим более подробно структуру строки описания типа.
// Строка описания типа шаблона документа
STRINGTABLE PRELOAD
DISCARDABLE BEGIN
IDR_NOTETYPE "\nNotenNotenNote Files (*.tnd)\n.tnd\nNote.Document\nNote Document"
END
Как видите, строка состоит из семи подстрок (первая — пустая), разделенных символом "n", которые содержат дополнительную информацию о типе документа:
- Заголовок главного окна SDI-приложения (Main frame caption). He используется для MDI-приложений (обратите внимание, что в приведенном примере это поле отсутствует).
- Имя файла, присваиваемое новому документу по умолчанию (Doc type name) — Note. Если эта подстрока отсутствует, то используется имя Unfitted или его аналог для локализованных версий Windows (Без Имени — для русской версии).
- Имя типа документа (File new name (OLE short name)) — Note. Если в приложении определено больше одного шаблона, то при создании нового документа на экране отображается блок диалога для выбора типа создаваемого документа.
- Описание типа документа и его фильтра (Filter name) — Note Files (*.tnd). Эта строка отображается в списке типов документов стандартных блоков диалога Open (Открыть) и Save As (Сохранить как).
- Расширение, используемое для документов этого типа (File extension) — .tnd.
- Идентификатор типа документа, хранящийся в реестре Windows (File type ID), — Note.Document.
- Имя типа документа, хранящееся в реестре Windows (File new name (OLE long name)), — Note Document. Это же имя используется в качестве длинного имени объекта OLE, если в приложение включена соответствующая поддержка.
Примечание
В скобках указаны названия соответствующих полей диалога Advanced Options (Дополнительные параметры) мастера создания каркаса приложения AppWizard.
Если какая-либо из этих подстрок не включается в строку, то вместо нее обязательно используется разделяющий символ "n". Заключительный символ "n" в строке является необязательным.
Доступ к этой информации осуществляется с помощью функции
virtual BOOL CDocTemplate::GetDocString (
CStringS rString,
enum DocStringlndex index)
Позволяет получить определенную подстроку, описывающую тип документа, которая хранится в шаблоне и получена из соответствующей строки файла ресурсов приложения. Найденная подстрока записывается в rString. Параметр index определяет индекс подстроки, информацию о котором необходимо получить. Он может принимать одно из следующих значений:
CDocTemplate::windowTitle
Имя, отображаемое в заголовке главного окна приложения; представлено только в шаблоне документа для SDI-приложений
CDocTemplate::docName
Основа имени документа; имя нового документа этого типа складывается из основы, к которой добавляется число; если значение не определено, то по умолчанию используется Untitled (для русской версии Windows — Без Имени)
CDocTemplate::fileNewName
Имя типа документа; если значение не определено, то этот тип документа недоступен при выполнении команды FileNew (ФайлСоздать)
CDocTemplate::filterNewName
Описание типа документа и нейтрального символа для фильтра, сопоставляемого с документами этого типа. Данная строка изображается в списке типов файлов в блоке диалога File Open (Открытие файла); если значение не определено, то этот тип документа недоступен при выполнении команды FileOpen (Файл/Открыть)
CDocTemplate::filterExt
Расширение документов этого типа; еслизначение не определено, то данный тип документа недоступен при выполнении команды FileOpen (Файл/Открыть)
CDocTemplate::regFileTypeld
Идентификатор типа документа, хранящийся в реестре Windows. Эта строка предназначена только для внутреннего использования; если не определена, то тип документа не может быть зарегистрирован в File Manager (Диспечер файлов)
CDocTemplate::regFileTypeName
Имя типа документа, хранящегося в регистрационной базе данных; эта строка может быть отображена в блоках диалога приложения, вызываемых для доступа к регистрационной базе данных
Кроме того, в классе CDocTemptate объявлены еще четыре "чистые" функции: GetFirstDocPosition, GetNextDoc, OpenFileName и SetDefaultTitle. Наличие этих функций превращает CDocTemplate в абстрактный класс и, следовательно, его нельзя использовать непосредственно. Обычно приложения используют один из двух производных от него классов, предоставляемых библиотекой MFC: CSingleDocTemplate — для SDI- и CMultiDocTemplate — для MDI-приложений.
Примечание
Если по каким-либо причинам может потребоваться интерфейс, который фундаментально отличается от SDI и MDI, то можно образовать свой класс непосредственно из CDocTemplate.
Для полноты картины приведу прототипы еще нескольких функций этого класса, которые в явном виде используются достаточно редко, но в некоторых случаях могут быть полезны.
Если шаблон поддерживает несколько типов файлов, то, используя функцию MatchDocType для каждого шаблона, можно определить, какие шаблоны документов подходят для данного файла, и выбрать тот, который нужен:
virtual Confidence CDocTemplate::MatchDocType (
LPCTSTR IpszPathName,
CDocument *&rpDocMatch)
Служит для определения типа шаблона документа, используемого для открытия файла. Параметры: IpszPathName — полное имя файла; rpDocMatch — указатель на уже открытый документ, если файл, определенный в IpszPathName, открыт. Функция возвращает значение, определенное в перечислении Confidence:
enum Confidence {
noAttempt,
maybeAttemptForeign,
maybeAttemptNative,
yesbeAttemptForeign,
yesbeAttemptNative,
yesAlreadyOpen
};
Если файл, определенный в параметре IpszPathName, уже открыт, то функция возвращает CDocTemplate::yesAlreadyOpen и копирует объект CDocument файла в объект rpDocMatch. Если файл еще не открыт, но расширение имени в IpszPathName совпадает со значением, определенным в CDocTemplate::filterExt, то функция возвращает CDocTemplate::yesAttemptNative и устанавливает rpDocMatch в NULL. В остальных случаях функция возвращает значение CDocTemplate:: yesAttemptForeign. Другие члены перечисления можно использовать при переопределении этой функции.
virtual CDocument* CDocTemplate::CreateNewDocument ()
Создает новый документ, тип которого определяется текущим шаблоном. Функция возвращает указатель на вновь созданный документ или NULL в случае ошибки.
CDocTemplate — абстрактный класс, и на его основе объекты шаблонов не создаются. Его основная роль заключается в обеспечении шаблонов основными свойствами, а для создания конкретных объектов в библиотеке MFC реализованы два другие класса — СSingleDoTemplate и CMultiDocTemplate, которые специально адаптированы для работы соответственно в SDI- и MDI-приложениях.
Шаблоны однодокументных приложений
Для создания шаблона однодокументного интерфейса в библиотеке MFC реализован класс СSingleDocTemplate. Как вы помните, в SDI-приложениях главный фрейм является одновременно и фреймом документа, другими cловами — в каждый конкретный момент времени может быть открыт только один документ. Обычно SDI-приложения поддерживают один тип документа (хотя это и не является обязательным условием), т. е. они содержат только один объект класса CSingleDocTemplate.
Объекты этого класса обрабатываются внутри библиотеки MFC. В своей защищенной части класс содержит член, в котором хранится указатель на документ, присоединенный к шаблону:
class CSingleDocTemplate : public CDocTemplate
{
...
protected:
CDocument *m_pOnlyDoc;
...
}
Принцип действия и параметры конструктора полностью повторяют параметры базового класса CDocTemplate. Помимо конструктора, в классе реализованы все четыре "чистые" функции класса CDocTemplate.
virtual POSITION CDocTemplate::GetFirstDocPosition () .
Возвращает позицию первого документа из списка документов, ассоциированных с данным шаблоном, или NULL, если список пуст. Она переопределена в обоих производных классах— CSingleDocTemplate и CMultiDocTemplate. Если возникло желание создать свой класс на базе CDocTemplate, то эту функцию следует в нем переопределить.
virtual CDocument* CDocTemplate::GetNextDoc (POSITION SrPos)
Возвращает указатель на объект-документ из общего списка документов, ассоциированных с шаблоном, который хранится непосредственно за документом, заданным его позицией в списке (параметр rPos). Позиция полученного документа записывается в rPos. Если возвращен указатель на последний элемент списка, то в параметр rPos функция записывает NULL. Для получения указателя на первый документ списка необходимо вызвать эту функцию до GetFirstDocPosition. При использовании в качестве параметра rPos недопустимого значения библиотека MFC генерирует исключение.
virtual CDocument* CDocTemplate::OpenDocumentFile (
LPCTSTR IpszPathName,
BOOL bMakeVisible = TRUE)
Позволяет открыть файл, заданный полным именем IpszPathName, где содержится необходимый документ. Если значение этого параметра равно NULL, то вызывается функция CreateNewDocument, которая создает новый файл, содержащий документ типа, ассоциированного с этим шаблоном. При успешном завершении функция возвращает указатель на документ, в противном случае NULL.
virtual void CDocTemplate;.:SetDefaultTitle (CDocument *pDoc)
Загружает заголовок документа, используемый по умолчанию и определенный в строке ресурса, и выводит его в полосу заголовка фрейма документа.
Кроме перечисленных "чистых" функций, в классе переопределены также функции базового класса AddDocument и RemoveDocument.
Дата добавления: 2017-01-26; просмотров: 2213;