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

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

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

Диалоговое окно About

Окна типа About служат для выдачи пользователю информации о программе, ее авторах, авторских правах и т.д. Модальное диалоговое окно About появляется на экране при выборе в меню команды Fourier About..., в результате чего вызывается функция OnAbout():

void CMainWnd::OnAbout() { CDialog about("AboutBox", this); about.DoModal(); }

Конструктор класса CDialogвоспринимает текущее окно как родительский объект. С этой целью используется указатель this, который всегда указывает на текущий объект. Метод DoModal() выводит диалоговое окно About на экран. После щелчка на кнопке ОК Окно About удаляется с экрана и становится доступным окно приложения, которое при этом перерисовывается.

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

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

void CMainWnd::OnFourierData() CFourierDataDialog dlgFourierData(this); if (dlgFourierData.DoModal() == IDOK)

{

InvalidateRect(NULL, TRUE); UpdateWindow(); } };

В файле FOURIER.H классCFourierDataDialog объявлен потомком класса CDialog. Обратите внимание, что к моменту завершения функции DoModal()введенные пользователем данные уже переданы в программу. Это происходит в методе ОnОК (), вызываемом путем щелчка на кнопке ОК:

void CFourierDataDialog::ОnОК() 1 GetDlgItemText(IDD_TITLE, mytitle, 80); nterms = GetDlgItemInt(IDD_TERMS, NULL, 0); CDialog: :OnOK();

}

Функция GetDlgitemText() записывает строку заголовка графика (определяемую по идентификатору iddjtitle) в переменную mytitle. Аналогичным образом с помощью функции GetDlgltemlntО возвращается введенное пользователем количество членов ряда Фурье. Поле, в котором вводится это число, идентифицируется константой IDD_TERMS. Второй параметр функции GetDlgltemlnt() позволяет проконтролировать успешность преобразования введенной строки в число, но в нашем приложении эта возможность не используется. Если третий параметр не равен нулю, функция должна проверять наличие знака минус и в случае необходимости возвращать знаковое число. Но поскольку в нашем случае значения должны быть только положительными, этот параметр установлен равным 0.

Вызов функции OnExit( )

В меню также содержится команда Exit, при вызове которой с экрана удаляется окно приложения, для чего вызывается функция DestroyWindow():

void CMainWnd::OnExit() { DestroyWindow () ; }

Схема сообщений

Вмакросе BEGIN_MESSAGE_MAP указываются два класса: CMainWnd иCFrameWnd.

Принимающей стороной является класс CMainWnd, а в классе CFrameWndсодержатся базовые обработчики. Макрос on_hm_paint() управляет обработкой всех сообщений WM_PAINT, направляя их методу OnPaint(). Другой макрос, ON_WM_SIZE(), управляет сообщениями WM_SIZE и направляет их методу OnSize(). Макрос ON_WM_CREATE() связан с сообщениями wm_create, которые передаются методу OnCreate(). И еще один макрос,

341

on_command(), поддерживает обработку сообщений, связанных с выбором команд меню. Здесь для каждой команды указывается свой обработчик.

BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)

ON_WM_PAINT()

ON_WM_SIZE()

ON_WM_CREATE ()

ON_COMMAND(IDM_ABOUT, OnAbout)

ON_COMMAND(IDM_FOUR, OnFourierData)

ON_COMMAND(IDM_EXIT, OnExit) END_MESSAGE_MAP()

Как уже было сказано, наличие схемы сообщений позволяет избежать использог вания в программе сложных и чреватых ошибками конструкций с операторами switch/case.

Запуск программы

После запуска программы в окне приложения будет построен заданный по умолчанию ряд Фурье, состоящий из одного члена, что соответствует синусоиде (рис. 19.6). На рис. 19.7 показан ряд Фурье.

Рис. 19.6. График, выводимый по умолчанию

342

Рис. 19.7. Ряд Фурье из n членов

Построение гистограмм

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

В проект входят четыре файла: файл заголовков BARCHART.H, файл ресурсов BARCHARTR.H, файл сценариев ресурсов BARCHART.RCи программный файл

BARCHART.CPP. Файл BARCHART.Hсодержит описания классов CMainWnd, CTheAppИ CBarDataDialog:

class CMainWnd : public CFrameWnd

{

public: CMainWnd () ;

afx_msg void OnPaintO;

afx_msg void

OnSizeCUINT, int, int);

afx_msg int

OnCreate(LPCREATESTRUCT cs);

