Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
CPaintDC dc( this );
В MFC класс CPaintDC является подклассом более абстрактного класса CDC, инкапсулирующего контекст устройства Windows. В CDC есть множество функций-членов для рисования на экране, принтере и других устройствах. Класс CPaintDC является специфической разновидностью CDC, которая используется только в обработчиках сообщения WM_PAINT.
В приложениях на Windows API при обработке сообщения WM_PAINT приложение сначала должно вызвать функцию ::BeginPaint для получения контекста устройства, связанного с недействительной областью клиентской области окна. После выполнения в этом контексте всех необходимых операций рисования, приложение должно вызвать ::EndPaint для освобождения контекста и информирования Windows о завершении обновления окна. Если приложение при обработке WM_PAINT не будет вызывать функции ::BeginPaint и ::EndPaint, то Windows не будет удалять сообщение WM_PAINT из очереди и это сообщение будет поступать в окно постоянно.
Объекты класса CPaintDC вызывают ::BeginPaint из конструктора, а ::EndPaint – из деструктора.
После создания объекта CPaintDC в OnPaint создается объект CRect и вызовом CWnd::GetClientRect в него помещаются координаты клиентской области окна:
CRect rect;
GetClientRect( &rect );
Затем OnPaint вызывает CDC::DrawText для вывода строки "Hello, MFC":
dc. DrawText( "Hello, MFC", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER );
DrawText – это функция вывода текста в контекст устройства. У нее 4 параметра: указатель на отображаемую строку, количество символов в строке (или -1, если строка заканчивается нулем), указатель на структуру RECT или объект CRect с координатами области вывода, и флаги вывода. В приложении Hello используется комбинация из трех флагов, указывающих, что текст надо выводить в одну строку и центрировать и по горизонтали, и по вертикали внутри области rect.
Заметно, что среди параметров DrawText нет характеристик шрифта и цвета текста. Эти и другие параметры вывода являются атрибутами контекста устройства и управляются специальными функциями-членами CDC, например, SelectObject и SetTextColor. Т. к. приложение Hello не изменяет никаких атрибутов контекста устройства, то используется шрифт и цвет "по умолчанию" (черный). DrawText заполняет прямоугольник, описывающий текст, текущим фоновым цветом контекста устройства (по умолчанию – белый).
2.7 Карта сообщений
Как сообщение WM_PAINT, полученное от Windows, преобразуется в вызов функции-члена CMainWindow::OnPaint? Это делается с помощью карты сообщений. Карта сообщений – это таблица, связывающая сообщения и функции-члены для их обработки. Когда окно-рамка приложения Hello получает сообщение, то MFC просматривает карту сообщений, ищет в ней обработчик для сообщения WM_PAINT и вызывает OnPaint. Карты сообщений в MFC введены для того, чтобы избежать больших таблиц виртуальных функций, которые были бы необходимы, если в каждом классе завести виртуальную функцию для каждого возможного сообщения. Карту сообщений может содержать любой подкласс класса CCmdTarget.
Карты сообщений в MFC реализованы так, что в исходном тексте видны только макросы, которые использовать достаточно просто, а сложная обработка карт скрыта внутри MFC. Для добавления карты сообщений в класс надо сделать следующее:
1) Объявить карту сообщений в интерфейсной части класса с помощью макроса DECLARE_MESSAGE_MAP.
2) Создать карту сообщений в файле реализации. Она ограничена макросами BEGIN_MESSAGE_MAP и END_MESSAGE_MAP. Между ними размещаются макросы, идентифицирующие конкретные сообщения.
3) Добавить в класс функции-члены для обработки сообщений.
В приложении Hello класс CMainWindow обрабатывает только одно сообщение, WM_PAINT, поэтому карта сообщений выглядит так:
BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )
ON_WM_PAINT()
END_MESSAGE_MAP()
Карта сообщений начинается с макроса BEGIN_MESSAGE_MAP, в котором задается имя класса-владельца карты и имя его базового класса. (Карты сообщений наращиваются путем наследования. Имя базового класса необходимо, чтобы каркас приложений мог продолжить поиск обработчика сообщений и в карте базового класса, если его нет в карте текущего.). Макрос END_MESSAGE_MAP завершает карту сообщений. Между BEGIN_MESSAGE_MAP и END_MESSAGE_MAP располагаются элементы карты сообщений. Макрос ON_WM_PAINT определен в заголовочном файле MFC Afxmsg_.h. Этот макрос добавляет в карту сообщений элемент для обработки сообщения WM_PAINT. У этого макроса нет параметров, в нем жестко задана связь между сообщением WM_PAINT и функцией-членом OnPaint.
В MFC есть макросы для более чем 100 сообщений Windows, начиная от WM_ACTIVATE до WM_WININICHANGE. Узнать имя функции-обработчика сообщения для некоторого макроса ON_WM можно из документации по MFC, но правила обозначений прозрачны и можно просто заменить в имени сообщения префикс WM_ на On и преобразовать остальные символы имени сообщения, кроме первых символов отдельных слов, в нижний регистр. Например, WM_PAINT преобразуется в имя обработчика OnPaint, WM_LBUTTONDOWN в OnLButtonDown и т. п.
Типы параметров функции-обработчика сообщения можно узнать в справочной системе по MFC. В обработчик OnPaint не передается никаких параметров и у него нет возвращаемого значения. Но может быть и иначе, например, прототип обработчика OnLButtonDown выглядит так:
afx_msg void OnLButtonDown( UINT nFlags, CPoint point )
Параметр nFlags является набором битовых флагов, отражающих состояние кнопок мыши, клавиш Ctrl и Shift. В объекте point хранятся координаты указателя мыши в момент щелчка левой кнопкой. Параметры, передаваемые в обработчик сообщений, первоначально приходят в приложение в виде параметров сообщения wParam и lParam. В Windows API параметры wParam и lParam служат общим способом передачи информации о сообщении и не учитывают его специфику. Поэтому с обработчиками сообщений MFC работать гораздо удобнее, т. к. каркас приложения передает в них параметры в виде, наиболее удобном для конкретного сообщения.
Что будет, если вы хотите обработать сообщение, для которого в MFC нет макроса карты сообщений? Вы можете создать элемент карты для такого сообщения с помощью макроса ON_MESSAGE. У него два параметра: идентификатор сообщения и адрес соответствующей функции-члена класса. Например, для обработки сообщения WM_SETTEXT с помощью функции-члена OnSetText надо создать следующую запись в карте сообщений:
ON_MESSAGE( WM_SETTEXT, OnSetText )
Функция-член OnSetText должна быть объявлена так:
afx_msg LRESULT OnSetText( WPARAM wParam, LPARAM lParam );
В MFC есть еще ряд служебных макросов карты сообщений. Например, ON_COMMAND связывает с функциями-членами класса команды меню и события других элементов пользовательского интерфейса. Макрос ON_UPDATE_COMMAND_UI связывает элементы меню и другие объекты интерфейса с обработчиками обновления, которые синхронизируют состояние объектов интерфейса с внутренним состоянием приложения. Эти и другие макросы карты сообщений будут рассматриваться позже.
Еще раз вернемся к приложению Hello. В классе CMainWindow функция-член OnPaint и карта сообщений описываются в Hello. h:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
Макрос afx_msg применяется для удобочитаемости исходного текста, он напоминает о том, что OnPaint является обработчиком сообщений. Этот макрос указывать не обязательно, т. к. при компиляции он заменяется пробелом.
Макрос DECLARE_MESSAGE_MAP обычно идет последним оператором в объявлении класса, т. к. в него встроены модификаторы доступа Си++. Вы можете объявлять компоненты класса и после DECLARE_MESSAGE_MAP, но обязательно указывайте для них соответствующий модификатор доступа public, protected или private.
3. Резюме
Перечислим наиболее важные особенности устройства MFC-приложения Hello. Сразу после запуска приложения создается глобальный объект-приложение подкласса CWinApp. Функция каркаса MFC AfxWinMain вызывает функцию объекта-приложения InitInstance. Эта функция создает объект-главное окно приложения, а его конструктор создает и выводит на экран окно Windows. После создания окна, InitInstance делает окно видимым с помощью функции-члена ShowWindow и затем посылает этому окну сообщение WM_PAINT с помощью функции UpdateWindow. Затем InitInstance возвращает управление и AfxWinMain вызывает у объекта-приложения функцию-член Run, внутри которой реализован цикл обработки сообщений. MFC с помощью карты сообщений преобразует поступающие сообщения WM_PAINT в вызовы функции-члена CMainWindow::OnPaint, а OnPaint выводит в клиентскую область окна символьную строку "Hello, MFC". Вывод текста выполняется с помощью функции-члена DrawText объекта-контекста устройства CPaintDC.
В MFC, по сравнению с программированием в Windows API, заметны новые сложности. Окно создается в два этапа. Нужен объект-приложение. Отсутствует функция WinMain. Все это отличается от программирования для Windows на уровне API. Но, если сравнить исходный текст MFC-приложения Hello и текст аналогичной программы, пользующейся API, станет заметно бесспорное преимущество MFC. MFC уменьшает размер исходного текста, и он становится проще для понимания, т. к. значительная часть исходного текста располагается внутри библиотеки классов. Поведение классов MFC можно изменять путем наследования от них своих собственных подклассов. В результате MFC оказывается очень эффективным средством программирования для Windows. Преимущества MFC становятся особенно очевидны при использовании сложных возможностей Windows, например, элементов управления ActiveX или при связи с другими приложениями через интерфейс OLE.
4. Упражнения
1) Ознакомьтесь с иерархией классов, приведенной в документе "Иерархия классов MFC" или в справочной системе Visual C++ по теме "Hierarchy Chart".
2) На основе приведенных в лекции исходных файлов соберите приложение Hello. Для этого в Visual C++ надо выполнить следующие действия:
1. Выберите команду FileÞNew и затем перейдите на закладку Projects.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |


