Microsoft Visual C++ и MFC. Программирование для Win95 и WinNT

         

Окна MDI и главное окно однооконного приложения


Для приложений, имеющих однооконный интерфейс, роль главного окна приложения выполняет объект класса CFrameWnd или класса наследованного от базового класса CFrameWnd.

Главное окно однооконного приложения и дочерние MDI окна многооконного приложения обрабатывают командные сообщения одинаковым образом. Объект класса CFrameWnd или CMDIChildWnd, которому поступило командное сообщение, передает его соответствующему окну просмотра. Если окно просмотра не может обработать сообщение, проверяется таблица сообщений класса CFrameWnd или CMDIChildWnd.

Если главное окно однооконного приложения или окно MDI многооконного приложения не может обработать сообщение, оно передается объекту главного класса приложения.



Окно просмотра


В отличие от объектов, представляющих окна типа frame (объекты классов CMDIFrameWnd, CFrameWnd и CMDIChildWnd) окно просмотра в первую очередь проверяет собственную таблицу сообщений. И только в том случае, если командное сообщение не может быть обработано, оно передается документу, связанному с данным окном просмотра.



Органы диалоговых панелей управления


Не только меню и панели управления обновляются с использованием механизма команд обновления. Точно также можно обновить и состояние кнопок и других органов управления диалоговых панелей.



Органы управления OCX


На странице OLE Controls диалоговой панели Component Gallery представлены органы управления OCX. Количество этих компонент настолько велико, что мы не имеем возможности рассказать про них все. Поэтому мы ограничимся только несколькими органами управления, которые поставляются вместе с Microsoft Visual C++.

¨ По возможности используйте органы управления OCX. Это позволит сократить время на разработку вашего приложения и повысит его надежность.

Многие фирмы выпускают собственные органы управления OCX и распространяют их как отдельные продукты вместе с подробной документацией. Во многих случаях вместо разработки собственных органов управления вы можете приобрести уже готовые решения. Такой подход позволит сохранить много времени на разработке и отладке собственного программного кода.

Пиктограмма



Назначение соответствующего компонента

Сетка или таблица в каждой ячейке которой можно вывести текст или изображение

Орган управления, который позволяет обмениваться информацией через последовательный порт

Орган управления позволяет воспроизводить видео, записанное в форматах AVI, MPEG и QuickTime 

Орган управления, предназначенный для форматированного ввода и вывода данных

Кнопка с рисунком

Набор кнопок для приложений мультимедиа

Кнопки, имеющие нестандартные формы

Для добавления к проекту новых органов управления OCX, выберите соответствующую пиктограмму на странице OLE Control окна Component Gallry и нажмите кнопку Insert. Дальнейший процесс вставки компонента зависит от него самого.

Как правило, когда вы нажимаете кнопку Insert, у вас запрашивается различная дополнительная информация. Это могут быть названия классов, файлов и т. д. Когда вы введете всю необходимую информацию, начнется модификация проекта. В проект будут добавлены один или несколько классов, представляющих новый орган управления OCX. Методы этих классов вы будете использовать для взаимодействия с объектами OCX. Описание данных классов вы можете получить, нажав кнопку ? в панели Component Gallry.


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

Когда вы добавляете новые органы управления OCX в ваш проект, то в панели инструментов Controls появляются представляющие их пиктограммы. Так на рисунке 2.5 мы представили начальный набор органов управления панели Controls. После того как в проект добавлены органы управления Anibutton Control, Grid Control, Microsoft Comm Control, Microsoft Masked Ediit Control и VideoPlay Control, внешний вид панели изменится (рис. 2.6).



Рис. 2.5. Стандартные органы управления

Используя новые кнопки на панели Control также, как стандартные кнопки этой панели, вы можете поместить соответствующие органы управления на диалоговых панелях приложения.



Рис. 2.6. Новые органы управления OCX


Отображение текста в панели состояния


Для изменения текста в самом первом индикаторе панели состояния, который имеет идентификатор ID_SEPARATOR, можно воспользоваться методом SetWindowText. Этот метод определен в классе CWnd и вы можете его использовать, так как класс панели состояния наследуется от класса CWnd. Строку, которую надо вывести в панели состояния, следует передать через параметр lpszString:

void SetWindowText(LPCTSTR lpszString);

Метод SetWindowText изменяет текст в панели состояния, передавая ему сообщение WM_SETTEXT. Самый первый индикатор панели состояния, который имеет идентификатор ID_SEPARATOR, отличается от остальных индикаторов панели состояния. В нем отображаются подсказки для выбранных строк меню, кнопок панели управления и в некоторых других случаях. Фактически, этот индикатор используется различными объектами библиотеки MFC для отображения своего состояния или кратких подсказок.

Объекты MFC устанавливают текст первого идентификатора, непосредственно передавая окну панели состояния сообщение WM_SETTEXT. Отсюда, кстати, следует не очень утешительный вывод: текст, который вы выводите методом SetWindowText, может быть изменен в любой момент без вашего ведома. Чтобы исправить такое положение вещей, можно наследовать от класса CStatusBar собственный класс, в котором определить обработчик для сообщения WM_SETTEXT. Этот обработчик, например, может полностью игнорировать сообщения WM_SETTEXT или обрабатывать их только в особых случаях.

Если вам надо изменить текст не только в самом первом индикаторе, но и в других индикаторах панели состояния, можно воспользоваться методом SetPaneText, который определен в классе CStatusBar:

BOOL

SetPaneText(

   int nIndex,

   LPCTSTR lpszNewText,

   BOOL bUpdate = TRUE

);

Метод SetPaneText выводит в индикаторе с индексом nIndex текст, указанный в параметре lpszNewText. Параметр bUpdate позволяет сразу обновить данный индикатор. Если bUpdate содержит значение TRUE, то индикатор будет перерисован.

Текст, который отображается в индикаторе в данный момент, можно определить при помощи метода GetPaneText, также входящего в класс CStatusBar.


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

Имена для методов обработчиков сообщения ON_UPDATE_COMMAND_UI обычно составляются из строки OnUpdate и имени объекта, сообщения которого обрабатываются. Формат этих методов следующий:

afx_msg void OnUpdateCtrlName(CCmdUI* pCmdUI);

Обработчику сообщения ON_UPDATE_COMMAND_UI через параметр pCmdUI передается указатель на объект класса CCmdUI. Полученный объект класса CCmdUI представляет индикатор панели состояния.

¨     Сообщение ON_UPDATE_COMMAND_UI также используется и для обновления других объектов пользовательского интерфейса, например строк меню и кнопок панелей управления

Во время обработки сообщения ON_UPDATE_COMMAND_UI вы можете изменить текст в данном индикаторе, вызвав метод SetText класса CCmdUI. Новый текст для индикатора надо указать в качестве параметра lpszText метода SetText:

virtual void SetText(LPCTSTR lpszText);

Метод SetText не выполняет автоматическое изменение размера индикатора. Поэтому, вы должны сами следить за шириной отображаемого текста и в случае необходимости корректировать размер индикатора при помощи метода SetPaneInfo.

Во время обработки сообщения ON_UPDATE_COMMAND_UI можно не только изменить текст в индикаторе, можно полностью заблокировать индикатор. В заблокированном индикаторе текст не отображается. Чтобы выполнить блокировку индикатора, при обработке соответствующего сообщения надо вызвать метод Enable.

Метод Enable, также как метод SetText, определен в классе CCmdUI и имеет следующий прототип:

virtual void Enable(BOOL bOn = TRUE);

Единственный параметр метода bOn выбирает новое состояние индикатора. Если в качестве параметра bOn указать значение TRUE или вызвать метод Enable без параметра, индикатор переходит в нормальное состояние - текст внутри индикатора отображается. Если через параметр bOn передать значение FALSE, тогда выполняется блокировка индикатора.


Панель для выбора шрифта


Стандартная диалоговая панель Font предназначена для выбора шрифта. Диалоговая панель Font отображает список шрифтов, установленных в системе, и позволяет выбрать название шрифта, его начертание, кегль, выделение, цвет, набор национальных символов (рис. 4.7).

Для управления диалоговой панелью Font в библиотеку классов MFC включен класс CFontDialog. Методы этого класса можно использовать для отображения панели Font и определения характеристик шрифта, выбранного пользователем.

Рис. 4.7. Стандартная диалоговая панель Font

Конструктор класса CFontDialog:

CFontDialog(

   LPLOGFONT lplfInitial = NULL,

   DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,

   CDC* pdcPrinter = NULL,

   CWnd* pParentWnd = NULL

);

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

Мы не станем подробно описывать параметры конструктора, вы найдете это описание в документации Microsoft Visual C++. Сейчас мы приведем только краткий обзор этих параметров. Дополнительную информацию по использованию стандартных панелей выбора шрифта вы можете получить в 14 томе “Библиотеки системного программиста”.

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

Параметр dwFlags задает набор флагов, управляющих различными режимами работы панели Font.

Через параметр pdcPrinter можно передать конструктору контекст отображения принтера, шрифты которого будут представлены в диалоговой панели Font. Данный параметр используется только в том случае, если в параметре dwFlags указан флаг CF_PRINTERFONTS или CF_BOTH.

Через параметр pParentWnd можно указать родительское окно для далоговой панели Font.



Панель для выполнения поиска и замены


Класс CFindReplaceDialog предназначен для управления диалоговыми панелями Find и Replace. Диалоговая панель Find (рис. 4.11) используется для поиска известных строк в документе приложения, а панель Replace (рис. 4.12) позволяет выполнять замену одной строки на другую.

Рис. 4.11. Стандартная диалоговая панель Find

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

Рис. 4.12. Стандартная диалоговая панель Replace

Мы расскажем о стандартных диалоговых панелях Find и Replace в одной из следующих книг серии “Библиотека системного программиста”, которуые мы посвятим Microsoft Visual C++ и библиотеке MFC.



Панель состояния


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

Когда вы разрабатываете приложение с оконным интерфейсом при помощи средств MFC AppWizard, вы можете указать, будет ли приложение иметь панель состояния. Этой возможностью управляет переключатель Initial status bar на одной из панелей создания приложения AppWizard. Внешний вид этой панели представлен на рисунке 3.3.

По умолчанию переключатель Initial status bar установлен, и все оконные приложения, построенные с использованием средств MFC AppWizard, имеют панель состояния. В ней отображается текущее состояние приложения или краткая подсказка для выбранных строк меню, а также текущее положение клавиш <Caps Lock>, <Scroll Lock> и <Num Lock>.



Панель управления


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

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

Чтобы выйти из этого положения, создают несколько отдельных панелей управления, которые можно открывать или закрывать по своему усмотрению. Такая организация панелей управления используется очень часто. Достаточно взглянуть на любое офисное приложение Microsoft - Microsoft Word или Microsoft Excel, или даже на среду Microsoft Visual C++.



Панель управления Extended


Панель Extended демонстрирует использование в панелях управления toolbar дополнительных органов управления - поля редактирования и списка combo-box. Сразу после запуска приложения MultiBar в списке combo-box содержатся три строки - First, Second и Third. В поле редактирования можно ввести новые строки для этого списка. После того, как вы наберете строку, нажмите кнопку

. Введенная строка появится в конце списка combo-box.

На рисунке 3.18 мы показали внешний вид панели управления Extended с открытым списком combo-box, после того как в нее добавлена строка Fifth.

Рис. 3.18. Новая строка в списке combo-box

Панель управления Extended можно присоединить к любой стороне главного окна приложения или разместить в отдельном мини-окне. Когда панель управления Extended отображается в мини-окне, ее форму можно изменять. Ширина панели Extended не может быть меньше, чем самый широкий орган управления.



Панель управления Player


Панель управления Player состоит из девяти кнопок, сгруппированных в четыре отдельные группы. Панель Player предназначена для управления музыкальным центром. Все кнопки имеют краткие подсказки.

При нажатии на кнопки панели управления Player на экране появляется сообщение, о том, что команда не поддерживается. Обратите внимание на кнопки Pause, Type, CD и WAVE.

Кнопка Pause работает как переключатель. Если вы на нее нажмете - она остается в нажатом положении до тех пор, пока вы не нажмете на нее еще один раз. Кнопки Type, CD и WAVE работают вместе как переключатель с зависимой фиксацией. Одновременно может быть нажата только одна из этих кнопок.

Панель управления Player можно присоединить к трем из четырех сторон главного окна приложения - к верхней, левой и нижней. К правой стороне окна панель Player не присоединяется (рис. 3.17). Вы также можете использовать для панели Player отдельное мини окно, форму которого можно изменять.

Рис. 3.17. Изменение формы панели управления Player



Панель управления Slyle


Панель управления Slyle отображается исключительно в отдельном мини-окне. Вы не сможете пристыковать ее ни к одной из сторон главного окна приложения MultiBar. Кнопки панели управления Slyle отображаются в три ряда по четыре кнопки в каждом ряду. В отличие от панелей управления Extended и Player, форма панели управления Slyle не изменяется.

Два верхних ряда кнопок в панели управления MultiBar имеют краткие подсказки. Если указатель мыши задержится над ними на некоторое время, то около него появится маленькое окно tooltip с кратким описанием соответствующей кнопки. Кнопки из нижнего ряда подсказок не имеют.



Панель управления toolbar


Не смотря на то, что приложение имеет два меню, для него определена только одна панель управления IDR_MAINFRAME. Идентификаторы первых трех и последних двух кнопок этой панели соответствуют идентификаторам строк и меню IDR_MAINFRAME и меню IDR_MULTITYPE. А вот вторые три идентификатора имеют соответствие только в меню IDR_MULTITYPE. Пока ни один документ не открыт и отображается меню IDR_MAINFRAME, эти кнопки недоступны и отображаются серым цветом:

//////////////////////////////////////////////////////////////

// Панель управления Toolbar

IDR_MAINFRAME TOOLBAR DISCARDABLE  16, 15

BEGIN

   BUTTON      ID_FILE_NEW

   BUTTON      ID_FILE_OPEN

   BUTTON      ID_FILE_SAVE

   SEPARATOR

   BUTTON      ID_EDIT_CUT

   BUTTON      ID_EDIT_COPY

   BUTTON      ID_EDIT_PASTE

   SEPARATOR

   BUTTON      ID_FILE_PRINT

   BUTTON      ID_APP_ABOUT

END

Образ кнопок панели управления расположен в файле Toolbar.bmp, записанном в подкаталоге res каталога проекта (рис. 1.6):

//////////////////////////////////////////////////////////////

// Изображение Bitmap, определяющее кнопки приложения

IDR_MAINFRAME   BITMAP   MOVEABLE PURE   "res\\Toolbar.bmp"

Панелям управления мы уделили в этой книге отдельную главу, которая имеет название “Меню, панели управления и панели состояния”. В ней описаны принципы устройства и работы панелей управления, приведены простые примеры создания дополнительных панелей управления, в том числе панелей управления на основе шаблонов диалоговых панелей.

Рис. 1.6. Панель управления



Панель выбора цвета


Чтобы отобразить на экране стандартную диалоговую панель выбора цвета, надо создать объект класса CColorDialog, а затем вызвать метод DoModal. При создании объекта класса CColorDialog используйте следующий конструктор:

CColorDialog(

   COLORREF clrInit = 0,

   DWORD dwFlags = 0,

   CWnd* pParentWnd = NULL

);

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

Первый параметр clrInit позволяет указать цвет, выбранный по умолчанию сразу после открытия диалоговой панели. Если параметр не будет указан, в качестве цвета, выбранного по умолчанию будет использоваться черный цвет.

Параметр dwFlags содержит набор флагов, управляющих диалоговой панелью выбора цвета. Подробно про эти флаги вы можете прочитать в 14 томе “Библиотеки системного программиста”, в разделе, описывающем структуру CHOOSECOLOR.

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

Если при создании объекта CColorDialog вы не укажите параметр dwFlags, вы, тем не менее, можете выполнить настройку диалоговой панели, обратившись непосредственно к элементу m_cc данного класса. Параметр dwFlags, указанный в конструкторе, используется для инициализации m_cc. Изменения в элемент m_cc должны быть внесены до того, как панель будет отображена на экране.



Панель выбора файлов


Среди стандартных диалоговых панелей, для которых в библиотеке MFC создан специальный класс, есть панели для работы с файловой системой - Open и Save As (рис. 4.4). Диалоговая панель Open позволяет выбрать один или несколько файлов, расположенных на дисках компьютера, и открыть их для дальнейшего использования. Диалоговая панель Save As позволяет выбрать имя файла для записи в него документа.

Для управления диалоговыми панелями Open и Save As предназначен один единственный класс - CFileDialog. Рассмотрим конструктор класса CFileDialog более подробно:

CFileDialog(

  

BOOL bOpenFileDialog,

  

LPCTSTR lpszDefExt = NULL,

  

LPCTSTR lpszFileName = NULL,

  

DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,

  

LPCTSTR lpszFilter = NULL,

  

CWnd* pParentWnd = NULL

);

Объекты класса CFileDialog представляют диалоговую панель Open или Save As в зависимости от параметра bOpenFileDialog. Если параметр bOpenFileDialog содержит значение TRUE, тогда создается объект, управляющий диалоговой панелью Open, а если FALSE - диалоговой панелью Save As.

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

Так, чтобы создать объект класса CFileDialog, представляющий стандартную диалоговую панель для открытия файлов (mFileOpen), и объект, представляющий стандартную диалоговую панель для сохранения файлов (mFileSaveAs), можно воспользоваться следующими вызовами конструктора класса:

// Объект mFileOpen представляет стандартную

// диалоговую панель Open

CFileDialog   mFileOpen(TRUE);

// Объект mFileOpen представляет диалоговую

// панель SaveAs

CFileDialog   mFileSaveAs(TRUE);

Во многих случаях файлы, которые вы открываете или закрываете в вашем приложении, имеют определенное расширение. Параметр lpszDefExt позволяет задать расширение файлов, используемое по умолчанию. Если пользователь не укажет расширение файла явным образом, ему автоматически присваивается расширение, принятое по умолчанию. В случае если параметр lpszDefExt не указан или содержит значение NULL, то расширение файлов должно задаваться явно.


В некоторых случаях требуется, чтобы диалоговые панели для открытия или сохранения файлов отображались с уже выбранным именем файла. Пользователь может согласиться с предложенным именем или выбрать другое. Чтобы указать имя файла, используемое по умолчанию, воспользуйтесь параметром lpszFileName. Если параметр lpszFileName имеет значение NULL, данная возможность не реализуется.

Вы можете изменить внешний вид и некоторые другие характеристики стандартных диалоговых панелей для открытия и сохранения файлов с помощью параметра dwFlags. В него записывается комбинация флагов, управляющих различными характеристиками этих панелей. Назначение данного параметра соответствует полю Flags структуры OPENFILENAME. Описание структуры OPENFILENAME вы можете найти в 13 томе “Библиотеки системного программиста”.

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

Вы можете указать список фильтров для диалоговых панелей Open и Save As через параметр lpszFilter. Одновременно можно указать несколько фильтров. Каждый фильтр задается двумя строками - строкой, содержащей имя фильтра, и строкой, в которой паречислены соответствующие ему расширения имен файлов. Если одному типу файлов соответствуют несколько расширений, они разделяются символом ;. Строка, содержашая имя фильтра, отделяется от строки с расширениями файлов символом |. Если используются несколько фильтров, то они также отделяются друг от друга символом |.

Диалоговые панели, представленные объектами класса CFileDialog, могут иметь или не иметь родительского окна. Чтобы указать родительское окно, передайте конструктору CFileDialog указатель на него через параметр pParentWnd.



Рис. 4.4. Стандартная диалоговая панель Save As


Панели для вывода документа на печать


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

В приложения, подготовленные с использованием средств MFC AppWizard и построенные по технологии документ - окно просмотра, по умолчанию “встроена” возможность вывода редактируемого документа на печать.

Так, например, в меню File приложения Multi находятся три строки, которые управляют процессом печати документов, подготовленных в приложении. Мы привели внешний вид меню File приложения Multi на рисунке 4.10.

Рис. 4.8. Меню File, приложения Multi

Чтобы распечатать документ, достаточно выбрать из меню File строку Print. На экране появится диалоговая панель Print, представленная нами на рисунке 4.9. В ней вы можете выбрать печатающее устройство для печати документов (группа Name), указать будет ли печататься весь документ, либо его часть (группа Print range), а также сколько копий документа будет напечатано (группа Copies). Вы также можете настроить различные характеристики печатающего устройства, если нажмете кнопку Properties в группе Printer.

Рис. 4.9. Стандартная диалоговая панель Print

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

В группе Printer вы можете указать печатающее устройство для печати документов и настроить его соответствующим образом. Группа Paper задает формат бумаги на котором будет печататься документ и режим подачи бумаги в печатающее устройство. Группа Orientation включает только один переключатель, определяющий ориентацию бумаги. Он принимает положение Portrait для вертикальной ориентации изображения на бумаги (режим “портрет”) или Landscape для горизонтальной ориентации изображения на бумаги (режим “ландшафт”).




Рис. 4.10. Стандартная диалоговая панель Print

В приложении Multi есть даже режим предварительного просмотра документа перед печатью. Если вы выберите из меню File строку Print Preview, то в главное окно приложения изменит свой внешний вид. В нем вы сможете просмотреть, как будет выглядеть документ после печати.

Если не требуется выполнять специфическую обработку документа перед печатью, то скорее всего, вам вообще не потребуется самостоятельно добавлять программный код, отвечающий за процесс печати. Тем более маловероятно, что вы будете самостоятельно создавать диалоговые панели типа Print, Print Setup или Print Preview. По этой причине мы не станем в этой книге рассматривать классы CPrintDialog и CPageSetupDialog. Процедура создания этих панелей практически не отличается от создания панели на основе класса CFileDialog. Описание методов классов CPrintDialog и CPageSetupDialog вы можете получить из документации Microsoft Visual C++.


Панели управления и панели состояния


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

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

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



Панели управления приложения MultiBar


Постройте приложение MultiBar и запустите его. На экране появится главное окно приложения MultiBar, в котором отображаются сразу три панели управления - Extended, Player и Slyle. Панели управления Extended и Player присоединены к верхней и нижней границам окна, а панель управления Slyle отображается в отдельном мини-окне (рис. 3.16).

Рис. 3.16. Приложение MultiBar

Приложение MultiBar имеет меню View, состоящее из названий панелей управления Extended, Player и Slyle. Выбирая из меню View названия панелей управления, вы можете убрать их с экрана и опять отобразить (закрыть и открыть).

Панели управления, которые отображаются в мини-окнах, также можно закрыть, если нажать на переключатель

 в верхнем правом углу окна. Чтобы снова открыть закрытую панель управления, используйте меню View.



Пиктограмма


В файле ресурсов приложения Multi определены две пиктограммы IDR_MULTITYPE и IDR_MAINFRAME. Каждая из этих пиктограмм содержит по два изображения размером 32х32 и 16х16 пикселов. Внешний вид пиктограмм соответствует пиктограммам, используемым приложением с однооконным интерфейсом. Для однооконного приложения пиктограмма, представляющая документ, называлась IDR_SINGLETYPE, а не IDR_MULTITYPE. Такая разница в названиях возникла исключительно из-за разницы в названиях проектов приложений:

//////////////////////////////////////////////////////////////

// Пиктограммы

IDR_MAINFRAME   ICON   DISCARDABLE   "res\\Multi.ico"

IDR_MULTITYPE   ICON   DISCARDABLE   "res\\MultiDoc.ico"

Пиктограмма IDR_MAINFRAME представляет приложение, когда оно минимизировано (рис. 1.4). Эта же пиктограмма отображается в левом верхнем углу главного окна приложения.

Рис. 1.4. Пиктограмма IDR_MAINFRAME

Пиктограмма IDR_MULTITYPE используется для представления документа с которым работает приложение (рис. 1.5). В отличие от приложения с однооконным интерфейсом, которое не использует эту пиктограмму, приложение с многооконным интерфейсом отображает пиктограмму IDR_MULTITYPE в левом верхнем углу окна документа.

Рис. 1.5. Пиктограмма IDR_MULTITYPE



Положение панели управления


Панель управления приложения Bar нельзя переместить с одной границы окна к другой и нельзя разместить ее в отдельном окне, независимом от главного окна приложения. Единственное, что вы можете сделать, так это выбрать начальное положение панели управления, установив в момент вызова метода Create флаг CBRS_TOP или CBRS_BOTTOM.

Чтобы вы смогли перемещать панель управления с одной границы окна к другой надо:

1. Разрешить перемещение панели управления для окна, которое содержит панель управления. Для этого следует вызвать метод EnableDocking данного окна. Метод EnableDocking является элементом класса CFrameWnd

2.     Разрешить такое перемещение для самой панели управления. Для этого следует вызвать метод EnableDocking панели управления. Метод EnableDocking является элементом класса CControlBar

3.     Переместить панель управления к одной из сторон окна приложения или вывести ее в отдельном окне. Для этого необходимо вызвать метод DockControlBar или FloatControlBar данного окна приложения. Методы DockControlBar и FloatControlBar являются элементами класса CFrameWnd

Если в одном окне отображается несколько панелей управления, то вы должны вызвать для этого окна метод EnableDocking, а затем для каждой панели управления в отдельности вызвать методы EnableDocking и DockControlBar (или FloatControlBar).

¨     Если вы не выполните хотя бы один пункт из трех, перечисленных выше, панель управления будет жестко привязана к одной из границ окна, или возникнет ошибка во время работы приложения

Параметры методов CFrameWnd::EnableDocking, CControlBar::EnableDocking, а также CFrameWnd::DockControlBar и CFrameWnd::FloatControlBar определяют границы окна, к которым можно пристыковать панель управления. Рассмотрим эти методы более подробно.



Повторное использование кода


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

На заре развития программирования повторное использование программного кода достигалось за счет использования подпрограмм или процедур. Созданные процедуры и подпрограммы записывались в специальные библиотеки и использовались при разработке новых программ.

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



Приложение DialogBar


Создайте новый проект под названием DialogBar. В качестве типа приложения выберите из списка Type строку Application. Настройте проект DialogBar, точно также как вы настраивали проекты Bar и MultiBar: укажите, что приложение будет работать с библиотекой классов MFC.

Наберите в редакторе исходный текст приложения и сохраните его в файле DialogBar.cpp (листинг 3.10). Чтобы ускорить набор исходного текста приложения, за основу вы можете взять файл Bar.cpp приложения Bar. Готовый файл DialogBar.cpp включите в проект.

Листинг 3.10. Файл DialogBar.cpp

//============================================================

// Приложение DialogBar

// (c) Frolov G.V., 1996

// E-mail: frolov@glas.apc.org

//============================================================

// Исключаем редко используемые определения из

// включаемых файлов

#define VC_EXTRALEAN                     

// Включаемый файл для MFC

#include <afxwin.h>

#include <afxext.h>

#include <afxcmn.h>

// Включаемый файл для ресурсов приложения

#include "resource.h"

//============================================================

// Класс CDlgBarApp - главный класс приложения

//============================================================

class CDlgBarApp : public CWinApp

{

public:

   // Мы будем переопределять метод InitInstance

   virtual BOOL InitInstance();

};

 

// Создаем объект приложение класса CDlgBarApp

CDlgBarApp DlgBarApp;

 

//============================================================

// Класс CDlgBarWindow - представляет главное окно

//============================================================

class CDlgBarWindow : public CFrameWnd

{

// Определяем панель управления

protected:

   // Панель управления на основе класса CDialogBar      

   CDialogBar       m_wndDialogBar;

  

protected:

   // Метод OnCreate используется для создания диалоговой

   // панели управления

   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

public:


   // Объявляем конструктор класса CDlgBarWindow

   CDlgBarWindow();

   // Объявляем методы для обработки команд от диалоговой

   // панелей управления

   afx_msg BOOL DlgBarCommand(UINT nID);

   afx_msg void DlgBarCombo();

  

   // Макрокоманда необходима, так как класс

   // CDlgBarWindow обрабатывает сообщения

   DECLARE_MESSAGE_MAP()   

};

//============================================================

// Метод BarCommand

// Обрабатывает команды, выводит на экран сообщение

//============================================================

BOOL CDlgBarWindow::DlgBarCommand(UINT nID)

{

   CString szCommandAbout;

   // Загружаем текстовую строку с идентификатором,

   // соответствующим идентификатору поступившего командного

   // сообщения и выводим ее на экран

   if(szCommandAbout.LoadString(nID))

      MessageBox(szCommandAbout);

   else

   {

      // Ошибка при загрузке строкового ресурса

      TRACE0("Failed to load string\n");

      return -1;     

   }

  

   return TRUE;

}

//============================================================

// Метод DlgBarCombo

// Обрабатывает команды, выводит на экран сообщение

//============================================================

void CDlgBarWindow::DlgBarCombo()

{

   // Отображаем сообщение о том, что сделан выбор из списка

   MessageBox("Combo-box selection changed");

}

//============================================================

// Таблица сообщений класса CDlgBarWindow

//============================================================

BEGIN_MESSAGE_MAP(CDlgBarWindow, CFrameWnd)

   // Макрокоманда вызывает метод OnCreate

   ON_WM_CREATE()

//============================================================

   // Обработчики команд от диалоговой панели управления

   // Командные сообщения от кнопок Set и Clear

   ON_COMMAND_EX(IDC_BUTTON_SET, DlgBarCommand)

   ON_COMMAND_EX(IDC_BUTTON_CLEAR, DlgBarCommand)



   ON_COMMAND_EX(IDC_CHECK1, DlgBarCommand)

   // Командные сообщения от переключателя Alighn

   ON_COMMAND_EX(IDC_RADIO_LEFT, DlgBarCommand)

   ON_COMMAND_EX(IDC_RADIO_CENTER, DlgBarCommand)

   ON_COMMAND_EX(IDC_RADIO_RIGHT, DlgBarCommand)

  

   // Командные сообщения от списка combo-box

   ON_CBN_SELCHANGE( IDC_COMBO_COLOUR, DlgBarCombo)

  

END_MESSAGE_MAP()

//============================================================

// Метод InitInstance класса CDlgBarApp

// Создает главное окно приложения и отображает его на экране

//============================================================

BOOL CDlgBarApp::InitInstance()

{

   m_pMainWnd = new CDlgBarWindow();

   m_pMainWnd -> ShowWindow(m_nCmdShow);

   m_pMainWnd -> UpdateWindow();

   return TRUE;

}

//============================================================

// Конструктор класса CDlgBarWindow

//============================================================

CDlgBarWindow::CDlgBarWindow()

{

   // Создаем окно приложения, соответствующее

   // данному объекту класса CDlgBarWindow

   Create(NULL, "Dialog Bar", WS_OVERLAPPEDWINDOW,

          rectDefault, NULL);

}

//============================================================

// Метод OnCreate класса CDlgBarWindow

// Используется для создания панелей управления

//============================================================

int CDlgBarWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

   // Вызываем метод OnCreate базового класса

   if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

      return -1;

//============================================================

   // Создаем диалоговую панель управления

   if (!m_wndDialogBar.Create(this, IDD_DIALOG_BAR, CBRS_TOP,

                              IDD_DIALOG_BAR))

   {

      // Ошибка при создании диалоговой панели управления

      TRACE0("Failed to create dialog bar\n");

      return -1;

   }

   return 0;



}

Создайте новый файл ресурсов и включите его в проект под именем DialogBar.rc. Создайте шаблон диалоговой панели, которая будет использоваться в качестве диалоговой панели управления.

Откройте панель свойств редактируемой панели управления Dialog Properties. Откройте страницу General и присвойте диалоговой панели идентификатор IDD_DIALOG_BAR. Затем откройте страницу Styles. Выберите из списка Style стиль диалоговой панели Child. Укажите, что диалоговая панель не имеет рамки - из списка Border надо выбрать строку None. Все остальные переключатели из страницы Styles и из страниц More Styles и Extended Styles должны быть отключены.

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

Разместите в шаблоне диалоговой панели несколько органов управления. Для нашего примера вам надо создать две кнопки Set и Clear с идентификаторами IDC_BUTTON_SET и IDC_BUTTON_CLEAR, три переключателя Left, Center и Right с зависимой фиксацией, имеющие идентификаторы IDC_RADIO_LEFT, IDC_RADIO_CENTER и IDC_RADIO_RIGHT, а также список combo-box с идентификатором IDC_COMBO_COLOUR. В список IDC_COMBO_COLOUR внесите несколько начальных значений. Мы записали в него названия различных цветов - Red, Blue, Green, Yellow, Black и White. Эти строки будут содержаться в списке сразу после отображения на экране диалоговой панели.

Добавьте в файл ресурсов строковые ресурсы, описывающие органы управления диалоговой панели. Они должны иметь идентификаторы, соответствующие идентификаторам органов управления.

Мы привели файл ресурсов, который у вас должен получиться в листинге 3.11.

Листинг 3.11. Файл DialogBar.rc

//Microsoft Developer Studio generated resource script.

//

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

//////////////////////////////////////////////////////////////



#undef APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

//

// Russian resources

#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_RUS)

#ifdef _WIN32

LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT

#pragma code_page(1251)

#endif //_WIN32

#ifdef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE DISCARDABLE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE DISCARDABLE

BEGIN

    "#include ""afxres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE DISCARDABLE

BEGIN

    "\r\n"

    "\0"

END

#endif    // APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// Dialog

//

IDD_DIALOG_BAR DIALOG DISCARDABLE  0, 0, 227, 50

STYLE WS_CHILD

FONT 8, "MS Sans Serif"

BEGIN

    CONTROL     "Left", IDC_RADIO_LEFT, "Button",

                   BS_AUTORADIOBUTTON, 95, 10, 40,10

    CONTROL     "Center", IDC_RADIO_CENTER, "Button",

                   BS_AUTORADIOBUTTON, 95, 19, 45, 11

    CONTROL     "Right", IDC_RADIO_RIGHT, "Button",

                   BS_AUTORADIOBUTTON, 95, 30, 40, 9

    GROUPBOX    "Aligns",IDC_STATIC,85,0,80,45

    PUSHBUTTON  "Set",IDC_BUTTON_SET,175,5,45,15

    PUSHBUTTON  "Clear",IDC_BUTTON_CLEAR,175,30,45,15

    COMBOBOX    IDC_COMBO_COLOUR, 5, 5, 70, 50,

                   CBS_DROPDOWNLIST | CBS_SORT |

                   WS_VSCROLL | WS_TABSTOP

END

//////////////////////////////////////////////////////////////

//

// DESIGNINFO

//

#ifdef APSTUDIO_INVOKED

GUIDELINES DESIGNINFO DISCARDABLE

BEGIN

    IDD_DIALOG_BAR, DIALOG

    BEGIN

        LEFTMARGIN, 7

        RIGHTMARGIN, 220

        TOPMARGIN, 7

        BOTTOMMARGIN, 43

    END

END

#endif    // APSTUDIO_INVOKED



//////////////////////////////////////////////////////////////

//

// Dialog Info

//

IDD_DIALOG_BAR DLGINIT

BEGIN

    IDC_COMBO_COLOUR, 0x403, 4, 0

0x6552, 0x0064,

    IDC_COMBO_COLOUR, 0x403, 5, 0

0x6c42, 0x6575, "\000"

    IDC_COMBO_COLOUR, 0x403, 6, 0

0x7247, 0x6565, 0x006e,

    IDC_COMBO_COLOUR, 0x403, 7, 0

0x6559, 0x6c6c, 0x776f, "\000"

    IDC_COMBO_COLOUR, 0x403, 6, 0

0x6c42, 0x6361, 0x006b,

    IDC_COMBO_COLOUR, 0x403, 6, 0

0x6857, 0x7469, 0x0065,

    0

END

//////////////////////////////////////////////////////////////

//

// String Table

//

STRINGTABLE DISCARDABLE

BEGIN

    IDC_RADIO_LEFT          "Left radio box"

    IDC_RADIO_CENTER        "Center radio box"

    IDC_RADIO_RIGHT         "Right radio box"

    IDC_BUTTON_SET          "Set button pressed"

END

STRINGTABLE DISCARDABLE

BEGIN

    IDC_BUTTON_CLEAR        "Clear button pressed"

END

#endif    // Russian resources

//////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

// Generated from the TEXTINCLUDE 3 resource.

//

//////////////////////////////////////////////////////////////

#endif    // not APSTUDIO_INVOKED

Идентификаторы ресурсов приложения DialogBar и идентификаторы органов управления диалоговой панели IDD_DIALOG_BAR определены в файле resource.h. Этот файл создается автоматически редактором ресурсов Microsoft Visual C++. Исходный текст файла представлен в листинге 3.12.

Листинг 3.12. Файл resource.h

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by DialogBar.rc

//

#define IDD_DIALOG_BAR                  101

#define IDC_RADIO_LEFT                  1004

#define IDC_RADIO_CENTER                1005

#define IDC_RADIO_RIGHT                 1006

#define IDC_BUTTON_SET                  1007



#define IDC_BUTTON_CLEAR                1008

#define IDC_COMBO_COLOUR                1012

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        104

#define _APS_NEXT_COMMAND_VALUE         40001

#define _APS_NEXT_CONTROL_VALUE         1014

#define _APS_NEXT_SYMED_VALUE           101

#endif

#endif

Постройте приложение DialogBar и запустите его. На экране появится главное окно приложения, в верхней части которого отображается диалоговая панель управления (рис. 3.19).



Рис. 3.19. Приложение DialogBar

Поработайте с приложением DialogBar. Если вы будете нажимать на кнопки диалоговой панели управления, изменять положение переключателя или выбирать новые строки из списка combo-box, то на экране будут появляться короткие сообщения, описывающие выбранный орган управления.


Приложение FileDlg


Создайте новый проект, присвоив ему имя FileDlg. В качестве типа приложения выберите из списка Type строку Application. Наберите в редакторе исходный текст приложения и сохраните его в файле FileDlg.cpp (листинг 4.1). Включите набранный файл в проект.

Выберите из меню Build строку Settings. На экране появится диалоговая панель Project Settings, предназначенная для настройки различных характеристик проекта. Откройте в этой диалоговой панели страницу General и выберите из списка Microsoft Foundation Classes строку Use MFC in a Shared Dll.

Листинг 4.1. Файл FileDlg.cpp

//============================================================

// Приложение FileDlg

// (c) Frolov G.V., 1996

// E-mail: frolov@glas.apc.org

//============================================================

// Включаемый файл для библиотеки MFC

#include <afxwin.h>

// Включаемый файл для стандартных диалоговых панелей

#include <afxdlgs.h>

//============================================================

// Класс CFileDlgApp

// Наследуем от базового класса CWinApp главный

// класс приложения CFileDlgApp

//============================================================

class CFileDlgApp : public CWinApp

{

public:

   // Мы будем переопределять метод InitInstance,

   // предназначенный для инициализации приложения

   virtual BOOL InitInstance();

};

 

// Создаем объект приложение класса CFileDlgApp

CFileDlgApp FileDlgApp;

 

//============================================================

// Метод InitInstance класса CFileDlgApp

// Переопределяем виртуальный метод InitInstance

// класса CWinApp. Он вызывается каждый раз при запуске

// приложения

//============================================================

BOOL CFileDlgApp::InitInstance()

{

   // Определяем объект класса CFileDialog, представляющий

   // стандартную диалоговую панель Open

   CFileDialog mFileOpen(TRUE);

   // Переменная pos будет использоваться для получения

      // полных имен файлов, выбранных в панели Open


   POSITION pos;

     

   // В строку msg будут записываться названия файлов

   CString msg;

   // Устанавливаем флаг OFN_ALLOWMULTISELECT, который

   // разрешает одновременно выбирать несколько файлов

   mFileOpen.m_ofn.Flags |= OFN_ALLOWMULTISELECT;

     

   // Отображаем диалоговую панель Open и позволяем

   // пользователю выбрать с помощью нее один или

   // несколько файлов

   int result = mFileOpen.DoModal();

   // Проверяем как была закрыта диалоговая панель Open -

   // по нажатию кнопки OK или Cancel

   if(result == IDCANCEL)

   {

      // Если пользователь отказался от выбора файлов и

      // нажал кнопку Cancel отображаем соответствующее

      // сообщение

      AfxMessageBox("File not selected");

   }

   else if(result == IDOK)

   {

      // Если пользователь нажал кнопку OK, определяем

      // начальную позицию для метода GetNextPathName

      pos = mFileOpen.GetStartPosition();

      // В цикле получаем имена файлов, выбранных в

      // диалоговой панели Open. После получения всех

      // имен, завершаем приложение

      while(pos != NULL ) {

         // Получаем имя очередного файла

         msg = mFileOpen.GetNextPathName( pos );

         // Отображаем имена файлов

         AfxMessageBox("Selected File - " + msg);

      }

   }

   return TRUE;

}

Постройте проект и запустите полученное приложение, выбрав из меню Build строку Execute FileDlg.exe. На экране появится стандартная диалоговая панель Open (рис. 4.5).



Рис. 4.5. Стандартная диалоговая панель Open

С помощью нее вы можете выбрать несколько файлов из любого каталога компьютера. После того, как вы выберите интересующие вас файлы, нажмите кнопку Open. Диалоговая панель Open закроется, и на экране последовательно будут отображаться сообщения, содержащие полные имена выбранных файлов (рис. 4.6).



Рис. 4.6. Стандартная диалоговая панель Open

Кроме файла afxwin.h, в котором определены классы, методы, константы и другие структуры библиотеки классов MFC, в исходный текст приложения включен файл afxdlgs.h. В этом файле содержатся определения классов, предназначенных для управления стандартными диалоговыми панелями, а также определены еще два класса CPropertySheet и CPropertyPage, предназначенные для построения блокнотов, включающих несколько диалоговых панелей.



В нашем проекте определен только один класс CFileDlgApp. В класс CFileDlgApp входит метод InitInstance. Кроме того, определен глобальный объект FileDlgApp класса CFileDlgApp. Мы не будем подробно останавливаться на том, как устроено приложение FileDlg. Соответствующую информацию вы можете получить в 24 томе из серии “Библиотека системного программиста”, который служит введением в язык программирования Си++ и библиотеку классов MFC.

Метод InitInstance главного класса приложения CFileDlgApp вызывается автоматически при запуске приложения. Мы используем метод InitInstance чтобы продемонстрировать вам работу стандартной диалоговой панели Open.

Сначала создается объект mFileOpen класса CFileDialog. В качестве параметра конструктора CFileDialog указывается значение TRUE, которое указывает, что данный объект класса будет управлять стандартной диалоговой панелью Open:

CFileDialog mFileOpen(TRUE);

Определение объекта класса CFileDialog не вызывает автоматического отображаеия на экране соответствующей диалоговой панели. Для этого вызывается метод DoModal. Непосредственно перед обращением к методу DoModal мы устанавливаем флаг OFN_ALLOWMULTISELECT в поле Flags элемента данных m_ofn класса CFileDialog. Если данный флаг установлен, то в диалоговой панели можно будет выбрать сразу несколько файлов. В противном случае, из панели можно будет выбрать только один файл:

mFileOpen.m_ofn.Flags |= OFN_ALLOWMULTISELECT;

Метод DoModal класса CFileDialog отображает на экране соответствующую диалоговую панель (в нашем случае диалоговую панель Open) и позволяет пользователю выбрать из нее один или несколько файлов. Результат работы метода DoModal записывается в переменную result:

int result = mFileOpen.DoModal();

Если пользователь отказался от выбора файлов и нажал кнопку Cancel, тогда метод DoModal возвращает значение IDCANCEL. В этом случае приложение отображает сообщение File not selected и завершает свою работу:

AfxMessageBox("File not selected");

Если пользователь выбрал из диалоговой панели Open один или несколько файлов и нажал кнопку Open, тогда метод DoModal возвращает значение IDOK. В этом случае вызывается метод GetStartPosition, который записывает в переменную pos типа POSITION значение, необходимое методу GetNextPathName для получения всех имен выбранных файлов:

POSITION pos;

pos = mFileOpen.GetStartPosition();

Переменная pos передается методу GetNextPathName. Этот метод получает очередное имя выбранного файла и изменяет значение переменной pos. До тех пор, пока значение pos не станет равно NULL, метод GetNextPathName вызывается в цикле и получает очередное имя файла:

while(pos != NULL ) {

   // Получаем имя очередного файла

   msg = mFileOpen.GetNextPathName( pos );

   // Отображаем имена файлов

   AfxMessageBox("Selected File - " + msg);

}

Полученные имена файлов отображаются на экране с помощью функции AfxMessageBox. Обратите внимание, что в качестве параметра этой функции передается результат операции конкатенации строки Selected File и объекта класса CString.


Приложение готово


Все, приложение готово. Постройте проект и запустите полученный выполняемый файл. На экране появится диалоговая панель New, представленная на рисунке 1.15.

Рис. 1.15. Выбор типа нового документа

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

Выберите из списка тип документа, который вы будете создавать и нажмите на кнопку OK. Откроется главное окно приложения и окно MDI с новым документом выбранного типа.

Когда вы будете создавать новые документы через меню (строка New меню File), или панель управления (кнопка

), вам будет предложено выбрать тип нового документа. Для этого также будет использоваться диалоговая панель New, описанная выше.

Одновременно можно открыть несколько документов различного типа, причем каждый документ может иметь несколько окон просмотра. Документы каждого типа имеют различные названия и расширения имени файлов, используемые по умолчанию.



Приложение Multi


Создайте новое приложение с многооконным интерфейсом и назовите его Multi. При определении свойств приложения оставьте все предложения по умолчанию. Приложение Multi не будет использовать технологию OLE и сетевые технологии, не будет работать с базами данных. Процедура создания приложений с использованием MFC AppWizard описана в разделе “Приложение с оконным интерфейсом” 24 тома серии “Библиотека системного программиста”, поэтому мы будем считать, что вы уже создали проект.

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