afx_msg void

OnAboutO;

afx_msg void

OnBarData ();

afx_msg void

OnExitO;

DECLARE_MESSAGE_MAP ()

};

class CTheApp : public CWinApp

{

public:

virtual BOOL Initlnstance (); }; class CBarDataDialog : public CDialog

<

343

public:

CBarDataDialog (CWnd* pParentWnd=NULL) : CDialog ("BarDlgBox", pParentWnd)

{}

virtual void OnOK(); };

Файл BARCHARTR.Hсодержит идентификаторы команд меню и элементов управления диалоговых окон:

#define IDM_ABOUT 10 #define IDM_INPUT 20

#define

IDM_EXIT

30 #define DM_TITLE

300 #define DM_XLABEL 301

.....,„__

302 ' #define DM_P1

303

#define

DM_YLABEL

#define DM_P2 304 #define DM_P3 305 Idefine DM_P4 306 #define DM_P5 307

#define DM_P6 308 #define DM_P7 309 #define DM_P8 310 f define DM_P9 311 #define DM_P10 312

Описания меню и двух диалоговых окно представлены в файле BARCHART.RC: #include "resource. h"

# include "barchartr .h"

#define APSTODIO_READONLY_SYMBOLS

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

#define APSTODIO_HIDDEN_SYMBOLS #include "windows.h"

#undef APSTUDIO_HIDDEN_SYMBOLS #include "afxres.h"

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

#undef APSTUDIO_READONLY_SYMBOLS

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

// Ресурсы для английского (США) языка

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32

LANGUAGE LANG^ENGLISH, SUBLANG_ENGLISH_US tpragma code_page(1252) #endif // WIN32

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

//

// Меню

//

BARMENU MENU DISCARDABLE BEGIN

POPUP "Bar_Chart" BEGIN

MENUITEM "About Box...",IDM_ABOUT MENUITEM "Bar Values...",IDM_INPUT MENUITEM "Exit", IDM_EXIT END END

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

//

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

//

ABOUTDLGBOX DIALOG DISCARDABLE 14,22, 200, 75 STYLE WS_POPUP I WS_CAPTION

CAPTION "About Box" BEGIN

CTEXT "A Bar Chart Application", -1,30,5, 144,8

CTEXT "A Simple MFC Windows Application1;, -1,30,17,144, 8

344

CTEXT "By William H. Murray and Chris H. Pappas", -1,28/ 28,144, 8

CTEXT "(c)Copyright 1998",-1, 68,38, 83, 8 DEFPUSHBUTTON "ОК", IDOK, 84, 55, 32, 14, WS_GROUP

END

BARDLGBOX DIALOG DISCARDABLE 42,65526,223,209 STYLE WS_POPUP I WS_CAPTION

CAPTION "Bar Chart Data" BEGIN

GROUPBOX "Bar Chart Title:",100, 5, 11,212,89,WSJTABSTOP GROUPBOX "Bar Chart Heights", 101, 5, 105, 212, 90,WSJTABSTOP LTEXT "Title:", -1,43,35,28,8, NOT WS_GROUP

EDITTEXT DM_TITLE, 75,30,137,12

LTEXT "x-axis label:",-1,15,55, 55,8, NOT WS_GROUP

EDITTEXT DM_XLABEL, 75,50,135, 12

 

75,

60,8, NOT WS_GROUP

LTEXT

"y-axis

label:",-1,15,

 

EDITTEXT.DM_YLABEL, 75,70,135,12

40,

8,

NOT WS_GROUP

LTEXT

"Bar #1

", -1,45,125,

LTEXT

"Bar #2

", -1,45,140,

40,

8,

NOT WS_GROUP

LTEXT

"Bar #3

", -1,45,155,

40,

8,

NOT WS_GROUP

LTEXT

"Bar #4

", -1,45,170,

40,

8,

NOT WS_GROUP

LTEXT

"Bar #5

", -1,45,185,

40,

8,

NOT WS GROUP

LTEXT "Bar #6 ", -1,130, 125> 40,8, NOT WS_GROOP LTEXT "Bar #7 ", -1,130, 140, 40,8, NOT WS_GROUP LTEXT "Bar #8 ", -1,130, 155, 40,8, NOT WS_GROUP LTEXT "Bar #9 ", -1,130, 170,40,8, NOT WS_GROUP LTEXT "Bar #10:",-1,130, 185, 45,8, NOT WS_GROUP EDITTEXT DM_P1, 90,120, 30,12

