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

Visual C++ 6. Руководство Разработчика [rus]

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

Рис. 20.7. Шаг 6: перечень генерируемых классов

В шестом окне мастера AppWizard отображается список классов, которые будут сгенерированы для нашего приложения, а именно CGraphApp, CMainFrame, CGraphDoc и CGraphView.

Для класса CGraphView, реализующего функции области просмотра, в списке Baseclass

можно выбрать базовый класс (CEditView, CFormView, CHtmlView, CListView, CRichEditView, CScrollView, CTreeView или CView), от которого он будет порождаться. Класс CView, потомок CWnd, является родительским для всех перечисленных классов. Область просмотра служит буфером между документом и пользователем и представляет собой дочернее окно главного окна приложения. Она содержит графический образ документа, выводимого на экран или принтер, а также поддерживает возможность редактирования документа с помощью клавиатуры и мыши. Класс CFormView описывает область просмотра с полосами прокрутки, основанную на шаблоне диалогового окна и включающую элементы управления. Класс CEditView реализует функции текстового редактора и будет использован в следующем примере этой главы.

После щелчка на кнопке Finish будет выведено окно с итоговым отчетом, подготовленным мастером AppWizard(рис. 20.8).

Рис. 20.8. Отчет, выдаваемый мастером AppWizard после установки всех опций

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

Мастер классов

С помощью мастера ClassWizard для разрабатываемого приложения можно сгенерировать дополнительные программные блоки. В частности, вы можете создать подпрограммы обработки сообщений wm_paint, WM_MOUSEMOVE и т.д. Как уже упоминалось, для запуска мастера классов в меню View нужно выбрать команду ClassWizard.... Добавив в программу

361

функцию OnPaint(), мы получим возможность обрабатывать сообщения wm_paint, связанные с перерисовкой рабочей области окна. Для этого в раскрывшемся окне, в списках Classname и ObjectIDs, необходимо выбрать класс CGraphView(рис. 20.9).

Рис. 20.9. Окно мастера классов, в котором выбран класс CGraphView

В списке Messages теперь отображается перечень сообщений, связанных с этим классом. Выполните двойной щелчок на сообщении wm_paint, и в списке Memberfunctions появится функция OnPaint() (рис. 20.10). После щелчка на кнопке ОК данная функция будет добавлена в файл GRAPHVIEW.CPP.

Следующий этап — это компиляция и тестирование нового приложения.

362

Рис. 20.10 В проект добавлена функция OnPaint()

Построение приложения

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

Build команду RebuildAll(рис. 20.11).

Рис. 20.11. Команда Rebuild All выполняет построение приложения

Во время построения приложения все данные об этом процессе будут выводиться на экран на вкладке Build окна Output(рис. 20.12).

363

Рис. 20.12. Вывод информации о ходе компиляции

Компилятор сообщает о том, что четыре исходных файла — GRAPH.CPP, MAINFRM.CPP, GRAPHDOC.CPP и GRAPHVIEW.CPPбыли успешно скомпилированы и скомпонованы. По правде говоря, это лишь вершина айсберга. Если вы просмотрите папку проекта, то найдете там еще около 30 различных файлов, сообщить о которых компилятор не посчитал нужным.

Исполняемый файл приложения по умолчанию будет записан в папку DEBUG.

Окно пусто, так как ни одна функция рисования в программу пока не добавлена. К тому же многие команды меню не будут работать. Дело в том, что код для обработки сообщений, связанных с выбором команд меню, вы должны ввести самостоятельно. Он не может быть сгенерирован автоматически. Но если вы хорошо усвоили предыдущий материал, то создание необходимого кода не станет для вас большой проблемой. В последнем примере этой главы будет показано, как написать соответствующие функции.

364

Рис. 20.13. Окно программы

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

Мастер AppWizard автоматически создал четыре файла: Graph.cpp MainFrm.cpp GraphDoc.cpp

и GraphView.cpp, каждый из них связан с соответствующим файлом заголовков. Файлы заголовков содержат описания классов, используемых в исходных файлах.

Файл Graph.cpp

Это основной файл и его код показан ниже:

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

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

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

//ициализация класса CGraphApp CGraphApp::Initlnstance() //Стандартная инициализация.

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

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

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

//Измените раздел реестра, где будут храниться //параметры программы. tRegistryKey(_T("LocalAppWizard-GeneratedApplications"));

adStdProfileSettings(); // Загрузка параметров из INI-файла, //в том числе списка последних открытых файлов //Регистрация шаблона документов приложения

SingleDocTemplate* pDocTemplate; 'OcTemplate = new CSingleDocTemplate

(

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

// CGraphApp

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

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

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

365

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

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

ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) END_MESSAGE_MAP() //{{AFX_DATA_INIT(CAboutDlg) //}}AFX DATA INIT

}

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

//}}AFX_DATA_MAP i