Сразу после запуска приложения Multi, открывается дочернее окно, предназначенное для просмотра документа, которое получает название Multi1. Вы можете создать новые дочерние окна, выбрав из меню File строку New - открыть новый документ или строку Open - открыть файл (рис. 1.1). Для просмотра уже открытого документа можно открыть еще одно окно (рис. 1.11). В названии такого окна указывается дополнительный числовой индекс.

Если одновременно открыто несколько окон, то можно упорядочить расположение этих окон и пиктограмм, представляющих минимизированные окна. Для этого специально предназначено меню Window.

Рис. 1.1. Приложение Multi

Теперь рассмотрим внимательно сам проект Multi, подготовленный для нас MFC AppWizard. Найдите окно Project Workspace и откройте страницу FileView. Вы увидите список всех исходных файлов, входящих в проект (рис. 1.2). В отдельную папку Dependencies будут помещены названия вспомогательных файлов проекта. Эти файлы не входят в проект непосредственно, но используются либо для хранения ресурсов, либо как включаемые файлы, указанные директивой #include в одном или нескольких основных файлах проекта.

Рис. 1.2. Окно Project Workspace, файлы проекта

В следующей таблице кратко описаны основные файлы проекта Multi. Ниже мы подробно рассмотрим ресурсы приложения Multi, а также опишем составляющие его классы и их методы.


Имя файла

Описание

ChildFrm.cpp

Файле содержит определение методов класса CChildFrame

ChildFrm.h

В файле находится определение класса дочернего окна MDI - CChildFrame

MainFrm.cpp

Файл содержит определения методов класса CMainFrame

MainFrm.h

Содержит описание класса главного окна приложения, который называется CMainFrame. Класс CMainFrame наследуется от базового класса CFrameWnd, определенного в библиотеке классов MFC

Multi.cpp

Основной файл приложения. В нем определены методы основного класса приложения CMultiApp

Multi.h

В этом файле перечислены другие включаемые файлы и описан главный класс приложения CMultiApp

Multi.pch

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

Multi.rc

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

MultiDoc.cpp

Включает определение методов класса CMultiDoc

MultiDoc.h

Содержит определение класса документов приложения - CMultiDoc

MultiView.cpp

Включает определение методов класса CMultiView

MultiView.h

Содержит описание класса окна просмотра приложения - CMultiView

ReadMe.txt

Текстовый файл, содержащий описание проекта. В нем кратко рассмотрен каждый файл, входящий в проект, перечислены классы приложения, а также представлена некоторая другая дополнительная информация

res\Multi.ico

Пиктограмма приложения

res\Multi.rc2

В этом файле определены ресурсы, которые нельзя редактировать с помощью редактора ресурсов среды Visual C++

res\MultiDoc.ico

Пиктограмма для документов приложения

res\Toolbar.bmp

Файл содержит растровое изображение кнопок панели управления

Resource.h

Файл содержит определения идентификаторов ресурсов приложения, например, идентификаторы строк меню

StdAfx.h, StdAfx.cpp

Использование этих файлов позволяет ускорить процесс повторного построения проекта. Более подробное описание файлов представлено ниже


Приложение MultiBar


Создайте новый проект под названием MultiBar. В качестве типа приложения выберите из списка Type строку Application. Настройте проект MultiBar, точно также как вы настраивали проект Bar - укажите, что приложение будет работать с библиотекой классов MFC.

Наберите в редакторе исходный текст приложения и сохраните его в файле MultiBar.cpp (листинг 3.7). За основу вы можете взять файл Bar.cpp приложения Bar. Включите готовый файл MultiBar.cpp в проект.

Листинг 3.7. Файл MultiBar.cpp

//============================================================

// Приложение MultiBar

// (c) Frolov G.V., 1996

// E-mail: frolov@glas.apc.org

//============================================================

// Исключаем редко используемые определения из

// включаемых файлов

#define VC_EXTRALEAN

// Включаемый файл для MFC

#include <afxwin.h>

#include <afxext.h>

#include <afxcmn.h>

// Включаемый файл для ресурсов приложения

#include "resource.h"

//============================================================

// Класс CMultiBarApp - главный класс приложения

//============================================================

class CMultiBarApp : public CWinApp

{

public:

   // Мы будем переопределять метод InitInstance

   virtual BOOL InitInstance();

};

 

// Создаем объект приложение класса CMultiBarApp

CMultiBarApp MultiBarApp;

 

   //============================================================

// Класс CExtendedBar - класс панели управления Extended

   //============================================================

class CExtendedBar : public CToolBar

{

public:

   // Дополнительные органы управления панели Extended

   CEdit m_edit;          // текстовый редактор

   CComboBox m_combo_box; // список с текстовым редактором

};

   //============================================================

// Класс CMultiBarWindow - представляет главное окно

//============================================================

class CMultiBarWindow : public CFrameWnd


{

// Определяем панели управления

protected:

   // Панель управления Player

   CToolBar       m_wndPlayerBar;

   // Панель управления Style

   CToolBar       m_wndStyleBar;

   // Панель управления Extended

   CExtendedBar   m_wndExtendedBar;

  

protected:

   // Метод OnCreate используется для создания

   // панелей управления

   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

public:

   // Объявляем конструктор класса CMultiBarWindow

   CMultiBarWindow();

   // Объявляем методы для обработки команд от панелей

   // управления

   afx_msg void BarCommandOne();

   afx_msg void BarCommandRange(UINT nID);

   afx_msg void AddStringToComboBox();

   // Объявляем метод для обработки команд от меню View

   afx_msg BOOL ShowStyle(UINT nID);

   // Макрокоманда необходима, так как класс

   // CMultiBarWindow обрабатывает сообщения

   DECLARE_MESSAGE_MAP()   

};

//============================================================

// Метод BarCommandRange

// Обрабатывает команды от панели управления

   //============================================================

void CMultiBarWindow::BarCommandRange( UINT nID )

{

   // Обработчик не выполняет никакой работы

}

  //============================================================

// Метод BarCommand

// Обрабатывает команды от кнопок панелей управления

   //============================================================

void CMultiBarWindow::BarCommandOne()

{

   // Отображаем сообщение о том, что команда не реализована

   MessageBox("Command not implemented");       

}

//============================================================

// Метод AddStringToComboBox

// Обрабатывает команду от кнопки Add панели

// управления Extended

   //============================================================

void CMultiBarWindow::AddStringToComboBox()

{

   // Получаем строку, введенную в текстовом редакторе m_edit

   char  tmpStr[39];

   m_wndExtendedBar.m_edit.GetLine(0, tmpStr,40);



   // Добавляем новую строку к списку m_combo_box

   m_wndExtendedBar.m_combo_box.AddString(tmpStr);

}

//============================================================

// Метод ShowStyle

// Обрабатывает команды от меню View

   //============================================================

BOOL CMultiBarWindow::ShowStyle(UINT nID)

{

   // Определяем указатель на панель управления,

   // соответствующую идентификатору nID

   CControlBar* pBar = GetControlBar(nID);

   // Определяем, отображается в данный момент панель

   // управления на экране или нет

   BOOL bShow = ((pBar -> GetStyle() & WS_VISIBLE) != 0);

  

   // Изменяем состояние панели управления: если панель

   // управления отображается на экране, удаляем ее с экрана,

   // если нет - отображаем

   ShowControlBar( pBar, !bShow, FALSE);

     

   return TRUE;

}

  //============================================================

// Таблица сообщений класса CMultiBarWindow

   //============================================================

BEGIN_MESSAGE_MAP(CMultiBarWindow, CFrameWnd)

   // Макрокоманда вызывает метод OnCreate

   ON_WM_CREATE()

   // Обработчики команд от панели управления Player

   ON_COMMAND(ID_STOP, BarCommandOne)

   ON_COMMAND(ID_PLAY, BarCommandOne)

   ON_COMMAND(ID_PAUSE, BarCommandOne)

   ON_COMMAND_RANGE(ID_LEFT, ID_RIGHT, BarCommandRange)

   ON_COMMAND_RANGE(ID_TYPE, ID_WAVE,  BarCommandRange)

   // Обработчики команд от панели управления Extended

   ON_COMMAND(ID_ADD, AddStringToComboBox)

   ON_COMMAND_RANGE(ID_FOTO, ID_DISK,  BarCommandRange)

   // Обработчик команд от панели управления Style

   ON_COMMAND_RANGE(ID_UNDERLINE, ID_MARK_4, BarCommandRange)

   // Обработчики команд меню View

   ON_COMMAND_EX(ID_Style, ShowStyle)

   ON_COMMAND_EX(ID_Extended, ShowStyle)

   ON_COMMAND_EX(ID_Player, ShowStyle)

END_MESSAGE_MAP()

   //============================================================



// Метод InitInstance класса CMultiBarApp

// Создает главное окно приложения и отображает его на экране

//============================================================

BOOL CMultiBarApp::InitInstance()

{

   m_pMainWnd = new CMultiBarWindow();

   m_pMainWnd -> ShowWindow(m_nCmdShow);

   m_pMainWnd -> UpdateWindow();

   return TRUE;

}

   //============================================================

// Конструктор класса CMultiBarWindow

//============================================================

CMultiBarWindow::CMultiBarWindow()

{

   // Создаем окно приложения, соответствующее

   // данному объекту класса CMultiBarWindow

   Create(NULL, "Multi Bar", WS_OVERLAPPEDWINDOW,

          rectDefault, NULL, MAKEINTRESOURCE(IDR_MENU));

}

//============================================================

// Метод OnCreate класса CMultiBarWindow

// Используется для создания панелей управления

//============================================================

int CMultiBarWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

   // Вызываем метод OnCreate базового класса

   if(CFrameWnd::OnCreate(lpCreateStruct) == -1)

      return -1;

   // Разрешаем присоединение панелей управления ко

   // всем сторонам окна CMultiBarWindow

   EnableDocking(CBRS_ALIGN_ANY);

  

   //  Переменные для изменения стилей кнопок

   UINT nBarStyle;

   int nIndex;

   //============================================================

// Создаем и отображаем панель управления Player

//============================================================

   // Создаем панель управления toolbar

   if(!m_wndPlayerBar.Create(this, WS_CHILD | WS_VISIBLE |

      CBRS_SIZE_DYNAMIC | CBRS_BOTTOM  |

      CBRS_TOOLTIPS, ID_Player))

   {

      // Ошибка при создании панели управления

      TRACE0("Failed to create toolbar\n");

      return -1;

   }

  

   // Загружаем ресурс панели управления Player

   if(!m_wndPlayerBar.LoadToolBar(IDR_PLAYER))



   {

      // Ошибка при загрузке ресурса панели управления

      TRACE0("Failed to load toolbar\n");

      return -1;

   }

  

   // Устанавливаем заголовок панели управления Player

   m_wndPlayerBar.SetWindowText("Player");     

  

   // Из кнопок с идентификаторами ID_TYPE, ID_CD_DRV и

   // ID_WAVE делаем трехпозиционный переключатель с зависимой

   // фиксацией. Устанавливаем для этих кнопок стиль

   // TBBS_CHECKGROUP

   nIndex = m_wndPlayerBar.CommandToIndex(ID_TYPE);

   nBarStyle = m_wndPlayerBar.GetButtonStyle(nIndex) |

               TBBS_CHECKGROUP;

   m_wndPlayerBar.SetButtonStyle(nIndex, nBarStyle);

   nIndex = m_wndPlayerBar.CommandToIndex(ID_CD_DRV);

   nBarStyle = m_wndPlayerBar.GetButtonStyle(nIndex) |

               TBBS_CHECKGROUP;

   m_wndPlayerBar.SetButtonStyle(nIndex, nBarStyle);

   nIndex = m_wndPlayerBar.CommandToIndex(ID_WAVE);

   nBarStyle = m_wndPlayerBar.GetButtonStyle(nIndex) |

               TBBS_CHECKGROUP;

   m_wndPlayerBar.SetButtonStyle(nIndex, nBarStyle);

   

   // Из кнопки с идентификатором ID_PAUSE делаем

   // переключатель. Устанавливаем для этой кнопки стиль

   // TBBS_CHECKBOX

   nIndex = m_wndPlayerBar.CommandToIndex(ID_PAUSE);

   nBarStyle = m_wndPlayerBar.GetButtonStyle(nIndex) |

               TBBS_CHECKBOX;

   m_wndPlayerBar.SetButtonStyle(nIndex, nBarStyle);

  

   // Разрешаем пристывковывать панель управления Player к

   // любой строке родительского окна

   m_wndPlayerBar.EnableDocking(CBRS_ALIGN_ANY );

   // Пристывковываем панель управления Player к

   // родительскому окну

   DockControlBar(&m_wndPlayerBar);

//============================================================

// Создаем и отображаем панель управления Style

//============================================================

   // Создаем панель управления toolbar

   if(!m_wndStyleBar.Create(this, WS_CHILD | WS_VISIBLE |

      CBRS_SIZE_FIXED | CBRS_TOP | CBRS_TOOLTIPS, ID_Style))



   {

      // Ошибка при создании панели управления

      TRACE0("Failed to create toolbar\n");

      return -1;

   }

   // Загружаем ресурс панели управления Style

   if(!m_wndStyleBar.LoadToolBar(IDR_STYLE))

   {

      // Ошибка при загрузке ресурса панели управления

      TRACE0("Failed to load toolbar\n");

      return -1;

   }

   // Устанавливаем заголовок панели управления Style

   m_wndStyleBar.SetWindowText("Style");  

   // Запрещаем пристывковывать панель управления Player к

   // родительскому окну

   m_wndStyleBar.EnableDocking(0);

   // Устанавливаем для кнопки ID_SUBSCRIPT стиль TBBS_WRAPPED

   nIndex = m_wndStyleBar.CommandToIndex(ID_SUBSCRIPT);

   nBarStyle = m_wndStyleBar.GetButtonStyle(nIndex) |

               TBBS_WRAPPED;

   m_wndStyleBar.SetButtonStyle(nIndex, nBarStyle);

 

   // Устанавливаем для кнопки ID_TEXT_JUSTIFY стиль

   // TBBS_WRAPPED

   nIndex = m_wndStyleBar.CommandToIndex(ID_TEXT_JUSTIFY);

   nBarStyle = m_wndStyleBar.GetButtonStyle(nIndex) |

               TBBS_WRAPPED;

   m_wndStyleBar.SetButtonStyle(nIndex, nBarStyle);

 

   // Отображаем панель управления Style в мини-окне.

   // Начальные координаты панели управления определяются

   // значением объекта pointStyleBar класса CPoint

   CPoint pointStyleBar(100, 100);

   FloatControlBar(&m_wndStyleBar, pointStyleBar);

 

//============================================================

// Создаем и отображаем панель управления Extended

//============================================================

   // Создаем панель управления Extended

   if(!m_wndExtendedBar.Create(this,

      WS_CHILD | WS_VISIBLE | CBRS_SIZE_DYNAMIC |

      CBRS_TOP | CBRS_TOOLTIPS, ID_Extended))

   {

      // Ошибка при создании панели управления

      TRACE0("Failed to create toolbar\n");

      return -1;

   }

  

   // Загружаем ресурс панели управления Extended

   if(!m_wndExtendedBar.LoadToolBar(IDR_EXTENDED))



   {

      // Ошибка при загрузке ресурса панели управления

      TRACE0("Failed to load toolbar\n");

      return -1;

   }

   // Устанавливаем заголовок панели управления Extended

   m_wndExtendedBar.SetWindowText("Extended");     

   // Увеличиваем размер первого разделителя.

   // Этот разделитель имеет индекс 2

   m_wndExtendedBar.SetButtonInfo(2, IDW_EDIT,

      TBBS_SEPARATOR, 130);

   // Определяем координаты прямоугольной области панели

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

   CRect rectEdit;

   m_wndExtendedBar.GetItemRect(2, &rectEdit);

   // Делаем отступ с левой и правой стороны

   rectEdit.left += 6;

   rectEdit.right -= 6;

  

   // Размещаем на панели управления Extended, в области

   // rectEdit однострочный текстовый редактор

   if(!m_wndExtendedBar.m_edit.Create(WS_CHILD |

      ES_AUTOHSCROLL|WS_VISIBLE|WS_TABSTOP|WS_BORDER,

      rectEdit, &m_wndExtendedBar, IDW_EDIT))

   {

      // Ошибка при создании текстового редактора

      TRACE0("Failed to create edit-box\n");

      return FALSE;

   }

   // Увеличиваем размер второго разделителя.

   // Этот разделитель имеет индекс 4

   m_wndExtendedBar.SetButtonInfo(4, IDW_COMBO,

      TBBS_SEPARATOR, 150);

   // Определяем координаты прямоугольной области панели

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

   CRect rectComboBox;

   m_wndExtendedBar.GetItemRect(4, &rectComboBox);

   // Делаем отступ с левой и правой стороны

   rectComboBox.left += 6;

   rectComboBox.right -= 6;

   // Увеличиваем высоту прямоугольной области, чтобы в ней

   // можно было разместить список combo-box

   rectComboBox.bottom = rectComboBox.top + 80;

   // Размещаем на панели управления Extended, в области

   // rectComboBox список combo-box

   if(!m_wndExtendedBar.m_combo_box.Create(

      CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_VSCROLL |

      ES_AUTOHSCROLL | CBS_DISABLENOSCROLL,

      rectComboBox, &m_wndExtendedBar, IDW_COMBO))

   {

      // Ошибка при создании списка

      TRACE0("Failed to create combo-box\n");

      return FALSE;

   }

   // Добавляем три строки в список m_combo_box

   m_wndExtendedBar.m_combo_box.AddString("One");

   m_wndExtendedBar.m_combo_box.AddString("Two");

   m_wndExtendedBar.m_combo_box.AddString("Third");

  

   // Разрешаем пристывковывать панель управления Extended к

   // любой из строн родительского окна

   m_wndExtendedBar.EnableDocking(CBRS_ALIGN_ANY );

   // Пристывковываем панель управления Extended к

   // родительскому окну

   DockControlBar(&m_wndExtendedBar);

   return 0;

}


Приложение MultiMenu


Создайте новый проект под названием MultiMenu. В качестве типа приложения выберите из списка Type строку Application. Настройте проект MultiMenu, указав что приложение будет работать с библиотекой классов MFC.

Наберите в редакторе исходный текст приложения и сохраните его в файле MultiMenu.cpp (листинг 3.1). Включите готовый файл MultiMenu.cpp в проект.

Листинг 3.1. Файл MultiMenu.cpp

//============================================================

// Приложение MultiMenu

// (c) Frolov G.V., 1996

// E-mail: frolov@glas.apc.org

//============================================================

// Включаемые файлы для MFC

#include <afxwin.h>

#include <afxext.h>

#include <afxcmn.h>

// Включаемый файл для ресурсов приложения и идентификаторов

#include "resource.h"

//============================================================

// Класс CMultiMenuApp - главный класс приложения

//============================================================

class CMultiMenuApp : public CWinApp

{

public:

   // Мы будем переопределять метод InitInstance,

   // предназначенный для инициализации приложения

   virtual BOOL InitInstance();

};

 

// Создаем объект приложение класса CMultiMenuApp

CMultiMenuApp MultiMenuApp;

 

//============================================================

// Класс CMultiMenuWindow - представляет главное окно

//============================================================

class CMultiMenuWindow : public CFrameWnd

{

protected: 

   // Панель состояния

   CStatusBar  m_wndStatusBar;  

  

   // Флаг управляет строкой Prosess меню Mission

   BOOL  bEnable;

   // Флаг управляет строкой Construction меню Mission

   BOOL  bRadio; 

   // Флаг управляет строкой Restrict меню Menu

   int   nCheck; 

      

protected:

   // Метод для создания окна приложения и панели состояния

   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

   // Методы для обработки командных сообщений


   // от меню приложения

   afx_msg void CMultiMenuWindow::OnDisable();

   afx_msg void CMultiMenuWindow::OnCommand();

   afx_msg void CMultiMenuWindow::OnExit();

   afx_msg void CMultiMenuWindow::OnConstruct();

   afx_msg void CMultiMenuWindow::OnRestrictMenu();

   afx_msg void CMultiMenuWindow::OnFullMenu();

   // Методы для обновления меню

   afx_msg void OnUpdateProcess(CCmdUI* pCmdUI);

   afx_msg void OnUpdateConstruct(CCmdUI* pCmdUI);

   afx_msg void OnUpdateDisable(CCmdUI* pCmdUI);

  

public:

   // Конструктор класса CMultiMenuWindow

   CMultiMenuWindow();

   // Макрокоманда необходима, так как класс

   // CMultiMenuWindow обрабатывает сообщения

   DECLARE_MESSAGE_MAP()   

};

//============================================================

// Таблица сообщений класса CMultiMenuWindow

//============================================================

BEGIN_MESSAGE_MAP(CMultiMenuWindow, CFrameWnd)

  

   // Макрокоманда вызывает метод OnCreate

   ON_WM_CREATE()

   // Макрокоманда вызывает метод OnContextMenu

   ON_WM_CONTEXTMENU()

   // Макрокоманды для обработки командных сообщений

   ON_COMMAND(ID_MENU_DISABLE, OnDisable)

   ON_COMMAND(ID_MISSION_CONSTRUCT, OnConstruct)

   ON_COMMAND(ID_FILE_EXIT, OnExit)

   ON_COMMAND(ID_MISSION_PROCESS, OnCommand)

  

   ON_COMMAND(ID_MENU_RESTRICT, OnRestrictMenu)

   ON_COMMAND(ID_MENU_FULL, OnFullMenu)

   // Обработчики сообщений ON_UPDATE_COMMAND_UI

   ON_UPDATE_COMMAND_UI(ID_MISSION_PROCESS, OnUpdateProcess)

   ON_UPDATE_COMMAND_UI(ID_MISSION_CONSTRUCT,

                           OnUpdateConstruct)

   ON_UPDATE_COMMAND_UI(ID_MENU_DISABLE, OnUpdateDisable)

END_MESSAGE_MAP()

// Индикатор панели управления

UINT indicator = ID_SEPARATOR;

//============================================================

// Метод InitInstance класса CMultiMenuApp

// Создает главное окно приложения и отображает его на экране

//============================================================



BOOL CMultiMenuApp::InitInstance()

{

   m_pMainWnd = new CMultiMenuWindow();

   m_pMainWnd -> ShowWindow(m_nCmdShow);

   m_pMainWnd -> UpdateWindow();

   return TRUE;

}

//============================================================

// Конструктор класса CMultiMenuWindow

//============================================================

CMultiMenuWindow::CMultiMenuWindow()

{

   // Создаем окно приложения, соответствующее

   // данному объекту класса CMultiMenuWindow

   Create(NULL, "Multi Menu Sample", WS_OVERLAPPEDWINDOW,

      rectDefault, NULL, MAKEINTRESOURCE(IDR_FULL_MENU));

   // Загружаем таблицу клавиш акселерации

   LoadAccelTable(MAKEINTRESOURCE(IDR_ACCELERATOR));

   // Инициализируем флаги

   bEnable = TRUE;        

   bRadio = TRUE;        

   nCheck = 0;

}

//============================================================

// Метод OnCreate класса CMultiMenuWindow

// Вызывается во время создания окна приложения

//============================================================

int CMultiMenuWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

   // Вызываем метод OnCreate базового класса

   if(CFrameWnd::OnCreate(lpCreateStruct) == -1)

      return -1;

  

   // Создаем панель состояния

   if(!m_wndStatusBar.Create(this))

   {

      // Ошибка при создании панели состояния

      TRACE0("Failed to create status bar\n");

      return -1;  

   }

   // Отображаем индикаторы панели состояния

   if(!m_wndStatusBar.SetIndicators(&indicator,1))

   {

      // Ошибка при установке индикатора

      TRACE0("Failed to set indicators\n");

      return -1;  

   }

  

   return 0;

}

//============================================================

// Метод OnDisable класса CMultiMenuWindow

// Изменяем состояние флагов bEnable и nCheck

//============================================================

void CMultiMenuWindow::OnDisable()

{

   // Меняем значение bEnable с TRUE на FALSE и наоборот



   bEnable = !bEnable;

  

   // Меняем значение bEnable с 1 на 0 и наоборот

   nCheck = (nCheck == 1) ? 0 : 1;

}

//============================================================

// Метод OnRestrictMenu класса CMultiMenuWindow

// Изменяем меню приложения с IDR_FULL_MENU на

// IDR_RESTRICT_MENU

//============================================================

void CMultiMenuWindow::OnRestrictMenu()

{

   CMenu menuOld;       // текущее меню

   CMenu menuRestrict;  // новое меню

   CMenu* pMenu;

   // Получаем указатель на текущее меню

   pMenu = this->GetMenu();

  

   // Связываем меню с объектом menuOld

   menuOld.Attach(pMenu->m_hMenu);

   // Удаляем меню

   menuOld.DestroyMenu();

  

   // Загружаем меню IDR_RESTRICT_MENU

   menuRestrict.LoadMenu(IDR_RESTRICT_MENU);

   // Устанавливаем загруженное меню

   SetMenu(&menuRestrict);

   // Разрываем связь меню с объектом menuRestrict

   menuRestrict.Detach();

}

//============================================================

// Метод OnFullMenu класса CMultiMenuWindow

// Изменяем меню приложения с IDR_RESTRICT_MENU на

// IDR_FULL_MENU

//============================================================

void CMultiMenuWindow::OnFullMenu()

{

   CMenu menuOld;

   CMenu menuRestrict;

   CMenu* pMenu;

   pMenu = this->GetMenu();

   menuOld.Attach(pMenu->m_hMenu);

   menuOld.DestroyMenu();

   menuRestrict.LoadMenu(IDR_FULL_MENU);

   SetMenu(&menuRestrict);

   menuRestrict.Detach();

}

//============================================================

// Метод OnCommand класса CMultiMenuWindow

//============================================================

void CMultiMenuWindow::OnCommand()

{

   MessageBox("Command not implemented");

}

//============================================================

// Метод OnConstruct класса CMultiMenuWindow

// Изменяем состояние флага bRadio

//============================================================



void CMultiMenuWindow::OnConstruct()

{

   // Меняем значение bRadio с TRUE на FALSE и наоборот

   bRadio = !bRadio;

}

//============================================================

// Метод OnExit класса CMultiMenuWindow

//============================================================

void CMultiMenuWindow::OnExit()

{

   // Завершаем приложение

   DestroyWindow();

   return;

}

//============================================================

// Метод OnUpdateProcess класса CMultiMenuWindow

//============================================================

void CMultiMenuWindow::OnUpdateProcess(CCmdUI* pCmdUI)

{

   // Блокируем или разблокируем строку Process меню Mission

   pCmdUI->Enable(bEnable);

}

//============================================================

// Метод OnUpdateConstruct класса CMultiMenuWindow

//============================================================

void CMultiMenuWindow::OnUpdateConstruct(CCmdUI* pCmdUI)

{

   // Устанавливаем или снимаем пометку

   // строки Construction меню Mission

   pCmdUI->SetRadio(bRadio);

}

//============================================================

// Метод OnUpdateDisable класса CMultiMenuWindow

//============================================================

void CMultiMenuWindow::OnUpdateDisable(CCmdUI* pCmdUI)

{

   // Устанавливаем или удаляем пометку

   // у строки Disable меню Menu

   pCmdUI->SetCheck(nCheck);

}

Создайте новый файл ресурсов и включите его в проект под именем MultiMenu.rc. Включите в него два меню, присвоив им идентификаторы IDR_RESTRICT_MENU и IDR_FULL_MENU.

Введите строки этих меню в соответствии с представленным нами файлом ресурсов (листинг 3.2). Для всех строк меню введите их описания. Они будут записаны в файл ресурсов как строковые ресурсы, имеющие одинаковые идентификаторы со строками меню.

Добавьте в файл ресурсов строку Ready, выбрав для нее идентификатор AFX_IDS_IDLEMESSAGE. Эта строка будет отображаться в панели состояния во время “бездействия” приложения.



Включите в файл ресурсов таблицу акселераторов, состоящую из трех команд: ID_MENU_DISABLE, ID_MISSION_PROCESS и ID_FILE_EXIT. Присвойте им комбинации клавиш <Ctrl+D>, <Ctrl+P> и <Ctrl+E> соответственно.

Листинг 3.2. Файл MultiMenu.rc

//Microsoft Developer Studio generated resource script.

//

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

//////////////////////////////////////////////////////////////

#undef APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

// Russian resources

#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_RUS)

#ifdef _WIN32

LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT

#pragma code_page(1251)

#endif //_WIN32

#ifdef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE DISCARDABLE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE DISCARDABLE

BEGIN

    "#include ""afxres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE DISCARDABLE

BEGIN

    "\r\n"

    "\0"

END

#endif    // APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// Menu

//

IDR_RESTRICT_MENU MENU DISCARDABLE

BEGIN

    POPUP "&File"

    BEGIN

        MENUITEM "P&rocess\tCtrl+P",  ID_MISSION_PROCESS

        MENUITEM SEPARATOR

        MENUITEM "E&xit\tCtrl+E",     ID_FILE_EXIT

    END

    POPUP "&Menu"

    BEGIN

        MENUITEM "Full",              ID_MENU_FULL

        MENUITEM "Disa&ble\tCtrl+D",  ID_MENU_DISABLE

    END

    POPUP "&Help", HELP

    BEGIN

        MENUITEM "Help index",        ID_HELP_HELPINDEX



        MENUITEM SEPARATOR

        MENUITEM "System info",       ID_HELP_SYSTEMINFO

    END

END

IDR_FULL_MENU MENU DISCARDABLE

BEGIN

    POPUP "&File"

    BEGIN

        MENUITEM SEPARATOR

        MENUITEM "E&xit\tCtrl+E",     ID_FILE_EXIT

    END

    POPUP "&Menu"

    BEGIN

        MENUITEM "Restrict",          ID_MENU_RESTRICT

        MENUITEM "Disa&ble\tCtrl+D",  ID_MENU_DISABLE

    END

    POPUP "M&ission"

    BEGIN

        MENUITEM "P&rocess\tCtrl+P",  ID_MISSION_PROCESS

        MENUITEM SEPARATOR

        MENUITEM "Construction",      ID_MISSION_CONSTRUCT

    END

    POPUP "&Help", HELP

    BEGIN

        MENUITEM "Help index",        ID_HELP_HELPINDEX

        MENUITEM "Context help",      ID_HELP_CONTEXTHELP

        MENUITEM SEPARATOR

        MENUITEM "System info",       ID_HELP_SYSTEMINFO

    END

END

//////////////////////////////////////////////////////////////

//

// Accelerator

//

IDR_ACCELERATOR ACCELERATORS DISCARDABLE

BEGIN

    "D",   ID_MENU_DISABLE,    VIRTKEY, CONTROL, NOINVERT

    "E",   ID_FILE_EXIT,       VIRTKEY, CONTROL, NOINVERT

    "P",   ID_MISSION_PROCESS, VIRTKEY, CONTROL, NOINVERT

END

//////////////////////////////////////////////////////////////

//

// String Table

//

STRINGTABLE DISCARDABLE

BEGIN

    AFX_IDS_IDLEMESSAGE     "Ready"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_FILE_EXIT            "Exit application"

    ID_MISSION_PROCESS      "Process"

    ID_HELP_HELPINDEX       "Open help index"

    ID_HELP_CONTEXTHELP     "Context help"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_HELP_SYSTEMINFO      "Display system info"

    ID_MISSION_CONSTRUCT    "Construct"

    ID_MENU_RESTRICT        "Restrict menu"



    ID_MENU_FULL            "Display full menu"

    ID_MENU_DISABLE         " Disable command Process from menu Mission"

END

#endif    // Russian resources

//////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

//////////////////////////////////////////////////////////////

#endif    // not APSTUDIO_INVOKED

Идентификаторы ресурсов приложения MultiMenu определены в файле resource.h. Этот файл создается автоматически редактором ресурсов Microsoft Visual C++. Исходный текст этого файла представлен в листинге 3.3.

Листинг 3.3. Файл resource.h

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by MultiMenu.rc

//

#define IDR_RESTRICT_MENU               106

#define IDR_FULL_MENU                   107

#define IDR_ACCELERATOR                 108

#define ID_FILE_EXIT                    40009

#define ID_MISSION_PROCESS              40013

#define ID_HELP_HELPINDEX               40014

#define ID_HELP_CONTEXTHELP             40015

#define ID_HELP_SYSTEMINFO              40016

#define ID_MISSION_CONSTRUCT            40017

#define ID_MENU_RESTRICT                40019

#define ID_MENU_FULL                    40020

#define ID_MENU_DISABLE                 40025

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        110

#define _APS_NEXT_COMMAND_VALUE         40027

#define _APS_NEXT_CONTROL_VALUE         1000

#define _APS_NEXT_SYMED_VALUE           101

#endif

#endif

Постройте приложение MultiMenu и запустите его. На экране появится окно приложения с главным меню и панелью состояния (рис. 3.4).

В панели состояния расположен один индикатор. В нем отображается подсказка о выбранной строке меню приложения или системного меню, а если приложение “бездействует” - строка Ready.





Рис. 3.4. Приложение MultiMenu

Сразу после запуска приложения MultiMenu используется меню с идентификатором IDR_FULL_MENU. Если вы выберите из меню Menu строку Restrict, то меню приложения будет заменено на меню IDR_RESTRICT_MENU. Это сокращенный вариант меню IDR_FULL_MENU, в котором отсутствуют некоторые строки, а строка Process перенесена из меню Mission в меню File.

Различные строки меню IDR_FULL_MENU и IDR_RESTRICT_MENU иллюстрируют режимы отображения строк меню. Так, при выборе из меню Menu строки Disable, блокируется строка Process в меню Mission. Около строки Disable при этом отображается символ Ö (рис. 3.3). Чтобы снять блокировку, выберите строку Disable из меню Menu еще раз. Символ Ö также исчезнет.

При выборе строки Process из меню Mission на экране появляется сообщение. Когда строка Process заблокирована, выбрать ее невозможно.

Если вы выберите из меню Mission строку Construction, то она будет выделена символом ·. Повторный выбор этой строки снимает с нее выделение.

Чтобы завершить работу приложения MultiMenu, можно выбрать из меню File строку Exit или выбрать из системного меню приложения строку Close. Все остальные строки меню приложения не работают и заблокированы.

Для ускорения выбора некоторых команд из меню приложения можно воспользоваться клавишами акселерации. В программе определены три такие комбинации.

Комбинация клавиш

Соответствующая строка меню

<Ctrl+D>

Строка Disable из меню Menu

<Ctrl+P>

Строка Process из меню Mission или из меню File (для сокращенного варианта меню)

<Ctrl+E>

Строка Exit из меню File


Приложение Status


Создайте новый проект под названием Status. В качестве типа приложения выберите из списка Type строку Application. Настройте проект Status, указав, что приложение будет работать с библиотекой классов MFC.

Наберите в редакторе исходный текст приложения и сохраните его в файле Status.cpp (листинг 3.13). Включите готовый файл DialogBar.cpp в проект.

Листинг 3.13. Файл Status.cpp

//============================================================

// Приложение Status

// (c) Frolov G.V., 1996

// E-mail: frolov@glas.apc.org

//============================================================

// Включаемые файлы для MFC

#include <afxwin.h>

#include <afxext.h>

#include <afxcmn.h>

// Включаемый файл для ресурсов приложения и идентификаторов

#include "resource.h"

//============================================================

// Класс CStateApp - главный класс приложения

//============================================================

class CStateApp : public CWinApp

{

public:

   // Мы будем переопределять метод InitInstance,

   // предназначенный для инициализации приложения

   virtual BOOL InitInstance();

};

 

// Создаем объект приложение класса CStateApp

CStateApp StateApp;

 

//============================================================

// Класс CStateWindow - представляет главное окно

//============================================================

class CStateWindow : public CFrameWnd

{

protected: 

   CStatusBar  m_wndStatusBar;   // Панель состояния

   BOOL  bIndicatorTEXT;         // Флаг для управления

                                 // индикатором

                                 // ID_INDICATOR_TEXT

    

protected:

   // Метод для создания окна приложения и панели состояния

   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

public:

   // Объявляем конструктор класса CStateWindow

   CStateWindow();

   // Объявляем методы для обработки команд меню

   afx_msg BOOL OnMenuDirectADD_SUB(UINT nID);


   afx_msg void OnMenuProcessBar();

   afx_msg void OnMenuDisableADD_SUB();

   afx_msg void OnMenuSwitchTEXT();

   afx_msg void OnMenuExit();

  

   // Метод для обработки команды ON_UPDATE_COMMAND_UI

   // от индикатора ID_INDICATOR_TEXT

   afx_msg void OnUpdateTEXT(CCmdUI* pCmdUI);

  

   // Макрокоманда необходима, так как класс

   // CStateWindow обрабатывает сообщения

   DECLARE_MESSAGE_MAP()   

};

//============================================================

// Таблица сообщений класса CStateWindow

//============================================================

BEGIN_MESSAGE_MAP(CStateWindow, CFrameWnd)

  

   // Макрокоманда вызывает метод OnCreate

   ON_WM_CREATE()

   // Обработчик сообщения ON_UPDATE_COMMAND_UI

   ON_UPDATE_COMMAND_UI(ID_INDICATOR_TEXT, OnUpdateTEXT)

  

   // Обработчики команд меню Work

   ON_COMMAND(ID_WORK_PROCESS, OnMenuProcessBar)

   ON_COMMAND(ID_WORK_DISABLE_ADDSUB, OnMenuDisableADD_SUB)

   ON_COMMAND(ID_WORK_ON_SWITCH_TEXT, OnMenuSwitchTEXT)

  

   ON_COMMAND_EX(ID_WORK_DIRECT_ADD, OnMenuDirectADD_SUB)

   ON_COMMAND_EX(ID_WORK_DIRECT_SUB, OnMenuDirectADD_SUB)

   ON_COMMAND(ID_WORK_EXIT, OnMenuExit)

  

END_MESSAGE_MAP()

//============================================================

// Индикаторы панели управления. Порядок идентификаторов

// соответствует порядку индикаторов в панели состояния

// (до тех пор, пока он не изменен методом SetPaneInfo)

//============================================================

static UINT indicators[] =

{

   ID_SEPARATOR,           // Самый первый индикатор

   ID_INDICATOR_OVR,       // Индикатор OVR

   ID_INDICATOR_PROGRESS,  // Резервирование места для

                           // progress bar

   ID_INDICATOR_CAPS,      // Индикатор клавиши <Caps Lock>

   ID_INDICATOR_NUM,       // Индикатор клавиши <Num Lock>

   ID_INDICATOR_SCRL,      // Индикатор клавиши <Scroll Lock>

   ID_INDICATOR_TEXT,      // Индикатор TEXT/PIC



   ID_INDICATOR_ADD,       // Индикатор ADD/SUB (начальное

                           // состояние START)

};

//============================================================

// Метод InitInstance класса CStateApp

// Создает главное окно приложения и отображает его на экране

//============================================================

BOOL CStateApp::InitInstance()

{

   m_pMainWnd = new CStateWindow();

   m_pMainWnd -> ShowWindow(m_nCmdShow);

   m_pMainWnd -> UpdateWindow();

   return TRUE;

}

//============================================================

// Конструктор класса CStateWindow

//============================================================

CStateWindow::CStateWindow()

{

   // Создаем окно приложения, соответствующее

   // данному объекту класса CStateWindow

   Create(NULL, "Status Bar Sample", WS_OVERLAPPEDWINDOW,

      rectDefault, NULL, MAKEINTRESOURCE(IDR_MENU));

  

   // Устанавливаем значение флага bIndicatorTEXT

   bIndicatorTEXT = TRUE;

}

//============================================================

// Метод OnMenuProcessBar класса CStateWindow

//============================================================

void CStateWindow::OnMenuProcessBar()

{

    // Определяем координаты индикатора ID_INDICATOR_PROGRESS

    RECT rectProgress;

   

    m_wndStatusBar.GetItemRect(

       m_wndStatusBar.CommandToIndex(ID_INDICATOR_PROGRESS),

         &rectProgress);

   // Создаем полосу progress bar. Размещаем ее

   // на месте индикатора ID_INDICATOR_PROGRESS

   CProgressCtrl ctrlProgressBar;

   if(!ctrlProgressBar.Create(WS_CHILD | WS_VISIBLE,

                          rectProgress, &m_wndStatusBar, 1))

   {

      // Ошибка при создании progress bar

      TRACE0("Failed to create progress bar\n");

      return;

   }

   // Устанавливаем границы для progress bar

   ctrlProgressBar.SetRange(0, 100);

   // Устанавливаем шаг приращения для progress bar



   ctrlProgressBar.SetStep(1);

 

   // Плавно увеличиваем положение progress bar

   for(int i=0;i<100;i++)

   {

      // Выполняем короткую задержку

      Sleep(10);

     

      // Выполняем шаг приращения progress bar

      ctrlProgressBar.StepIt();

   }

  

   // По завершении, отображаем текст в самом первом

   // индикаторе панели состояния

   m_wndStatusBar.SetWindowText("Process completed");

}

//============================================================

// Метод OnMenuDirectADD_SUB класса CStateWindow

//============================================================

BOOL  CStateWindow::OnMenuDirectADD_SUB(UINT nID)

{

   // Определяем индекс индикатора ID_INDICATOR_ADD

   int nIndex =

          m_wndStatusBar.CommandToIndex(ID_INDICATOR_ADD);

   // Устанавливаем нормальный режим отображения индикатора

   m_wndStatusBar.SetPaneStyle(nIndex, SBPS_NORMAL);

   // Из меню Work выбрана строка Direct set ADD

   if(nID == ID_WORK_DIRECT_ADD)

   {

      // Выводим текст ADD

      m_wndStatusBar.SetPaneText(nIndex, "ADD");

   }

   // Из меню Work выбрана строка Direct set SUB

   else if(nID == ID_WORK_DIRECT_SUB)

   {

      // Изменяем внешний вид индикатора

      m_wndStatusBar.SetPaneStyle(nIndex, SBPS_POPOUT);

      // Выводим текст SUB

      m_wndStatusBar.SetPaneText(nIndex, "SUB");

   }

   return TRUE;

}  

//============================================================

// Метод OnMenuDisableADD_SUB класса OnMenuDisableADD_SUB

//============================================================

void CStateWindow::OnMenuDisableADD_SUB()

{

   // Определяем индекс индикатора ID_INDICATOR_ADD  

   int nIndex =

          m_wndStatusBar.CommandToIndex(ID_INDICATOR_ADD);

  

   // Блокируем индикатор

   m_wndStatusBar.SetPaneStyle(nIndex, SBPS_DISABLED);

}  

//============================================================

// Метод OnUpdateTEXT класса CStateWindow



//============================================================

void CStateWindow::OnMenuSwitchTEXT()

{

   // Изменяем состояние флага bIndicatorTEXT,

   // который используется методом OnUpdateTEXT

   bIndicatorTEXT = !bIndicatorTEXT;

}

//============================================================

// Метод OnMenuExit класса CStateWindow

//============================================================

void CStateWindow::OnMenuExit()

{

   // Завершаем приложение

   DestroyWindow();

   return;

}

//============================================================

// Метод OnCreate класса CStateWindow

// Вызывается во время создания окна приложения

//============================================================

int CStateWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

   // Вызываем метод OnCreate базового класса

   if(CFrameWnd::OnCreate(lpCreateStruct) == -1)

      return -1;

  

   // Создаем панель состояния

   if(!m_wndStatusBar.Create(this))

   {

      // Ошибка при создании панели состояния

      TRACE0("Failed to create status bar\n");

      return -1;  

   }

   // Отображаем индикаторы панели состояния

   if(!m_wndStatusBar.SetIndicators(indicators,

                         sizeof(indicators)/sizeof(UINT)))

   {

      // Ошибка при установке индикаторов

      TRACE0("Failed to set indicators\n");

      return -1;  

   }

  

   // Устанавливаем характеристики индикатора

   // ID_INDICATOR_PROGRESS

   m_wndStatusBar.SetPaneInfo(

      m_wndStatusBar.CommandToIndex(ID_INDICATOR_PROGRESS),

      ID_INDICATOR_PROGRESS,

      SBPS_DISABLED |   // Текст не отображается

      SBPS_NOBORDERS,   // Рамка вокруг индикатора отсутствует

      150 );            // Ширина индикатора 150 пикселов

   return 0;

}

//============================================================

// Метод OnUpdateTEXT класса CStateWindow

// Обрабатывает сообщение ON_UPDATE_COMMAND_UI

// от индикатора ID_INDICATOR_TEXT



//============================================================

void CStateWindow::OnUpdateTEXT(CCmdUI* pCmdUI)

{

   // В зависимости от состояния флага bIndicatorTEXT

   // отображаем в индикаторе ID_INDICATOR_TEXT

   // строку TEXT или PIC

   if(bIndicatorTEXT)

      pCmdUI->SetText("TEXT"); // отображаем строку TEXT

   else

      pCmdUI->SetText("PIC");  // отображаем строку PIC

   // Разрешаем отображение текста в индикаторе

   pCmdUI->Enable();

}

Создайте новый файл ресурсов и включите его в проект под именем Status.rc. Включите в него меню, присвоив ему идентификатор IDR_MENU. Введите строки меню IDR_MENU в соответствии с представленным нами файлом ресурсов (листинг 3.14). Для всех строк меню введите их описания. Они будут записаны в файл ресурсов как строковые ресурсы, имеющие одинаковые идентификаторы со строками меню.

Добавьте в файл ресурсов строку Ready, выбрав для нее идентификатор AFX_IDS_IDLEMESSAGE. Эта строка будет отображаться в панели состояния во время “бездействия” приложения.

Добавьте в файл ресурсов строки, представляющие индикаторы панели состояния: ID_INDICATOR_ADD, ID_INDICATOR_PROGRESS и ID_INDICATOR_TEXT.

Листинг 3.14. Файл Status.rc

//Microsoft Developer Studio generated resource script.

//

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

//////////////////////////////////////////////////////////////

#undef APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

// Russian resources

#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_RUS)

#ifdef _WIN32

LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT

#pragma code_page(1251)

#endif //_WIN32

#ifdef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// TEXTINCLUDE



//

1 TEXTINCLUDE DISCARDABLE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE DISCARDABLE

BEGIN

    "#include ""afxres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE DISCARDABLE

BEGIN

    "\r\n"

    "\0"

END

#endif    // APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// Menu

//

IDR_MENU MENU DISCARDABLE

BEGIN

    POPUP "Work"

    BEGIN

        MENUITEM "Process",          ID_WORK_PROCESS

        MENUITEM "Direct set ADD",   ID_WORK_DIRECT_ADD

        MENUITEM "Direct set SUB",   ID_WORK_DIRECT_SUB

        MENUITEM "Disable ADD SUB",  ID_WORK_DISABLE_ADDSUB

        MENUITEM "Switch TEXT",      ID_WORK_ON_SWITCH_TEXT

        MENUITEM SEPARATOR

        MENUITEM "Exit",             ID_WORK_EXIT

    END

END

//////////////////////////////////////////////////////////////

//

// String Table

//

STRINGTABLE DISCARDABLE

BEGIN

    ID_INDICATOR_ADD        "START"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_INDICATOR_PROGRESS   "neve display"

    ID_INDICATOR_TEXT       "TEXT"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_WORK_PROCESS         " Display and play progress bar"

    ID_WORK_DIRECT_ADD      "Set indicator ID_INDICATOR_ADD

                             to ADD"

    ID_WORK_ON_SWITCH_TEXT  "Switch text in indicator

                             ID_INDICATOR_TEXT"

    ID_WORK_DIRECT_SUB      "Set indicator ID_INDICATOR_ADD

                             to SUB"

    ID_WORK_DISABLE_ADDSUB  "Disable indicator

                             ID_INDICATOR_ADD"

    ID_WORK_EXIT            "Exit application"

END

STRINGTABLE DISCARDABLE

BEGIN

    AFX_IDS_IDLEMESSAGE     "Ready"

END

#endif    // Russian resources



//////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

//////////////////////////////////////////////////////////////

#endif    // not APSTUDIO_INVOKED

Идентификаторы ресурсов приложения Status определены в файле resource.h. Этот файл создается автоматически редактором ресурсов Microsoft Visual C++. Исходный текст файла resource.h представлен в листинге 3.15.

Листинг 3.15. Файл resource.h

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by Status.rc

//

#define ID_INDICATOR_ADD                1

#define IDR_MENU                        101

#define ID_INDICATOR_PROGRESS           102

#define ID_INDICATOR_TEXT               103

#define ID_WORK_PROCESS                 40001

#define ID_WORK_DIRECT_ADD              40006

#define ID_WORK_ON_SWITCH_TEXT          40007

#define ID_WORK_DIRECT_SUB              40008

#define ID_WORK_DISABLE_ADDSUB          40009

#define ID_WORK_EXIT                    40010

#define ID_TIMER_CHECK                  0xE001

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        106

#define _APS_NEXT_COMMAND_VALUE         40011

#define _APS_NEXT_CONTROL_VALUE         1000

#define _APS_NEXT_SYMED_VALUE           104

#endif

#endif

Постройте приложение Status и запустите его. На экране появится главное окно приложения, в нижней части которого отображается панель состояния (рис. 3.23).



Рис. 3.23. Приложение Status

В панели состояния расположены несколько индикаторов. Самый первый индикатор, размер которого зависит от размера окна приложения, отображает подсказку о выбранной строке меню приложения или системного меню, а если приложение “бездействует” в нем отображается строка Ready.

Следующий индикатор OVR. В нашем приложении он не действует. Вы сами можете разработать программный код для управления этим индикатором.



Вслед за идентификатором OVR следует свободное пространство, занятое индикатором. Этот индикатор не отображается на панели и предназначен только для резервирования места под линейный индикатор progress bar.

Если вы выберите из меню Work строку Process, то на этом месте появится линейный индикатор, плавно меняющий свое значение. Мы используем линейный индикатор, чтобы отображать ход какого-нибудь длительного процесса.

После того, как линейный индикатор покажет окончание процесса, он будет удален с панели состояния, а в самом первом индикаторе появится надпись Process completed.

Затем в панели состояния следуют три стандартных индикатора CAP, NUM и SCRL, которые отображают текущее состояние клавиш <Caps Lock>, <Num Lock> и <Scroll Lock>.

Следующий индикатор, который мы рассмотрим, называется TEXT. Если вы выберите из меню Work строку Switch TEXT, то надпись TEXT в индикаторе заменится на PIC. Повторный выбор данной строки меню восстановит предыдущее состояние индикатора.

Последний индикатор в панели состояния START. Этот индикатор управляет тремя строками меню Work. При выборе строки Direct set ADD в индикаторе отображается строка ADD, а при выборе строки Direct set SUB - SUB. Во втором случае также меняется оформление индикатора. Если вы выберите из меню Work строку Disable ADD SUB, то индикатор будет заблокирован.


Процедура создания диалоговой панели управления


Как и в случае разработки обычных диалоговый панелей, сначала следует подготовить шаблон диалоговой панели, которая будет использоваться в качестве панели управления. Для этого можно воспользоваться редактором ресурсов Microsoft Visual C++.

В шаблоне диалоговой панели следует установить только один стиль - WS_CHILD. Диалоговая панель управления будет выступать в качестве дочернего окна и не должна иметь ни заголовка ни рамки.

Готовый шаблон следует сохранить в файле ресурсов проекта. На этом подготовка шаблона диалоговой панели управления считается законченной и надо приступить к написанию программного кода для работы с нею.

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

Затем надо переопределить метод OnCreate класса окна и добавить в нем вызов метода Create класса CDialogBar для объекта представляющего диалоговую панель управления.

Если вы добавляете диалоговую панель управления к приложению, созданному с использованием средств MFC AppWizard, то в нем уже определен метод OnCreate и вам только остается добавить в него соответствующий вызов метода Create.

Органы управления диалоговой панели передают сообщения непосредственно своему родительскому окну. Добавьте в таблицу сообщений класса окна соответствующие макрокоманды для получения сообщений и включите в класс окна методы для их обработки.

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



Простое приложение с панелью управления


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

Чтобы подробнее разобраться с устройством и возможностями панелей управления, гораздо лучше взять маленькое приложение, программный код которого можно охватить буквально одним взглядом. Возьмем за основу приложение MFStart с одним единственным окном, представленное нами в первой книге серии “Библиотека системного программиста”, посвященной программированию в Microsoft Visual C++ с применением классов MFC.

¨ К сожалению, если вы не используете для создания приложения MFC AppWizard, то вам, скорее всего, не будут доступны и возможности ClassWizard. Сейчас нам придется пожертвовать удобством в разработке приложения ради простоты его исходных текстов.

Создайте новый проект под названием Bar. В качестве типа приложения выберите из списка Type строку Application. Выберите из меню Build строку Settings или нажмите комбинацию клавиш <Alt+F7>. На экране появится диалоговая панель Project Settings. В этой панели расположены несколько страниц, позволяющих настроить различные характеристики проекта.

Откройте страницу General. Выберите из списка Microsoft Foundation Classes строку Use MFC in a Shared Dll или строку Use MFC in a Static Library. Эта настройка указывает Microsoft Visual C++, что в приложении используются классы библиотеки MFC.

Наберите в редакторе исходный текст приложения и сохраните его в файле Bar.cpp (листинг 3.4). Затем включите этот файл в проект. Для простоты мы включили в один файл весь программный код приложения.

Листинг 3.4. Файл Bar.cpp

//============================================================

// Приложение Bar

// (c) Frolov G.V., 1996

// E-mail: frolov@glas.apc.org

//============================================================

// Исключаем редко используемые определения из


// включаемых файлов

#define VC_EXTRALEAN

// Включаемый файл для MFC

#include <afxwin.h>

#include <afxext.h>

#include <afxcmn.h>

// Включаемый файл для ресурсов приложения

#include "resource.h"

//============================================================

// Класс CBarApp - главный класс приложения

//============================================================

class CBarApp : public CWinApp

{

public:

   // Мы будем переопределять метод InitInstance,

   // предназначенный для инициализации приложения

   virtual BOOL InitInstance();

};

 

// Создаем объект приложение класса CBarApp

CBarApp MyBarApp;

 

//============================================================

// Класс CBarWindow - представляет главное окно

//============================================================

class CBarWindow : public CFrameWnd

{

protected:  // control bar embedded members

   CToolBar    m_wndToolBar;

  

protected:

   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

public:

   // Объявляем конструктор класса CBarWindow

   CBarWindow();

   // Объявляем методы для обработки команд меню

   afx_msg void BarCommand();

   // Макрокоманда необходима, так как класс

   // CBarWindow обрабатывает сообщения

   DECLARE_MESSAGE_MAP()   

};

//============================================================

// Метод BarCommand

// Обрабатывает команду ID_TEST_BEEP

//============================================================

void CBarWindow::BarCommand()

{

   MessageBox("Command not implemented");       

}

//============================================================

// Таблица сообщений класса CBarWindow

//============================================================

BEGIN_MESSAGE_MAP(CBarWindow, CFrameWnd)

   ON_WM_CREATE()

   ON_COMMAND(ID_FILE_OPEN, CBarWindow::BarCommand)

   ON_COMMAND(ID_FILE_SAVE, CBarWindow::BarCommand)

   ON_COMMAND(ID_TOOL_EXIT, CBarWindow::BarCommand)



END_MESSAGE_MAP()

//============================================================

// Метод InitInstance класса CBarApp

//============================================================

BOOL CBarApp::InitInstance()

{

   // Создаем объект класса CBarWindow

   m_pMainWnd = new CBarWindow();

   // Отображаем окно на экране

   m_pMainWnd -> ShowWindow(m_nCmdShow);

   // Обновляем содержимое окна

   m_pMainWnd -> UpdateWindow();

   return TRUE;

}

//============================================================

// Конструктор класса CBarWindow

//============================================================

CBarWindow::CBarWindow()

{

   // Создаем окно приложения, соответствующее

   // данному объекту класса CBarWindow

   Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW,

         rectDefault, NULL );

}

//============================================================

// Метод OnCreate класса CBarWindow

// Вызывается во время создания окна приложения

//============================================================

int CBarWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

   // Вызываем метод OnCreate базового класса

   if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

      return -1;

   // Создаем панель управления toolbar. В качестве

   // родительского окна указываем окно CBarWindow

   if (!m_wndToolBar.Create(this))

   {

      // Ошибка при создании панели управления

      TRACE0("Failed to create toolbar\n");

      return -1;

   }

   if (!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

   {

      // Ошибка при загрузке ресурса панели управления

      TRACE0("Failed to load toolbar\n");

      return -1;

   }

   return 0;

}

Теперь необходимо создать ресурс панели управления toolbar. Вы можете сделать это несколькими способами - создать панель управления “с нуля” или скопировать уже готовую панель управления из другого приложения, например из приложения Multi, представленного в главе “Многооконное приложение”.

Перед тем как приступить к разработке панели управления, создайте файл ресурсов и включите его в проект. Для этого выберите из меню File строку New. Из открывшейся диалоговой панели New выберите строку Resource Script и нажмите на кнопку OK. Будет создан пустой файл ресурсов. Сохраните его в каталоге приложения под именем Bar.rc и включите в проект.


Редактор панели управления


Начиная с версии 4.0 Microsoft Visual C++, панель управления является отдельным ресурсом, таким же как меню или шаблон диалоговой панели. Редактор ресурсов Microsoft Visual C++ позволяет создать новую панель управления или изменить уже существующую. В редакторе вы не только можете нарисовать новые кнопки, вы сразу можете присвоить им идентификаторы и вызвать ClassWizard, чтобы добавить программный код, вызываемый при нажатии на данную кнопку. В самом простом случае процедура добавления новой кнопки к уже существующей панели управления займет у вас всего несколько минут.

Создайте с помощью MFC AppWizard новый проект или откройте проект, созданный ранее, например, проект Multi. В окне Project Workspace откройте страницу ResourceView. Откройте папку ресурсов Toolbar. В ней располагается только один ресурс этого типа, имеющий идентификатор IDR_MAINFRAME. Загрузите этот ресурс в редактор ресурсов (рис. 3.7).

Рис. 3.7. Редактор ресурсов toolbar

В верхней части окна редактора ресурсов типа toolbar отображается редактируемая панель управления. С помощью мыши можно выбирать кнопки этой панели, которые вы желаете изменить. Редактирование изображения кнопок выполняется в нижней части окна редактора, разделенной на две области, в которых отображается кнопка в нормальном и увеличенном масштабе. Для редактирования предназначены инструменты, представленные в панели Graphics. Вы также можете задавать цвета из палитры Colors.

Редактор ресурсов позволяет присвоить идентификаторы отдельным кнопкам панели управления. Для этого сделайте двойной щелчок по изображению кнопки в верхней части окна редактора. На экране появится диалоговая панель Toolbar Button Properties (рис. 3.8).

Рис. 3.8. Диалоговая панель Toolbar Button Properties

Идентификатор кнопки вводится в списке ID. По умолчанию в списке ID отображается идентификатор, который кнопка имеет в данный момент. Вы можете заменить его другим идентификатором, выбрав его из списка или введя его вручную. Если кнопке, идентификатор еще не присвоен и поле ID пустое, то когда вы закроете панель Toolbar Button Properties, идентификатор будет создан автоматически.

В полях Width и Height выводятся, соответственно, ширина и высота кнопок панели управления в пикселах. Эти два значения относятся ко всем кнопкам панели, а не только к кнопке, выбранной для редактирования в данный момент.

В поле Prompt отображается текстовая строка, описывающая кнопку панели управления. Строка состоит из двух частей, разделенных символом \n. Первая часть содержит описание кнопки, отображаемое в панели состояния когда кнопка выбрана (или соответствующей строки меню, если в меню есть строка с таким же идентификатором). Во второй части строки находится короткое описание кнопки. Оно отображается в окне подсказки tooltips, если вы поместите указатель мыши над кнопкой и некоторое время подождете.

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



Ресурсы клавиш акселераторов


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

Для создания и изменения таблиц акселераторов следует использовать редактор ресурсов Microsoft Visual C++. Он позволяет определить соответствие комбинаций клавиш и идентификаторов командных сообщений (рис. 3.3).

Рис. 3.3. Редактор таблицы клавиш ускорения

Для приложений имеющих оконный интерфейс, и созданных с использованием MFC AppWizard, таблица акселераторов создается автоматически. Таблица акселераторов загружается приложением, во время создания главного окна приложения методом LoadFrame. Мы уже рассматривали этот метод, который также используется для загрузки меню и ряда других ресурсов:

// Создаем главное окно многооконного приложения

CMainFrame* pMainFrame = new CMainFrame;

// Загружаем ресурсы с идентификатором IDR_MAINFRAME,

// в том числе и таблицу акселераторов

if(!pMainFrame->LoadFrame(IDR_MAINFRAME))

   return FALSE;

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

Чтобы определить таблицу акселераторов для документов данного типа, надо просто включить ее в файл ресурсов приложения, присвоив ей идентификатор данного типа документов:

CMultiDocTemplate* pDocTemplate;

pDocTemplate = new CMultiDocTemplate(

   IDR_MULTITYPE,

   RUNTIME_CLASS(CMultiDoc),

   RUNTIME_CLASS(CChildFrame),

   RUNTIME_CLASS(CMultiView));

AddDocTemplate(pDocTemplate);

Если приложение создается без использования средств MFC AppWizard и модели документ - окно просмотра, вы можете загрузить таблицу акселераторов, с помощью метода LoadAccelTable, входящего в состав класса CFrameWnd:

BOOL LoadAccelTable(LPCTSTR lpszResourceName);

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

Как и многие другие методы классов MFC, метод LoadAccelTable возвращает в случае успешного завершения ненулевое значение и нуль в случае ошибки. Ошибка во время загрузки таблицы акселераторов может случиться, если вы неправильно укажите идентификатор (или имя) ресурса таблицы.



Ресурсы Microsoft


Вместе с Microsoft Visual C++ поставляется файл Common.res, содержащий различные ресурсы - пиктограммы, курсоры, изображения bitmap. Вы можете свободно использовать эти ресурсы в своих приложениях и распространять их.

¨ Вместо того, чтобы самому рисовать картинки для пиктограмм, панелей управления и курсоров или заказывать их у художника, обратите внимание на файл Common.res. Возможно, в нем есть то, что вам надо.

Во время установки Microsoft Visual C++ не происходит копирования файла ресурсов Common.res на жесткий диск компьютера. Поэтому вы должны скопировать его отдельно или использовать непосредственно с компакт диска. На компакт дисках Microsoft Visual C++ этот файл расположен в каталоге Msdev\Samples\Mfc\General\Clipart\.

Чтобы включить некоторые ресурсы из файла Common.res в файл ресурсов вашего приложения, откройте в Microsoft Visual C++ файл Common.res и файл ресурсов приложения. Затем скопируйте интересующие вас ресурсы и сохраните изменения на диске.



Ресурсы приложений и панель состояния


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



Ресурсы приложения


Рассмотрим ресурсы, которые MFC AppWizard создал для нашего приложения. Откройте страницу RecourceView в окне проекта Project Workspace. В нем отображается полный список всех ресурсов приложения (рис. 1.3).

Рис. 1.3. Окно Project Workspace, ресурсы приложения

Сравните эти ресурсы с ресурсами приложения с однооконным интерфейсом (том 24 серии “Библиотека системного программиста”). Вы заметите, что в состав приложения с многооконным интерфейсом входит больше ресурсов. Так, например, для многооконного приложения определены два меню, две пиктограммы, больше размер таблицы текстовых строк.



Ресурсы приложения Dater


В файле ресурсов приложения Dater определены меню, панель управления и таблица клавиш акселераторов IDR_MAINFRAME, шаблон диалоговой панели IDD_DATER_FORM, который используется окном просмотра и шаблон информационной панели IDD_ABOUTBOX. В файле ресурсов также расположены строковые ресурсы, описывающие строки меню, кнопки панелей управления и индикаторы панели состояния. Мы привели исходный текст файла Dater.rc в листинге 5.3.

Листинг 5.3. Файл Dater.rc

//Microsoft Developer Studio generated resource script.

//

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

//////////////////////////////////////////////////////////////

#undef APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

// English (U.S.) resources

//#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_ENU)

//#ifdef _WIN32

//LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

//#pragma code_page(1252)

//#endif //_WIN32

#ifdef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE DISCARDABLE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE DISCARDABLE

BEGIN

    "#include ""afxres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE DISCARDABLE

BEGIN

   "#define _AFX_NO_SPLITTER_RESOURCES\r\n"

   "#define _AFX_NO_OLE_RESOURCES\r\n"

   "#define _AFX_NO_TRACKER_RESOURCES\r\n"

   "#define _AFX_NO_PROPERTY_RESOURCES\r\n"

   "\r\n"

   "#if !defined(AFX_RESOURCE_DLL)defined(AFX_TARG_ENU)\r\n"

   "#ifdef _WIN32\r\n"

   "LANGUAGE 9, 1\r\n"

   "#pragma code_page(1252)\r\n"

   "#endif\r\n"

   "#include ""res\\Dater.rc2""  // non-Microsoft Visual C++


                                 // edited resources\r\n"

   "#include ""afxres.rc""       // Standard components\r\n"

   "#include ""afxdb.rc""        // Database resources\r\n"

   "#endif\0"

END

#endif    // APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// Icon

//

IDR_MAINFRAME   ICON   DISCARDABLE   "res\\Dater.ico"

IDR_DATERTYPE   ICON   DISCARDABLE   "res\\DaterDoc.ico"

//////////////////////////////////////////////////////////////

//

// Bitmap

//

IDR_MAINFRAME   BITMAP  MOVEABLE PURE   "res\\Toolbar.bmp"

//////////////////////////////////////////////////////////////

//

// Toolbar

//

IDR_MAINFRAME TOOLBAR DISCARDABLE  16, 15

BEGIN

    BUTTON      ID_EDIT_CUT

    BUTTON      ID_EDIT_COPY

    BUTTON      ID_EDIT_PASTE

    SEPARATOR

    BUTTON      ID_FILE_PRINT

    SEPARATOR

    BUTTON      ID_RECORD_FIRST

    BUTTON      ID_RECORD_PREV

    BUTTON      ID_RECORD_NEXT

    BUTTON      ID_RECORD_LAST

    SEPARATOR

    BUTTON      ID_APP_ABOUT

END

//////////////////////////////////////////////////////////////

//

// Menu

//

IDR_MAINFRAME MENU PRELOAD DISCARDABLE

BEGIN

   POPUP "&File"

   BEGIN

       MENUITEM "E&xit",                ID_APP_EXIT

   END

   POPUP "&Edit"

   BEGIN

      MENUITEM "&Undo\tCtrl+Z",         ID_EDIT_UNDO

      MENUITEM SEPARATOR

      MENUITEM "Cu&t\tCtrl+X",          ID_EDIT_CUT

      MENUITEM "&Copy\tCtrl+C",         ID_EDIT_COPY

      MENUITEM "&Paste\tCtrl+V",        ID_EDIT_PASTE

   END

   POPUP "&Record"

   BEGIN

      MENUITEM "&First Record",         ID_RECORD_FIRST

      MENUITEM "&Previous Record",      ID_RECORD_PREV

      MENUITEM "&Next Record",          ID_RECORD_NEXT



      MENUITEM "&Last Record",          ID_RECORD_LAST

   END

   POPUP "&View"

   BEGIN

      MENUITEM "&Toolbar",              ID_VIEW_TOOLBAR

      MENUITEM "&Status Bar",           ID_VIEW_STATUS_BAR

   END

   POPUP "&Help"

   BEGIN

      MENUITEM "&About Dater...",       ID_APP_ABOUT

   END

END

//////////////////////////////////////////////////////////////

//

// Accelerator

//

IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE

BEGIN

    "Z",            ID_EDIT_UNDO,           VIRTKEY, CONTROL

    "X",            ID_EDIT_CUT,            VIRTKEY, CONTROL

    "C",            ID_EDIT_COPY,           VIRTKEY, CONTROL

    "V",            ID_EDIT_PASTE,          VIRTKEY, CONTROL

    VK_BACK,        ID_EDIT_UNDO,           VIRTKEY, ALT

    VK_DELETE,      ID_EDIT_CUT,            VIRTKEY, SHIFT

    VK_INSERT,      ID_EDIT_COPY,           VIRTKEY, CONTROL

    VK_INSERT,      ID_EDIT_PASTE,          VIRTKEY, SHIFT

    VK_F6,          ID_NEXT_PANE,           VIRTKEY

    VK_F6,          ID_PREV_PANE,           VIRTKEY, SHIFT

END

//////////////////////////////////////////////////////////////

//

// Dialog

//

IDD_ABOUTBOX DIALOG DISCARDABLE  0, 0, 217, 55

STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU

CAPTION "About Dater"

FONT 8, "MS Sans Serif"

