
Паппас К., Мюррей У. - Visual C++ 6. Руководство разработчика - 2000
.pdf
Рис. 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
- #13.08.201334.52 Mб107Липман С., Лажойе Ж., Му Б. - Язык программирования C++. Вводный курс - 2007.djvu
- #13.08.201347.18 Mб151Литвиненко Н.А. - Технология программирования на C++. Win32 API-приложения - 2010.djvu
- #
- #
- #13.08.201317.53 Mб116Оберг Р., Торстейсон П. - Архитектура .NET и программирование на Visual C++ - 2002.pdf
- #
- #
- #
- #
- #
- #