    Общие элементы управления 

    В этой главе будет представлена одна из наиболее интересных тем, связанных 
с программированием под Windows, — общие элементы управления. В предыдущих 
главах были рассмотрены стандартные элементы управления, которые 
поддерживаются всеми версиями Windows. Но, начиная с Windows 95, было 
определено несколько новых элементов, названных общими элементами управления, 
которые теперь поддерживаются также в Windows NT и Win32s 1.3. Они дополняют 
стандартные элементы, одновременно обеспечивая больше возможностей и гибкости. 
Общие элементы управления позволяют улучшить интерфейс любого приложения 
Windows, придавая ему более совершенный вид. Все эти новые элементы 
поддерживаются в MFC, начиная с версии 4. 

    237 

    Вот список общих элементов управления (табл. 10.1): 

    Таблица 10.1. Общие элементы управления 

    Элемент                         Описание 

    Окно анимации (Animation control)	Специальное окно, предназначенное для 
отображения AVI-файлов. 
    Заголовок (Header control)	Заголовок столбца таблицы. 
    Горячая клавиша (Hot key control)	Условный элемент, предназначенный для 
поддержки заданных пользователем горячих клавиш. 
    Список изображений (Image list)	Список графических изображений. 
    Список пиктограмм (List view control)	Список пиктограмм и связанных с ними 
текстовых меток. 
    Индикатор состояния (Progress bar)	Визуальный индикатор, отображающий 
степень выполнения определенной задачи. 
    Лист свойств (Property sheet)	Диалоговое окно с отображенным в нем набором 
свойств. Также используется для создания мастеров (wizards). 
    Усложненное поле ввода (Rich edit control)	Поле ввода с расширенными 
возможностями редактирования. 
    Строка (окно) состояния (Status bar, или Status window)	Строка, в которой 
отображается вспомогательная информация, относящаяся к приложению. 
    Закладка (Tab control)	Меню, организованное в виде закладок. 
    Панель инструментов (Toolbar)	Меню, организованное графическим образом в 
виде различных кнопок с изображениями. 
    Всплывающая подсказка (Tooltip)	Небольшое всплывающее поле с текстом. 
Обычно используется для описания кнопок панелей инструментов. 
    
    Регулятор, также называемый ползунком (Trackbar, или Slider control)Окно 
просмотра деревьев (Tree view control)Стрелки, или поле с прокруткой (Up/down 
control, или Spin control)	Элемент, имеющий ползунок. Работает по принципу 
полосы прокрутки, но, в отличие от нее, больше напоминает регулятор тембра в 
стереомагнитофонс.Окно, предназначенное для просмотра древовидных структур 
данных.Элемент, содержащий две кнопки с изображениями стрелок, направленных 
вверх и вниз. Называется полем с прокруткой, если используется совместно с 
полем ввода. 
    Эти элементы называются общими, поскольку представляют широкий набор 
элементов управления, используемых многими приложениями. Вы наверняка 
сталкивались с некоторыми (если не со всеми) из них, если работали с новыми 
версиями . Windows,                                                            

    238                                    MFC: основы программирования j 

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

    Подключение и инициализация общих элементов управления 

    Для работы с общими элементами управления в программу должен быть включен 
стандартный библиотечный файл AFXCMN.H. Необходимо также проверить, чтобы 
одновременно с программой компоновалась библиотека общих элементов управления 
(называющаяся COMCTL32.LIB). Как правило, она автоматически включается в 
MFC-программу, но различные компиляторы могут вести себя по-разному. 
    В приложении, в котором используются какие-либо общие элементы управления, 
перед первым обращением к ним должна вызываться API-функция 
InitCommonControls(). Она проверяет, загружена ли специальная динамическая 
библиотека (DLL) и инициализирована ли подсистема общих элементов управления. 
Прототип этой функции таков: 

    void InitCommonControls() ; 

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

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

    Наиболее распространенным из общих элементов управления является, 
наверное, панель инструментов. Это, по сути, графическое меню, в котором все 
элементы представлены в виде кнопок с различными графическими изображениями. 
Чаще всего панель инструментов используется совместно со стандартным меню, 
предлагая, фактически, альтернативный способ выбора его элементов. В MFC 
панели инструментов описываются классом CToolBarCtrl. 

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

    Для создания панели инструментов необходимо сначала объявить объект типа 
CToolBarCtrl, а затем вызвать функцию CreateQ. Ее прототип таков: 
    BOOL CToolBarCtrl::Create(DWORD duStyle, const RECT &SizePos, CWnd *0wner, 
UINT ID} ; 

    10. Общие элементы управления                                   239 

    Стиль панели инструментов определяется параметром dwStyle. Он обязательно 
должен включать константу WS_CHILD. Могут также указываться и другие 
стандартные стили, такие как WS_BORDER или WS_VISIBLE. Кроме того, имеется два 
специальных стиля, которые предназначены для панелей инструментов. Один из них 
TBSTYLE_TOOLTIPS. При задании такого стиля будут использоваться всплывающие 
подсказки. (О них речь пойдет позднее.) Вторым стилем является 
TBSTYLE_WRAPABLE. Задание этого стиля означает, что чересчур длинные панели 
инструментов будут автоматически переходить на другую строку. Можно также 
указывать следующие стили, относящиеся к общим элементам управления (табл. 10.2): 

    Таблица 10.2. Стили панелей инструментов 

    Стиль	Эффект 

    CCSADJUSTABLE	Положение панели инструментов может изменяться 
    пользователем 
    CCSBOTTOM	Панель инструментов располагается внизу родитель 
    ского окна 
    CCSNODIVIDER	Между панелью инструментов и родительским окном нет 
разделительной линии 
    CCSJMOHILITE	Панель инструментов не выделяется цветом при ак 
    тивизации 
    CCSNOMOVEY	Панель инструментов не может быть растянута по 
    вертикали 
    CCSNORESIZE	Размер и позиция панели инструментов фиксированы 
    CCSTOP	Панель инструментов располагается вверху родительского окна (это 
установка по умолчанию) 

    Обычно значение параметра SizePos игнорируется. Но при задании стиля | 
CCS_NORESIZE для панели инструментов будут использованы фиксированные к 
значения размера и позиции, указываемые в параметре SizePos. По умолчанию 
панель | инструментов располагается вверху родительского окна, а ее размер 
автоматически подгоняется под размеры окна. 
    Указатель на объект родительского окна передается в параметре Owner. 
Идентификатор панели инструментов указывается в параметре ID. Функция CreateQ 
возвращает ненулевое значение при успешном завершении и ноль — в противном случае. 
    Панель инструментов, созданная после вызова функции CreateQ, не 
