Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Вкладки диалогового окна ClassWizard




Для того чтобы вывести на экран диалоговое окно мастера ClassWizard, нужно выбрать из меню View--ClassWizard или нажать <Ctrl+W>. ClassWizard имеет диалоговое окно с несколькими вкладками. На рис. 3.1 показана вкладка Message Maps (Карты сообщений). В верхней ее части имеется два раскрывающихся списка. В одном — Project— представлен проект, над которым вы в настоящее время работаете (в данном случае— ShowString), в другом— Class name— класс, карта сообщений которого редактируется (в данном случае— CShowSthngApp). Информация о карте сообщений этого класса выведена в других полях вкладки.

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

В правой верхней части окна находятся четыре кнопки, пользуясь которыми, можно включить новый класс в проект, новую функцию — в существующий класс, для того чтобы перехватывать выделенное в левом окне сообщение, удалить функцию, которая ответственна за обработку выделенного сообщения, или вывести на экран текст этой функции. Типовая методика следующая — нужно выбрать класс, сообщение и щелкнуть на кнопке Add Function с тем, чтобы добавить функцию, которая будет ответственна за обработку заданного сообщения. Ниже перечислены операции, которые будут выполнены после щелчка на Add Function.

• В конец файла текста программы включается заготовка ("скелет" — skeleton) функции.

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

• В файл заголовка также включается новый компонент карты сообщений.

• Обновляются списки сообщений и функций-членов в окнах вкладки.

После включения новой функции щелчок на Edit Code позволит наполнить созданную ClassWizard заготовку функции содержанием соответственно тому, как планируется обрабатывать данное Сообщение. Того же результата можно достичь, сделав двойной щелчок на имени функции в списке Member Functions.

Этот список находится ниже окон списков Object IDs и Messages. В нем перечислены функции-члены текущего класса, которые связаны с определенными сообщениями. В данном случае имеются две такие функции.

• InitInstance(). Перегружает виртуальную функцию класса CWinApp — базового класса для CShowStringApp. Эта функция помечена символом V в списке, что означает— виртуальная функция (Virtual function).

• OnAppAbout(). Перехватывает команду ID_APP_ABOUT; помечена символом W в списке, что означает — сообщение окна (Window message).

Функция InitInstance() вызывается после запуска приложения. Вам нет необходимости углубляться в подробности ее работы— ClassWizard просто напоминает, что эта функция уже перегружена для данного приложения.

И наконец, ниже окна списка Member Functions выведено сообщение, напоминающее о назначении выделенного сообщения. В данном случае текст Called to implement wait cursors (Вызывается для установки курсора ожидания) — это описание виртуальной функции DoWaitCursor().

В Visual C++ начиная с версии 5.0 предлагается новый дополнительный способ перехвата сообщений. Вместо того чтобы вызвать ClassWizard и затем не забыть найти правильное имя класса в раскрывающемся списке, нужно просто щелкнуть правой кнопкой мыши на имени класса в окне ClassView и затем выбрать пункт Add Windows Message Handler (Добавление обработчиков сообщений Windows) контекстного меню. Диалоговое окно, которое в результате появится на экране, показано на рис. 3.2.

В этом диалоговом окне не показаны виртуальные функции, которые перечислены в главном окне CiassWizard. Глядя на это окно, легко сообразить, что данный класс перехватывает команду ID_APP_ABOUT, но не перехватывает обновление команды (command update).

Для того чтобы добавить новую виртуальную функцию, нужно сделать двойной щелчок на имени класса в ClassView и выбрать пункт Add New Virtual Function (Добавление новой виртуальной функции) контекстного меню. Диалоговое окно, которое в результате появится на экране, показано на рис. 3.3.

На, рис. 3.3 видно, что в классе CShowStringApp уже перегружена виртуальная функция InitInstance(), но существуют и другие виртуальные функции, которые можно перегрузить. Как и на вкладке, сообщение в самом низу окна напоминает вам о назначении каждой функции. Сам же текст сообщения — Саlled to implement wait cursors (Вызывается для установки курсора ожидания) —тот же, что и на вкладке (см. рис. 3.1).

Какой класс должен перехватывать сообщение

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

• Активное представление (вид)

• Документ, представленный в нем

• Фрейм (рамка окна), который содержит активное представление

• Объект-приложение

Список сообщений

Существует почти 900 различных сообщений. Поскольку обычно для организации перехвата сообщений в приложении используется ClassWizard, представленный в нем список будет значительно короче (ведь в него отбираются только те сообщения, которые подходят для выбранного класса). Отнюдь не каждое окно может получить то или иное сообщение. Например, только класс, являющийся наследником CListBox, может получить сообщение типа LB_SETSEL, которое заставляет элемент управления типа список передвинуть подсветку на некоторый элемент списка. Префикс в имени сообщения указывает тип окна, для которого предназначено сообщение или которое его породило.

Какая разница, скажем, между ВМ-(button message) и ВN-(button notification) сообщением? ВМ-сообщение — это сообщение, направленное объекту-кнопке, например "Действуй так, как будто на тебе щелкнули". A BN-сообщение — это сообщение с кодом извещения, поступающего от объекта-кнопки окну, в котором эта кнопка находится и которое является "владельцем" кнопки. Это сообщение может, например, гласить: "Ой, на мне щелкнули!". То же самое справедливо для всех других модификаций сообщений, префиксы которых завершаются литерой М или N.

Иногда префикс не заканчивается буквой М. Например, СВ — это префикс для сообщений от объекта - поля со списком, в то время как CBN является префиксом сообщения с кодом извещения, которое поле со списком передает окну-владельцу. Например, CBN_SELCHANGE— это сообщение от поля со списком, извещающее "родителя" о том, что пользователь выбрал другой элемент списка.

 