BEGIN

   ICON            IDR_MAINFRAME,IDC_STATIC,11,17,20,20

   LTEXT           "Dater Version 1.0",

                   IDC_STATIC,40,10,119,8,SS_NOPREFIX

   LTEXT           "Copyright © 1996",IDC_STATIC,40,25,119,8

   DEFPUSHBUTTON   "OK",IDOK,178,7,32,14,WS_GROUP

END

IDD_DATER_FORM DIALOG DISCARDABLE  0, 0, 201, 101

STYLE WS_CHILD

FONT 8, "MS Sans Serif"

BEGIN

    LTEXT           "E-Mail",IDC_STATIC,5,35,20,8

    LTEXT           "Priority",IDC_STATIC,5,86,22,8



    EDITTEXT        IDC_NAME,35,5,160,15,ES_AUTOHSCROLL

    LTEXT           "Name",IDC_STATIC,5,10,20,8

    EDITTEXT        IDC_ADDRESS,35,30,160,15,ES_AUTOHSCROLL

    EDITTEXT        IDC_PRIORITY,35,80,80,15,ES_AUTOHSCROLL

    LTEXT           "Phone",IDC_STATIC,5,60,22,8

    EDITTEXT        IDC_PHONE,35,55,80,15,ES_AUTOHSCROLL

END

#ifndef _MAC

//////////////////////////////////////////////////////////////

//

// Version

//

VS_VERSION_INFO VERSIONINFO

 FILEVERSION 1,0,0,1

 PRODUCTVERSION 1,0,0,1

 FILEFLAGSMASK 0x3fL

#ifdef _DEBUG

 FILEFLAGS 0x1L

#else

 FILEFLAGS 0x0L

#endif

 FILEOS 0x4L

 FILETYPE 0x1L

 FILESUBTYPE 0x0L

BEGIN

    BLOCK "StringFileInfo"

    BEGIN

        BLOCK "040904B0"

        BEGIN

            VALUE "CompanyName", "\0"

            VALUE "FileDescription", "DATER MFC Application\0"

            VALUE "FileVersion", "1, 0, 0, 1\0"

            VALUE "InternalName", "DATER\0"

            VALUE "LegalCopyright", "Copyright © 1996\0"

            VALUE "LegalTrademarks", "\0"

            VALUE "OriginalFilename", "DATER.EXE\0"

            VALUE "ProductName", "DATER Application\0"

            VALUE "ProductVersion", "1, 0, 0, 1\0"

        END

    END

    BLOCK "VarFileInfo"

    BEGIN

        VALUE "Translation", 0x409, 1200

    END

END

#endif    // !_MAC

//////////////////////////////////////////////////////////////

//

// DESIGNINFO

//

#ifdef APSTUDIO_INVOKED

GUIDELINES DESIGNINFO DISCARDABLE

BEGIN

    IDD_ABOUTBOX, DIALOG

    BEGIN

        LEFTMARGIN, 7

        RIGHTMARGIN, 210

        TOPMARGIN, 7

        BOTTOMMARGIN, 48

    END

    IDD_DATER_FORM, DIALOG

    BEGIN

        LEFTMARGIN, 7

        RIGHTMARGIN, 194



        TOPMARGIN, 7

        BOTTOMMARGIN, 94

    END

END

#endif    // APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// String Table

//

STRINGTABLE DISCARDABLE

BEGIN

    IDP_FAILED_OPEN_DATABASE "Cannot open database."

END

STRINGTABLE PRELOAD DISCARDABLE

BEGIN

   IDR_MAINFRAME "Dater\n\nDater\n\n\n

                  Dater.Document\nDater Document"

END

STRINGTABLE PRELOAD DISCARDABLE

BEGIN

    AFX_IDS_APP_TITLE       "Dater"

    AFX_IDS_IDLEMESSAGE     "Ready"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_INDICATOR_EXT        "EXT"

    ID_INDICATOR_CAPS       "CAP"

    ID_INDICATOR_NUM        "NUM"

    ID_INDICATOR_SCRL       "SCRL"

    ID_INDICATOR_OVR        "OVR"

    ID_INDICATOR_REC        "REC"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_APP_ABOUT   "Display program information, version

                    number and copyright\nAbout"

    ID_APP_EXIT    " Quit the application; prompts to save

                    documents\nExit"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_FILE_MRU_FILE1       "Open this document"

    ID_FILE_MRU_FILE2       "Open this document"

    //...

    ID_FILE_MRU_FILE16      "Open this document"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_NEXT_PANE   "Switch to the next window pane\nNext Pane"

    ID_PREV_PANE   "Switch back to the previous window pane\n

                    Previous Pane"

END

STRINGTABLE DISCARDABLE

BEGIN

   ID_WINDOW_SPLIT "Split the active window into panes\nSplit"

END

STRINGTABLE DISCARDABLE

BEGIN

   ID_EDIT_CLEAR        "Erase the selection\nErase"

   ID_EDIT_CLEAR_ALL    "Erase everything\nErase All"

   ID_EDIT_COPY         "Copy the selection and put it on the



                         Clipboard\nCopy"

   ID_EDIT_CUT          " Cut the selection and put it on the

                         Clipboard\nCut"

   ID_EDIT_FIND         "Find the specified text\nFind"

   ID_EDIT_PASTE        "Insert Clipboard contents\nPaste"

   ID_EDIT_REPEAT       "Repeat the last action\nRepeat"

   ID_EDIT_REPLACE      "Replace specific text with different

                         text\nReplace"

   ID_EDIT_SELECT_ALL   "Select the entire document\n

                         Select All"

   ID_EDIT_UNDO      "Undo the last action\nUndo"

   ID_EDIT_REDO      "Redo the previously undone action\nRedo"

END

STRINGTABLE DISCARDABLE

BEGIN

   ID_VIEW_TOOLBAR     "Show or hide the toolbar\n

                        Toggle ToolBar"

    ID_VIEW_STATUS_BAR "Show or hide the status bar\n

                        Toggle StatusBar"

END

STRINGTABLE DISCARDABLE

BEGIN

   ID_RECORD_FIRST  "Move to first record\nFirst Record"

   ID_RECORD_LAST   "Move to final record\nLast Record"

   ID_RECORD_NEXT   "Move to next record\nNext Record"

   ID_RECORD_PREV   "Move to previous record\nPrevious Record"

END

STRINGTABLE DISCARDABLE

BEGIN

   AFX_IDS_SCSIZE        "Change the window size"

   AFX_IDS_SCMOVE        "Change the window position"

   AFX_IDS_SCMINIMIZE    "Reduce the window to an icon"

   AFX_IDS_SCMAXIMIZE    "Enlarge the window to full size"

   AFX_IDS_SCNEXTWINDOW  "Switch to the next document window"

   AFX_IDS_SCPREVWINDOW  "Switch to the previous document

                          window"

   AFX_IDS_SCCLOSE       "Close the active window and prompts

                          to save the documents"

END

STRINGTABLE DISCARDABLE

BEGIN

    AFX_IDS_SCRESTORE    "Restore the window to normal size"



    AFX_IDS_SCTASKLIST   "Activate Task List"

END

//#endif    // English (U.S.) resources

//////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

#define _AFX_NO_SPLITTER_RESOURCES

#define _AFX_NO_OLE_RESOURCES

#define _AFX_NO_TRACKER_RESOURCES

#define _AFX_NO_PROPERTY_RESOURCES

#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_ENU)

#ifdef _WIN32

LANGUAGE 9, 1

#pragma code_page(1252)

#endif

#include "res\Dater.rc2"  // non-Microsoft Visual C++ edited resources

#include "afxres.rc"         // Standard components

#include "afxdb.rc"          // Database resources

#endif

//////////////////////////////////////////////////////////////

#endif    // not APSTUDIO_INVOKED

Идентификаторы ресурсов приложения Dater определены в файле resource.h. Этот файл создается автоматически редактором ресурсов Microsoft Visual C++. Исходный текст файла resource.h представлен в листинге 3.15.

Листинг 5.4. Файл resource.h

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by Dater.rc

//

#define IDD_ABOUTBOX                    100

#define IDD_DATER_FORM                  101

#define IDP_FAILED_OPEN_DATABASE        103

#define IDR_MAINFRAME                   128

#define IDR_DATERTYPE                   129

#define IDC_NAME                        1000

#define IDC_ADDRESS                     1001

#define IDC_PRIORITY                    1002

#define IDC_PHONE                       1003

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_3D_CONTROLS                1

#define _APS_NEXT_RESOURCE_VALUE        130

#define _APS_NEXT_COMMAND_VALUE         32771

#define _APS_NEXT_CONTROL_VALUE         1004

#define _APS_NEXT_SYMED_VALUE           101

#endif



#endif

Наибольший интерес в файле ресурсов приложения Dater представляют строки меню Record и соответствующие им кнопки панели управления. Эти строки и кнопки позволяют просматривать в окне приложения все записи базы данных.

Строка меню Record

Идентификатор

Описание

First Record

ID_RECORD_FIRST

Перейти к первой записи

Previous Record

ID_RECORD_PREV

Перейти к предыдущей записи

Next Record

ID_RECORD_NEXT

Перейти к следующей записи

Last Record

ID_RECORD_LAST

Перейти к последней записи

Командные сообщения с идентификаторами ID_RECORD_FIRST, ID_RECORD_PREV, ID_RECORD_NEXT и ID_RECORD_LAST обрабатываются виртуальным методом OnMove класса окна просмотра CRecordView.

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


Ресурсы приложения MultiBar


Создайте новый файл ресурсов и включите его в проект под именем MultiBar.rc. Теперь надо создать три панели управления toolbar и включить их в файл ресурсов. Изображения кнопок панелей управления вы можете нарисовать самостоятельно или скопировать их из файла ресурсов Common.res, поставляемого вместе с Microsoft Visual C++. Более подробная информация о файле Common.res представлена в разделе “Ресурсы Microsoft”.

При создании панелей управления руководствуйтесь информацией из файла ресурсов приложения MultiBar (листинг 3.3) и изображениями кнопок панелей управления (рис. 3.3, 3.4, 3.5).

Первая панель управления должна иметь идентификатор IDR_PLAYER и содержать девять кнопок с идентификаторами ID_LEFT, ID_PLAY, ID_RIGHT, ID_STOP, ID_PAUSE, ID_EJECT, ID_TYPE, ID_CD_DRV и ID_WAVE. Между кнопками ID_RIGHT и ID_STOP, ID_PAUSE и ID_EJECT, ID_EJECT и ID_TYPE вставьте разделители. Для каждой из кнопок вы также можете ввести их текстовые описания.

Вторая панель управления должна иметь идентификатор IDR_STYLE и содержать двенадцать кнопок с идентификаторами ID_UNDERLINE, ID_2_UNDERLINE, ID_SUPERSCRIPT, ID_SUBSCRIPT, ID_TEXT_LEFT, ID_ID_TEXT_CENTER, ID_TEXT_RIGHT, ID_TEXT_JUSTIFY, ID_MARK_1, ID_MARK_2, ID_MARK_3 и ID_MARK_4. Для первых шести кнопок введите их текстовые описания.

Третья панель управления должна иметь идентификатор IDR_EXTENDED. Определите в ней четыре кнопки с идентификаторами ID_FOTO, ID_PRINTER, ID_ADD и ID_DISK. Между кнопками ID_PRINTER и  ID_ADD, а также ID_ADD и ID_DISK вставьте разделители. Введите текстовые описания кнопок.

В файл ресурсов, кроме панелей управления toolbar, включите меню IDR_MENU с тремя строками Style, Extended и Player, которые имеют идентификаторы ID_Style, ID_Extended и ID_Player. Обратите внимание, что идентификаторы строк меню соответствуют идентификаторам панелей управления.

Файл ресурсов приложения MultiBar мы привели в листинге 3.8. В нем определены ресурсы панелей управления toolbar с идентификаторами IDR_PLAYER, IDR_STYLE и IDR_EXTENDED, ресурсы изображений этих панелей управления с соответствующими идентификаторами, меню приложения, а также несколько строковых ресурсов с описаниями кнопок панелей управления. Идентификаторы строковых ресурсов соответствуют идентификаторам кнопок панелей управления, которые они описывают.


Листинг 3.8. Файл MultiBar.rc

// Microsoft Developer Studio generated resource script.

//

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

#include "afxres.h"

//////////////////////////////////////////////////////////////

#undef APSTUDIO_READONLY_SYMBOLS

//////////////////////////////////////////////////////////////

//

// Russian resources

#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_RUS)

#ifdef _WIN32

LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT

#pragma code_page(1251)

#endif //_WIN32

#ifdef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE DISCARDABLE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE DISCARDABLE

BEGIN

    "#include ""afxres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE DISCARDABLE

BEGIN

    "\r\n"

    "\0"

END

#endif    // APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

//

// Toolbar

//

IDR_PLAYER TOOLBAR DISCARDABLE  16, 15

BEGIN

    BUTTON      ID_LEFT

    BUTTON      ID_PLAY

    BUTTON      ID_RIGHT

    SEPARATOR

    BUTTON      ID_STOP

    BUTTON      ID_PAUSE

    SEPARATOR

    BUTTON      ID_EJECT

    SEPARATOR

    BUTTON      ID_TYPE

    BUTTON      ID_CD_DRV

    BUTTON      ID_WAVE

END

IDR_STYLE TOOLBAR DISCARDABLE  16, 15

BEGIN

    BUTTON      ID_UNDERLINE

    BUTTON      ID_2_UNDERLINE

    BUTTON      ID_SUPERSCRIPT

    BUTTON      ID_SUBSCRIPT

    BUTTON      ID_TEXT_LEFT

    BUTTON      ID_ID_TEXT_CENTER

    BUTTON      ID_TEXT_RIGHT

    BUTTON      ID_TEXT_JUSTIFY

    BUTTON      ID_MARK_1

    BUTTON      ID_MARK_2

    BUTTON      ID_MARK_3

    BUTTON      ID_MARK_4

END

IDR_EXTENDED TOOLBAR DISCARDABLE  16, 15



BEGIN

    BUTTON      ID_FOTO

    BUTTON      ID_PRINTER

    SEPARATOR

    BUTTON      ID_ADD

    SEPARATOR

    BUTTON      ID_DISK

END

//////////////////////////////////////////////////////////////

//

// Bitmap

//

IDR_PLAYER              BITMAP  DISCARDABLE     "player.bmp"

IDR_STYLE               BITMAP  DISCARDABLE     "style.bmp"

IDR_EXTENDED            BITMAP  DISCARDABLE     "extended.bmp"

//////////////////////////////////////////////////////////////

//

// Menu

//

IDR_MENU MENU DISCARDABLE

BEGIN

    POPUP "View"

    BEGIN

        MENUITEM "Style",                       ID_Style

        MENUITEM "Extended",                    ID_Extended

        MENUITEM "Player",                      ID_Player

    END

END

//////////////////////////////////////////////////////////////

//

// String Table

//

STRINGTABLE DISCARDABLE

BEGIN

    ID_LEFT              "Rewind to begin\nRewind to begin"

    ID_RIGHT             "Rewind to end\nRewind to end"

    ID_PLAY              "Play\nPlay"

    ID_STOP              "Stop\nStop"

    ID_PAUSE             "Pause\nPause"

    ID_EJECT             "Eject\nEject"

    ID_TYPE              "Type drive\nType"

    ID_CD_DRV            "CD drive\nCD"

    ID_BUTTON40010       "Wave/nWave File"

    ID_WAVE              "Wave file\nWAWE"

    ID_UNDERLINE         "Underline\nUnderline"

    ID_2_UNDERLINE       "Double underline\nDouble underline"

    ID_SUPERSCRIPT       "Superscript\nSuperscript"

    ID_SUBSCRIPT         "Subscript\nSubscript"

END

STRINGTABLE DISCARDABLE

BEGIN

    ID_ADD               "Add from edit-box item to combo-

                          box\nAdd item to list"

END

STRINGTABLE DISCARDABLE

BEGIN



    ID_TEXT_LEFT         "Left text\nLeft"

    ID_ID_TEXT_CENTER    "Center text\nCenter"

    ID_TEXT_RIGHT        "Right text\nRight"

    ID_TEXT_JUSTIFY      "Justify text\nJustify"

    ID_FOTO              "Foto\nFoto"

    ID_PRINTER           "Printer\nPrinter"

    ID_DISK              "Disk\nDisk"

END

STRINGTABLE DISCARDABLE

BEGIN

    IDW_EDIT             "Edit\nEdit"

    IDW_COMBO            "Combo box\nCombo box"

END

#endif    // Russian resources

//////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED

//////////////////////////////////////////////////////////////

// Generated from the TEXTINCLUDE 3 resource.

//

//////////////////////////////////////////////////////////////

#endif    // not APSTUDIO_INVOKED

Изображения кнопок панелей управления располагаются в отдельных файлах player.bmp (рис. 3.14), style.bmp  (рис. 3.15) и extended.bmp (рис. 3.13) в главном каталоге проекта. Файлы изображений панелей управления содержат только изображения кнопок. В них не представлены разделители и дополнительные органы управления.

В принципе, изображения панели управления можно редактировать в любом графическом редакторе, который работает с 16-цветными изображениями в формате BMP. Примером такого приложения является графический редактор Microsoft Paint, поставляемый вместе с операционными системами Windows 95 и Windows NT версии 4.0. Однако, лучше использовать редактор ресурсов среды Microsoft Visual C++, так как он не только разрешает редактировать существующие кнопки, но также позволяет добавлять новые кнопки вместе с соответствующими идентификаторами и строковыми ресурсами.



Рис. 3.13. Изображение кнопок панели управления Extended



Рис. 3.14. Изображение кнопок панели управления Player



Рис. 3.15. Изображение кнопок панели управления Style

Идентификаторы всех ресурсов приложения MultiBar и идентификаторы дополнительных органов управления панели Extended определены в файле resource.h. Этот файл автоматически создается редактором ресурсов Microsoft Visual C++.



Мы привели исходный текст файла resource.h в листинге 3.9.

Листинг 3.9. Файл resource.h

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by MultiBar.rc

//

#define IDW_EDIT                        101

#define IDW_COMBO                       102

#define IDR_PLAYER                      103

#define IDR_STYLE                       105

#define IDR_EXTENDED                    107

#define IDR_MENU                        109

#define ID_LEFT                         40001

#define ID_RIGHT                        40002

#define ID_PLAY                         40003

#define ID_STOP                         40004

#define ID_PAUSE                        40005

#define ID_EJECT                        40007

#define ID_TYPE                         40008

#define ID_CD_DRV                       40009

#define ID_WAVE                         40011

#define ID_UNDERLINE                    40012

#define ID_2_UNDERLINE                  40013

#define ID_SUPERSCRIPT                  40014

#define ID_SUBSCRIPT                    40015

#define ID_TEXT_LEFT                    40017

#define ID_ID_TEXT_CENTER               40018

#define ID_TEXT_RIGHT                   40019

#define ID_TEXT_JUSTIFY                 40020

#define ID_MARK_1                       40021

#define ID_MARK_2                       40022

#define ID_MARK_3                       40023

#define ID_MARK_4                       40024

#define ID_FOTO                         40025

#define ID_PRINTER                      40026

#define ID_DISK                         40027

#define ID_Style                        40029

#define ID_Extended                     40030

#define ID_Buttons                      40031

#define ID_Player                       40031

#define ID_ADD                          40032

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        110

#define _APS_NEXT_COMMAND_VALUE         40033

#define _APS_NEXT_CONTROL_VALUE         1000

#define _APS_NEXT_SYMED_VALUE           103

#endif

#endif


Ресурсы текстовых документов


Откройте редактор ресурсов приложения. Вам требуется создать меню, пиктограмму и строковый ресурс с идентификатором IDR_EDITORTYPE. Самый простой путь для этого заключается в копировании и изменении идентификатора ресурсов, относящихся к графическим документам. Идентификатор этих ресурсов IDR_MULTITYPE. Чтобы скопировать ресурс, вы можете выбрать интересующий вас ресурс из окна проекта, записать его в обменный буфер clipboard, вставить его, а затем изменить идентификатор на IDR_EDITORTYPE.

На первом этапе разработки приложения скопированные меню и пиктограмму вы можете оставить без изменения. Потом вы можете изменить их по своему усмотрению.

Строковый ресурс IDR_EDITORTYPE, описывающий документ, желательно изменить сразу. Для графического документа строковый ресурс IDR_MULTITYPE выглядит следующим образом:

\nGraph\nGraph\nGraph Files (*.LIS)\n.LIS\nGraph.Document\n

Graph Document

Чтобы текстовый документ имел другое название типа документа, расширение файлов принятое по умолчанию, измените строковый ресурс с идентификатором IDR_EDITORTYPE:

\nText\nTexti\nTexti Files (*.TXT)\n.TXT\nText.Document\n

Text Document



Сеть Internet


В состав версии 4.2 включены абсолютно новые классы для работы с сетью Internet, основанные на программном интерфейсе Wininet. С их помощью вы легко сможете создавать клиентские приложения для работы с серверами WWW, FTP и Goufer.

Microsoft Visual C++ версии 4.2 позволяет реализовать новую технологию ActiveX, предложенную Microsoft для использования в сети Internet. В MFC AppWizard добавлены средства, ускоряющие разработку органов управления ActiveX.



Синхронизация окон просмотра документа


Как правило, многооконные приложения позволяют открыть для одного документа несколько окон просмотра. Наше приложение тоже не составляет исключения. Чтобы открыть дополнительное окно для просмотра уже открытого документа, выберите из меню Window строку New.

Откроется новое окно. Заголовки окон просмотра одного документа будут одинаковыми за исключением того, что каждое такое окно имеет дополнительный числовой идентификатор, означающий номер окна. На рисунке 1.14 мы показали как будет выглядеть приложение Multi, если в нем создать два новых документа Multi1 и Multi2, а затем открыть два дополнительных окна для просмотра документа Multi2.

Рис. 1.14. Окно Project Workspace, класс CMultiView

К сожалению, окна просмотра документа несогласованны. Если вы внесете в документ изменения через одно окно, они не появятся во втором до тех пор, пока содержимое окна не будет перерисовано. Чтобы избежать рассогласования между окнами просмотра одного и того же документа, необходимо сразу после изменения документа в одном окне вызвать метод UpdateAllViews, определенный в классе CDocument:

void UpdateAllViews(

   CView* pSender,

   LPARAM lHint = 0L,

   CObject* pHint = NULL

);

Метод UpdateAllViews вызывает метод CView::OnUpdate для всех окон просмотра данного документа, за исключением окна просмотра, указанного параметром pSender. Как правило, в качестве pSender используют указатель того окна просмотра через который был изменен документ. Его состояние изменять не надо, так как оно отображает последние изменения в документе.

Если изменение документа вызвано другими причинами, не связанными с окнами просмотра, в качестве параметра pSender можно указать значение NULL. В этом случае будут вызваны методы OnUpdate всех окон просмотра без исключения.

Параметры lHint и pHint могут содержать дополнительную информацию об изменении документа. Методы OnUpdate получают значения lHint и pHint и могут использовать их, чтобы сократить перерисовку документа.

