
- •Глава 12 Современный пользовательский интерфейс
- •Основы элементов управления общего пользования
- •Инициализация библиотеки
- •Создание элементов управления общего пользования
- •Стили элементов управления общего пользования
- •Основные стили окна
- •Флаги расширенного стиля окна
- •Флаги основного стиля элемента управления общего пользования
- •Флаги стиля, специфичные для конкретного элемента управления
- •Посылка сообщений элементам управления общего пользования
- •Уведомляющие сообщения от элементов управления общего пользования
- •Элементы управления главного окна
- •Панели инструментов
- •Создание панели инструментов
- •Стили окна панели инструментов
- •Задание изображений на поверхности кнопок
- •Заполнение массива tbbutton
- •Пример создания панели инструментов
- •Перемещение и изменение размеров панели инструментов
- •Поддержка элемента управления подсказка
- •Добавление дочерних окон в панель инструментов
- •Резервирование места для дочернего окна на панели инструментов
- •Создание элементов управления на панели инструментов
- •Изменение размеров панели инструментов с дочерними окнами
- •Поддержка окон подсказки для дочерних окон панели инструментов
- •Изменение конфигурации панели инструментов
- •Строка состояния
- •Создание строки состояния
- •Перемещение и изменение размеров строки состояния
- •Поддержка просмотра меню
- •Просмотр элементов меню
- •Просмотр элементов всплывающего меню
- •Просмотр системного меню
- •Программа gadgets
Поддержка окон подсказки для дочерних окон панели инструментов
Кроме обработки уведомления TTN_NEEDTEXT создание работоспособного окна подсказки для кнопок панели инструментов — дело достаточно простое. Для дочерних окон в панели инструментов требуется еще одно дополнительное усилие: добавление дочернего окна в список инструментов, создаваемый элементом управления подсказка.
Добавление дочернего окна в список инструментов, создаваемый элементом управления подсказка, требует посылки сообщения TTM_ADDTOOL окну подсказки. Но для начала необходимо получить описатель окна подсказки. Это делается путем посылки панели инструментов сообщения TB_GETTOOLTIP:
hwndTT = ToolBar_GetToolTips (hwndToolBar) ;
Сообщение TTM_ADDTOOL требует указатель на структуру типа TOOLINFO, которая описывает инструмент элемента управления подсказка. Структура TOOLINFO определена в файле COMMCTRL.H как показано ниже:
typedef struct tagTOOLINFOA
{
UINT cbSize ;
UINT uFlags ;
HWND hwnd ;
UINT uId ;
RECT rect ;
HINSTANCE hinst ;
LPSTR lpszText ;
} TOOLINFOA, NEAR *PTOOLINFOA, FAR *LPTOOLINFOA ;
Поле cbSize структуры TOOLINFO соответствует информации о версии, специфичной для элемента управления подсказка, и должен быть равен размеру структуры TOOLINFO. Пренебрежение этим правилом может привести к тому, что подсказка проигнорирует это сообщение.
Поле uFlags позволяет иметь некоторую гибкость при задании инструмента. Первый флаг, TTF_IDISHWND, требуется тогда, когда в качестве инструмента передается описатель дочернего окна. Он показывает, что в поле uId находится описатель окна. Другой флаг, TTF_CENTERTIP, заставляет окно подсказки выводиться в центре по горизонтали под инструментом, а не как по умолчанию — ниже и справа относительно курсора мыши. Третий флаг, TTF_SUBCLASS, требует, чтобы элемент управления подсказка создал новую оконную процедуру для отслеживания потока сообщений. Без этого флага вам пришлось бы создавать другой механизм для передачи подробностей сообщений мыши элементу управления подсказка.
Третье поле, hwnd, идентифицирует окно, содержащее инструмент. Конечно, в данном случае это окно панели инструментов.
Поле uId содержит произвольный идентификатор, который создатель инструмента (например, панель инструментов) присваивает каждому инструменту. Например, панель инструментов устанавливает каждой своей кнопке индекс относительно нуля и передает этот индекс в окно подсказки, когда добавляет каждую кнопку в список подсказки. Когда этот идентификатор содержит описатель окна, как это бывает, если целое дочернее окно становится инструментом, то флаг TTF_IDISHWND в поле uFlags уведомляет об этом подсказку.
Местоположение инструмента в его родительском окне задается структурой rect, что позволяет элементу управления подсказка осуществлять контроль положения указателя мыши для каждой конкретной кнопки на панели инструментов. В случае, если окно целиком является инструментом, т. е. если указан флаг TTF_IDISHWND, то это поле игнорируется.
Текст, который выводится в качестве подсказки на дисплей, определяется комбинацией значений полей hinst и lpszText, задающих текстовую строку как ресурс. В качестве альтернативы, возможно указать, что необходим запрос в уведомляющем сообщении TTN_NEEDTEXT. Для этого надо указать в поле lpszText значение LPSTR_TEXTCALLBACK.
Ниже показано, как программа GADGETS добавляет поддержку окна подсказки для комбинированного списка, находящегося в панели инструментов:
TOOLINFO ti ;
ZeroMemory (&ti, sizeof (TOOLINFO)) ;
ti.cbSize = sizeof (TOOLINFO) ;
ti.uFlags = TTF_IDISHWND | TTF_CENTERTIP | TTF_SUBCLASS ;
ti.hwnd = hwndToolBar ;
ti.uId = (UINT) (HWND) hwndComboBox ;
ti.lpszText = LPSTR_TEXTCALLBACK ;
bSuccess = ToolTip_AddTool (hwndTT, &ti) ;
Ценность комбинированных списков в том, что они состоят из комбинации двух или более элементов управления: контейнер комбинированного списка, окно редактирования или статическое окно и список. Для того чтобы обеспечить полную поддержку окон подсказки, видимые компоненты должны быть добавлены в список инструментов подсказки. Программа GADGETS добавляет поддержку окна подсказки для окна редактирования следующим образом:
// Добавление окна подсказки для окна редактирования комбинированного списка
hwndEdit = GetWindow (hwndComboBox, GW_CHILD) ;
ti.cbSize = sizeof (TOOLINFO) ;
ti.uFlags = TTF_IDISHWND | TTF_CENTERTIP | TTF_SUBCLASS ;
ti.hwnd = hwndToolBar ;
ti.uId = (UINT) (HWND) hwndEdit ;
ti.lpszText = LPSTR_TEXTCALLBACK ;
bSuccess = ToolTip_AddTool (hwndTT, &ti) ;
Если элемент управления подсказка знает о дочерних окнах, то подсказка появляется на экране тогда, когда курсор мыши останавливается над дочерним окном. В определении этого момента есть некая магия, что возможно благодаря введению новой оконной процедуры (window subclassing), на что указывает флаг TTF_SUBCLASS. Новая оконная процедура отслеживает сообщения мыши, и когда замечает подходящее, посылает сообщение TTM_RELAYEVENT в элемент управления подсказка.
Если по каким-либо причинам вы решите, что использование техники введения новой оконной процедуры нежелательно, например, потому что оно уже было сделано, то существует несколько альтернативных путей. Вы можете модифицировать оконную процедуру дочернего элемента управления и просто отправлять сообщение TTM_RELAYEVENT при получении сообщения от мыши. Также возможно добавить ловушку (hook) типа WH_GETMESSAGE для поиска сообщений мыши для конкретного окна. Вероятно, наиболее простой путь — это добавление небольшого фрагмента кода в цикл обработки сообщений вашей программы. Поскольку это основной путь, по которому проходят все сообщения мыши (а также клавиатуры, таймера и др.), то этот вариант хорош в тех случаях, когда применение флага TTF_SUBCLASS нецелесообразно. Ниже приведен фрагмент цикла обработки сообщений программы GADGETS, если бы в ней не использовался этот флаг:
while (GetMessage (&msg, NULL, 0, 0))
{
if (pMsg->hwnd == hwndCombo || pMsg->hwnd == hwndEdit)
{
if (pMsg->message >= WM_MOUSEFIRST &&
pMsg->message <= WM_MOUSELAST)
{
ToolTip_RelayEvent (hwndTT, pMsg) ;
}
}
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}