Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Паппас К., Мюррей У. - Visual C++ 6. Руководство разработчика - 2000

.pdf
Скачиваний:
290
Добавлен:
13.08.2013
Размер:
4.96 Mб
Скачать

поверх документа Word, а панели инструментов и меню будут интегрированы в окно Word(рис. 21.3). При этом сам Wordавтоматически перейдет в режим разметки страниц.

Рис. 21.3. В качестве внедряемого объекта выбран рисунок из приложения Paint

Теперь, используя все средства и возможности программы Paint, можно нарисовать изображение, которое вы хотите добавить в текстовый документ (рис. 21.4). После завершения работы над рисунком выберите в меню File команду Save.

391

Рис. 21.4. Рисунок, внедряемый в текстовый документ, создаетсяы с помощью программы Paint

Окончив работу над рисунком, щелкните мышью на текстовом документе за пределами области рисования, чтобы' возвратиться в Wordи закрыть редактор Paint. На рис. 21.5 показан документ Word, содержащий внедренный объект.

392

Рис. 21.5. Текстовый документ Word с внедренным рисунком

А теперь самое интересное. Предположим, вы решили, что внедренный объект требует изменений. Выполните на нем двойной щелчок. При этом запустится исходное приложение, в которое будет загружен объект для редактирования (рис. 21.6).

393

Рис. 21.6. При необходимости отредактировать внедренный объект выполните на нем двойной щелчок

394

Рис. 21.7. Отредактированный объект

Связывание

Технология OLE поддерживает также динамическое связывание объектов, созданных в разных приложениях. При наличии связи приложения могут одновременно использовать одни и те же объекты. Раньше связывание было довольно неустойчивым механизмом, поскольку связи легко разрывались при перемещении файлов на диске. В настоящий момент в OLEиспользуются псевдонимы (monikers), позволяющие успешно решать многие из существовавших прежде проблем. Псевдонимом называется специальный СОМ-объект, в котором хранится имя связанного объекта и информация о его местоположении. Именно псевдонимы выполняют задачу поиска объектов, освобождая от этого приложение-контейнер.

Создание OLE-контейнера

Приложение-контейнер Cnt, созданием которого мы сейчас займемся, напоминает программу Graphс SDI-интерфейсом, созданную нами в предыдущей главе. В данном приложении будут использованы два важных OLE-класса: COleClientItem и COleDocument. Класс COleDocument

управляет списком объектов класса COleClientItem. Класс СOleClientItem, в свою очередь, управляет внедренными или связанными объектами и поддерживает взаимодействие между контейнером и сервером.

Обратите внимание на тот факт, что код приложения полностью создан мастером AppWizard. Полученный шаблон впоследствии можно расширить дополнительными средствами, написав соответствующие фрагменты самостоятельно или воспользовавшись мастером ClassWizard.

Работа с мастером приложений

395

Работа с мастером AppWizardдостаточно подробно рассматривалась в предыдущей главе. Поэтому сейчас мы сконцентрируем внимание лишь на наиболее важных моментах создания приложения Cnt.

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

MicrosoftVisualC++ в меню File командуNew.

В окне Newвыберите элемент MFC AppWizard(exe), в результате чего будет запущен мастер приложений, работа с которым осуществляется в шесть этапов.

1.В первом окне установите опцию Singledocument.

2.Во втором окне не задавайте поддержку баз данных.

3.В третьем окне установите опцию Container, указывающую на то, что приложение будет OLE-контейнером. В этом же окне следует включить поддержку элементов управления ActiveX.

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

5.В пятом окне установите опцию MFC Standard, опцию включения комментариев в программу и опцию статической компоновки библиотеки MFC .

6.Наконец, в шестом окне, просмотрите список классов, которые будут созданы автоматически, и щелкните на кнопке Finish.

Мастер приложений отобразит окно с отчетом о сделанных установках. Если все правильно, щелкните на кнопке ОК, с тем чтобы запустить процесс генерации кода нового приложения.