Мы изменяем документ только в методе OnLButtonDown. Поэтому добавьте вызов UpdateAllViews в нем. Разместите его после добавления нового элемента в массив pointFigCenter и установки флага модификации документа (метод UpdateAllViews следует вызывать после метода SetModifiedFlag):


void CMultiView::OnLButtonDown(UINT nFlags, CPoint point)

{

   // ...

   // Устанавливаем флаг изменения документа

   pDoc->SetModifiedFlag();

   // Сообщаем всем окнам просмотра кроме данного об

   // изменении документа

   pDoc->UpdateAllViews(this);

  

   // Вызываем метод OnLButtonDown базового класса CView

   CView::OnLButtonDown(nFlags, point);

}

Постройте проект и запустите приложение. Теперь все окна просмотра документа синхронизированы. Когда вы меняете документ в одном окне, автоматически происходит изменения во всех остальных окнах просмотра.

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

Выход из этого положения существует. При вызове метода UpdateAllViews можно указать, какой объект надо дорисовать. А потом надо переопределить метод OnUpdate так, чтобы приложение дорисовывало в окнах просмотра одну только новую фигуру. Для передачи информации от метода UpdateAllViews методу OnUpdate используют параметры lHint и pHint.

Рассмотрим более подробно, как работает метод OnUpdate:

virtual void

OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);

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

Второй и третий параметры - lHint и pHint содержат дополнительную. информацию, указанную во время вызова метода UpdateAllViews. Если дополнительная информация не определена, тогда эти параметры содержат значения 0L и NULL соответственно.

Метод OnUpdate вызывается, когда после изменения документа вызывается метод CDocument::UpdateAllViews. Метод также вызывается методом OnInitialUpdate (если вы не переопределите метод OnInitialUpdate).

Реализация OnUpdate из класса CView, определяет, что вся внутренняя область окна просмотра подлежит обновлению и передает данному окну сообщение WM_PAINT (для этого вызывается функция InvalidateRect). Это сообщение обрабатывается методом OnDraw.



Параметр lHint имеет тип LPARAM и может содержать любое 32-битное значение. В нашем случае мы можем передавать через этот параметр индекс элемента массива документа, который надо перерисовать.

Параметр pHint является указателем на объект типа CObject. Поэтому если вы желаете его использовать, вы должны определить собственный класс, наследованный от базового класса CObject, создать объект этого класса и передать указатель на него методу UpdateAllViews.

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

Когда вы будете разрабатывать метод OnUpdate, вы должны проверять тип объекта, передаваемого через параметр pHint. Для этого можно воспользоваться методом IsKindOf класса CObject. Метод IsKindOf позволяет узнать тип объекта уже на этапе выполнения приложения.

В нашем приложении новые фигуры добавляются в документ во время обработки сообщения WM_LBUTTONDOWN методом OnLButtonDown класса окна просмотра. Модифицируем этот метод так, чтобы после изменения документа метод UpdateAllViews передавал остальным окнам просмотра индекс добавленного элемента в массиве pointFigCenter редактируемого документа:

//////////////////////////////////////////////////////////////

// Метод для обработки сообщения WM_LBUTTONDOWN

void CMultiView::OnLButtonDown(UINT nFlags, CPoint point)

{

   // ...

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

   // элемент

   pDoc->pointFigCenter.Add(point);

   // Устанавливаем флаг изменения документа

   pDoc->SetModifiedFlag();

   // Записываем в переменную nNewFig индекс последнего

   // элемента массива pointFigCenter

   int nNewFig;

   nNewFig = pDoc->pointFigCenter.GetUpperBound();

   // Сообщаем всем окнам просмотра кроме данного об

   // изменении документа, указывая индекс нового элемента

   // массива, представляющего документ



   pDoc->UpdateAllViews(this, nNewFig);

   // Вызываем метод OnLButtonDown базового класса CView

   CView::OnLButtonDown(nFlags, point);

}

Теперь мы должны переопределить метод OnUpdate так, чтобы при вызове через метод UpdateAllViews он отображал на экране только последний элемент массива pointFigCenter.

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

Когда вы переопределяете метод OnUpdate, вы должны иметь в виду, что этот метод вызывается не только методом UpdateAllViews. В некоторых случаях он может быть вызван, если надо перерисовать все изображение в окне просмотра. В этом случае параметр lHint содержит 0, а параметр pHint - NULL Вы должны обрабатывать эту ситуацию отдельно, вызывая метод InvalidateRect и обновляя все окно целиком:

//////////////////////////////////////////////////////////////

// CMultiView

void CMultiView::OnUpdate(

   CView* pSender, LPARAM lHint, CObject* pHint)

{

   // Получаем указатель на документ, относящийся к данному

   // окну просмотра

   CMultiDoc* pDoc = GetDocument();

   ASSERT_VALID(pDoc);

   // Если lHint равен нулю, выполняем обработку по умолчанию

   if (lHint==0L)

      CView::OnUpdate(pSender, lHint, pHint);

   // В противном случае отображаем заданный элемент документа

   else

   {

      // Получаем контекст отображения окна просмотра

      CClientDC dc(this);

      // Отображаем фигуру, определенную элементом массива

      // pointFigCenter с индексом lHint

      dc.Rectangle(

            pDoc->pointFigCenter[lHint].x-10,

            pDoc->pointFigCenter[lHint].y-10,

            pDoc->pointFigCenter[lHint].x+10,

            pDoc->pointFigCenter[lHint].y+10

      );

   }

}

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

В нашем примере мы отображаем новый объект непосредственно из метода OnUpdate. Однако лучше если метод OnUpdate только укажет методу OnDraw область окна просмотра, которую надо перерисовать. Для этого можно воспользоваться методом CWnd::InvalidateRect.


Создание базы данных


Итак, мы решили создать базу данных на основе обычного текстового файла. Запустите любой текстовый редактор, например Notepad. Вы также можете воспользоваться текстовым редактором среды Microsoft Visual C++. Наберите в нем файл TextBase.txt, представленный в листинге 5.1.

Листинг 5.1. Файл TextBase.txt

NAME;ADDRESS;PRIORITY;PHONE

Фролов Григорий Вячеславович;frolov@glas.apc.org;1;(не известен)

Фролов Александр Вячеславович;frolov@glas.apc.org;1;(не известен)

Евсеев Святослав Олегович;sun@power.com;4;8783-77-35

Николаев Петр Иванович;lis@nikol.com;4;1242-09-09

Петров Евгений Николаевич;petr@power.com;7;5453-59-05

Файл TextBase.txt содержит шесть записей (строк). Каждая запись состоит из четырех полей, разделенных символами ;. Самая первая строка отличается от остальных. Она содержит названия полей таблицы, котоорые мы будем использовать далее.

После того, как файл создан, запишите его в каталоге TEXTBASE. Мы разместили каталог TEXTBASE на диске E:, но вы можете записать его на любом другом диске.

Следующим шагом является создание так называемого источника данных, который заключается в подключении текстового драйвера ODBC к файлу TextBase.txt. Обраащаясь к этому источнику данных, программа получает доступ к базе даанных через соответствующий драйвер ODBC.

Для подключения к базе данных драйвера ODBC и создания источника данных используйте приложение 32bit ODBC. Пиктограмма приложения 32bit ODBC находится в окне Control Panel

Откройте Control Panel и запустите приложение 32bit ODBC. На экране появится диалоговая панель Data Source (рис. 5.1).

Рис. 5.1. Диалоговая панель Data Source

Нажмите кнопку Add в диалоговой панели Data Source. На экране появится диалоговая панель Add Data Source (рис. 5.2). В ней вы должны выбрать драйвер ODBC, который будет использоваться для доступа к базе данных.

Если драйвер ODBC для текстовых файлов отсутствует в списке Installed ODBC Drivers, значит он не установлен на вашем компьютере. Чтобы подключить этот драйвер (а также другие драйверы ODBC) повторите установку Microsoft Visual C++ и укажите драйверы ODBC с которыми вы будете работать.


Для первого приложения, использующего драйвера ODBC, мы используем базу данных, представляющую собой обычный текстовый файл. Поэтому выберите из списка Installed ODBC Drivers строку Microsoft Text Driver, представляющую текстовый драйвер ODBC. Нажмите кнопку OK.



Рис. 5.2. Диалоговая панель Add Data Source

Откроется диалоговая панель ODBC Text Setup (рис. 5.3). Эта панель позволяет выбрать базу данных, для дооступа к которой будет использоваться текстовый драйвер ODBC.

В поле Data Source Name введите имя базы данных, под которым она будет использоваться. В поле Description можно занести текстовое описание базы данных.

Так как мы знаем место расположения файла базы данных, убедитесь, что переключатель Use Current Directory выключен и нажмите кнопку Select Directory. На экране появится стандартная диалоговая панель для выбора файлов, но список файлов в ней будет заблокирован. Выберите из нее каталог, в котором записан файл базы данных TextBase.txt. В нашем примере этот файл расположен в каталоге TEXTBASE на диске E:.



Рис. 5.3. Диалоговая панель ODBC Text Setup

Нажмите кнопку OK. Стандартная диалоговая панель выбора файлов закроется. Теперь в поле Directory диалоговой панели ODBC Text Setup будет отображаться имя каталога нашей базы данных.

Как только текстовая база данных (точнее каталог с файлами этой базы) будет выбрана, вы сможете воспользоваться кнопкой Options, расположенной в правом нижнем углу диаалоговой панели ODBC Text Setup. Когда вы нажмете на эту кнопку, внешний вид диалоговой панели ODBC Text Setup изменится (рис. 5.4). В нижней части панели появится новая группа органов управления, которая имеет название Files.



Рис. 5.4. Расширенный вариант панели ODBC Text Setup

В группе Extension List вы должны указать расширения файлов, которые входят в базу данных. Вы можете ввести расширение *.txt или использовать маску *.*. Так как в нашем примере каталог TEXTBASE содержит единственный файл TextBase.txt, то это не имеет значения. Заметим, что маска *.* используется по умолчанию, когда переключатель Default (*.*) установлен.



Теперь надо определить формат таблииц, входящих в базу данных. Нажмите кнопку Define Format. На экране откроется диалоговая панель Define Text Format (рис. 5.5).



Рис. 5.5. Диалоговая панель Define Text Format

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

Выберите из списка Tables имя файла TextBase.txt. Теперь надо определить формат этого файла.

Из списка Format выберите строку, соответствующую типу разделителей, которыми вы отделяете отдельные поля таблицы. Мы использовали в нашем примере разделитель ;. Поэтому выберите из списка Format строку Custom Delimited и введите в поле Delimiter символ ;.

В зависимости от того, какой набор символов используется в вашей таблице, установите переключатель Characters в положение ANSI или OEM. Мы заполнили файл TextBase.txt в формате ANSI, поэтому переведите переключатель в соответствующее положение.

В поле Rows to Scan определите количество строк таблицы, которые будут проверяться при выборе формата. Оставьте это значение без изменения.

Если первая строка файла содержит названия полей соответствующей таблицы, установите переключатель Column Name Header. Обратите внимание на листинг 5.1 файла TextBase.txt. Первая строка этого файла как раз содержит названия полей таблицы. Поэтому переключатель Column Name Header надо установить.

А теперь нажмите кнопку Guess в группе Columns и, ...о чудо: программа установки сама определит формат полей таблицы. Названия этих полей, взятые из первой строки файла TextBase.txt появятся в списке группы Columns. Последовательно выбитите из этого списка названия всех полей таблицы. В полях Data Type, Name и Width будут отображаться тип, имя и максимальная ширина выбранного поля. В случае необходимости вы можете изменить эти значения.

Поля NAME, ADDRESS и PHONE будут определены как символьные строки, имеющие максимальную длинну 255 символов. Поле PRIORITY будет определено как число Integer.



Если первая строка файла таблицы не содержит имена полей, то переключатель Column Name Header должен быть выключен. Нажмите кнопку Guess в группе Columns. Программа установки определит формат полей таблицы и присвоит им имена F1, F2, F3 и т. д. В последствии вы можете изменить названия полей, изменив их в поле Name и нажав кнопку Modify.

После того, как формат файла определен, вы можете закрыть все диалоговые панели приложения 32bit ODBC. Обратите внимание, что в диалоговой панели Data Source появится еще один источник данных - Address Pad (Microsoft Text Driver (*.txt; *.csv)).

В каталоге TEXTBASE, содержащем файл базы данных TextBase.txt появится еще один файл - schema.ini. Этот файл содержит информацию о таблицах (в нашем случае об единственной таблице) базы данных. В принципе, вы можете изменять характеристики источника данных Address Pad через этот файл, но лучше использовать приложение 32bit ODBC из Control Panel. Для этого запустите приложение 32bit ODBC, выберите из списка имя источника и нажмие кнопку Setup. Откроется панель ODBC Text Setup, через которую можно полностью управлять всеми параметрами базы данных.

Листинг 5.2. Файл schema.ini

[textbase.txt]

ColNameHeader=True

Format=Delimited(;)

MaxScanRows=25

CharacterSet=ANSI

Col1=NAME Char Width 255

Col2=ADDRESS Char Width 255

Col3=PRIORITY Integer

Col4=PHONE Char Width 255


Создание нового класса документа и класса окна просмотра


Создайте два новых класса - класс документа и класс окна отображения для хранения и отображения на экране текстовой информации. Для создания новых классов используйте MFC ClassWizard.

Сначала откройте панель ClassWizard и нажмите кнопку Add Class. Откроется новая диалоговая панель Create New Class. Введите в поле Name имя нового класса - CEditorDoc, а в поле Base Class выберите имя базового класса CDocument. Нажмите кнопку Create. ClassWizard создаст класс CEditorDoc, определение которого он разместит в файле CEditorDoc.h, а реализацию методов класса в файле CEditorDoc.cpp.

Не закрывая ClassWizard, создайте класс окна просмотра текстового документа. Нажмите кнопку Add Class. В поле Name диалоговой панели Create New Class введите имя класса окна просмотра CEditorView, а в поле Base Class выберите имя его базового класса CEditView. Нажмите кнопку Create. ClassWizard создаст класс CEditorView, определение которого он разместит в файле CEditorView.h, а реализацию методов класса в файле CEditorView.cpp.

Теперь вы можете определить, как записывать и считывать текстовый документ из файла на диске. Когда ClassWizard создает для вас класс документа, наследованный от базового класса CDocument, он сразу создает шаблон метода Serialize. К сожалению, этот шаблон придется переделать.

Мы уже изучали класс CEditView в предыдущей книге, посвященной MFC, и вы должны знать, что объекты этого класса сами хранят данные редактируемого документа. Поэтому для записи и чтения документа метод Serialize класса документа должен вызвать соответствующий метод класса окна просмотра. Измените метод Serialize следующим образом:

//////////////////////////////////////////////////////////////

// Метод класса Serialize CEditorDoc

void CEditorDoc::Serialize(CArchive& ar)

{

   ((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);

}

На этом реализация классов для хранения и отображения текстового документа закончена и можно перейти к самому интересному - к созданию шаблона нового документа.



Создание новой панели управления


Выберите из меню Insert строку Resource, а затем из открывшейся диалоговой панели Insert Resource выберите строку Toolbar и нажмите на кнопку OK.

Запустится редактор ресурсов и в нем будет загружена новая панель управления. Создайте панель управления, постепенно добавляя к ней по одной кнопке. Для каждой кнопки нарисуйте ее изображение, а также присвойте ей уникальный идентификатор и строку описания (см. раздел “Редактор панели управления”).

При создании панелей управления руководствуйтесь информацией из файла ресурсов приложения Bar (листинг 3.5) и изображениями кнопок панелей управления (рис. 3.9).

Панель управления приложения Bar должна иметь идентификатор IDR_MAINFRAME. В ней следует расположить девять кнопок с идентификаторами ID_FILE_NEW, ID_FILE_OPEN, ID_FILE_SAVE, ID_EDIT_CUT, ID_EDIT_COPY, ID_EDIT_PASTE, ID_FILE_PRINT, ID_APP_ABOUT и ID_TOOL_EXIT.

Между кнопками ID_FILE_SAVE и ID_EDIT_CUT, ID_EDIT_PASTE и ID_FILE_PRINT, вставьте разделители. Для каждой из кнопок вы также можете ввести их текстовые описания.

Сохраните измененный файл ресурсов.



Создание шаблона текстовых документов


Шаблоны документов, с которыми работает приложение определяют все характеристики данного типа документа. Они включают информацию о классе документа, классе окна просмотра, классе окна рамки, а также о ресурсах, связанных с данным типом документов.

Шаблоны документов создаются объектом приложения во время его инициализации. Откройте метод InitInstance главного класса приложения CMultiApp. В нем создается только один объект класса CMultiDocTemplate, который представляет графический документ и средства для работы с ним.

Так как наше приложение должно работать не только с графическими, но и с текстовыми документами, вы должны создать еще один объект шаблона документов, представляющий текстовый документ. Класс текстового документа называется CEditorDoc, класс окна для его просмотра CEditorView. В качестве окна рамки мы используем класс CChildFrame. Ниже представлен соответствующий фрагмент метода InitInstance:

//////////////////////////////////////////////////////////////

// CMultiApp initialization

BOOL CMultiApp::InitInstance()

{

   // ...

   // Регистрируем шаблоны документов приложения

   CMultiDocTemplate* pDocTemplate;

   pDocTemplate = new CMultiDocTemplate(

      IDR_MULTITYPE,

      RUNTIME_CLASS(CMultiDoc),

      RUNTIME_CLASS(CChildFrame),

      RUNTIME_CLASS(CMultiView));

   AddDocTemplate(pDocTemplate);

   pDocTemplate = new CMultiDocTemplate(

      IDR_EDITORTYPE,

      RUNTIME_CLASS(CEditorDoc),

      RUNTIME_CLASS(CChildFrame),

      RUNTIME_CLASS(CEditorView));

   AddDocTemplate(pDocTemplate);

   // ...

   return TRUE;

}

При создании шаблона документов указывается идентификатор, который определяет меню, пиктограмму и некоторую другую полезную информацию, связанную с документами данного типа. Мы указали для шаблона текстового документа идентификатор IDR_EDITORTYPE. Здесь мы несколько забежали вперед, так как такой идентификатор еще не определен. Мы вернемся к ресурсам текстового документа в следующем разделе.

Чтобы созданный шаблон текстовых документов добавить к списку шаблонов документов приложения, надо вызвать метод AddDocTemplate, указав ему адрес объекта шаблона.



Стандартная библиотека языка Си++


В Microsoft Visual C++ версии 4.2 реализована стандартная библиотека языка Си++. В нее включены всевозможные функции, которые вы теперь можете использовать в своих программах.



Стандартные диалоговые панели


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

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

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

Класс

Описание

CColorDialog

Панель для выбора цвета

CFileDialog

Панель выбора файлов для открытия и сохранения на диске

CFindReplaceDialog

Панель для выполнения операции поиска и замены

CFontDialog

Панель для выбора шрифта

CPrintDialog

Панель для вывода документа на печать

CPageSetupDialog

Панель выбора формата документа

Кроме перечисленных в таблице, существует класс COleDialog, который определяет стандартные панели диалогов, предназначенные для управления технологией OLE. В этой книге мы не рассматриваем программирование OLE и поэтому не будем останавливаться на классе COleDialog.

Рис. 4.1. Классы стандартных диалоговых панелей

Классы, управляющие стандартными диалоговыми панелями, определены в файле afxdlgs.h. Если вы используете в своем приложении эти классы, вы должны включить файл afxdlgs.h в исходные тексты при помощи директивы препроцессора #include:

// Включаемый файл для стандартных диалоговых панелей

#include <afxdlgs.h>

Класс COleDialog и другие классы, которые используются для управления стандартными диалоговыми панелями, связанными с технологией OLE, определены в другом файле - afxodlgs.h.



Таблица акселераторов


Таблица акселераторов IDR_MAINFRAME приложения полностью соответствует таблице акселераторов, добавленной MFC AppWizard к ресурсам приложения с однооконным интерфейсом:
//////////////////////////////////////////////////////////////
// Таблица акселераторов
IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE
BEGIN
   "N",            ID_FILE_NEW,            VIRTKEY,CONTROL
   "O",            ID_FILE_OPEN,           VIRTKEY,CONTROL
   "S",            ID_FILE_SAVE,           VIRTKEY,CONTROL
   "P",            ID_FILE_PRINT,          VIRTKEY,CONTROL
   "Z",            ID_EDIT_UNDO,           VIRTKEY,CONTROL
   "X",            ID_EDIT_CUT,            VIRTKEY,CONTROL
   "C",            ID_EDIT_COPY,           VIRTKEY,CONTROL
   "V",            ID_EDIT_PASTE,          VIRTKEY,CONTROL
   VK_BACK,        ID_EDIT_UNDO,           VIRTKEY,ALT
   VK_DELETE,      ID_EDIT_CUT,            VIRTKEY,SHIFT
   VK_INSERT,      ID_EDIT_COPY,           VIRTKEY,CONTROL
   VK_INSERT,      ID_EDIT_PASTE,          VIRTKEY,SHIFT
   VK_F6,          ID_NEXT_PANE,           VIRTKEY
   VK_F6,          ID_PREV_PANE,           VIRTKEY,SHIFT
END
Мы расскажем вам подробнее о таблице акселераторов в разделе “Таблица акселераторов”. Дополнительную информацию вы сможете получить в 13 томе серии “Библиотека системного программиста”.

Класс CMultiApp может получать сообщения


Класс CMultiApp может получать сообщения и имеет таблицу сообщений. Таблицу сообщений класса CMultiApp расположена в файле Multi.cpp. Она содержит четыре макрокоманды для обработки командных сообщений от меню приложения:
//////////////////////////////////////////////////////////////
// Таблица сообщений класса CMultiApp
BEGIN_MESSAGE_MAP(CMultiApp, CWinApp)
   //{{AFX_MSG_MAP(CMultiApp)
   ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
   //}}AFX_MSG_MAP
   ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
   ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
   ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
Только для одного командного сообщения, имеющего идентификатор ID_APP_ABOUT, вызывается метод обработчик OnAppAbout, определенный в классе CMultiApp. Остальные три командных сообщения ID_FILE_NEW, ID_FILE_OPEN и ID_FILE_PRINT_SETUP передаются для обработки методам класса CWinApp, который является базовым классом для CMultiApp.
Метод-обработчик OnAppAbout вызывается объектом главного класса приложения, когда пользователь выбирает из меню Help строку About. OnAppAbout создает объект класса CAboutDlg, представляющий модальную диалоговую панель About и вызывает для него метод DoModal, отображающий панель на экране (рис. 1.9):
void CMultiApp::OnAppAbout()
{
   CAboutDlg aboutDlg;
   aboutDlg.DoModal();
}

Рис. 1.9. Окно Project Workspace, класс CMainFrame

Таблица сообщений класса CChildFrame


Таблица сообщений класса CChildFrame не содержит обработчиков сообщений:

// Объекты класса CChildFrame создаются динамически

IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)

// Таблица сообщений

BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)

   //{{AFX_MSG_MAP(CChildFrame)

   //}}AFX_MSG_MAP

END_MESSAGE_MAP()



Таблица сообщений класса CDlgBarWindow


