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

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

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

Рис. 17.19. Диаграмма, построенная с учетом введеных пользователем данных

311

Глава 18. Основы библиотеки MFC

Зачем нужны библиотеки классов

Принципы, лежащие в основе MFC

Ключевые особенности MFC

Все начинается с CObject

Иерархия классов MFC

Простейшее MFC -приложение

o Файл SIMPLE.CPP

o Файл AFXWIN.H

o Создание класса, производного от CWinApp

o Класс CFrameWnd

o Реализация метода Initlnstance()

o Конструктор

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

Из предыдущих глав вы узнали, что создание даже самых простых приложений Windowsс использованием стандартных API-функций является довольно сложной задачей, требующей много времени и внимания. Например, код простейшего приложения SWP.C(мы рассматривали его в предыдущей главе) на языке С занял почти две страницы текста. Большая часть кода нужна лишь для того, чтобы вывести на экран окно приложения и поддерживать его работу.

Компилятор MicrosoftVisualC++ предлагает мощную библиотеку классов (Mi- crosoftFoundationClasses— MFC ), предназначенную для разработки 32-разрядных приложений, отвечающих всем стандартам и требованиям сегодняшнего дня. В MFC инкапсулированы все API-функции Windowsи дополнительно обеспечивается поддержка панелей инструментов, страниц свойств, технологии OLE, элементов управления ActiveXи многое другое. Кроме того, имеются функции управления базами данных, основанными на разных источниках данных, включая ОАО и ODBC. Поддерживается и разработка приложений для Internet.

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

Зачем нужны библиотеки классов

MFC предоставляет программистам удобные классы объектов, в которых инкапсулированы все наиболее важные структуры и API-функции. Библиотеки классов, подобные MFC , обеспечивают гораздо больше возможностей и значительно проще в использовании, чем традиционные библиотеки функций языка С, о которых говорилось в двух предыдущих главах.

Ниже перечислены основные преимущества использования библиотек классов:

устраняются конфликты, связанные с совпадением имен стандартных и программных функций, а также переменных;

312

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

обеспечивается наследование кода;

размер кода значительно сокращается.

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

Принципы, лежащие в основе MFC

Создатели MFC при разработке данного продукта придерживались строгих правил и стандартов. Основные принципы, на которых базируется MFC , перечислены ниже:

возможность комбинировать обычные вызовы функций с использованием методов классов;

баланс между производительностью и эффективностью базовых классов;

преемственность в переходе от использования API-функций к библиотеке классов;

простота переноса библиотеки классов на разные платформы: от Windows3.1 к 'Windows 95/NT, затем к Windows98 и т.д.;

органичная взаимосвязь с традиционными средствами программирования на C++, позволяющая избежать чрезмерного усложнения программного кода.

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

Одна из поставленных перед разработчиками MFC задач состояла в том, чтобы программисты, уже знакомые с API-функциями, не заучивали новый, далеко не малый набор имен функций и констант. Это требование строго соблюдалось при именовании членов классов. Данная особенность выгодно отличает MFC от других библиотек классов.

При создании MFC также учитывалась возможность работы в смешанном режиме. Другими словами, в одной программе могут применяться как библиотека MFC , так и API-функции. Некоторые функции, например SetCursor() и GetSystemMetrics(), должны вызываться напрямую, даже если в приложении используется MFC . Еще одно важное свойство, на которое обращали внимание разработчики Microsoft, — это возможность непосредственного использования базовых классов в программах. Существовавшие до MFC библиотеки классов были чересчур абстрактными. В Microsoft их называли "тяжелыми классами", поскольку основанные на них приложения отличались большим размером программного кода и недостаточно быстро выполнялись. Разработчикам MFC удалось найти золотую середину между разумным уровнем абстрактности и размером кода.

Ключевые особенности MFC

Ниже перечислены основные достоинства библиотеки MFC .

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

Улучшенная система диагностики, позволяющая записывать в файл информацию об используемых объектах. Также сюда следует отнести возможность контроля за содержимым переменных-членов.

313

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

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

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

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

Поддержка COM (ComponentObjectModel— модель компонентных объектов).

Использование тех же соглашений об именовании методов классов, которые применялись при подборе имен для API-функций Windows. Это существенно облегчает идентификацию действий, выполняемых классами.

Опытный программист сразу же оценит две наиболее важные особенности MFC : знакомые имена методов и привязка сообщений к обработчикам. Если вы вернетесь к программе PIE.С, рассмотренной в предыдущей главе, то убедитесь в обилии блоков switch/case. Увлечение такими конструкциями чревато возникновением трудно обнаруживаемых ошибок при выполнении программы. Эту проблему легко обойти с помощью MFC .

Профессиональный разработчик будет удовлетворен быстротой выполнения про-фаммного кода библиотечных классов. Интенсивное использование MFC теперь не щшведет к тяжеловесности полученного приложения.