EDITTEXT DM_P2, 90,135,30, 12

EDITTEXT DM_P3, 90,150, 30,12

EDITTEXT DM_P4, 90,165,30, 12

EDITTEXT DM_P5, 90,180, 30,12

EDITTEXT DM_P6, 180, 120, 30,12

EDITTEXT DM_P7, 180, 135, 30,12

EDITTEXT DM_P8, 180, 150, 30,12

EDITTEXT DM_P9, 180, 165,30,12 EDITTEXT DM_P10, 180, 180, 30,12 PUSHBUTTON "ОК", IDOK, 54,195,24,14 END

PUSHBUTTON "Cancel", IDCANCEL, 124, 195,34,14 #ifdef APSTUDIO_INVOKED

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

1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END

2 TEXTINCLUDE DISCARDABLE BEGIN #define APSTUDIO_HIDDEN_SYMBOLS\r\n" #include ""windows.h""\r\n"

#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" "#include ""afxres.h""\r\n"

"\0" END

3 TEXTINCLUDE DISCARDABLE BEGIN

"\r\n"

 

"\0" END

 

#endif

// APSTUDIO_INVOKED

345

#endif

// Ресурсы для английского

(США) языка

Ниже приведен текст файла BARCHART.CPP.

//

//barchart.cpp

//Построение гистограмм.

#include <afxwin.h> #include <string.h> #include <math.h> #include <stdlib.h>

#include "barchartr.h" // идентификаторы ресурсов #include "barchart.h"

#define maxnumbar 10

char szTString[80] = "(barchart title area)"; char szXString[80]= "x-axis label";

char szYString[80] = "y-axis label";

int iBarSize[maxnumbar] = {20,10, 40, 50}; int m_cxClient, m_cyClient;

CTheApp theApp; CMainWnd::CMainWnd() {

Create(AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,LoadCursor(NULL, IDC_CROSS),

(HBRDSH)'GetStockObject (WHITE_BRUSH) , NULL) , "Bar Chart Application with the MFC ", WS_OVERLAPPEDWINDOW, rectDefault, NULL, "BarMenu");

}

void CMainWnd::OnSize(OINT, int x, int y) ( m_cxClient = x;

m_cyClient = y; )

void CMainWnd::OnPaint()

{

CPaintDC dc(this);

static DWORD dwColorflO] = {

RGB(0,0, d),

// черный

RGB(245,0, 0),

// красный

RGB(0,245,0),

// зеленый

RGB(0,0, 245),

// синий

RGB(245,245, 0),

// желтый

RGB(245,0, 245),

//пурпурный

RGB(0,245,245),

// голубой

RGB(0,80,80),

// голубовато-серый

RGB(80,80,80),

// темно-серый

RGB(245, 245, 245)};// белый CFont newfont;

CFont* oldfont; CBrush newbrush; CBrush* oldbrush;

int i, iNBars, iBarWidth, iBarMax; int ilenMaxLabel;

int xl,x2,yl,y2;

int iBarSizeScaled[maxnumbar] ; char sbuffer[10],*strptr; iNBars = 0;

for(i=0;i < maxnumbar; i++){ iffiBarSize [i]!= 0) iNBars++;

346

}

iBarWidth = 400/iNBars;

//Поиск столбца, имеющего максимальную высоту iBarMax = iBarSize[0]; for(i=. 0; i < iNBars; i++) if(iBarMax < iBarSize[i])iBarMax = iBarSize [i];

//Преобразование максимального значения по у встроку

strptr = _itoa(iBarMax, sbuffer, 10); ilenMaxLabel = strlen(sbuffer);

//Масштабирование столбцов в массиве.

//Максимальная высота столбца — 270. for(i= 0; i < iNBars; i++)

iBarSizeScaled[i] = iBarSize[i]* (270/iBarMax);

//Задание режима отображения //и создание области просмотра dc.SetMapMode(MM_ISOTROPIC) ; dc.SetWindowExt(640,400);

dc.SetViewportExt(m_cxClient, m_cyClient); dc.SetViewportOrg(0, 0) ;

//Выводтекставокно, еслидлянегохватаетместаif(m_cxClient > 200) ( ' newfont.CreateFont(12,12, О, О, FW_BOLD,

FALSE, FALSE, FALSE, OEM_CHARSET, OOT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAOLT_QUALITY, VARIABLE_PITCH | FF_ROMAN,

"Roman");

oldfont = dc.SelectObject(Snewfont); dc.TextOut((300- (strlen(szTString)*10/2) ) ,

15,szTString, strlen(szTString)); dc.TextOut((300-(strlen(szXString)* 10/2)) , 365,szXString, strlen(szXString));

dc.TextOut((90ilenMaxLabel*12), 70,strptr, ilenMaxLabel); // удалениеобъекташрифтаdc.SelectObject(oldfont); newfont.DeleteObject();

newfont.CreateFont(12,12,900,900,FW_BOLD,

FALSE, FALSE,.FALSE, OEM_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_ROMAN, "Roman");

oldfont = dc.SelectObject(Snewfont) ;

dc.TextOut(50,200+ (strlen(szXString)*10/2), szYString, strlen(szYString));

//удаление объекта шрифта dc.SelectObject(oldfont) ; newfont.DeleteObj ect() ; }

//Рисование осей координат dc.MoveTo(99,49); dc.LineTo(99,350); dc.LineTo(500, 350); dc.MoveTo(99,350);

//Начальные значения

xl = 100; yl = 350;

x2 = xl + iBarWidth; // Рисование столбцов

for(i=0;i < iNBars; i++) { newbrush.CreateSolidBrush(dwColor[i]), oldbrush = dc.SelectObject(Snewbrush) y2 = 350 - iBarSizeScaled[i]; dc.Rectangle(xl,yl,x2, y2);

xl = x2;

347

x2 += IBarWidth; // удаление кисти

dc.SelectObject(oldbrush); newbrush.DeleteObject(); }

int CMainWnd::OnCreate(LPCREATESTRUCT) { UpdateWindow();

return (0);

}

void CMainWnd::OnAbout() {

CDialog about("AboutDlgBox", this); about.DoModal(); }

void CBarDataDialog::OnOK()

{

GetDlgltemText(DMJTITLE, szTString, 80); GetDlgltemText(DM_XLABEL, szXString, 80); GetDlgltemText(DM_YLABEL, szYString, 80); iBarSize[0] = GetDlgltemlnt(DM_P1, NULL, 0) iBarSize[l]= GetDlgltemlnt(DM_P2, NULL, 0) iBarSize[2] = GetDlgltemlnt(DM_P3, NULL, 0) iBarSize[3] = GetDlgltemlnt(DM_P4, NULL, 0) iBarSize[4] = GetDlgltemlnt(DM_P5, NULL, 0) iBarSize[5] = GetDlgltemlnt(DM_P6, NULL, 0) iBarSize[6]= GetDlgltemlnt(DM_P7, NULL, 0) iBarSize[7] = GetDlgltemlnt(DM_P8, NULL, 0) iBarSize[8] = GetDlgltemlnt(DM_P9, NULL, 0) iBarSize[9]= GetDlgltemlnt(DM_P10, NULL, 0) CDialog: :OnOK();

}

void CMainWnd::OnBarData() {

CBarDataDialog dlgBarData(this); if(dlgBarData.DoModal{) == IDOK) InvalidateRect(NULL, TRUE); UpdateWindow(); ) };

void CMainWnd::OnExit() { DestroyWindowO ; }

BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd) ON_WM_PAINT() ON_WM_SIZE() ON_WM_CREATE ()

ON_COMMAND(IDM_ABOUT, OnAbout) ON_COMMAND(IDM_INPUT, OnBarData) ON_COMMAND(IDM_EXIT, OnExit)

END_MESSAGE_MAP()

BOOL CTheApp::Initlnstance() { m_pMainWnd = new CMainWnd (); m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow() ; return TRUE;

}

Файл BARCHART.H

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

CMainWnd:

afx_msg void OnPaint();

afx_msg void OnSize(UINT, int, int); afx_msg int OnCreate(LPCREATESTROCT cs); afxjnsg void OnAbout();

afx_msg void OnBarData();

348

afx_msg void OnExit();

Объявление класса CBarDataDialog аналогично объявлению класса CFourierDataDialog из предыдущего примера. В то же время окно ввода данных поддерживает теперь ввод большего числа значений, хотя при его разработке мы взяли за основу аналогичное диалоговое окно из предыдущей программы.

Файлы ресурсов

Два исходных файла, BARCHARTR.H и BARCHRT.RC, объединяются компилятором ресурсов

Microsoft в единый файл ресурсов BARCHART.RES.