инициализирована и еще не может быть использована. Для этого необходимо 
выполнить два дополнительных действия. Во-первых, в панель должны быть 
добавлены кнопки. Во-вторых, для каждой из них должно быть задано свое 
изображение. Кроме того, с каждым изображением может быть связана своя 
текстовая метка, но это делается редко, так как они занимают дополнительное 
место, поэтому лучше для подобных целей использовать всплывающие подсказки. 

    240                                     MFC: основы программирования 


    Добавление кнопок в панель инструментов 

    Кнопки добавляются в панель инструментов путем вызова функции 
AddButtoiisQ, которая имеет следующий прототип: 

    BOOL CToolBarCtrl::AddButtons(int Num, LPTBBUTTON IpButtons}; 

    Здесь параметр Num определяет количество кнопок, которые будут добавлены в 
панель инструментов. Параметр IpButtons является указателем на массив структур 
типа TBBUTTON, описывающих данные кнопки. Функция возвращает ненулевое 
значение при успешном завершении и ноль — в противном случае. 
    Каждая структура TBBUTTON, содержащаяся в массиве, на который указывает 
параметр IpButtons, определяет одну из кнопок панели. Таким образом, размер 
массива должен соответствовать количеству кнопок. Структура TBBUTTON 
определена следующим образом: 

    typedef struct _TBBUTTON ( 
    int iBitmap; 
    int idCommand; 
    BYTE fsState 
    BYTE fsStyle 
    DWORD dwData 
    int iString; 
    } TBBUTTON; 

    В поле iBitmap содержится индекс изображения, связанного с кнопкой. 
Индексация кнопок в массиве ведется с нуля, а сами кнопки отображаются слева направо. 
    Идентификатор кнопки хранится в поле idCommand. При каждом нажатии кнопки 
родительскому окну будет посылаться сообщение WM_COMMAND, включающее в себя 
идентификатор нажатой кнопки. Обычно данные сообщения обрабатываются так же, 
как и сообщения меню. 
    Начальное состояние кнопки хранится в поле fsState. Значением поля может 
быть какая-либо из следующих констант (одна или несколько) (табл. 10.3): 

    Таблица 10.3. Значения поля fsState 

    КонстантаTBSTATECHECKED TBSTATEENABLE TBSTATEHIDDEN TBSTATEJNDETERMINATE 
TBSTATEPRESSED TBSTATEWRAP	Состояние кнопкиКнопка нажата Кнопка активна и 
может быть нажата Кнопка скрыта и неактивна Кнопка выделена серым цветом и 
неактивна Кнопка нажатаКнопки, следующие за этой, будут располагаться с новой строки 
    Стиль кнопки содержится в поле fsStyle. Значением поля может быть 
комбинация из следующих констант (табл. 10.4): 

    10 Общир элемента" управления                                   241 


    Таблица 10.4. Стили кнопок 

   Константа Стиль кнопки

TBSTYLEBUTTON 
TBSTYLECHECK
TBSTYLECHECKGROUP 
TBSTYLEGROUP 
TBSTYLESEP	

Стандартная кнопка
Состояние кнопки меняется с нажатого на отпущенное, и наоборот, при 
каждом нажатии кнопки (переключаемая кнопка)
Переключаемая кнопка, входящая в группу кнопок, из которых только одна может 
быть в нажатом положении
Стандартная кнопка, входящая в группу кнопок, из которых только одна 
может быть в нажатом положенииКнопка-разделитель (в этом случае значением поля 
idConiniand должен быть ноль) 

    Обратите внимание на стиль TBSTYLE_SEP. При задании данного стиля кнопки 
панели инструментов будут разделены между собой небольшими промежутками. Это 
позволяет визуально объединять кнопки в группы. 
    В поле dwData содержится информация, определяемая пользователем. Поле 
iString содержит индекс возможной текстовой метки, связанной с кнопкой. 
Значением этих полей должен быть ноль, если они не используются. 

    Добавление изображений к кнопкам 

    Когда кнопки добавлены в панель инструментов, необходимо каждой из них 
присвоить соответствующее изображение. Для этого предназначена функция 
AddBitrnap0> имеющая такой прототип: 

    int CToolBarCtrl::AddBitmap(int Num, UINT BitmapID) ; 

    Здесь параметр Num определяет количество добавляемых изображений. В 
параметре Bitmap JD передается идентификатор ресурса того изображения, которое 
содержит все изображения кнопок. Есть перегруженная версия этой функции, в 
которой в качестве второго параметра разрешено передавать указатель на объект 
типа CBitniap. В некоторых случаях это может быть очень удобно. Функция 
возвращает индекс первого изображения или -1 при возникновении ошибки. 
    Для создания изображений кнопок обычно используется графический редактор. 
Данный процесс мало чем отличается от создания пиктограмм или курсоров 
(описано в главе 7). Стандартный размер изображения кнопки панели инструментов 
16х15 (т.е. ширина 16 пикселей и высота 15 пикселей). Это хорошо согласуется с 
размерами стандартной кнопки (24х22). 
    Еще раз напомним: с панелью инструментов может быть связано только одно 
изображение, и оно должно содержать изображения всех кнопок панели. Таким 
образом, если в панели шесть кнопок, то в изображение, связанное с данной 
панелью, должны быть включены шесть изображений. Например, если каждое 
изображение для кнопок имеет размеры 16х15 и в панели шесть кнопок, то размер 
всего изображения должен быть 96х15. 

    242                                     MFC: основы программирования 

    В примерах данной главы панель инструментов содержит пять кнопок. 
Изображение каждой кнопки должно иметь размер 16х15. Это означает, что 
необходимо создать общее изображение размером 80х15 (рис. 10.1). Оно должно 
быть названо TOOLBAR.BMP. Панель инструментов будет использоваться как 
альтернатива меню для программы работы с графикой из предыдущей главы. 

    Рис. 10.1. Изображение кнопок панели в процессе редактирования 


    Изменение размера панели инструментов 

    Когда панель инструментов инициализирована, ее размеры устанавливаются 
соответственно текущим размерам родительского окна. Но если размер этого окна 
изменить, то размер панели инструментов автоматически изменен не будет. Особых 
неприятностей это не причиняет, но при увеличении окна панель инструментов 
может оказаться слишком маленькой. Решить данную проблему довольно легко. 
Каждый раз при изменении размеров главного окна в программе должна вызываться 
функция AutoSizeQ, имеющая такой прототип: 

    void CToolBarCtrl::AutoSize(); 

    Эта функция автоматически устанавливает размеры панели инструментов 
соответственно размерам его родительского окна. 
    Поскольку в программах часто требуется изменять размеры панели 
инструментов, нужно как-то узнавать, когда такая необходимость возникает. К 
счастью, это также очень легко. Каждый раз при изменении размеров главного 
окна программе посылается сообщение WM_SIZE. До сих пор нам не приходилось 
явно на него отвечать, поскольку изменение размеров автоматически 
обрабатывается Windows. Но каждая программа, содержащая панель инструментов, 
может отвечать на это сообщение изменением размеров панели. Сообщение WMJSIZE 
обрабатывается стандартным обработчиком OnSizeQ, прототип которого таков: 

    afx msq void OnSize(UINT What, int Width, int Height); 

    Если реакцией на данное сообщение будет лишь изменение размеров панели 