BEGIN_MESSAGE_MAP (CAboutDlg, CDialog)

//{ (AFX_MSG_MAP (CAboutDlg) //}}AFX_MSG_MAP END_MESSAGE_MAP ( )

//Функция, управляющая выводом окна About void CGraphApp : : OnAppAbout ( )

{

CAboutDlg aboutDlg; aboutDlg . DoModal ( ) ;

}

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

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

Первая схема сообщений, содержащаяся в этом файле, принадлежит классу CGraphApp. В ней сообщения с идентификаторами id_app_about, id_file_new и ID_FILE_OPEN связываются С обработчиками OnAppAbout() , CWinApp: :OnFileNew()и CWinApp: :OnFileOpen(). В файле содержатся реализации конструктора класса CGraphApp, а также его методов initinstance() и OnAppAbout().

Диалоговое окно About принадлежит классу CAboutDlg, являющемуся потомком класса CDialog. У него имеется схема сообщений, конструктор и метод DoDataExchange ().

Файл MAINFRM.CPP

Файл MAINFRM.CPPсодержит реализацию класса CMainFrame, который порождается от класса CFrameWnd и управляет SDI-окном приложения.

//MainFrm.cpp: реализация класса CMainFrame// #include "stdafx.h"

#include "Graph.h" #include "MainFrm.h" #ifdef _DEBUG

#def ine new DEBUG_NEW #undef THIS_FILE

static char THIS_FILE[]= _ FILE #endif

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

1 1 CMainFrame

IMPLEMENT_DYNCREATE (CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd)

//{ (AFX_MSG_MAP (CMainFrame)

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

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

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

//}}AFX_MSG_MAP END_MESSAGE_MAP ( )

366

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

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

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

}

CMainFrame::-CMainFrame()

{

}

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

returnFALSE;

//TODO: здесь можно модифицировать класс окна,

//изменяя поля структуры cs.

return TRUE; }

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

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

void CMainFrame: :AssertValid()const

{

CFrameWnd: :AssertValid() ;

void CMainFrame: : Dump (CDumpContext &dc) const { CFrameWnd: : Dump (dc);

}

#endif //_DEBUG

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

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

Внимательно просмотрев этот листинг, вы заметите, что конструктор и деструктор не содержат никакого кода, обработчики сообщений отсутствуют, а для функций AssertValid(), Dump() и PreCreateWindow() вызываются одноименные методы базового класса.

Файл GRAPHDOC.CPP

Файл GRAPHDOC.CPP содержит реализацию класса CGraphDoc, который управляет работой с документом, а также обеспечивает загрузку и сохранение данных документа.

//GraphDoc.cpp: реализация класса CGraphDoc// #include "stdafx.h"

#include "Graph. h" #include "GraphDoc. h"

tifdef _DEBOG #define new DEBUGJSIEW #undef THIS_FILE

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

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

//CGraphDoc

IMPLEMENT_DYNCREATE (CGraphDoc, CDocument)

BEGIN_MESSAGE_MAP (CGraphDoc, CDocument) //( (AFX_MSGJXIAP (CGraphDoc)

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

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

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

//}}AFX_MSG_MAP END_MESSAGE_MAP ( )

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

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

367

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

}

CGraphDoc::-CGraphDoc ()

{

}

BOOL CGraphDoc::OnNewDocument()

if (ICDocument::OnNewDocument{)) return FALSE;

: // TODO: здесь добавьте код повторной инициализации

//(специфика SDI-приложений).

return TRUE; )

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

// Сериализация класса CGraphDoc

void CGraphDoc: : Serialize (CArchive Sar) { if (ar . IsStoring () ) {

//TODO: здесь добавьте код сохранения } else{

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

} }

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

//Диагностика класса CGraphDoc fifdef _DEBUG

void CGraphDoc::AssertValid() const

{

CDocument::AssertValid(); }

void CGraphDoc: : Dump (CDumpContext Sdc) const f CDocument :: Dump (dc); ) #endif //_DEBUG

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

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

Проанализировав этот листинг, вы вновь обнаружите, что схема сообщений, конструктор и деструктор класса пусты. Для остальных четырех функций вызываются их реализации из базового класса. Функция Serializedреализует концепцию постоянства документа. В следующем примере посредством этой функции будет организован файловый ввод/вывод данных документа.

Файл GRAPHVBEW.CPP

Файл GRAPHVIEW.CPP содержит реализацию класса CGraphview, который порождается от класса CView и отвечает за отображение документа.

// GraphView.cpp: реализация класса CGraphView// #include "stdafx.h"

#include "Graph. h" #include "GraphDoc.h" #include "GraphView.h" #ifdef _DEBUG

#define new DEBUG_NEW #undef THIS__FILE

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

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

// CGraphview

IMPLEMENT_DYNCREATE (CGraphview, CView) BEGIN_MESSAGE_MAP (CGraphview, CView) // ( {AFX_MSG_MAP (CGraphview) ON_WM_PAINT()