Файл заголовков BARCHARTR.Hсодержит идентификаторы трех команд меню: idm_about, idm_inputи IDM_EXIT. Еще тринадцать идентификаторов относятся к элементам управления диалогового окна ввода данных. Три из них, dm_title, DM_XLABLEи dm_ylable, связаны с заголовком и подписями к осям. Остальные десять констант, от DM_P1 до ом_Р10, указывают на целочисленные значения, введенные для отдельных столбцов гистограммы.

Файл сценариев ресурсов BARCHART.RCсодержит описания меню и двух диалоговых окон. Приложение содержит два диалоговых окна. Окно About практически идентично тому, что использовалось в предыдущем приложении, а окно ввода данных является более сложным.

Файл BARCHART.CPP

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

Вконстанте maxnumbarхранится информация о максимально допустимом числе столбцов гистограммы:

#definemaxnumbar 10

В следующих массивах записаны заданные по умолчанию заголовок гистограммы, подписи к осям, а также размеры четырех столбцов:

char szTString[80] = "(barchart title area)"; char szXString[80] = "x-axis label";

char szXString[80] - "y-axis label"; int iBarSize[maxnumbar] = (20,10,40,50};

Размеры рабочей области окна приложения также сохраняются в глобальных переменных:

int i^i_cxClient, m_cyClient;

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

Цвета столбцов гистограммы выбираются из массива dwColor в определенном порядке. Например, если гистограмма состоит из трех столбцов, то им будут назначены черный, красный и зеленый цвета.

Классы CFont и CBrush позволяют передавать объекты шрифтов и кистей любым функциям класса CDC (базовый класс для работы с контекстами устройств). Новые шрифты требуются для вывода заголовка гистограммы и подписей к осям. Как объявляются такие объекты, показано ниже:

CFont newfont;

CFont* oldfont;

CBrush newbrush;

CBrush* oldbrush;

Масштабирование столбцов

349

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

iNBars = 0;

for(i=0;i < maxnumbar; i++)

{

 

if (IBarSizefi]

!= 0) iNBars++;

}

 

Значения записываются в этот массив при закрытии диалогового окна ввода данных, в методе ОnОК ( ) . Ширина столбцов зависит от их количества, так как ширина самой гистограммы постоянна. Для вычисления ширины столбцов используется следующая формула:

IBarWidth = 400/iNBars;

Высота столбцов регулируется с учетом максимального введенного значения. Сначала определяется, какова будет высота самого большого столбца:

// Поиск столбца с максимальной высотой

IBarMax = iBarSize[0]; for(i= 0; i< iNBars; i++) if(iBarMax < iBarSize [i])iBarMax = iBarSize [i];

Максимальное значение будет выведено слева от оси у. Для преобразования числового значения в строку вызывается функция __itoa( ) :

// Преобразование максимального значения по оси у в строку

strptr = _itoa (iBarMax, sbuffer, 10); ilenMaxLabel= strlen (sbuffer)

;

Размеры остальных столбцов масштабируются в соответствии с максимальным значением:

//Масштабирование столбцов в массиве.

//Максимальная высота столбца — 270. for(i=0;i < iNBars; i++)

iBarSizeScaled[i] = iBarSize[i] * (270/iBarMax);

Подготовка окна

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

// Задание режима отображения //исоздание области просмотра dc.SetMapMode(MM_ISOTROPIC) ; dc.SetWindowExt(640,400);

dc.SetViewportExt(m_cxClient, m_cyClient); dc.SetViewportOrg(0, 0) ;

Благодаря этому коду изображение гистограммы при изменении размеров окна будет автоматически масштабироваться.

Вывод текста в окно

В предыдущем приложении мы выводили текстовую информацию в окно при использовании шрифта, установленного по умолчанию. При необходимости применить какой-нибудь специальный шрифт или изменить ориентацию текста можно воспользоваться функциями работы со шрифтами, основными из которых являются CreateFont () иCreateFontlndirect () . В нашем примере использовалась функция CreateFont().

Что такое шрифт

Под шрифтом понимают набор печатных символов, имеющих одинаковые начертание и размер. Шрифт включает символы букв, знаков препинания и других вспомогательных знаков. В качестве примеров различных шрифтов можно привести Arial размером в 12 пунктов, TimesNewRoman в 12 пунктов, TimesNewRomanв 14 пунктов и т.д. Пункт — это наименьшая единица в типографской системе мер, равная 0,376 мм. 72 пункта составляют один дюйм.

350

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