инструментов, то все параметры функции можно проигнорировать. Но поскольку 
ситуации могут быть разные, на всякий случай приведем описание параметров функции: 
    • параметры Width и Height содержат новые размеры рабочей области окна; 
    • параметр What указывает на то, при каких обстоятельствах произошло 
изменение размеров окна. 

    10. Общие элементы управления                                    243 

    Параметр What может принимать одно из следующих значений (табл. 10.5): 

    Таблица 10.5. Значения параметра What 

    Значение Причина 

    SIZE_RESTORED Размеры окна изменены пользователем 
    SIZE_MAXIMIZED Окно было раскрыто на весь экран 
    SIZE_MINIM1ZED Окно было минимизировано 
    SIZE_MAXH1DE Другое окно было раскрыто на весь экран 
    SIZE_MAXSHOW Было активизировано другое окно 

    Как уже говорилось, если реакцией на сообщение WM_PAINT должно быть лишь 
изменение размеров панели инструментов, то ни один из параметров 
функции-обработчика не потребуется. В примерах данной главы тело данного 
обработчика состоит из одного вызова функции AutoSizeQ. 

    Дополнительные функции класса CToolBarCtrl 

    Панели инструментов являются полностью автоматизированными элементами 
управления. Но в класс CToolBarCtrl включено также несколько функций, 
позволяющих управлять такими панелями программным путем. 
    Состояние кнопки панели (нажато/отпущено) можно изменять с помощью функции 
PressBiittonQ. Ее прототип таков: 

    BOOL CToolBarCtrl::PressButton(int ID, BOOL Pressed =TRUE); 

    Здесь параметр ID является идентификатором кнопки. Если параметр Pressed 
не равен нулю, то кнопка будет нажата, иначе — вернется в нормальное 
состояние. Функция возвращает ненулевое значение при успешном завершении и 
ноль — в противном случае. 
    Сходную роль выполняет функция CheckButtonQ, прототип которой таков: 

    BOOL CToolBarCtrl::CheckButton(int ID, BOOL Checked=TRUE) ; 

    Значение параметров функции и возвращаемый ею результат такие же, как и в 
предыдущем случае. 
    Чтобы сделать кнопку невидимой, необходимо вызвать функцию HideButtonQ. Ее 
прототип таков: 

    BOOL CToolBarCtrl::HideButton(int ID, BOOL Hldden=TRUE); 

    Здесь, как и ранее, параметр ID является идентификатором кнопки. Если 
параметр Hidden не равен нулю, то кнопка станет невидимой, в противном случае 
кнопка вновь появится на экране. При успешном завершении функция также 
возвращает ненулевое значение, а при возникновении ошибки — ноль. 
    Чтобы сделать кнопку активной или неактивной, необходимо вызвать функцию 
Enal)leBiitton(), которая имеет следующий прототип: 

    BOOL CToolBarCtrl::EnableButton(int ID, BOOL EnabledvTRUE); 


    244                                    MFC: основы программирования 

    Здесь параметр ID также является идентификатором кнопки. Если параметр 
Enabledне равен нулю, то кнопка станет активной. Это означает, что она может 
быть нажата пользователем. Если же данный параметр равен нулю, то кнопка 
станет неактивной и нажать ее будет нельзя. Функция возвращает ненулевое 
значение при успешном завершении и ноль — в противном случае. 

    Пример работы с панелью инструментов 

    В следующем примере к программе из предыдущей главы будет добавлена панель 