Все начинается с CObject

Большинство библиотек классов, в том числе и MFC , имеют какой-нибудь один общий родительский класс, от которого порождаются все остальные. В MFC таковым является CObject. Ниже показано описание этого класса, взятое из файла AFX.H. (Файлы заголовков библиотеки MFC хранятся в папке MFC /INCLUDE.)

/////////// Класс CObject является базовым для классов MFC class CObject

{

public:

//Модель объекта (проверка типа, выделение памяти, уничтожение) virtual CRuntimeClass* GetRuntimeClass0

const/virtual -CObject (); // необходим виртуальный деструктор

//Резервирование и удаление памяти

void* PASCAL operator new(size_t nSize); void* PASCAL operator new(size_t, void* p) ; void PASCAL operator delete(void* p) ;

fif defined(_DEBUG) && ! defined (_AFX_NO_DEBUG_CRT) '?','_

//позволяет отслеживать имя файла и номер строки

//(используется при отладке)

void* PASCAL operator new(size_t nSize, LPCSTR IpszFileName, intnLine); #endif

//Конструктор копирования и оператор инициализации с присваиванием

//недоступны, поэтому в случае попытки использовать соответствующие

//конструкции будет выдано сообщение об ошибке компилятора,

//что позволит избежать непредсказуемости выполнения программы. protected: CObject ();

private:

314

CObject(const CObjectS objectSrc); //реализация отсутствует void operator=(const CObjectS objectSrc);// реализация отсутствует

//Атрибуты

public:

BOOL IsSerializableОconst;

BOOL IsKindOf(const CRuntimeClass* pClass) const;

//Виртуальные методы

virtual void Serialize (CArchiveS ar) ;

//Поддержка диагностики virtual void AssertValidO const;

virtual void Dump (CDumpContextS. dc) const;

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

public:

static const AFX_DATA CRuntimeClass classCObject; #ifdef _AFXDLL

static CRuntimeClass* PASCAL _GetBaseClass(); #endif

};

}

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

Обратите внимание, из каких компонентов состоит описание класса CObject. Как видите, здесь четко прослеживается выделение блоков открытых (public), закрытых (private) и защищенных (protected) членов класса. CObjectтакже обеспечивает возможность динамического определения типа и сериализации. Вспомните, что возможность динамической проверки типа позволяет определять тип объекта во время выполнения программы. Сведения о состоянии объекта можно сохранить в файле на диске, благодаря чему реализуется концепция постоянства.

Все остальные классы MFC порождаются от CObject. Примером такого класса может служить CGdiObject(объявлен в файле AFXWIN.H), описание которого приведено ниже.

///////////

//Абстрактныйкласс CGdiObject дляметода CDC: :SelectObject class CGdiObject : public CObject {

DECLARE_DYNCREATE (CGdiObject) public:

//Атрибуты

HGDIOBJ m_hObject; // должна быть первой переменной-членом operator HGDIOBJ () const;

HGDIOBJ GetSafeHandleO const;

static CGdiObject* PASCAL FromHandle (HGDIOBJ hObject) ; static void PASCAL DeleteTempMap () ;

BOOL Attach (HGDIOBJ hObject) ; HGDIOBJ Detach () ;

// Конструкторы

CGdiObject() ; // должен создавать объект производного класса

BOOLDeleteObject() ; // Методы

int GetObject (int nCount, LPVOID IpObject) const; UINT GetObjectTypeO const;

BOOL CreateStockObject (int nlndex) ; BOOL UnrealizeObjectO ;

BOOL operator— (const CGdiObjectS ob j ) const; root. nnf=rator! = (const CGdiObiectS obi)const; // Реализация

315

public:

virtual -CGdiObject() ; tifdef _DEBUG virtual void Dump (CDumpContextS. dc) const; virtual void AssertValid() const; #endif };

Класс CGdiObjectи его методы позволяют создавать и использовать в приложениях такие графические объекты, как перья, кисти и шрифты. От CGdiObject порождаются некоторые другие классы, в частности CPen.

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

Например, в традиционных процедурных программах вызов функции DeleteObject()имеет следующий синтаксис:

DeleteObject(hBRUSH); /* где hBRUSHдескриптор кисти */

В MFC -приложениях того же результата можно достичь путем вызова функции-члена: newbrush.DeleteObject (); // где newbrushтекущая кисть

Иерархия классов MFC

Ниже показан список классов библиотеки MFC , порожденных от CObject.

CObject

CException

CArchiveException CDaoException CDBException CFileException

CInternetException

CMemoryException CNotSupportedException COleDispatchException COleException CResourceException CUserException

CFile CMemFile CSharedFile