Теперь осталось только построить исполняемый файл приложения, выбрав для этого в меню Build команду Rebuild All. В результате в папку DEBUG будет добавлен файлСМТ.ЕХЕ.

Анализ программного кода

Приложение включает пять основных исходных файлов, сгенерированных мастером

AppWizard: CNT.CPP, MAINFRM.CPP, CNTDOC.CPP, CNTVIEW.CPP и CNTRITEM.CPP.

Файл CNT.CPP

Текст, содержащийся в файле CNT.CPP, почти идентичен тексту файлов GRAPH.CPP и EDITOR.CPP приложений Graphи Editor, описанных в предыдущей главе. Поэтому рекомендуем вам вернуться к той главе и еще раз прочитать пояснения к указанным файлам.

Листинг файла CNT.CPP показан ниже.

//Cnt.cpp: определяет работу приложения.

#include "stdafx.h" #include "Cnt.h"

#include "MainFrm.h" #include "CntDoc.h" #include "CntView.h" #ifdef _DEBUG

#define new DEBUG_NEW #undef THIS_FILE

static char THIS_FILE[] = _FILE_; #endif

////////////////////////////////////////////////////////////////

//CCntApp

BEGIN_MESSAGE_MAP {CCntApp, CWinApp) //{(AFX_MSG_MAP (CCntApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

//ПРИМЕЧАНИЕ: мастер классов будет добавлять и удалять здесь

//макросы схемы сообщений.

//НЕ РЕДАКТИРУЙТЕ то, что здесь находится.

//}}AFX_MSG_MAP

// Стандартные операции с документами

ON_COMMAND(ID_FILE_NEW, CWinApp :: OnFileNew) ON__COMMAND(ID_FILE_OPEN, CWinApp: :OnFileOpen)

396

// Стандартная команда задания установок принтера

ON_COmAND(ID_FILE_PRINT_SETUP, CWinApp: :OnFilePrintSetup) END_MESSAGE_MAP()

////////////////////////////////////////////////////////////////

//КонструкторклассаCCntApp CCntApp::CCntApp() {

//TODO: здесь добавьте код конструктора.

//Все наиболее важные команды инициализации

//разместите в методе Initlnstance. }////////////////////////////////////////////////////////////////

//Единственный объект класса CCntAppCCntApptheApp;

////////////////////////////////////////////////////////////

//Инициализация класса CCntApp

BOOLCCntApp::Initlnstance() {

//Инициализация библиотек OLE if(!Afx01eInit() )

{

AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } AfxEnableControlContainer ();

//Стандартнаяинициализация.

//Если вам не нужны используемые здесь возможности

//и вы хотите сократить размер исполняемого файла,

//удалите ненужные команды.

tifdef _AFXDLL Enable3dControls();

//эта функция вызывается при

//динамической компоновке MFC #else Enable3dControlsStatic();

//эта функция вызывается при

//статической компоновке MFC #endif

//Измените раздел реестра, где будут храниться

//параметры программы.

SetRegistryKey(_T("Local AppWizard-Generated Applications"));

LoadStdProfileSettings();

//загрузка параметров из INI-файла

//Регистрация шаблонов документов приложения

CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate (

IDR_MAINFRAME, RUNTIME_CLASS (CCntDoc) ,

RUNTIME_CLASS (CMainFrame) , // основное SDI-окно>> RUNTIME_CLASS (CCntView) ) ; pDocTemplate->SetContainer!nfo(IDR_CNTR_INPLACE) ; AddDocTemplate (pDocTemplate) ;

//Анализ командной строки на предмет поиска системных команд, // DDEкоманд или команд открытия файлов. CCommandLinelnfo cmdlnfo; ParseCommandLine (cmdlnf о) ;

//Обработка команд, указанных в командной строке

if ( ! ProcessShellCommand (cmdlnfo) ) return FALSE; // Отображение окна приложенияm

_pMainWnd->ShowWindow (SW_SHOW) ; m_pMainWnd->UpdateWindow() ; return TRUE;

397

}

////////////////////////////////////////////////////////////////

//Класс CAboutDlg, управляющий окном About class CAboutDlg : public CDialog { public: CAboutDlg ( ) ;

//Данные диалогового окна

//{{AFX_DATA (CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA

//Виртуальные функции, сгенерированные мастером ClassWizard //{{AFX_VIRTUAL (CAboutDlg)

protected:

virtual void DoDataExchange (CDataExchange* pDX) ; //})AFX_VIRTUAL

//Реализация

protected:

//{ { AFX_MSG (CAboutDlg)

//Обработчики сообщений отсутствуют

//})AFXMSG DECLARE_MESSAGE_MAP() };

CAboutDlg: : CAboutDlg () : CDialog (CAboutDlg: : IDD) { //{fAFX_DATA_INIT (CAboutDlg)

//}}AFX DATA INIT

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg)

/ / } } AFX_DATA_MAP }

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg)