инструментов, которая дублирует команды меню. С ее помощью можно вызывать 
отображение линий, прямоугольников и эллипсов. Кроме того, можно очищать окно 
и вызывать систему помощи (Help). В программе обрабатывается сообщение 
WM_SIZE, при получении которого изменяется размер панели инструментов. 
Программа позволяет также сделать панель невидимой, а затем снова вывести ее 
на экран. 
    Вот текст файла ресурсов программы: 

    ; TOOLBAR.RC 
    ^include <afxres.h> ^include "ids.h" 
    IDTB_BMP BITMAP "toolbar.bmp" 
    ToolbarMenu MENU ( 
    POPUP "Draw" ( 
    MENUITEM "&Lines\tF2", IDM_LINES 
    MENUITEM "SRectangles\tF3", IDM_RECTANGLES 
    MENUITEM "&Ellipses\tF4", IDM_ELLIPSES 
    MENUITEM "&Reset\tF5", IDM_RESET 
    } 
    POPUP "Options" 
    ( 
    MENUITEM "SShow Toolbar\tF6", IDM_SHOWTB 
    MENUITEM "SHide Toolbar\tF7", IDM_HIDETB 
    MENUITEM "E&xit\tF8", IDM_EXIT 
    ) 
    MENUITEM "SHelp", IDM_HELP 
    I 
    ToolbarMenu ACCELERATORS 
    ( 
    VK_F2, IDM_LINES, VIRTKEY 
    VK_F3, IDM_RECTANGLES, VIRTKEY 
    VK_F4, IDM_ELLIPSES, VIRTKEY 
    VK_F5, IDM_RESET, VIRTKEY 
    VK_F6, IDM_SHOWTB, VIRTKEY 
    VK_F7, IDM_HIDETB, VIRTKEY 


    10. Общие элементы управления                                   245 


    VK_F8, IDM_EXIT, VIRTKEY 
    VK_F1, IDM__HELP, VIRTKEY 
    } 
    Вот текст библиотечного файла IDS.H: 
    // IDS.H 
    #define IDM_LINES       100 
    #define IDM_RECTANGLES 101 
    ftdefine IDM_ELLIPSES    102 
    ^define IDM_ENLARGE     103 
    #define IDM_ORG         104 
    #define IDM_RESET       105 
    #define IDM_SHOWTB      106 
    ^define IDM_HIDETB      107 
    ^define IDM_EXIT        108 
    ftdefine IDM_HELP        109 
    #define ID_TB           200 
    #define IDTB_BMP        300 
    ftdefine NUMBUTTONS      б 
    Это текст файла TOOLBAR. H, содержащего объявления порождаемых классов: 
    // TOOLBAR.H 
    ^include "ids.h" 
    // Это класс для создания главного окна 
    class CMainHin : public CFrameWnd 
    { 
    CDC m memDC; // контекст устройства, связанный с 
    // виртуальным окном 
    CBitmap m bmp; // образ виртуального окна 
    CBrush m_bkbrush; // кисть для виртуального окна 
    // объявление перьев 
    CPen m RedPen, m YellowPen, m GreenPen, m BluePen; 
    CPen m_01dPen; 
    CToolBarCtrl m_TB; // объект панели инструментов 
    public: 
    CMainHin() ; 
    afx_msg void OnPaint();                                            , 
    afx_msg void OnSize(UINT How, int Width, int Height);              ' 
    afx msg void OnLinesO;                                            | 
    afx_msg void OnRectangles();                                       ! 


    246                                    MFC: основы программирования 


    afx msg void OnEllipses(); 
    afx msg void OnResetO; 
    afx_msg void OnShowTBO; 
    afx_msg void OnHideTBQ; 
    afx msq void OnExit(); 
    afx msg void OnHeipO; 
    void InitToolbar() ; 
    DECLARE_MESSAGE_MAP() 
    ); 
    // Это класс для создания приложения 
    class CApp : public CWinApp 
    ( 
    public: 
    BOOL Initlnstance () ; 
    }; 
    Это текст самой программы: 
    // Работа с панелью инструментов 
    #include <afxwin.h> 
    #include <afxcmn.h> 
    ^include "toolbar.h" 
    Hnclude "ids.h" 
    int maxX, maxY; // размеры экрана 
    CMainWin::CMainWin() 
    ( 
    Create (NULL, "Using a Toolbar", 
    WS_OVERLAPPEDWINDOW, rectDefault, 
    NULL, "ToolbarMenu") ; 
    // Загрузка таблицы быстрого доступа 
    if(!LoadAccelTable("ToolbarMenu")) 
    MessageBox ("Cannot Load Accelerators", "Error"); 
    maxX = GetSystemMetrics(SM_CXSCREEN) ; 
    maxY = GetSystemMetrics(SM_CYSCREEN) ; 
    CClientDC DC(this) ; 
    // создание образа виртуального окна 
    m_memDC.CreateCompatibleDC(&DC) ; 
    m_bmp.CreateCompatibleBitmap(&DC, maxX, maxY) ; 
    m_memDC.SelectObject(&m_bmp) ; 
    // выбор стандартного фона 
    m_bkbrush.Create3tockObject(WHITE_BRUSH) ; 


    10. Общие элементы управления                                   247 


    m_memDC.Select0bject(&m bkbrush); 
    // закраска фона виртуального окна 
    m_memDC.PatBlt(0, 0, maxX, maxY, PATCOPY); 
    // создание перьев 
    m_RedPen.CreatePen(PS_SOLID, 1, RGB (255, 0, 0) ) ; 
    m_GreenPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0) ) ; 
    m_BluePen.CreatePen(PS_SOLID, 3, RGB(О, О, 255)); 
    m_YellowPen.CreatePen(PS_SOLID, 4, RGB(255, 255, 0)) ; 
    m__01dPen.CreateStockObject(BLACK_PEN) ; 
    InitCoinmonControls () ; 
    InitToolbar () ; 
    ) 
    // Инициализация приложения 
    BOOL CApp::Initlnstance() 
    { 
    m_pMainWnd = new CMainWin; 
    m pMainWnd->ShowWindow(m nCmdShow); 
    m_pMainWnd->UpdateWindow() ; 
    return TRUE; 
    ) 
    // Это очередь сообщений приложения 
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    ON_WM_PAINT() 
    ON_WM_SIZE () 
    ON_COMMAND(IDM_LINES, OnLines) 
    ON_COMMAND(IDM_RECTANGLES, OnRectangles) 
    ON_COMMAND(IDM_ELLIPSES, OnEllipses) 
    ON_COMMAND(IDM_RESET, OnReset) 
    ON_COMMAND(IDM_SHOWTB, OnShowTB) 
    ON_COMMAND(IDM_HIDETB, OnHideTB) 
    ON_COMMAND(IDM_EXIT, OnExit) 
    ON_COMMAND(IDM_HELP, OnHelp) 
    END_MESSAGE_MAP() 
    // Вывод на экран содержимого виртуального окна 
    afx msg void CMainWin::OnPaint() 
    < 
    CPaintDC DC(this) ; 
    DC.BitBlt(0, 0, maxX, maxY, &m_memDC, О, О, SRCCOPY) ; 
    } 
    // Изменение размера панели инструментов 
    afx_msg void CMainWin::OnSize(UINT How, int Width, int Height) 
    { 
    m_TB.AutoSize() ; 
    } 


    248                                     MFC: основы программирования 


    // Обработка сообщения IDM_EXIT 
    afx msg void CMainWin::OnExit() 
    int response; 
    response = MessageBox("Quit the Program?", "Exit", MB YESNO); 
    if(response == IDYES) 
    SendMessage(WM_CLOSE); // завершение приложения 
    ) 
    // Обработка сообщения IDM_HELP 
    afx msq void CMainWin::OnHelp () 
    ( 
    m_TB.PressButton(IDM_HELP, TRUE) ; 
    MessageBox("Toolbar Demo", "Help"); 
    m_TB.PressButton(IDM_HELP, FALSE) ; 
    ) 
    // Отображение линий и точек 
    afx msg void CMainWin::OnLines() f 
    //отображение четырех точек 
    m_memDC.SetPixel(40, 14, RGB(255, 0, 0) ) ; 
    m_memDC.SetPixel (41, 14, RGB(0, 255, 0)); 
    m_memDC.SetPixel(42, 14, RGB(0, 0, 255)); 
    m__memDC.SetPixel(43, 14, RGB(0, 0, 0) ) ; 
    m_memDC.LineTo(100, 50); 
    m_memDC.MoveTo(100, 50); 
    // изменение цвета пера на зеленое 
    m_memDC.SelectObject(&m_GreenPen) ; 
    m_memDC.LineTo(200, 100); 
    // изменение цвета пера на желтое 
    m_memDC.SelectObject(&m_YellowPen) ; 
    m_memDC.LineTo(0, 200); 
    // изменение цвета пера на синее 
    m_memDC.SelectObject(&m_BluePen) ; 
    m_memDC.LineTo(200, 200); 
    // изменение цвета пера на красное 
    m_memDC.SelectObject(&m_RedPen) ; 
    m_memDC.LineTo(0, 0) ; 
    m_memDC.LineTo(100, 150); 
    m_memDC.MoveTo(0, 0) ; 
    m_memDC.LineTo(100, 250); 
    m_memDC.MoveTo(0, 0) ; 
    m_memDC.LineTo(100, 350); 


    10. Общие элементы управления                                   249 


    // восстановление первоначальной кисти 
    m_memDC.SelectObject(&m_01dPen) ; 
    m_memDC.Arc(0, 0, 300, 300, 0, 50, 200, 0) ; 
    //отображение пересекающихся линий, которые определяют дугу 
    m_memDC.MoveTo(150, 150); 
    m_memDC.LineTo(0, 50); 
    m_memDC.MoveTo (150, 150); 
    m_memDC.LineTo(200, 0); 
    InvalidateRect(NULL) ; 
    } 
    // Отображение прямоугольников 
    afx_msg void CMainWin::OnRectangles () 
    ( 
    CBrush HollowBrush; 
    // создание "пустого" заполнения 
    HollowBrush.CreateStockObject(HOLLOW_BRUSH) ; 
    m_memDC.SelectObject(&HollowBrush) ; 
    // отображение нескольких прямоугольников                         i 
    m_memDC.Rectangle (50, 50, 300, 300);                              i 
    m_memDC.RoundRect(125, 125, 220, 240, 15, 13); 
    // использование красного пера 
    m_memDC.SelectObject(&m_RedPen);                                   j 
    rn_memDC.Rectangle(100, 100, 200, 200); 
    m_memDC.SelectObject(&m_01dPen); // восстановление прежнего перс 
    // восстановление прежней кисти 
    m_memDC.SelectObject(&m_bkBrush) ; 
    InvalidateRect(NULL);                                              j 
    ) 
    // Отображение эллипсов 
    afx_msg void CMainWin::OnEllipses () 
    ( 
    CBrush Brush; 
    // создание синей кисти 
    Brush.CreateSolidBrush(RGB(0, 0, 255)); 
    m_memDC.SelectObject(SBrush) ; 
    // отображение эллипсов, заполненных синим цветом 
    m_memDC.Ellipse(50, 200, 100, 280); 
    m_memDC.Ellipse(75, 25, 280, 100); 
    // использование красного пера 
    m_memDC.SelectObject(&m_RedPen) ; 


    250                                     MFC: основы программировании 


    // создание зеленой кисти 
    Brush.DeleteObject(); // удаление синей кисти 
    Brush.CreateSolidBrush(RGB(0, 255, 0)) ; 
    m_meniDC . SelectObject ( SBrush) ; // выбор зеленой кисти 
    m_memDC.Ellipse (100, 100, 200, 200); 
    // отображение сектора 
    m_memDC.Pie(200, 200, 340, 340, 225, 200, 200, 250); 
    m_memDC.SelectObject(&m_01dPen); // восстановление прежнего пера 
    m meniDC.SelectObject(&m bkBrush); // восстановление прежней кисти 
    InvalidateRect(NULL) ; 
    ) 
    // Очистка окна 
    afx msg void CMainWin::OnReset() 
    ( 
    m_memDC.PatBlt(0, 0, maxX, maxY, PATCOPY); 
    InvalidateRect(NULL) ; 
    1 
    // Отображение панели инструментов 
    afx_msg void CMainWin::OnShowTB() 
    ( 
    m_TB.ShowWindow(SW_RESTORE) ; 
    ) 
    // Удаление панели инструментов с экрана 
    afx_msg void CMainWin::OnHideTB() 
    ( 
    m_TB.ShowWindow(SW_HIDE) ; 
    } 
    // Инициализация панели инструментов 
    void CMainWin::InitToolbar() 
    ( 
    RECT r; 
    TBBUTTON tbButtons[NUMBUTTONS] ; 
    r.left = r.top = r.right = r.bottom = 0; 
    m_TB.Create(MS_VISIBLE | WS_CHILD | WS_BORDER, r, this, ID_TB) ; 
    tbButtons[0].iBitmap = 0; 
    tbButtons[0].idCommand = IDM_LINES; 
    tbButtons[0].fsState = TBSTATE_ENABLED; 
    tbButtons[0].fsStyle = TBSTYLE_BUTTON; 
    tbButtons[0].dwData = 0; 
    tbButtons[0].iString = 0; 


    10. Общие элементы управления                                   25 1 


    tbButtons[1].iBitmap = 1; 
    tbButtons [1].idCommand = IDM_RECTANGLES; 
    tbButtons[1].fsState = TBSTATE_ENABLED; 
    tbButtons [1].fsStyle = TBSTYLE_BUTTON; 
    tbButtons [1].dwData = 0; 
    tbButtons[1].iString = 0; 
    tbButtons[2].iBitmap = 2; 
    tbButtons[2].idCommand = IDM_ELLIPSES; 
    tbButtons[2].fsState = TBSTATE_ENABLED; 
    tbButtons[2].fsStyle = TBSTYLE_BUTTON; 
    tbButtons[2].dwData = 0; 
    tbButtons[2].iString = 0; 
    tbButtons[3].iBitmap = 3; 
    tbButtons[3].idCommand = IDM_RESET; 
    tbButtons[3].fsState = TBSTATE_ENABLED; 
    tbButtons[3].fsStyle = TBSTYLE_BUTTON; 
    tbButtons[3].dwData = 0; 
    tbButtons[3].iString = 0; 
    // кнопка-разделитель 
    tbButtons[4].iBitmap = 0; 
    tbButtons[4].idCommand = 0; 
    tbButtons[4].fsState = TBSTATE_ENABLED; 
    tbButtons[4].fsStyle = TBSTYLE_SEP; 
    tbButtons[4].dwData = 0; 
    tbButtons[4].iString = 0; 
    tbButtons[5].iBitmap = 4; 
    tbButtons[5].idCommand = IDM_HELP; 
    tbButtons[5].fsState = TBSTATE_ENABLED; 
    tbButtons[5].fsStyle = TBSTYLE_BUTTON; 
    tbButtons[5].dwData = 0; 
    tbButtons[5].iString = 0; 
    m_TB.AddButtons(NUMBUTTONS, tbButtons) ; 
    m_TB.AddBitmap(NUMBUTTONS, IDTB_BMP);                              ! 
    } 
    CApp App; // создание экземпляра приложения 

    Программа, как видите, довольно проста. Приведем ее краткое описание. (Та 
часть программы, которая не связана с работой с панелью инструментов, была 
рассмотрена в предыдущей главе.) Панель инструментов описывается объектом 
т_ТВ, который является членом класса CMainWin. В конструкторе CMainWinQ 
размещен вызов функции InitCommonControls(), за которым следует вызов функции 
InitToolbarO. Внутри этой функции происходит инициализация панели 
инструментов. Информация, относящаяся к панели, содержится в массиве 
tbButtons. Заметьте, что пятая структура массива описывает простую 
кнопку-разделитель. После инициализации массива кнопки добавляются в панель 
инструментов путем вызова функции 

    252                                     MFC: основы программирование 

    AddButtons(). Вслед за этим с помощью функции AddBidnapO к кнопкам 
добавляются соответствующие изображения. 
    Каждая кнопка в панели инструментов соответствует определенной команде 
главного меню. В частности, с каждой кнопкой (кроме кнопки-разделителя) связан 
идентификатор соответствующего элемента меню. При нажатии кнопки программе 
посылается сообщение WM_COMMAND, частью которого является идентификатор 
кнопки, как если бы была выбрана команда меню. Фактически, одна и та же 
функция обрабатывает и нажатие кнопки панели инструментов, и выбор элемента меню. 
    Поскольку панель инструментов является окном, она может быть отображена на 
экране или скрыта, как и любое окно, с помощью функции ShowWindowQ. Чтобы 
сделать панель невидимой, выберите в меню Options команду Hide Toolbar. Чтобы 
затем снова отобразить панель, выберите в том же меню команду Show Toolbar. 
Так как панель инструментов перекрывает часть рабочей области окна, нужно 
всегда предоставлять пользователю возможность скрывать панель, если в ней нет 
необходимости. Как видно из программы, это очень легко сделать. 
    В программе есть один весьма интересный момент. Обратите внимание на текст 
функции OnHelpO. Как можно заметить, при выборе команды Help (через главное 
меню или панель инструментов) кнопка Help панели инструментов нажимается 
программным путем с помощью 4)ункции PressButton(). Когда пользователь 
закрывает диалоговое окно помощи, эта кнопка программно "отпускается" — также 
с помощью функции PressButtoiiQ. Таким образом, кнопка Help остается нажатой 
все время, пока на экране находится диалоговое окно помощи. Это иллюстрирует 
возможность программного управления панелью инструментов при возникновении 
такой необходимости. 
    Пример работы программы показан на рис. 10.2. 

    Рис. 10.2. Пример работы с панелью инструментов 

    10. Общие элементы управления                                         253 


    Создание всплывающих подсказок 

    При работе в Windows вам, вероятно, приходилось видеть, как в некоторых 
