Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming_Windows_95_Part_I.pdf
Скачиваний:
96
Добавлен:
05.06.2014
Размер:
4.61 Mб
Скачать

434

LPTBNOTIFY ptbn =(LPTBNOTIFY) lParam; switch(ptbn->iItem)

{

case 0:

lstrcpy(ptbn->pszText, "Help"); ptbn->tbButton.iBitmap = STD_HELP; ptbn->tbButton.idCommand = 11; ptbn->tbButton.fsState = TBSTATE_ENABLED; ptbn->tbButton.fsStyle = TBSTYLE_BUTTON; ptbn->tbButton.dwData = 0; ptbn->tbButton.iString = 10;

return 1; case 1:

lstrcpy(ptbn->pszText, "Delete"); ptbn->tbButton.iBitmap = STD_DELETE; ptbn->tbButton.idCommand = 12; ptbn->tbButton.fsState = TBSTATE_ENABLED; ptbn->tbButton.fsStyle = TBSTYLE_BUTTON; ptbn->tbButton.dwData = 0; ptbn->tbButton.iString = 11;

return 1; default:

return 0;

}

Если у вас уже есть массив описаний TBBUTTON, то самый быстрый путь ответа на это сообщение состоит в использовании функции memcpy для копирования TBBUTTON для каждого получаемого сообщения. Ниже показано, как программа GADGETS делает это:

lstrcpy(ptbn->pszText, GetString(ptbn->iItem)); memcpy(&ptbn->tbButton, &tbb[iButton], sizeof(TBBUTTON));

Строка состояния

Строки состояния (status bar) — окна только для вывода информации, часто располагающиеся в нижней части главного окна программы. Наиболее частое использование строки состояния состоит в том, что она используется для отображения подробного описания пунктов меню при их просмотре пользователем, также как официант комментирует тот или иной пункт меню в ресторане. Когда меню не просматривается, программы часто отображают в строке состояния сопутствующую информацию. Также часто отображается состояние клавиш сдвига

— <Caps Lock>, <Num Lock>, <Scroll Lock>. В программах текстовых процессоров часто отображается также текущая страница, строка, столбец.

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

Создание строки состояния

Простейший путь создания строки состояния состоит в вызове функции CreateStatusWindow:

hwndStatusBar = CreateStatusWindow(

WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | CCS_BOTTOM, "Ready", hwndParent, 2

);

Эта функция вызывает функцию CreateWindow, которая создает дочернее окно с родительским окном hwndParent, с текстом окна "Ready" (этот текст отображается в первом окне строки состояния), идентификатором, равным 2. Флаги стиля окна заданы в первом параметре.

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

435

Категория

Флаг стиля

Описание

Представление

SBARS_SIZEGRIP

Отображает диагональную штриховку в

 

 

правом углу строки состояния. Эта область

 

 

служит для изменения размеров родительского

 

 

окна.

Начальное положение

CCS_TOP

Помещает строку состояния в верхнюю часть

 

 

родительского окна.

 

CCS_BOTTOM

Помещает строку состояния в нижнюю часть

 

 

родительского окна (по умолчанию).

 

CCS_NOMOVEY

Запрещает перемещение относительно оси y.

Запрет автоматического

CCS_NOPARENTALIGN

Строка состояния устанавливает свою высоту

изменения размеров и

 

(cy). Но не устанавливает свое местоположение

местоположения

 

(x,y) и ширину (cx). Для соответствующей

 

 

обработки необходимо после создания

 

 

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

 

CCS_NORESIZE

Запрещает все автоматические перемещения и

 

 

изменения размеров. Это запрещает

 

 

следующие флаги стиля: CCS_TOP,

 

 

CCS_BOTTOM, CCS_NOMOVEY и

 

 

CCS_NOPARENTALIGN. Вы должны явно

 

 

задать размеры и положение строки состояния.

Перемещение и изменение размеров строки состояния

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

case WM_SIZE:

{

int cxParent = LOWORD(lParam); int cyParent = HIWORD(lParam); int x, y, cx, cy;

RECT rWindow;

// Оставить высоту окна строки состояний без изменений

GetWindowRect(hwndStatusBar, &rWindow); cy = rWindow.bottom — rWindow.top;

x = 0;

y = cyParent — cy; cx = cxParent;

MoveWindow(hwndStatusBar, x, y, cx, cy, TRUE);

}

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

Поддержка просмотра меню

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

Меню окна посылает сообщение WM_MENUSELECT, когда пользователь просматривает пункты меню, и сообщение WM_COMMAND, когда пользователь выбирает пункт меню (см. главу 10). Для поддержки отображения вспомогательной информации о пунктах меню следует обрабатывать сообщение

WM_MENUSELECT.

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

436

void MenuHelp(

 

 

UINT

uMsg,

// WM_MENUSELECT

WPARAM

wParam,

// параметр wParam

LPARAM

lParam,

// параметр lParam

HMENU

hMainMenu,

// описатель главного меню

HINSTANCE

hInst,

// описатель экземпляра

HWND

hwndStatus,

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

UINT FAR

*lpwIDs

// таблица строк

);

 

Первый параметр, uMsg, должен быть равен WM_MENUSELECT, хотя наличие этого параметра (и его описание в документации по Win32) говорит о том, что обработка сообщения WM_COMMAND была заложена еще при разработке функции. В качестве второго и третьего параметров передаются параметры wParam и lParam оконной процедуры. Эти три параметра, взятые вместе, описывают то, какую часть системы меню просматривает пользователь, и является ли он пунктом, всплывающего меню или системного.

