
- •Глава 12 Современный пользовательский интерфейс
- •Основы элементов управления общего пользования
- •Инициализация библиотеки
- •Создание элементов управления общего пользования
- •Стили элементов управления общего пользования
- •Основные стили окна
- •Флаги расширенного стиля окна
- •Флаги основного стиля элемента управления общего пользования
- •Флаги стиля, специфичные для конкретного элемента управления
- •Посылка сообщений элементам управления общего пользования
- •Уведомляющие сообщения от элементов управления общего пользования
- •Элементы управления главного окна
- •Панели инструментов
- •Создание панели инструментов
- •Стили окна панели инструментов
- •Задание изображений на поверхности кнопок
- •Заполнение массива tbbutton
- •Пример создания панели инструментов
- •Перемещение и изменение размеров панели инструментов
- •Поддержка элемента управления подсказка
- •Добавление дочерних окон в панель инструментов
- •Резервирование места для дочернего окна на панели инструментов
- •Создание элементов управления на панели инструментов
- •Изменение размеров панели инструментов с дочерними окнами
- •Поддержка окон подсказки для дочерних окон панели инструментов
- •Изменение конфигурации панели инструментов
- •Строка состояния
- •Создание строки состояния
- •Перемещение и изменение размеров строки состояния
- •Поддержка просмотра меню
- •Просмотр элементов меню
- •Просмотр элементов всплывающего меню
- •Просмотр системного меню
- •Программа gadgets
Уведомляющие сообщения от элементов управления общего пользования
Как и предопределенные элементы управления, элементы управления общего пользования посылают своему родительскому окну уведомляющие сообщения. Уведомляющие сообщения информируют родительское окно о том, что что-то произошло с окном: пользователь нажал кнопку мыши на элементе управления, напечатал текст, переместил фокус ввода на элемент управления или переместил его с элемента управления.
В отличие от предопределенных элементов управления, которые посылают уведомления как сообщения WM_COMMAND, элементы управления общего пользования посылают уведомления как сообщения WM_NOTIFY. Таким образом, если добавить элемент управления общего пользования к существующему коду, то смешивания обработки уведомляющих сообщений от предопределенных элементов управления и элементов управления общего пользования в программе не произойдет. Сообщения WM_NOTIFY также предотвращают путаницу с уведомляющими сообщениями от меню, которые тоже выражаются в виде сообщений WM_COMMAND.
Однако, не все уведомления элементов управления общего пользования приходят как сообщения WM_NOTIFY. В частности, панель инструментов, использующая сообщения WM_NOTIFY для большинства уведомлений, посылает сообщения WM_COMMAND, когда нажимается кнопка. Поскольку панель инструментов используется для поддержки выбора из меню, тот же код обработки сообщений WM_COMMAND, что для поддержки меню и быстрых клавиш, будет обрабатывать сообщения от панели инструментов. Еще одно исключение — полоса прокрутки, связанная с окном редактирования для изменения значения, которая также посылает сообщения WM_VSCROLL или WM_HSCROLL при нажатии на стрелки.
Хотя каждый элемент управления общего пользования имеет свой собственный набор кодов уведомления, существует общий набор уведомлений. Этот набор приведен в следующей таблице:
Код уведомления |
Описание |
NM_CLICK |
Пользователь сделал щелчок левой кнопкой мыши |
NM_DBLCLK |
Пользователь сделал двойной щелчок левой кнопкой мыши |
(продолжение)
Код уведомления |
Описание |
NM_KILLFOCUS |
Элемент управления потерял фокус ввода |
NM_OUTOFMEMORY |
Ошибка нехватки памяти |
NM_RCLICK |
Пользователь сделал щелчок правой кнопкой мыши |
NM_RDBLCLK |
Пользователь сделал двойной щелчок правой кнопкой мыши |
NM_RETURN |
Пользователь нажал клавишу <Enter> |
NM_SETFOCUS |
Элемент управления получил фокус ввода |
Не все элементы управления общего пользования обязательно посылают каждое из этих уведомляющих сообщений. Например, набор закладок для выбора не посылает уведомлений, связанных с изменением фокуса ввода (NM_KILLFOCUS и NM_SETFOCUS). При работе с каждым элементом управления общего пользования следует разобраться с тем, какие уведомляющие сообщения он посылает.
Один из методов разобраться в этом лабиринте уведомляющих сообщений, посылаемых элементами управления общего пользования, состоит в обработке каждого сообщения WM_NOTIFY и выводе соответствующего кода уведомления в окно отладчика. Эта задача упрощается за счет того, что коды уведомлений для каждого элемента управления общего пользования определены в уникальном диапазоне. Поэтому, простая таблица поиска может быть использована для интерпретации кода уведомления. Не имеет значения, с каким элементом управления общего пользования идет работа. Можно обрабатывать сообщение WM_NOTIFY так, как показано ниже, для вывода информации в окно отладчика с помощью функции OutputDebugString. Для просмотра результатов работы этой функции в Win32 API вам следует запустить программу в отладчике:
case WM_NOTIFY:
{
int idCtrl = (int) wParam;
LPNMHDR pnmh = (LPNMHDR) lParam;
#ifdef _DEBUG
// вывод уведомляющих сообщений в окно отладчика
LPSTR pText;
if (QueryNotifyText (pnmh->code, &pText) )
{
OutputDebugString (pText);
OutputDebugString ("\r\n");
}
#endif
[другие строки программы]
return 0;
}
Каждый пример программы в этой главе обрабатывает сообщение WM_NOTIFY так, как показано выше. Описания, которые необходимы для вызова функции QueryNotifyText, приведены ниже:
typedef struct tagCONTROLNOTIFICATIONS
{
UINT nCode ;
LPSTR pName ;
} CONTROLNOTIFICATIONS ;
BOOL QueryNotifyText (UINT nNotifyCode, LPSTR *pName) ;
Функция и определения данных для QueryNotifyText приведены ниже:
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <prsht.h>
#include "notify.h"
CONTROLNOTIFICATIONS cnLookupTable[] =
{
NM_OUTOFMEMORY, "NM_OUTOFMEMORY",
NM_CLICK, "NM_CLICK",
NM_DBLCLK, "NM_DBLCLK",
NM_RETURN, "NM_RETURN",
NM_RCLICK, "NM_RCLICK",
NM_RDBLCLK, "NM_RDBLCLK",
NM_SETFOCUS, "NM_SETFOCUS",
NM_KILLFOCUS, "NM_KILLFOCUS",
LVN_ITEMCHANGING, "LVN_ITEMCHANGING",
LVN_ITEMCHANGED, "LVN_ITEMCHANGED",
LVN_INSERTITEM, "LVN_INSERTITEM",
LVN_DELETEITEM, "LVN_DELETEITEM",
LVN_DELETEALLITEMS, "LVN_DELETEALLITEMS",
LVN_BEGINLABELEDITA, "LVN_BEGINLABELEDITA",
LVN_BEGINLABELEDITW, "LVN_BEGINLABELEDITW",
LVN_ENDLABELEDITA, "LVN_ENDLABELEDITA",
LVN_ENDLABELEDITW, "LVN_ENDLABELEDITW",
LVN_COLUMNCLICK, "LVN_COLUMNCLICK",
LVN_BEGINDRAG, "LVN_BEGINDRAG",
LVN_BEGINRDRAG, "LVN_BEGINRDRAG",
LVN_GETDISPINFOA, "LVN_GETDISPINFOA",
LVN_GETDISPINFOW, "LVN_GETDISPINFOW",
LVN_SETDISPINFOA, "LVN_SETDISPINFOA",
LVN_SETDISPINFOW, "LVN_SETDISPINFOW",
LVN_KEYDOWN, "LVN_KEYDOWN",
HDN_ITEMCHANGINGA, "HDN_ITEMCHANGINGA",
HDN_ITEMCHANGINGW, "HDN_ITEMCHANGINGW",
HDN_ITEMCHANGEDA, "HDN_ITEMCHANGEDA",
HDN_ITEMCHANGEDW, "HDN_ITEMCHANGEDW",
HDN_ITEMCLICKA, "HDN_ITEMCLICKA",
HDN_ITEMCLICKW, "HDN_ITEMCLICKW",
HDN_ITEMDBLCLICKA, "HDN_ITEMDBLCLICKA",
HDN_ITEMDBLCLICKW, "HDN_ITEMDBLCLICKW",
HDN_DIVIDERDBLCLICKA, "HDN_DIVIDERDBLCLICKA",
HDN_DIVIDERDBLCLICKW, "HDN_DIVIDERDBLCLICKW",
HDN_BEGINTRACKA, "HDN_BEGINTRACKA",
HDN_BEGINTRACKW, "HDN_BEGINTRACKW",
HDN_ENDTRACKA, "HDN_ENDTRACKA",
HDN_ENDTRACKW, "HDN_ENDTRACKW",
HDN_TRACKA, "HDN_TRACKA",
HDN_TRACKW, "HDN_TRACKW",
TVN_SELCHANGINGA, "TVN_SELCHANGINGA",
TVN_SELCHANGINGW, "TVN_SELCHANGINGW",
TVN_SELCHANGEDA, "TVN_SELCHANGEDA",
TVN_SELCHANGEDW, "TVN_SELCHANGEDW",
TVN_GETDISPINFOA, "TVN_GETDISPINFOA",
TVN_GETDISPINFOW, "TVN_GETDISPINFOW",
TVN_SETDISPINFOA, "TVN_SETDISPINFOA",
TVN_SETDISPINFOW, "TVN_SETDISPINFOW",
TVN_ITEMEXPANDINGA, "TVN_ITEMEXPANDINGA",
TVN_ITEMEXPANDINGW, "TVN_ITEMEXPANDINGW",
TVN_ITEMEXPANDEDA, "TVN_ITEMEXPANDEDA",
TVN_ITEMEXPANDEDW, "TVN_ITEMEXPANDEDW",
TVN_BEGINDRAGA, "TVN_BEGINDRAGA",
TVN_BEGINDRAGW, "TVN_BEGINDRAGW",
TVN_BEGINRDRAGA, "TVN_BEGINRDRAGA",
TVN_BEGINRDRAGW, "TVN_BEGINRDRAGW",
TVN_DELETEITEMA, "TVN_DELETEITEMA",
TVN_DELETEITEMW, "TVN_DELETEITEMW",
TVN_BEGINLABELEDITA, "TVN_BEGINLABELEDITA",
TVN_BEGINLABELEDITW, "TVN_BEGINLABELEDITW",
TVN_ENDLABELEDITA, "TVN_ENDLABELEDITA",
TVN_ENDLABELEDITW, "TVN_ENDLABELEDITW",
TVN_KEYDOWN, "TVN_KEYDOWN",
TTN_NEEDTEXTA, "TTN_NEEDTEXTA",
TTN_NEEDTEXTW, "TTN_NEEDTEXTW",
TTN_SHOW, "TTN_SHOW",
TTN_POP, "TTN_POP",
TCN_KEYDOWN, "TCN_KEYDOWN",
TCN_SELCHANGE, "TCN_SELCHANGE",
TCN_SELCHANGING, "TCN_SELCHANGING",
TBN_GETBUTTONINFOA, "TBN_GETBUTTONINFOA",
TBN_GETBUTTONINFOW, "TBN_GETBUTTONINFOW",
TBN_BEGINDRAG, "TBN_BEGINDRAG",
TBN_ENDDRAG, "TBN_ENDDRAG",
TBN_BEGINADJUST, "TBN_BEGINADJUST",
TBN_ENDADJUST, "TBN_ENDADJUST",
TBN_RESET, "TBN_RESET",
TBN_QUERYINSERT, "TBN_QUERYINSERT",
TBN_QUERYDELETE, "TBN_QUERYDELETE",
TBN_TOOLBARCHANGE, "TBN_TOOLBARCHANGE",
TBN_CUSTHELP, "TBN_CUSTHELP",
UDN_DELTAPOS, "UDN_DELTAPOS",
PSN_SETACTIVE, "PSN_SETACTIVE",
PSN_KILLACTIVE, "PSN_KILLACTIVE",
PSN_APPLY, "PSN_APPLY",
PSN_RESET, "PSN_RESET",
PSN_HELP, "PSN_HELP",
PSN_WIZBACK, "PSN_WIZBACK",
PSN_WIZNEXT, "PSN_WIZNEXT",
PSN_WIZFINISH, "PSN_WIZFINISH",
PSN_QUERYCANCEL, "PSN_QUERYCANCEL"
} ;
int NOTIFY_COUNT = sizeof (cnLookupTable) / sizeof (CONTROLNOTIFICATIONS) ;
//-------------------------------------------------------------------
// QueryNotifyText: Convert notification codes into text (Преобразование уведомляющего кода в текст)
//-------------------------------------------------------------------
BOOL QueryNotifyText (UINT nNotifyCode, LPSTR *pName)
{
BOOL bFound = FALSE ;
int iNotify ;
for (iNotify = 0 ; iNotify < NOTIFY_COUNT ; iNotify++)
{
if (cnLookupTable[iNotify].nCode == nNotifyCode)
{
*pName = cnLookupTable[iNotify].pName ;
return TRUE ;
}
}
// Unknown notification code (неизвестный уведомляющий код)
*pName = "** Unknown **" ;
return FALSE ;
}