панелях инструментов при попадании курсора мыши на одну из кнопок появляется 
небольшое текстовое окошко. Такие окошки называются всплывающими подсказками. 
Они не являются обязательно необходимыми с технической точки зрения, но 
современный подход к построению интерфейса пользователя требует их наличия. 
(Кроме того, они гораздо лучше, чем текстовые метки, связанные с каждой 
кнопкой.) В данном параграфе мы рассмотрим, каким образом добавить такие 
подсказки к созданной ранее панели инструментов. 
    В первую очередь необходимо при создании панели инструментов в качестве 
стиля задать значение TBSTYLE_TOOLTIPS. Это указывает на то, что программе 
должно быть послано сообщение WM_NOTIFY, если курсор мыши задерживается над 
одной из кнопок панели более чем на полсекунды. Данное сообщение можно 
обрабатывать двумя способами: либо с помощью макрокоманды ON_NOTIFY(), либо с 
помощью макрокоманды ON_NOTIFY_RANGE(). Второй способ рекомендуется фирмой 
Microsoft, поэтому мы будем придерживаться именно его. 
    Применительно к всплывающим подсказкам макрокоманда ON_NOTIFV_RANGE() 
имеет следующий вид: 

    ON_NOTIFY_RANGE(TTN_NEEDTEXT, First, Last, TTipHandler) 

    Здесь TTN_NEEDTEXT — это идентификационный код сообщения WM_NOTIFY, 