Шестой параметр, hwndStatus, это описатель окна строки состояния. Функция MenuHelp посылает специфичное для строки состояния сообщение SB_SIMPLE для установки строки состояния в режим одного окна (простой) и для отображения соответствующего текста. Позднее, когда пользователь прекращает просмотр, функция MenuHelp посылает другое сообщение SB_SIMPLE для возврата строки состояния в режим многих окон (непростой).

Функция MenuHelp использует другие три параметра — hMainMenu, hInst и lpwIDs — для определения того, какую строку необходимо отобразить при просмотре элемента меню. Параметр hInst идентифицирует модуль, который может быть описателем экземпляра DLL или описателем экземпляра выполняемой программы, и является владельцем таблицы, содержащей строки меню (которые, как можно предположить, загружаются с помощью функции LoadString).

Возможность сделать так, чтобы функция MenuHelp работала правильно, состоит в том, чтобы передать правильное значение в четвертом и седьмом параметрах: hMainMenu и lpwIDs. Правильная установка этих значений является небольшим трюкачеством, поскольку существует три элемента для рассмотрения: командное меню, всплывающее меню и системное меню. Другая сложность состоит в том, что документация по Win32 говорит о том, что lpwIDs — массив, в котором осуществляет поиск функция MenuHelp. Несмотря на то, что имеет смысл использовать массив для хранения базовых значений строковых ресурсов, вы должны будете сами делать грамматический разбор массива, поскольку функция MenuHelp не делает этого.

Просмотр элементов меню

Функция MenuHelp вычисляет идентификатор ID строкового ресурса для элемента меню путем добавления значения идентификатора команды (полученного из младшего слова wParam) к значению, на которое ссылается lpwIDs. Например, следующий вызов функции MenuHelp отображает строковый ресурс с номером 125 в строке состояния:

UINT uiStringBase = 100; WPARAM wParam = 25;

MenuHelp(WM_MENUSELECT, wParam, lParam, NULL, hInst, hwndStatus, &uiStringBase);

Как показано в примере, описатель меню hMainMenu может быть равен NULL для отображения элементов меню команд, поскольку функция MenuHelp не использует это значение для расчета.

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

Просмотр элементов всплывающего меню

В случае всплывающего меню функция MenuHelp вычисляет строку-ресурс для отображения в строке состояния путем добавления индекса (с нулевой базой) всплывающего меню к значению, на которое ссылается lpwIDs. Для того чтобы это работало правильно, необходимо, чтобы четвертый параметр функции MenuHelp hMainMenu — имел значение описателя родительского по отношению к всплывающему меню окна. Структура, приведенная ниже, обеспечивает удобный путь для установки соответствия между описателями меню и базой строковых ресурсов:

typedef struct tagPOPUPSTRING

{

HMENU hMenu; UINT uiString;

} POPUPSTRING;

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

437

POPUPSTRING popstr[5];

и инициализируется при создании строки статуса следующим образом:

HMENU

hMainMenu

= GetMenu(hwndParent);

popstr[0].hMenu

= hMainMenu;

popstr[0].uiString

= IDS_MAIN_MENU;

popstr[1].hMenu

= GetSubMenu(hMainMenu, 2);

popstr[1].uiString

= IDS_TOOLBAR_MENU;

popstr[2].hMenu

= GetSubMenu(hMainMenu, 3);

popstr[2].uiString

= IDS_STATUSBAR_MENU;

popstr[3].hMenu

= NULL;

popstr[3].uiString

= 0;

При получении сообщения WM_MENUSELECT параметр lParam содержит описатель меню родительского окна. Работа функции MenuHelp по подбору правильного ресурса строки требует от вас поиска в массиве и передачи адреса, как последнего параметра функции MenuHelp. Ниже показано, как это реализуется в программе GADGETS:

if((fuFlags & MF_POPUP) &&(!(fuFlags & MF_SYSMENU)))

{

for(iMenu = 1; iMenu < MAX_MENUS; iMenu++)

{

if((HMENU) lParam == popstr[iMenu].hMenu)

{

hMainMenu =(HMENU)lParam; break;

}

}

}

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

Просмотр системного меню

Функция MenuHelp обеспечивает индикацию в строке состояния вспомогательной информации для системного меню и элементов системного меню. Все, что необходимо для этого — параметры сообщения WM_MENUSELECT wParam и lParam в том же виде, что и для других типов элементов меню. Кроме того, значение hMainMenu не должно быть равно реальному описателю системного меню; NULL — вполне подходит.

Пример

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

LRESULT Statusbar_MenuSelect(HWND hwnd, WPARAM wParam, LPARAM lParam)

{

UINT fuFlags =(UINT) HIWORD(wParam); HMENU hMainMenu = NULL;

int iMenu = 0;

// Обработка несистемных всплывающих меню if((fuFlags & MF_POPUP) &&(!(fuFlags & MF_SYSMENU)))

{

for(iMenu = 1; iMenu < MAX_MENUS; iMenu++)

{

if((HMENU) lParam == popstr[iMenu].hMenu)

{

hMainMenu =(HMENU)lParam; break;

}

}

}

// Отображение вспомогательной информации в строке состояния

MenuHelp(WM_MENUSELECT, wParam, lParam, hMainMenu, hInst, hwndStatusBar, &((UINT) popstr[iMenu].hMenu));

return 0;

}

Соседние файлы в предмете Операционные системы