Команды. Реализация обработки команд с помощью ClassWizard.

Команды

Что такое команда? Это сообщение специального типа, которое формируется в тех случаях, когда пользователь выбирает пункт меню, щелкает на кнопке или каким-либо другим способом дает системе понять, что ему что-то от нее нужно. В прежних версиях Windows и выбор из меню, и щелчок на кнопке формировали сообщение WM_COMMAND. Наступили новые времена, и теперь только выбор из меню порождает сообщение WM_COMMAND, а щелчок на кнопке или выбор в списке порождает сообщение WM_NOTIFY с кодом извещения от элемента управления.

Все сообщения команд содержат в качестве первого параметра идентификатор ресурса — выбранный пункт меню или кнопку, на которой щелкнули. Этот идентификатор ресурса присваивается в соответствии со стандартом на форматы подобного рода идентификаторов, например для пункта Save As меню File идентификатор будет иметь вид ID_FILE_SAVE.

Получать сообщения могут только объекты классов-наследников CWnd, а все объекты классов, порожденных от CCmdTarget, включая CWnd и CDocument, могут получать команды и извещения. Это означает, что класс, который наследует CDocument, может иметь карту сообщений, причем в ней не должно быть ни одного компонента, соответствующего сообщению, а только компоненты для команд и извещений. Тем не менее этот фрагмент программы по-прежнему называется картой сообщений.

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

Обновление команд

Рассмотрим, как программа выполняет блокировку определенных пунктов меню или кнопок в соответствии с контекстом задачи. Этот процесс назван обновлением команд (command updating).

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

Один состоит в том, чтобы организовать огромную таблицу, элементами которой будут все имеющиеся в приложении пункты меню, каждому из которых сопоставлен флаг. Состояние флага — TRUE или FALSE — указывает, доступен ли этот пункт меню. Как только возникает необходимость вывести меню на экран, можно быстренько просмотреть таблицу и все сразу станет ясно. При любой операции, которая может повлечь за собой изменения в статусе какого-либо пункта меню, таблица обновляется. Все это в совокупности называется подходом непрерывного обновления (continuous-updating approach).

Другой подход состоит в том, чтобы, не имея такой таблицы, перед каждым выводом меню на экран анализировать все условия, которые влияют на возможную блокировку. Он называется подходом обновления по требованию (update-on-demand approach). Именно такой подход и реализован в Windows.

Когда наступает время выводить на экран меню, конкретные объекты "знают", нужно ли блокировать связанный с ними пункт меню. Например, объект класса документа знает, был ли он модифицирован после последнего сохранения, и решает, стоит ли блокировать пункт Save меню File. Объект класса представления знает, есть ли выделенный фрагмент текста, и может решить, как поступить с пунктами Cut и Copy меню Edit. Все это означает, что комплексная задача блокировки пунктов меню в соответствии с контекстом приложения распределяется между различными объектами приложения, а не возлагается на главную вызывающую подпрограмму WndProc().

Подход, реализованный в MFC, состоит в том, чтобы использовать небольшой объект класса CCmdUI (класс интерфейса с командами пользователя — command user interface) и предоставить ему возможность перехватывать любые сообщения ON_UPDATE_COMMAND_UI. Организовать такой перехват можно, добавив (или предоставив возможность ClassWizard добавить) макрос ON_UPDATE_COMMAND_UI в карту сообщений. Объект класса CCmdUI также используется для блокировки или разблокировки командных кнопок и других элементов управления.

Класс CCmdUI имеет следующие функции-члены.

• Enable(). Принимает аргумент TRUE или FALSE. Блокирует элемент интерфейса пользователя, если передан аргумент FALSE, в противном случае делает элемент доступным.

• SetCheck(). Включает или выключает элемент управления.

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

• SetText(). Устанавливает текст надписи пункта меню или кнопки, если элемент управления — кнопка.

• DoUpdate(). Формирует сообщение.

Как правило, выбор, какая из перечисленных функций-членов нужна вам для определенных целен, очевиден. Ниже приведена упрощенная версия карты сообщений объекта класса CWhoisView, производного от CFormView, который выводит информацию на экран для пользователя. Соответствующая экранная форма имеет несколько текстовых полей, и пользователь может вставлять текст в одно из них. Карта сообщений содержит компонент перехвата обновления для команды ID_EDIT_PASTE, что в тексте программы выглядит следующим образом:

BEGIN_MESSAGE_MAP(CWhoisView, CFormView)

…ON_UPDATE_COMMAND_ID(ID_EDIT_PASTE, OnUpdateEditPaste)

 …END_MESSAGE_MAP()

Функция OnUpdateEditPaste(), которая перехватывает обновление, выглядит следующим образом:

void CWhoisView::OnUpdateEditPaste(CCmdUI * pCmdUI)

{pCmdUI->Enable(::IsCIipboardFormatAvailable(CF_TEXT));}

Здесь вызывается функция API ::IsCIipboardFormatAvailable(), которая проверяет, есть ли текст в системном буфере Clipboard. Дело в том, что другое приложение может загрузить из Clipboard изображение или другую нетекстовую информацию, но данное приложение такими возможностями не располагает. Поэтому, если в Clipboard содержится не текст, текстовое поле в экранной форме блокируется. Большинство функций обновления команд выглядит аналогично— они вызывают Enable() c аргументом, который формируется в результате вызова некоторой функции, возвращающей TRUE или FALSE, или— другой вариант— аргумент является просто логическим выражением.

 










Последнее изменение этой страницы: 2018-04-12; просмотров: 279.

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