которое посылается, если необходимо отобразить окошко подсказки. Параметры 
First и Last определяют диапазон значений иденти4)икаторов, которые будут 
связаны с данным сообщением. Для всплывающих подсказок, связанных с панелью 
инструментов, параметр и/у/должен равняться нулю, а параметр Last должен быть 
идентификатором панели инструментов. Это продиктовано тем, что идентификатор, 
передаваемый сообщением WM_NOTIFY, не обязательно будет уникальным. Поэтому 
программа должна сама определять диапазон значений идентификаторов. (Обычно 
значением идентификатора для всплывающих подсказок, связанных с панелью 
инструментов, является ноль.) Параметр TTipHandler— это имя обработчика 
идентификационных сообщений всплывающих подсказок. Этот обработчик должен 
иметь такой прототип: 

    afx_msg void TTipHandler(UINT idNoCUsed, NMHDR *Hdr, LRESULT *ResultNotUsed); 

    Здесь параметр idNotUsed является идентификатором, связанным с сообщением 
WM_NOTIFY. Поскольку этот идентификатор не уникален, он не используется. 
Параметр ResultNotUsed также не используется. Вместо этого информация, 
связанная! с сообщением WM_NOTIFY, передается в структуре, на которую 
указывает параметр: Hdr. Его тип NMHDR не является реальным типом структуры, 
передаваемой обработчику, а лишь обозначает его. Обычно данный указатель 
необходимо приводить к; соответствующему типу. Для всплывающих подсказок это 
будет тип TOOLTIPTEXT,! который определен следующим образом: 

    typedef struct! 
    NMHDR hdr; 
    LPSTR IpszText; 


    254                                    MFC: основы программирована 


    char szText[80] ; 
    HINSTANCE hinst; 
    UINT uFlags; 
    ) TOOLTIPTEXT; 

    В первом поле структуры TOOLTIPTEXT находится структура NMHDR, которая 
определена так: 

    typedef struct tagNMHDR 
    ( 
    HHND hwndFrom; // дескриптор элемента управления 
    UINT idFrom; // идентификатор элемента управления 
    UINT code; // идентификационный код 
    } NMHDR; 

    Если сообщение WM_NOTTFY было послано из-за необходимости вывести 
всплывающую подсказку, то в поле code будет содержаться значение TTNJNEEDTEXT, 
а в поле idFrom — идентификатор кнопки, для которой требуется подсказка. 
    Есть три способа создать требуемую подсказку. Можно скопировать ее текст в 
массив szText структуры TOOLTIPTEXT, записать указатель на этот текст в поле 
IpszText или передать идентификатор ресурса строки в файле ресурсов. В 
последнем случае идентификатор строки связывается с полем IpszText, а в поле 
hinst должен быть записан дескриптор ресурса строки. Легче всего просто 
передавать в поле IpszText указатель на строку, создаваемую в самой программе. 
    Чтобы пояснить вышесказанное, приведем текст функции-обработчика, которая 
создает всплывающие подсказки для предыдущей программы. 

    // Обработка вызовов подсказок 
    afx_msg void CMainWin::OnTTip(UINT idNotUsed, NMHDR *hdr, 
    LRESULT *ResultNotUsed) 
    ( 
    switch (hdr->idFrom) 
    ( 
    case IDM_LINES: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Lines"; 
    break; 
    case IDM_RECTANGLES: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Rectangles"; 
    break; 
    case IDM_ELLIPSES: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Ellipses"; 
    break; 
    case IDM_RESET: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Reset"; 
    breaks
    case IDM_HELP: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Help"; 
    break; 
    ) 
    ) 


    10. Общие элементы управления                                    255 

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

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

    Ниже представлена программа работы с панелью инструментов, включающая 