//}}AFX_MSG_MAP END_MESSAGE_MAP ( )

368

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

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

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

}

CGraphView::~CGraphView()

{

}

BOOL CGraphView::PreCreateWindow(CREATESTRUCT Ses)

{

//TODO: здесь можно модифицировать класс окна,

//изменяя поля структуры cs.

return CView::PreCreateWindow(cs); }

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

// Отображениедокумента

void CGraphview::OnDraw(CDC* pDC)

{

CGraphDoc*

pDoc =

GetDocument(); ASSERT_VALID(pDoc);

// TODO:

здесь

добавьте код отображения }

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

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

void CGraphView::AssertValid() const

{

CView::AssertValid(); }

void CGraphview: : Dump (CDumpContext Sdc) const { CView: : Dump (dc); }

CGraphDoc* CGraphview: : GetDocument () // отладочнаяверсия( ASSERT (m_pDocument->IsKindOf (RUNTIME_CLASS (CGraphDoc) ) ) ; return (CGraphDoc*)m_pDocument; } #endif //_DEBUG

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

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

void CGraphview: :OnPaint () {

CPaintDCdc(this);// контекст устройства для рисования

// TODO: здесь добавьте собственный код обработки сообщения

//Не вызывайте метод CView: :OnPaint ()

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

В функции OnDraw( ) запрашивается указатель pDoc на данные, содержащиеся в документе. Для функций AssertValid() и Dump()вызываются их аналоги из базового класса.

Вывод данных в окно

На первом этапе разработки приложения Graph с помощью мастеров Арр Wizardи ClassWizard был создан интерфейс приложения, ориентированный на работу с одним документом. С помощью мастера классов в класс CGraphview был добавлен обработчик сообщений WM_PAINT. Код для функции OnPaint() мы возьмем из программы GDI.CPP, рассматривавшейся в предыдущей главе.

// Обработчики сообщений класса CGraphView voidCGraphView::OnPaint()

{

static DWORD dwColor[9]={

RGB(0,0, 0),

// черный

RGB(255,0, 0),

// красный

369

RGB(0,255,0),

// зеленый

RGB(0,0, 255),

// синий

RGB(255, 255, 0),

// желтый

RGB(255,0, 255),

// пурпурный

RGB(0,255, 255),

// голубой

RGB (127,12V,127),

// серый

RGB (255,255, 255)};//.белый

int xcoord; POINT polylpts[4], polygpts[5]; CBrush newbrush; CBrush* oldbrush;

CPen newpen; CPen* oldpen;

CPaintDCdc(this);// контекст устройства для рисования

//рисование эллипса и заливка его красным цветом newpen.CreatePen(PS_SOLID, 1, dwColor[1]);

oldpen = dc.SelectObject(Sriewpen); newbrush.CreateSolidBrush(dwColor[1]) ; oldbrush = dc.SelectObject(Snewbrush); dc.Ellipse(275,300, 200, 250); dc.TextOut(220,265,"ellipse",7); dc.SelectObject(oldbrush) ; newbrush.DeleteObject() ; dc.SelectObject(oldpen) ; newpen.DeleteObject();

//рисование круга и заливка его синим цветом newpen.CreatePen(PS_SOLID, 1, dwColor[3]); oldpen = dc.SelectObject(snewpen) ; newbrush.CreateSolidBrush(dwColor[3]) ; oldbrush = dc.SelectObject(Snewbrush); dc.Ellipse(375,75, 525, 225); dc.TextOut(435,190,"circle",6) ; dc.SelectObject(oldbrush) ; newbrush.DeleteObject(); dc.SelectObject(oldpen);

newpen. DeleteObj ect ();

//рисование нескольких зеленых точек

for(xcoord = 400; xcoord < 450; xcoord += 5) dc.SetPixel(xcoord, 350, OL);

dc.TextOut(460,345, "<-pixels",9);

//рисование толстой черной диагональной линии newpen.CreatePen(PS_SOLID, 6, dwColor[0]); oldpen = dc.SelectObject (Snewpen); dc.MoveTo(20, 20); dc.LineTo(100, 100); dc.TextOut(60,20,"<-diagonal line",16); dc.SelectObject(oldpen); newpen.DeleteObject();

//рисование синей дуги

newpen.CreatePen(PS_DASH, 1, dwColor[3]); oldpen = dc.SelectObject(Snewpen); dc.Arc(25,125, 175, 225, 175, 225, 100, 125); dc.TextOut(50,150,"small arc ->",12); dc.SelectObject(oldpen); newpen.DeleteObject();

// рисование зеленого сегмента с толстым контуром newpen.CreatePen(PS_SOLID, 8, dwColor[2]);

oldpen = dc.SelectObject(Snewpen);

dc.Chord(125, 125, 275, 225, 275, 225, 200, 125);

370