КАРКАС MFC ПРОГРАММЫ
Приложение без главного окна, созданное с
помощью MFC.
Приложение без главного окна, созданное без
помощи MFC. Каркас MFC программы.
Организация исходного кода программы. Создание масштабируемых окон.
Регистрация собственного класса окна
средствами MFC
Приложение
без главного окна, созданное с помощью MFC
Самые простые приложения с использованием библиотеки
классов MFC можно создавать без применения автоматизированных средств
разработки приложений MFC AppWizard. Создадим приложение, отображающее на
экране маленькую диалоговую панель, которая содержит строку текста. В этом
приложении используется единственный класс, наследованный от базового класса
CWinApp.
#include
<afxwin.h> // Включаемый файл для MFC
// Класс
CFirstApp - главный класс приложения.
//
Наследуется от базового класса CWinApp.
class
CFirstApp:public CWinApp
{
public:
// Переопределение метода InitInstance,
// предназначенного для инициализациии
приложения.
virtual BOOL InitInstance();
};
// Создание
объекта приложения класса CFirstApp.
CFirstApp
theApp;
// Метод
InitInstance
//
Переопределение виртуального метода InitInstance класса CWinApp.
// Он
вызывается каждый раз при запуске приложения.
BOOL
CFirstApp::InitInstance()
{
AfxMessageBox("First MFC-application");
return FALSE;
}
В этом приложении определен только один класс -
CFirstApp, наследованный от базового класса CWinApp. В класс CFirstApp
входит метод InitInstance. Кроме того, определена одна глобальная
переменная - theApp.
Приложение
без главного окна, созданное без помощи MFC
Сравним исходный текст с аналогичным приложением,
созданным без использования библиотеки классов MFC. В этом приложении
присутствует главная функция приложения WinMain, которая вызывается, когда
пользователь или операционная система запускает приложение:
#include
<windows.h>
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR
lpCmdLine, int nShowCmd)
{
// Отображение диалоговой панели.
MessageBox(NULL,"First
MFC-application","Message",MB_OK);
// Завершение работы приложения
return 0;
}
Функция MessageBox создает, отображает и обрабатывает
диалоговую панель. Она содержит сообщение, название и выбранный пользователем
набор кнопок. Функция MessageBox имеет следующий прототип:
int MessageBox
(
HWND hWnd, // окно – владелец диалоговой панели, равно NULL если
// такового нет
LPCTSTR lpText, // сообщение, отображаемое в окне
LPCTSTR lpCaption, // Заглавие диалоговой панели
UINT uType // стиль диалоговой панели
);
В зависимости от значения uType диалоговая панель
содержит следующий набор кнопок:
MB_ABORTRETRYIGNORE |
Три кнопки:
Abort, Retry и Ignore. |
MB_OK |
Одна кнопка:
OK. |
MB_OKCANCEL |
Две кнопки: OK и
Cancel. |
MB_RETRYCANCEL |
Две кнопки:
Retry и Cancel. |
MB_YESNO |
Две кнопки: Yes
и No. |
MB_YESNOCANCEL |
Три кнопки:
Yes, No и Cancel. |
Возращаемыми
значениями функции MessageBox будут:
0 |
Диалоговое окно
не может быть создано из-за нехватки памяти |
IDABORT |
Нажата кнопка Abort. |
IDCANCEL |
Нажата кнопка
Cancel. |
IDIGNORE |
Нажата кнопка
Ignore. |
IDNO |
Нажата кнопка
No. |
IDOK |
Нажата кнопка
OK. |
IDRETRY |
Нажата кнопка
Retry. |
IDYES |
Нажата кнопка
Yes. |
КАРКАС MFC
ПРОГРАММЫ
Для
создания MFC программы необходимо выполнить
следующие действия:
1. От
CFrameWnd породить класс, определяющий окно.
2. От CWinApp породить класс, определяющий приложение.
3.
Создать очередь сообщений.
4.
Переопределить функцию InitInstance() класса CWinApp.
5. Создать
экземпляр класса, определяющего приложение.
ОРГАНИЗАЦИЯ
ИСХОДНОГО КОДА ПРОГРАММЫ
Рассмотрим еще раз программу, приведенную в уроке 2,
выводящую на экран окно. К приведенному раньше коду добавим пустую карту откликов
сна ообщения.
С целью упрощения организации MFC программ была разработана методика управления файлами.
Согласно ей, объявления полей данных и прототипы функций-членов порождаемых
классов должны содержаться в одном файле, а определения функций-членов в
другом.
Объявления
вынесем в файл mfc_test.h:
// В этом
файле порждаются основные классы
// Класс
создания главного окна
class
CMyMainWnd : public CFrameWnd
{
public:
CMyMainWnd();
DECLARE_MESSAGE_MAP()
};
// Класс
создания приложения
class
CMyApp : public CWinApp
{
public:
BOOL InitInstance();
};
Класс CMyMainWnd содержит конструктор и макрос
DECLARE_MESSAGE_MAP(). Макрос на самом деле разворачивается в декларацию карты
сообщений, которая определяет, какая член-функция класса должна вызываться в
ответ на сообщение Windows. Этот макрос применяется для любого окна, в котором
обрабатываются поступающие сообщения. Он должен быть последним в декларации
класса. В приведенном примере обработка сообщений не ведется, поэтому карта
сообщений пуста.
Определение
функций-членов и базовый код поместим в файл mfc_test.с:
#include <afxwin.h>
#include "mfc_test.h"
CMyMainWnd::CMyMainWnd()
{
Create(NULL,"My title");
}
BOOL CMyApp::InitInstance()
{
m_pMainWnd =
new CMyMainWnd();
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMyMainWnd,CFrameWnd)
END_MESSAGE_MAP()
CMyApp theApp;
Функция UpdateWindow()
указывает WINDOWS на необходимость послать
программе сообщение о том, что содержимое главного окна следует обновить. Для
нашей простой программы с технической точки зрения нет необходимости в вызове этой
функции.
Макрос BEGIN_MESSAGE_MAP
всегда имеет два параметра: первый - класс окна, второй - класс, от
которого порожден класс окна. В данном примере карта сообщений пустая, то есть
все сообщения обрабатывает MFC.
СОЗДАНИЕ
МАСШТАБИРУЕМЫХ ОКОН
В приведенном выше примере для создания окна
использовалась функция Create(), которая на самом деле имеет много параметров.
Ее прототип таков:
BOOL
CFrameWnd::Create(
LPCSTR ClassName, //
Имя Windows-класса окна
LPCSTR Title, //
Заголовок
DWORD Style = WS_OVERLAPPEDWINDOW, //
Стиль
const RECT &XYSize = rectDefault, // Область
CWnd *Parent = 0, //
Окно-предок
LPCSTR MenuName = 0, //
Имя ресурса меню
DWORD ExStyle = 0, //
Расширенные стили
CCreateContext *Context = 0 //
Доп. данные
);
Параметр ClassName определяет имя класса окна
для оконной подсистемы Windows. Обычно его не нужно явно задавать, так как MFC
выполняет всю необходимую черновую работу. Если ClassName = NULL, то используется стандартный класс окна, определенный
в CframeWnd. Можно
зарегистрировать собственное имя класса окна с помощью функции AfxRegisterWndClass(), создающей класс окна согласно заданной спецификации.
Функция AfxRegisterWndClass() возвращает
указатель на имя класса окна, которое можно использовать в качестве первого
параметра функции Create().
Параметр Title – это строка, содержащая
заголовок окна.
Параметр Style задает стиль окна. По
умолчанию создается стандартное перекрываемое окно (Style = WS_OVERLAPPEDWINDOW).
Можно задать свой стиль, объединив с помощью операции "или" несколько
констант из приведенных ниже:
Константа |
Элемент
окна |
WS_OVERLAPPED |
Стандартное
окно с рамкой |
WS_MAXIMIZEBOX |
Кнопка
максимизации |
WS_MINIMIZEBOX |
Кнопка
минимизации |
WS_SYSMENU |
Системное
меню |
WS_HSCROLL |
Горизонтальная
полоса прокрутки |
WS_VSCROLL |
Вертикальная
полоса прокрутки |
WS_OVERLAPPEDWINDOW |
Стандартное
окно с рамкой, содержащее системное меню, кнопки максимизации, минимизации и
закрытия. |
Начальное положение и размер окна определяются
параметром XYSize типа Rect, объявленного следующим
образом:
typedef struct tagRect
{
LONG
bottom;
LONG
left;
LONG
right;
LONG
top;
} RECT;
Rect – это структура, которая определяет экранные координаты
левого верхнего (left, top) и правого
нижнего (rigth, bottom) угла прямоугольника,
в котором будет отображено окно. Координаты задаются в
абсолютных единицах (пикселях) по отношению к экрану.
Параметр Parent содержит
указатель на окно, являющееся предком окна, создаваемгого функцией Create(). Так как главное окно находится на верхнем уровне иерархии
окон программы, то параметр имеет значение NULL.
Прграмма, создающее стандартное окно, верхний левый
угол которого имеет координаты (100, 100), а правый нижний (400, 400), должна
содержать следующие строки в конструкторе окна:
CMyMainWnd::CMyMainWnd()
{
RECT r;
r.left = r.top = 100; r.right = r.bottom =
400;
Create(NULL,"My First
Window",WS_OVERLAPPEDWINDOW,r);
}
РЕГИСТРАЦИЯ
СОБСТВЕННОГО КЛАССА ОКНА СРЕДСТВАМИ MFC
Функция AfxRegisterWndClass() используется для регистрации класса окна и имеет прототип:
LPCTSTR AFXAPI
AfxRegisterWndClass(
UINT
nClassStyle,
HCURSOR hCursor =
0,
HBRUSH hbrBackground =
0,
HICON hIcon =
0
);
Регистрация класса и создание окна совершается в
конструкторе CMyMainWnd:
CMyMainWnd::CMyMainWnd()
{
CString
StrClassName = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW |
CS_DBLCLKS,
LoadCursor(NULL, IDC_ARROW),
(HBRUSH)GetStockObject(COLOR_BTNFACE+1),
LoadIcon(NULL, IDI_APPLICATION));
Create(StrClassName,"My First Window",WS_OVERLAPPEDWINDOW,
CRect(100,100,400,400));
}