//Обработчики сообщений отсутствуют //}}AFX_MSG_MAPEND_MESSAGE_MAP()

//Функция, управляющая выводом окна About

void CCntApp::OnAppAbout()

{

CAboutDlg aboutDlg; aboutDlg.DoModal(); }

////////////////////////////////////////////////////////////////

// Другие функции класса CCntApp

Данный листинг содержит один фрагмент, заслуживающий особого внимания. В OLE используется концепция непосредственного редактирования (in-placeediting). Это означает, что после двойного щелчка на объекте, внедренном в документ контейнера, такой как наш, строка меню и панели инструментов соответствующего OLE-сервера замещают меню и панели инструментов контейнера. Например, если в документ приложения Cnt будет внедрена электронная таблица Excel, то после двойного щелчка на ней строка меню и панели инструментов программы Excel появятся в окне программы Cnt.

Смена меню происходит автоматически и обрабатывается библиотекой MFC с помощью средств OLE. Этот процесс становится возможным благодаря тому, что в приложение добавляется два ресурса меню: idr_mainfraimeи idr_cntr_inplace (имя последнего идентификатора уникально для данного приложения). По умолчанию отображается меню IDR_MAINFRAIME. Но когда внедренный объект активизируется для непосредственного редактирования, загружается меню idr_cntr_in-PLACE.

Файл MAINFRM.CPP

Опять-таки, текст файла MAINFRM.CPP, по сути, идентичен тексту одноименного файла приложения Editor из предыдущей главы. И мы рекомендуем вам еще раз вернуться к той главе и прочесть комментарии к нему. Но для полноты изложения текст файла все же приведем.

398

//MainFrm.cpp: реализация класса CMainFrame

#include "stdafx.h" #include "Cnt.h"

#include "MainFrm.h" tifdef _DEBUG #define new DEBUG_NEW

tundef THIS_FILE

Static char THIS_FILE[] = _FILE_; #endif

////////////////////////////////////////////////////////////////

//CMainFrame

IMPLEMENT_DYNCREATE (CMainFrame, CFrameWnd) i BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd) //{{AFX_MSG_MAP (CMainFrame)

//ПРИМЕЧАНИЕ: мастер классов будет добавлять и удалять здесь

//макросы схемы сообщений.

//НЕ РЕДАКТИРУЙТЕ то,что здесь находится.

//}}AFX_MSG_MAPEND_MESSAGE_MAP ( ) static UINT indicators!] = {

ID_SEPARATOR, // поля строки состояния

ID_INDICATOR_^CAPS,

ID_INDICATOR_NUM,

ID_INDICATOR_SCRL, };

////////////////////////////////////////////////////////////////

IIКонструктор и деструктор класса CMainFrame CMainFrame::CMainFrame() {

// TODO: здесь добавьте код конструктора.

}

CMainFrame::-CMainFrame() f