Таблица сообщений класса CDlgBarWindow обрабатывает сообщения от диалоговой панели управления. В ней также располагается макрокоманда ON_WM_CREATE, которая вызывает метод OnCreate во время создания окна:

ON_WM_CREATE()

Когда пользователь работает с диалоговой панелью управления, в ее родительское окно поступают сообщения. От кнопок Set и Clear и переключателя Alighn поступают командные сообщения, которые обрабатываются при помощи макрокоманд ON_COMMAND_EX:

// Командные сообщения от кнопок Set и Clear

ON_COMMAND_EX(IDC_BUTTON_SET, DlgBarCommand)

ON_COMMAND_EX(IDC_BUTTON_CLEAR, DlgBarCommand)

ON_COMMAND_EX(IDC_CHECK1, DlgBarCommand)

// Командные сообщения от переключателя Alighn

ON_COMMAND_EX(IDC_RADIO_LEFT, DlgBarCommand)

ON_COMMAND_EX(IDC_RADIO_CENTER, DlgBarCommand)

ON_COMMAND_EX(IDC_RADIO_RIGHT, DlgBarCommand)

Для обработки всех этих командных сообщений вызывается один и тот же метод DlgBarCommand, которому передается идентификатор кнопки или переключателя, вызвавшего сообщение.

От списка combo-box, расположенного в диалоговой панели управления, мы обрабатываем только одно сообщение с кодом извещения CBN_SELCHANGE. Это сообщение передается, когда пользователь выбирает из списка новую строку:

// Командные сообщения от списка combo-box

ON_CBN_SELCHANGE( IDC_COMBO_COLOUR, DlgBarCombo)



Таблица сообщений


Таблица сообщений класса CMainFrame содержит только одну макрокоманду ON_WM_CREATE, которая устанавливает для обработки сообщения WM_CREATE метод OnCreate. Сообщения WM_CREATE приходит во время создания главного окна приложения.
Непосредственно перед таблицей сообщений класса CMainFrame располагается макрокоманда IMPLEMENT_DYNAMIC. Она указывает, что объекты класса CMainFrame могут создаваться динамически во время работы приложения:
// Объекты класса CMainFrame могут создаваться автоматически
IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
// Таблица сообщений
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
   //{{AFX_MSG_MAP(CMainFrame)
   ON_WM_CREATE()
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

Таблица сообщений класса CMultiDoc


Таблица сообщений класса CMultiDoc не содержит ни одного обработчика сообщений:

// Объекты класса CMultiDoc могут создаваться динамически

IMPLEMENT_DYNCREATE(CMultiDoc, CDocument)

// Таблица сообщений класса CMultiDoc

BEGIN_MESSAGE_MAP(CMultiDoc, CDocument)

   //{{AFX_MSG_MAP(CMultiDoc)

   //}}AFX_MSG_MAP

END_MESSAGE_MAP()



Таблица сообщений класса CMultiMenuWindow


Таблица сообщений класса CMultiMenuWindow обрабатывает командные сообщения и команды обновления от меню приложения, а также содержит макрокоманду ON_WM_CREATE.

Макрокоманда ON_WM_CREATE вызывает метод OnCreate во время создания окна:

ON_WM_CREATE()

Для обработки командных сообщений от меню приложения в таблицу сообщений класса CMultiMenuWindow включены шесть макрокоманд ON_COMMAND. Они вызывают обработчики OnDisable, OnConstruct, OnCommand, OnFullMenu, OnRestrictMenu и OnMenuExit:

ON_COMMAND(ID_MENU_DISABLE, OnDisable)

ON_COMMAND(ID_MISSION_CONSTRUCT, OnConstruct)

ON_COMMAND(ID_FILE_EXIT, OnExit)

ON_COMMAND(ID_MISSION_PROCESS, OnCommand)

ON_COMMAND(ID_MENU_RESTRICT, OnRestrictMenu)

ON_COMMAND(ID_MENU_FULL, OnFullMenu)

Для обработки команд обновления в таблицу сообщений класса включены три макрокоманды ON_UPDATE_COMMAND_UI. Они вызывают методы OnUpdateProcess, OnUpdateConstruct и OnUpdateDisable:

ON_UPDATE_COMMAND_UI(ID_MISSION_PROCESS, OnUpdateProcess)

ON_UPDATE_COMMAND_UI(ID_MISSION_CONSTRUCT, OnUpdateConstruct)

ON_UPDATE_COMMAND_UI(ID_MENU_DISABLE, OnUpdateDisable)

Соответствие методов, вызываемых макрокомандами ON_COMMAND и ON_UPDATE_COMMAND_UI, строкам меню приложения вы можете посмотреть в файле ресурсов приложения, представленном в листинге 3.3.



Таблица сообщений класса CMultiView


Таблица сообщений класса CMultiView располагается в файле MultiView.cpp. Непосредственно перед ней расположена макрокоманда IMPLEMENT_DYNCREATE:

// Объекты класса CMultiView создаются динамически

IMPLEMENT_DYNCREATE(CMultiView, CView)

// Таблица сообщений класса CMultiView

BEGIN_MESSAGE_MAP(CMultiView, CView)

   //{{AFX_MSG_MAP(CMultiView)

   //}}AFX_MSG_MAP

   ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)

   ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)

   ON_COMMAND(ID_FILE_PRINT_PREVIEW,

                             CView::OnFilePrintPreview)

END_MESSAGE_MAP()


При добавлении контекстного меню к окну класса CMultiView, в таблицу сообщений класса CMultiView добавляется новая макрокоманда ON_WM_CONTEXTMENU:
//////////////////////////////////////////////////////////////
// Таблица сообщений класса CMultiView
// Объекты класса CMultiView создаются динамически
IMPLEMENT_DYNCREATE(CMultiView, CView)
// Таблица сообщений класса CMultiView. В нее добавлена
// макрокоманда ON_WM_CONTEXTMENU
BEGIN_MESSAGE_MAP(CMultiView, CView)
   ON_WM_CONTEXTMENU()
   //{{AFX_MSG_MAP(CMultiView)
   //}}AFX_MSG_MAP
   // Стандартные команды
   ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
   ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
   ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView::OnFilePrintPreview)
END_MESSAGE_MAP()

Таблица сообщений класса CSplashWnd


Таблица сообщений класса CSplashWnd содержит всего три макрокоманды, которые расположены внутри блока //{{AFX_MSG_MAP и поэтому управляются через ClassWizard:

BEGIN_MESSAGE_MAP(CSplashWnd, CWnd)

   //{{AFX_MSG_MAP(CSplashWnd)

   ON_WM_CREATE()

   ON_WM_PAINT()

   ON_WM_TIMER()

   //}}AFX_MSG_MAP

END_MESSAGE_MAP()

Две макрокоманды таблицы сообщений класса CSplashWnd уже давно вам знакомы. Это макрокоманда ON_WM_CREATE, которая вызывает метод OnCreate во время создания окна заставки (обработка сообщения WM_CREATE), и макрокоманда ON_WM_PAINT, которая вызывает метод OnPaint, когда надо перерисовать окно (обработка сообщения WM_PAINT).

Таблицы сообщений класса CSplashWnd содержит также ранее не описанную нами макрокоманду ON_WM_TIMER. Эта макрокоманда предназначена для обработки сообщений WM_TIMER от таймера и вызывает метод OnTimer.

Первоначально метод OnTimer определен в классе CWnd следующим образом. При вызове метода OnTimer для обработки сообщения WM_TIMER параметр nIDEvent содержит идентификатор таймера, вызвавшего это сообщение:

afx_msg void OnTimer(UINT  nIDEvent);

Для установки (“запуска”) таймера используется метод SetTimer, также входящий в состав класса CWnd. Мы расскажем об этом методе более подробно, когда будем описывать метод OnCreate класса CSplashWnd, так как именно он устанавливает таймер для отображения заставки.



Таблица сообщений класса CStateWindow


Таблица сообщений класса CStateWindow обрабатывает командные сообщения от меню Work, а также содержит макрокоманды ON_UPDATE_COMMAND_UI и ON_WM_CREATE.

Макрокоманда ON_UPDATE_COMMAND_UI вызывает метод OnUpdateTEXT для обновления состояния индикатора ID_INDICATOR_TEXT панели состояния:

ON_UPDATE_COMMAND_UI(ID_INDICATOR_TEXT, OnUpdateTEXT)

Макрокоманда ON_WM_CREATE вызывает метод OnCreate во время создания окна:

ON_WM_CREATE()

Для обработки командных сообщений от меню Work в таблицу сообщений класса CStateWindow включены несколько макрокоманд ON_COMMAND и ON_COMMAND_EX. Они вызывают обработчики OnMenuProcessBar, OnMenuDisableADD_SUB, OnMenuSwitchTEXT, OnMenuDirectADD_SUB и OnMenuExit:

ON_COMMAND(ID_WORK_PROCESS, OnMenuProcessBar)

ON_COMMAND(ID_WORK_DISABLE_ADDSUB, OnMenuDisableADD_SUB)

ON_COMMAND(ID_WORK_ON_SWITCH_TEXT, OnMenuSwitchTEXT)

ON_COMMAND(ID_WORK_EXIT, OnMenuExit)

ON_COMMAND_EX(ID_WORK_DIRECT_ADD, OnMenuDirectADD_SUB)

ON_COMMAND_EX(ID_WORK_DIRECT_SUB, OnMenuDirectADD_SUB)



Ресурсы приложения содержат несколько блоков,


Ресурсы приложения содержат несколько блоков, описывающих таблицы текстовых строк. Эти таблицы практически совпадают с таблицами текстовых строк, включенных MFC AppWizard в ресурсы приложения с однооконным интерфейсом.
Блоки текстовых строк, описывающие тип документов приложения, и основные характеристики главного окна приложения совпадают с соответствующими блоками однооконного приложения, за исключением строки с названием проекта:
//////////////////////////////////////////////////////////////
// Таблица текстовых строк
STRINGTABLE PRELOAD DISCARDABLE
BEGIN
   IDR_MAINFRAME   "Multi"
   IDR_MULTITYPE   "\nMulti\nMulti\n\n\nMulti.Document\nMulti
                    Document"
END
STRINGTABLE PRELOAD DISCARDABLE
BEGIN
   AFX_IDS_APP_TITLE     "Multi"
   AFX_IDS_IDLEMESSAGE   "Ready"
END
Блок текстовых строк, которые используются в панели состояния ststus bar, полностью совпадает с аналогичным блоком в ресурсах однооконного приложения:
STRINGTABLE DISCARDABLE
BEGIN
   ID_INDICATOR_EXT    "EXT"
   ID_INDICATOR_CAPS   "CAP"
   ID_INDICATOR_NUM    "NUM"
   ID_INDICATOR_SCRL   "SCRL"
   ID_INDICATOR_OVR    "OVR"
   ID_INDICATOR_REC    "REC"
END
В блоке текстовых строк, описывающих элементы меню, добавлен ряд текстовых строк, которые относятся к меню Window. Для однооконного приложения эти строки не определены, так как меню Window есть только у многооконных приложений:
STRINGTABLE DISCARDABLE
BEGIN
 ID_FILE_NEW         "Create a new document\nNew"
 ID_FILE_OPEN        "Open an existing document\nOpen"
 ...
 ID_PREV_PANE        "Switch back to the previous window
                      pane\nPrevious Pane"
 ID_WINDOW_NEW       "Open another window for the active
                      document\nNew Window"
 ID_WINDOW_ARRANGE   "Arrange icons at the bottom of the
                      window\nArrange Icons"


 ID_WINDOW_CASCADE   "Arrange windows so they overlap\nCascade
                      Windows"
 ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping
                      tiles\nTile Windows"
 ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping
                      tiles\nTile Windows"
 ID_WINDOW_SPLIT     " Split the active window into panes\nSplit"
 ...
 ID_EDIT_CLEAR       "Erase the selection\nErase"
 ID_VIEW_TOOLBAR     "Show or hide the toolbar\nToggle ToolBar"
 ID_VIEW_STATUS_BAR  "Show or hide the status bar\nToggle StatusBar"
END
По сравнению с ресурсами однооконного приложения, для приложений с многооконным пользовательским интерфейсом, добавлен еще один блок текстовых строк. В нем содержатся строки, имеющие отношение к многооконному интерфейсу приложения:
STRINGTABLE DISCARDABLE
BEGIN
 AFX_IDS_SCSIZE        "Change the window size"
 AFX_IDS_SCMOVE        "Change the window position"
 AFX_IDS_SCMINIMIZE    "Reduce the window to an icon"
 AFX_IDS_SCMAXIMIZE    "Enlarge the window to full size"
 AFX_IDS_SCNEXTWINDOW  "Switch to the next document
                        window"
 AFX_IDS_SCPREVWINDOW  "Switch to the previous document
                        window"
 AFX_IDS_SCCLOSE       "Close the active window and
                        prompts to save the documents"
 AFX_IDS_SCRESTORE     "Restore the window to normal size"
 AFX_IDS_SCTASKLIST    "Activate Task List"
 AFX_IDS_MDICHILD      "Activate this window"
 AFX_IDS_PREVIEW_CLOSE "Close print preview mode\nCancel
                        Preview"
END

Управление компонентами


Сразу после установки среды Microsoft Visual C++ в диалоговой панели Component Gallery отображается две станицы, содержащие компоненты - Microsoft и OLE Controls. Каждая страница представляет разные категории компонентов.

В диалоговой панели Component Gallery вы можете создавать и удалять страницы с компонентами, добавлять и удалять компоненты, перемещать их между категориями, переименовывать и выполнять над ними другие простые действия.

Для управления страницами компонентов и отдельными компонентами достаточно нажать кнопку Customize. Вы сможете выполнить все настройки в открывшейся диалоговой панели Customize Component Gallery.

Вся информация о компонентах и страницах Component Gallery записана в специальной базе данных. Эта база данных расположена в файле gallery.dat, в каталоге Msdev\Template. Если вы случайно удалили нужные компоненты с панели Component Gallery, вы можете восстановить их. Для этого надо удалить файл gallery.dat. Во время очередного запуска Microsoft Visual C++ заново создаст файл gallery.dat и восстановит все компоненты, поставляемые с Visual C++.



Версия приложения


Приложение Multi включает ресурс, описывающий версию приложения.  В этом ресурсе содержится информация о приложении и ее версии, данные о фирме-разработчике, авторские права:

//////////////////////////////////////////////////////////////

// Версия

VS_VERSION_INFO     VERSIONINFO

 FILEVERSION       1,0,0,1

 RODUCTVERSION    1,0,0,1

 ILEFLAGSMASK 0x3fL

#ifdef _DEBUG

   FILEFLAGS 0x1L

#else

   FILEFLAGS 0x0L

#endif

   FILEOS 0x4L

   FILETYPE 0x1L

   FILESUBTYPE 0x0L

BEGIN

   BLOCK "StringFileInfo"

   BEGIN

      BLOCK "040904B0"

      BEGIN

         VALUE "CompanyName", "Solaris\0"

         VALUE "FileDescription", "MULTI MFC Application\0"

         VALUE "FileVersion", "1, 0, 0, 1\0"

         VALUE "InternalName", "MULTI\0"

         VALUE "LegalCopyright",

               "Copyright © 1996 Frolov G.V.\0"

         VALUE "OriginalFilename", "MULTI.EXE\0"

         VALUE "ProductName", "MULTI Application\0"

         VALUE "ProductVersion", "1, 0, 0, 1\0"

      END

   END

   BLOCK "VarFileInfo"

   BEGIN

      VALUE "Translation", 0x409, 1200

   END

END



Виртуальные методы класса CFileDialog


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

 

Метод

Описание

OnShareViolation

Вызывается в случае нарушения прав доступа к файлу

OnFileNameOK

Вызывается для проверки имени файла, введенного в диалоговой панели

OnLBSelChangedNotify

Вызывается при изменении выделения в списке файлов диалоговой панели

OnInitDone

Вызывается для обработки сообщения WM_NOTIFY CDN_INITDONE

OnFileNameChange

Вызывается для обработки сообщения WM_NOTIFY CDN_SELCHANGE

OnFolderChange

Вызывается для обработки сообщения WM_NOTIFY CDN_FOLDERCHANGE

OnTypeChange

Вызывается для обработки сообщения WM_NOTIFY CDN_TYPECHANGE

Прототипы перечисленных выше виртуальных методов вы можете найти в справочной системе Microsoft Visual C++.



Visual C++ и Visual J++


Летом 1996 года Microsoft выпустила тестовую версию нового продукта, получившего название Visual J++. Его название перекликается с названием Visual C++, и можно подумать, что “Жи++” стал приемником Си++. Спешим вас успокоить, Жи++ не предназначен для замены Си++. Это совершенно другой язык программирования, основанный на языке Java, лицензию на который Microsoft приобрела у известной фирмы Sun Microsystems.

Предусмотрена интеграция Visual J++ в уже знакомую вам среду разработчика Microsoft Developer Studio. Более того, можно организовать взаимодействие Visual C++ и Visual J++.



Библиотека системного программиста" мы начали


В 24 томе серии " Библиотека системного программиста" мы начали рассказывать о программировании приложений Windows с использованием библиотек классов MFC. Вы узнали об основных принципах построения приложений MFC и наиболее важных классах. В этом томе мы продолжим изучение библиотеки классов MFC и ее возможностей.
Много внимания будет уделено созданию приложений, имеющих многооконный пользовательский интерфейс, основанный на использовании технологии MDI, основы которой мы уже излагали в предыдущих книгах серии "Библиотека системного программиста". Но теперь мы будем использовать для создания таких приложений не возможности программного интерфейса Windows, а классы библиотеки MFC. Если вы разрабатывали раньше многооконные приложения, то сможете по достоинству оценить насколько библиотека MFC упрощает работу программиста.
Мы создадим многооконное приложение с использованием MFC AppWizard и объясним как оно работает. Одно из преимуществ многооконного приложения - это возможность отображать в различных окнах одного приложения различные представления документов одного и того же типа или даже документы разных типов. Мы приведем пример приложения, которое отображает в своих окнах документы различного типа.
Развитый программный интерфейс операционной Windows значительно помогает программисту в разработке приложений, имеющих сложный пользовательский интерфейс. Создавая приложения Windows, программист избавлен от необходимости вручную рисовать окна, меню, диалоговые панели и т. д. Трудно даже представить, насколько усложнится задача разработки приложения, если вы решите создать программу, имеющую аналогичные возможности в операционной системе MS-DOS.
Когда вы начнете использовать в своих разработках не только функции программного интерфейса Windows (Windows API), но также и библиотеку классов MFC, создание сложных приложений Windows станет еще проще. Теперь в ваших руках будет высокоуровневое средство, включающее в себя функции Windows API.
Библиотека MFC не только служит для простого объединения функций Windows API в классы (например функции управляющие меню, объединяются в один класс, а функции управляющие панелью состояния, - в другой). Библиотека MFC обеспечивает взаимодействие составляющих ее классов, которые вместе нацелены на выполнение определенных задач. Недаром в документации и в дополнительной литературе встречается термин framework (каркас, основа, рабочая среда), употребляемый в отношении совокупности классов MFC и их внутреннему устройству.


Microsoft Visual C++ имеет еще одно средство, позволяющее упростить программисту работу и обеспечить повторное использование кода. Это так называемая галерея компонентов - Component Gallery. В нее входит набор отдельных модулей - компонент, которые программист может включать в свой проект для решения каких-либо задач.
Каждый такой компонент может содержать программный код с ресурсами и предназначается для решения определенных задач. Например, существует компонент, включив который в свой проект, вы получите возможность использовать контекстное меню, затратив минимум усилий для написания собственного программного кода. Можно сказать что компоненты - это готовые решения определенных задач, доступные вам.
Если в своей работе вы создаете классы и ресурсы, которые впоследствии потребуются вам или вашим коллегам, включите их в галерею компонентов, после чего их легко можно будет перенести в другие приложения.
После того, как вы изучите многооконные приложения и возможности использования галереи компонентов, мы рассмотрим средства библиотеки MFC, предназначенные для создания и управления меню, панелями управления и панелями состояния.
Мы также расскажем о старых знакомых - стандартных диалоговых панелях, которые представлены в библиотеки MFC отдельными классами.
В заключении мы покажем как использовать Microsoft Visual C++ и библиотеку классов MFC для доступа к базам данных. На примере мы покажем, как с помощью MFC AppWizard быстро разработать приложение для доступа к базам данных через ODBC драйверы.

Win32s посвящается


Microsoft Visual C++ версии 2.0 и все старшие версии этого продукта не позволяют разрабатывать 16-разрядные приложения для операционных систем Windows 3.хх.

Начиная с версии 4.2, приложения, подготовленные в Microsoft Visual C++ и MFC 4.2, также не будут работать в среде Windows 3.хх с установленной поддержкой 32-разрядных приложений Win32s.

Если вам все же необходимо создать приложение, способное работать в среде Win32s, следует воспользоваться более ранними версиями MFC, например MFC 4.1. К сожалению, в этом случае, последние новшества, введенные в библиотеку MFC 4.2, уже не будут вам доступны.



Заставка для приложения


Многие приложения Windows при запуске отображают на экране временную заставку. В ней, как правило, на фоне рисунка представлены название приложения, номер версии, другая справочная информация. Примером таких приложений могут служить Microsoft Word, Microsoft Excel и другие офисные приложения Microsoft. Microsoft Visual C++ также отображает заставку во время запуска.

С помощью Component Gallry и компонента Splash Screen вы затратите всего нескольких минут, чтобы добавить к приложению заставку.

Откройте проект приложения к которому надо добавить заставку. Выберите на панели Component Gallry из страницы Microsoft, пиктограмму Splash Screen. Затем нажмите кнопку Insert.

На экране появится диалоговая панель Splash Screen (рис. 2.2). В ней вы должны указать ряд характеристик. В поле Class Name отображается имя класса CSplashWnd, который будет отвечать за отображение заставки. Вы можете изменить это имя по своему усмотрению или оставить его без изменения. Во втором поле диалоговой панели - Bitmap resource ID отображается идентификатор изображения bitmap, который будет служить заставкой для приложения. По умолчанию в качестве идентификатора предлагается использовать изображение bitmap с идентификатором IDB_SPLASH.

Рис. 2.2. Диалоговая панель Splash Screen

Компонент Splash Screen добавит к вашему приложению заготовку изображения bitmap с идентификатором IDB_SPLASH. Поэтому вам останется только отредактировать ее на свой вкус. Мы привели уже отредактированное нами изображение IDB_SPLASH на рисунке 2.3.

Рис. 2.3. Изображение IDB_SPLASH

Определение класса CSplashWnd, управляющего окном заставки, и его методы записываются в файлы с именами Splash.cpp и Splash.h. Эти файлы будут размещены в каталоге вместе с остальными исходными файлами приложения. Если вам надо изменить названия данных файлов, нажмите на кнопку Change.

Когда вы заполните диалоговую панель Splash Screen, нажмите на кнопку OK. Начнется процесс встраивания компонента в проект. После его завершения закройте диалоговую панель Component Gallry, для чего нажмите на кнопку Close.

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