теперь и всплывающие подсказки. Пример работы программы показан на рис. J0.3. 
В программе используется тот же файл ресурсов и библиотечный файл IDS.H, что и 
в предыдущем примере. Вот текст файла TOOLTIP.H, содержащего объявления 
порождаемых классов: 

    // TOOLTIP.H 
    #include "ids.h" 
    // Это класс для создания главного окна                            
    class CMainWin : public CFrameWnd 
    ( 
    CDC m memDC; // контекст устройства, связанный с 
    // виртуальным окном 
    CBitmap m bmp; // образ виртуального окна 
    CBrush m bkbrush; // кисть для виртуального окна 
    // объявление перьев 
    CPen m RedPen, m_YellowPen, m GreenPen, m BluePen; 
    CPen m_01dPen; 
    CToolBarCtrl m ТВ; // объект панели инструментов 
    public: 
    CMainWin () ; 
    afx msg void OnPaintO; 
    afx_msg void OnSize(UINT How, int Width, int Height); 
    afx msg void OnLinesO; 
    afx msg void OnRectangles() ; 
    afx_msg void OnEllipses () ; 
    afx_msg void OnResetO; 
    afx_msg void OnShowTBO; 
    afx msg void OnHideTBO; 
    afx msg void OnExitO; 
    afx msg void OnHelpO; 


    256 MFC: основы программирования 


    afXJtisg void OnTTip(UINT idNotUsed, NMHDR *hdr, 
    LRESULT *ResultNotUsed) ; 
    void InitToolbar(); 
    DECLARE_MESSAGE_MAP() 
    1; 
    // Это класс для создания приложения 
    class CApp : public CWinApp 
    ( 
    public: 
    BOOL Initlnstance () ; 
    ); 
    Это текст самой программы: 
    // Использование всплывающих подсказок 
    finclude <afxwin.h> 
    #include <afxcmn.h> 
    #include "tooltip.h" 
    ^include "ids.h" 
    int maxX, maxY; // размеры экрана 
    CMainWin::CMainWin() 
    ( 
    Create(NULL, "Adding Tooltips", 
    WS_OVERLAPPEDWINDOW, rectDefault, 
    NULL, "ToolbarMenu"); 
    // Загрузка таблицы быстрого доступа 
    if(!LoadAccelTable("ToolbarMenu")) 
    MessageBox("Cannot Load Accelerators", "Error"); 
    maxX = GetSystemMetrics(SM_CXSCREEN); 
    maxY = GetSystemMetrics(SM_CYSCREEN) ; 
    CClientDC DC(this) ; 
    // создание образа виртуального окна 
    m_memDC.CreateCompatibleDC(&DC) ; 
    m_bmp.CreateCompatibleBitmap(&DC, maxX, maxY) ; 
    m memDC.SelectObject(&m bmp); 
    // выбор стандартного фона 
    m_bkbrush.CreateStockObject(WHITE_BRUSH) ; 
    m memDC.SelectObject(&m bkbrush); 
    // закраска фона виртуального окна 
    m_memDC.PatBlt(0, 0, maxX, maxY, PATCOPY); 
    // создание перьев 


    10. Общие элементы управления                                   257 


    m_RedPen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0) ) ; 
    m_GreenPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0) ) ; 
    m_BluePen.CreatePen(PS_SOLID, 3, RGB(0, 0, 255)); 
    m_YellowPen.CreatePen(PSJ30LID, 4, RGB(255, 255, 0) ) ; 
    m_01dPen.CreateStockObject(BLACK_PEN) ; 
    InitCommonControls(); 
    InitToolbar() ; 
    } 
    // Инициализация приложения 
    BOOL CApp::Initlnstance () 
    ( 
    m pMainWnd = new CMainWin; 
    m_pMainWnd->ShowWindow (m_nCindShow) ; 
    m_pMainWnd->UpdateWindow() ; 
    return TRUE; 
    } 
    // Это очередь сообщений приложения 
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    ON_WM_PAINT() 
    ON_WM_SIZE() 
    ON_COMMAND(IDM_LINES, OnLines) 
    ON_COMMAND(IDM_RECTANGLES, OnRectangles) 
    ON_COMMAND(IDM_ELLIPSES, OnEllipses) 
    ON_COMMAND(IDM_RESET, OnReset) 
    ON_COMMAND(IDM_SHOWTB, OnShowTB) 
    ON_COMMAND(IDM_HIDETB, OnHideTB) 
    ON_COMMAND(IDM_EXIT, OnExit) 
    ON_COMMAND(IDM_HELP, OnHelp) 
    ON_NOTIFY_RANGE(TTN_NEEDTEXT, 0, ID_TB, OnTTip) 
    END_MESSAGE_MAP() 
    // Вывод на экран содержимого виртуального окна 
    afx msg void CMainWin::OnPaint() 
    ( 
    CPaintDC DC(this) ; 
    DC.BitBlt(0, 0, maxX, maxY, &m_memDC, О, О, SRCCOPY) ; 
    } 
    // Изменение размера панели инструментов 
    afx_msg void CMainWin::OnSize(UINT How, int Width, int Height) 
    { 
    m_TB.Auto3ize () ; 
    } 
    // Обработка сообщения IDM EXIT 
    afx msg void CMainWin::OnExit() 


    258                                    MFC: основы программирования 


    int response; 
    response = MessageBox ("Quit the Program?", "Exit", MB_YESNO); 
    if (response == IDYES) 
    SendMessage(WM_CLOSE); // завершение приложения 
    } 
    // Обработка сообщения IDM_HELP 
    afx msg void CMainWin::OnHelp() 
    { 
    m_TB.PressButton(IDM_HELP, TRUE) ; 
    MessageBox ("Toolbar Demo", "Help"); 
    m_TB.PressButton(IDM_HELP, FALSE) ; 
    } 
    // Отображение линий и точек 
    afx msg void CMainWin::OnLines() 
    ( 
    //отображение четырех точек 
    m_memDC.SetPixel(40, 14, RGB(255, 0, 0)) ; 
    m_memDC.SetPixel(41, 14, RGB(0, 255, 0)) ; 
    m_mernDC.SetPixel (42, 14, RGB(0, 0, 255)); 
    m_memDC.SetPixel(43, 14, RGB(0, 0, 0)) ; 
    m_memDC.LineTo(100, 50); 
    m_memDC.MoveTo(100, 50); 
    // изменение цвета пера на зеленое 
    m_memDC.SelectObject(&m_GreenPen) ; 
    m_memDC.LineTo(200, 100); 
    // изменение цвета пера на желтое 
    m_memDC.SelectObject(&m_YellowPen) ; 
    m_memDC.LineTo(0, 200); 
    // изменение цвета пера на синее 
    m_memDC.SelectObject(&m_BluePen) ; 
    m_memDC.LineTo(200, 200); 
    // изменение цвета пера на красное 
    m_memDC.SelectObject(&m_RedPen) ; 
    m_memDC.LineTo(0, 0) ; 
    m_memDC.LineTo(100, 50); 
    m_memDC.MoveTo(0, 0) ; 
    m_memDC.LineTo(100, 250); 
    m_memDC.MoveTo(0, 0) ; 
    m_memDC.LineTo(100, 350); 


    10. Общие элементы управления                                   259 


    // восстановление первоначального пера 
    m_memDC.SelectObject(&m_01dPen) ; 
    m_memDC.Arc(0, 0, 300, 300, 0, 50, 200, 0) ; 
    //отображение пересекающихся линий, которые определяют дугу 
    m_memDC.MoveTo(150, 150); 
    m_memDC.LineTo(0, 50); 
    m_memDC.MoveTo(150, 150); 
    m_memDC.LineTo(200, 0) ; 
    InvalidateRect(NULL) ; 
    } 
    // Отображение прямоугольников 
    afx msg void CMainWin: .'OnRectangles () 
    ( 
    CBrush HollowBrush; 
    // создание "пустого" заполнения 
    HollowBrush.CreateStockObject(HOLLOW_BRUSH) ; 
    m_memDC.SelectObject(SHollowBrush) ; 
    // отображение нескольких прямоугольников 
    m_meniDC. Rectangle (50, 50, 300, 300); 
    m_memDC.RoundRect(125, 125, 220, 240, 15, 13); 
    // использование красного пера 
    m_memDC. SelectObject (&rn_RedPen) ; 
    m_memDC.Rectangle(100, 100, 200, 200); 
    m memDC.SelectObject(&m OldPen); // восстановление прежнего пера 
    // восстановление прежней кисти 
    m_memDC.SelectObject(&m_bkBrush) ; 
    InvalidateRect(NULL) ; 
    } 
    // Отображение эллипсов 
    afx msg void CMainWin::OnEllipses () 
    ( 
    CBrush Brush; 
    // создание синей кисти 
    Brush.CreateSolidBrush (RGB (0, 0, 255)); 
    ni_memDC.SelectObject(SBrush) ; 
    // отображение эллипсов, заполненных синим цветом 
    m_memDC.Ellipse (50, 200, 100, 280); 
    m_memDC.Ellipse (75, 25, 280, 100); 


    260                                    MFC: основы программирования 


    // использование красного пера 
    m memDC.SelectObject(&m RedPen); 
    // создание зеленой кисти 
    Brush.DeleteObject(); // удаление синей кисти 
    Brush.CreateSolidBrush(RGB(0, 255, 0)) ; 
    m_memDC.SelectObject(SBrush); // выбор зеленой кисти 
    m_memDC.Ellipse(100, 100, 200, 200); 
    // отображение сектора 
    m_memDC.Pie(200, 200, 340, 340, 225, 200, 200, 250); 
    
    m_memDC.SelectObject(&m_01dPen); // восстановление прежнего пера 
    m_memDC . SelectObject (Sttn_bkBrush) ; // восстановление прежней кисти 
    InvalidateRect(NULL) ; 
    } 
    // Очистка окна 
    afx msg void CMainWin::OnReset() 
    { 
    m_memDC.PatBlt(0, 0, maxX, maxY, PATCOPY); 
    InvalidateRect(NULL) ; 
    ) 
    
    // Отображение панели инструментов 
    afx_msg void CMainWin::OnShowTB() 
    { 
    in_TB.ShowWindow(SW_RESTORE) ; 
    } 
    
    // Удаление панели инструментов 
    afx_msg void CMainWin::OnHideTB() 
    { 
    m_TB.ShowWindow(SW_HIDE) ; 
    } 
    
    // Обработка вызовов подсказок 
    afx_msg void CMainWin::OnTTip(UINT idNotUsed, NMHDR *hdr, 
    
    LRESULT *ResultNotUsed) 
    ( 
    
    switch (hdr->idFrom) 
    { 
    case IDM_LINES: 
    ( (TOOLTIPTEXT *)hdr)->lpszText = "Lines"; 
    break; 
    case IDM_RECTANGLES: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Rectangles"; 
    break; 
    case IDM_ELLIPSES: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Ellipses"; 
    break; 


    10. Общие элементы управления                                   261 


    case IDM_RESET: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Reset"; 
    breaks
    case IDM_HELP: 
    ((TOOLTIPTEXT *)hdr)->lpszText = "Help"; 
    break; 
    } 
    } 
    // Инициализация панели инструментов 
    void CMainWin::InitToolbar() 
    { 
    RECT r; 
    TBBUTTON tbButtons[NUMBUTTONS] ; 
    r.left = r.top = r.right = r.bottom = 0; 
    m_TB.Create(WS_VISIBLE | WS_CHILD | WS_BORDER I 
    TBSTYLE_TOOLTIPS, r, this, ID_TB) ; 
    tbButtons[0].iBitmap = 0; 
    tbButtons[0].idCommand = IDM_LINES; 
    tbButtons [0].fsState = TBSTATE_ENABLED; 
    tbButtons[0].fsStyle = TBSTYLE_BUTTON; 
    tbButtons[0].dwData = 0; 
    tbButtons[0].iString = 0; 
    tbButtons [1].iBitmap = 1; 
    tbButtons [1].idCommand = IDM_RECTANGLES; 
    tbButtons[1].fsState = TBSTATE_ENABLED; 
    tbButtons[1].fsStyle = TBSTYLE_BUTTON; 
    tbButtons[1].dwData = 0; 
    tbButtons[1].iString = 0; 
    tbButtons[2].iBitmap = 2; 
    tbButtons[2].idCommand = IDM_ELLIPSES; 
    tbButtons[2].fsState = TBSTATE_ENABLED; 
    tbButtons[2].fsStyle = TBSTYLE_BUTTON; 
    tbButtons[2J.dwData = 0; 
    tbButtons[2].iString = 0; 
    tbButtons[3].iBitmap = 3; 
    tbButtons[3].idCommand = IDM_RESET; 
    tbButtons[3].fsState = TBSTATE_ENABLED; 
    tbButtons[3].fsStyle » TBSTYLE_BUTTON; 
    tbButtons[3].dwData = 0; 
    tbButtons [3].iString = 0; 
    // кнопка-разделитель 
    tbButtons[4].iBitmap = 0; 
    tbButtons[4].idCommand = 0; 
    tbButtons[4].fsState = TBSTATE_ENABLED; 


    262                                    MFC: основы программирования 


    tbButtons[4].fsStyle = TBSTYLE_SEP; 
    tbButtons[4].dwData = 0; 
    tbButtons[4].iString = 0; 
    tbButtons[5].iBitmap = 4; 
    tbButtons[5].idCommand = IDM_HELP; 
    tbButtons[5].fsState = TBSTATE_ENABLED; 
    tbButtons[5].fsStyle = TBSTYLE_BUTTON; 
    tbButtons[5].dwData = 0; 
    tbButtons[5].iString = 0; 
    m_TB.AddButtons(NUMBUTTONS, tbButtons) ; 
    m_TB.AddBitmap(NUMBUTTONS, IDTB_BMP) ; 
    } 
    CApp App; // создание экземпляра приложения 

    Рис. 10.3. Пример использования всплывающих подсказок 

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

    70. Общие элементы управления                                   263