int CMainFrame: :OnCreate (LPCREATESTRUCT IpCreateStruct) { if (CFrameWnd: :OnCreate (IpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |

WS_VISIBLE I CBRS_TOP | CBRS_GRIPPER I CBRSJTOOLTIPS I CBRS_FLYBY | CBRS_SIZE_DYNAMIC) | !m_wndToolBar.LoadToolBar(IDR_MAINFRAME) ) {

TRACEO ("Failed to create toolbar\n") ;

 

return-1; // создать панель инструментов не удалось

 

}

 

if (!m_wndStatusBar.Create(this)||

 

!m_wndStatusBar.Setlndicators(indicators,

 

sizeof(indicators)/sizeof(UINT))) (

// создать

TRACEO("Failedto create status bar\n"); return -1;

строку состояния неудалось}

 

//TODO: удалите следующие три строки, если вы не хотите,

//чтобы панель инструментов была перемещаемой.

m_wndToolBar . EnableDocking (CBRS_ALIGN_ANY) ; EnableDocking(CBRS_ALIGN_ANY) ;

DockControlBar (Sm_wndToolBar) ; return 0;

}

BOOL CMainFrame: : PreCreateWindow (CREATESTRUCT Ses) { if(ICFrameWnd: : PreCreateWindow (cs)) return FALSE;

// TODO: здесь можно модифицировать класс окна, изменяя поля структуры cs.

399

return TRUE; }

////////////////////////////////////////////////////////////////

//Диагностика класса CMainFrame #ifdef _DEBUG

void CMainFrame: :AssertValid () const

{

CFrameWnd: :AssertValid() ;

}

void CMainFrame::Dump(CDumpContext Sdc) const

{

CFrameWnd::Dump(dc); } #endif //_DEBUG

////////////////////////////////////////////////////////////////

//Обработчики сообщений класса CMainFrame

Файл CNTDOC.CPP

Файл CNTDOC.CPPсодержит ряд дополнительных фрагментов, с которыми ранее мы не встречались.

//CntDoc.cpp: реализация класса CCntDoc// #include "stdafx.h" #include "Cnt.h"

# include "CntDoc.h" #include "Cntrltem.h" tifdef _DEBUG #define new DEBUG_NEW lundef THIS_FILE

static char THIS_FILE[] = _ FILE _ ; #endif

////////////////////////////////////////////////////////////////

//CCntDoc

IMPLEMENT_DYNCREATE (CCntDoc, COleDocument)

BEGIN_MESSAGE_MAP (CCntDoc, COleDocument) //{{AFX_MSG_MAP (CCntDoc)

//ПРИМЕЧАНИЕ: мастер классов будет добавлять и удалять здесь

//макросы схемы сообщений.

//НЕ РЕДАКТИРУЙТЕ то, что здесь находится.

//}}AFX_MSG_MAP

// Используется стандартная реализация OLE-контейнера

ON_UPDATE_COMMAHD_UI ( ID_EDIT_PASTE,

COleDocument: :OnUpdatePasteMenu) ON_OPDATE_COMMAMD_OI ( ID_EDIT_PASTE_LINK ,

COleDocument: :OnUpdatePasteLinkMenu) ON_UPDATE_COMMMJD_UI ( ID_OLE_EDIT_CONVERT ,

COleDocument: :OnUpdateObjectVerbMenu) ON_COMMAND (ID_OLE_EDIT_CONVERT,

COleDocument: :OnEditConvert) ON_OPDATE_COMMAHD_OI (ID_OLE_EDIT_LINKS

,

COleDocument: :OnUpdateEditLinksMenu) ON_COMMAND (ID_OLE_EDIT_LINKS , COleDocument: :OnEditLinks)

ON_0PDATE_COMMAND_UI_RftNGE ( ID_OLE_VERB_FIRST , ID_OLE_VERB_IAST,

COleDocument: :OnUpdateObjectVerbMenu) END_MESSAGE_MAP ()

////////////////////////////////////////////////////////////////

// Конструктор и деструктор класса CCntDoc

'

CCntDoc: : CCntDoc( ) {

 

400

Соседние файлы в предмете Программирование на C++