COleStreamFile CMonikerFile CAsyncMonikerFile CDataPathProperty CCachedDataPathProperty CSocketFile

CStdioFile CInternetFile CGopherFile CHttpFile CRecentFileList CDC CClientDC CMetaFileDC CPaintDC

CWindowDC

CDocState

CImageList

CGdiObject CBitmap CBrush

316

CFont

CPalette

CPen

CRgn CMenu

CCommandLinelnfo

CDatabase

CRecordSet

CLongBinary

CDaoDatabase

CDaoQueryDef

CDaoRecordSet

CDaoTableDef

CDaoWorkspace

CSyncObject

CCriticalSection

CEvent

CMutex

CSemaphore CAsyncSocket

CSocket

CArray

CByteArray

CDWordArray

CObArray

CPtrArray

CStringArray

CUIntArray

CWordArray

CList

CObList

CPtrList

CStringList

CMap

CMapWordToOb

CMapWordToPtr

CMapPtrToPtr

CMapPtrToWord

CMapStringToOb

CMapStringToPtr

CMapStringToString

CInternetSession

CInternetconnection

CFtpConnection

CGopherConnection

CHttpConnection

CFileFind

CFtpFileFind

CGopherFileFind

CGopherLocator

CCmdTarget

CWinThread

CWinApp

COleControlModule

CDocTemplate

CMultiDocTemplate

317

CSingleDocTemplate

COleObjectFactory

COleTemplateServer

COleDataSource

COleDropSource

COleDropTarget

COleMessageFilter

CConnectionPoint

CDocument

COleDocument

COleLinkingDoc

COleServerDoc

CRichEditDoc CDocItem

COleClientltem

COleDocObjectltem

CRichEditcntrltem

COleServefltem

CDocObjectServerItem

CDocObjectServer

CWnd

CFrameWnd

CMDIChildWnd

CMDIFrameWnd

CMiniFrameWnd

COlelPFrameWnd

CSplitterWnd

CControlBar

CDialogBar

COleResizeBar

CReBar

CStatusBar

CToolBar

CPropertySheet

CPropertySheetEx

CDialog

CCommonDialog

CColorDialog

CFileDialog

CFindReplaceDialog

CFontDialog

COleDialog

COleBusyDialog

COleChangelcoriDialog

COleChangeSourceDialog

COleConvertDialog

COlelnsertDialog

COleLinksDialog

COleUpdateDialog

COlePasteSpecialDialog

COlePropertiesDialog

COlePageSetupDialog

CPrintDialog

COlePropertyPage

CPropertyPage

318

CPropertyPageEx CView

CCtrlView

CEditView

CListView

CRichEditView

CTreeView

CScrollView

CFormView

CDaoRecordView

CHtmlView

COleDBRecordView

CRecordView

CAnimateCtrl

CButton

CBitmapButton

CComboBox

CComboBoxEx

CDateTimeCtrl

CEdit

CHeaderCtrl

CHotKeyCtrl

CIPRddressCtrl

CListBox

CCheckListBox

CDragListBox

CListCtrl

CMonthCalCtrl

COleControl

CProgressCtrl

CReBarCtrl

CRichEditCtrl

CScrollBar

CSliderCtrl

CSpinButtonCtrl

CStatic

CStatusBarCtrl

CTabCtrl

CToolbarCtrl

CToolTipCtrl

CTreeCtrl

В следующем списке перечислены классы, которые не порождены от CObject.

CHtmlStream

CHttpFilter

CHttpFilterContext

CHttpServer

CHttpServerContexf

CArchive

CDumpContext

CRuntimeClass

CPoint

CRect

CSize

CString

319

CTime

CTimeSpan

CCreateContext

CMemoryState

COleSafeArray

CPrintlnfo

CCmdUI

COleCmdOI

CDaoFieldExchange

CDataExchange

CDBVariant

CFieldExchange

COleDataObject

COleDispatchDriver

CPropExchange

CRectTracker

CWaitCursor

CTypedPtrArray

CTypedPtrList

CTypedPtrMap

CFontHolder

CPictureHolder

COleCurrency

COleDateTime

COleDateTimeSpan

COleVariant

CMultiLock

CSingleLock

Эти два списка могут служить вам справочником при дальнейшем изучении возможностей MFC

.

Простейшее MFC -приложение

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

Рассматриваемая ниже программа SIMPLE.CPP просто открывает на экране свое окно, помещая а строку заголовка определенный текст.

Файл SIMPLE.CPP

Чтобы создать простейшее Windows-приложение на базе MFC , введите в окне компилятора VisualC++ следующий код: .

//

//simple.cpp

//Пример приложения, написанного с использованием MFC .

#include <afxwin.h>

Class CTheApp : public CWinApp

(

public:

virtual BOOL Initlnstance (); ); class CMainWnd : public CFrameWnd

(

320

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