Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Операционная система Windows 95 для программиста

© Александр Фролов, Григорий Фролов
Том 22, М.: Диалог-МИФИ, 1993, 271 стр.

[Назад] [Содеожание] [Дальше]

2.2. Орган управления Statusbar

Процедура создания органа управления Statusbar намного проще процедуры создания Toolbar . Вы можете создать Statusbar либо с помощью функции CreateWindowEx на основе класса окна STATUSCLASSNAME , либо воспользоваться специально предназначенной для этого функцией CreateStatusWindow.

В первом случае вы можете создать Statusbar, например, так:

hwndSb = CreateWindowEx( 
  0L,                     // расширенный стиль окна
  STATUSCLASSNAME,        // класс окна для Statusbar
  "",                     // заголовок окна отсутствует
  WS_CHILD | WS_BORDER |  // стиль окна
  WS_VISIBLE | SBARS_SIZEGRIP,
  0, 0, 0, 0,             // координаты, ширина, высота
  hWnd,                   // идентификатор родительского окна
  (HMENU)IDS_STATUSBAR,   // идентификатор Statusbar
  hInst,                  // идентификатор приложения
  NULL );                 // доп. данные для окна

Обратите внимание на стиль SBARS_SIZEGRIP . Если Statusbar имеет этот стиль, его правый нижний угол принимает вид, показанный на рис. 2.2.

Рис. 2.2. Орган управления Toolbar , имеющий стиль SBARS_SIZEGRIP

Во втором случае вы должны вызвать функцию CreateStatusWindow , прототип которой приведен ниже:

HWND CreateStatusWindow(
    LONG style,       // стиль окна
    LPCTSTR lpszText, // текст для первой области Statusbar
    HWND hwndParent,  // идентификатор родительского окна
    UINT wID          // идентификатор Statusbar
);

Обычно создание органов управления Statusbar и Toolbar выполняется приложением при обработке функцией главного окна сообщения WM_CREATE.

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

Определение режима работы Statusbar

Орган управления Statusbar может работать в двух режимах - стандартном и упрощенном.

В первом режиме приложение может разделить окно Statusbar на несколько областей для раздельного вывода в эти области текста или графической информации.

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

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

Разделение Statusbar на области

Для того чтобы разделить Statusbar на несколько областей достаточно сразу после создания послать ему сообщение SB_SETPARTS :

SendMessage(hwndSb, SB_SETPARTS, 3, (LPARAM)ptWidth);

Через параметр wParam передается количество областей (в нашем примере создается три области).

Параметр lParam должен содержать адрес массива ширин областей Toolbar :

int ptWidth[3]; // таблица ширин для Statusbar

Количество элементов в массиве должно быть равно количеству областей, на которые делится Statusbar.

Однако это еще не все.

При обработке сообщения WM_SIZE вы должны выполнить повторное определение областей:

void WndProc_OnSize(HWND hwnd, UINT state, int cx, int cy)
{
  SendMessage(hwndTb, WM_SIZE, cx, cy);
  SendMessage(hwndSb, WM_SIZE, cx, cy);
  ptWidth[0] = cx/2;
  ptWidth[1] = cx/2 + cx/4;
  ptWidth[2] = -1;
  SendMessage(hwndSb, SB_SETPARTS, 3, (LPARAM)ptWidth);
  return FORWARD_WM_SIZE(hwnd, state, cx, cy, DefWindowProc);
}

Когда обработчик сообщения WM_SIZE передает сообщение WM_SIZE органам управления Toolbar и Statusbar, они устанавливают размеры своих окон.

Затем необходимо подготовить массив ширин областей Statusbar.

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

Запись текста в область Statusbar

Для записи текста в область Statusbar необходимо использовать сообщение SB_SETTEXT :

SendMessage(hwndSb,SB_SETTEXT,0, (LPARAM)"Statusbar, Part 1");
SendMessage(hwndSb, SB_SETTEXT,1 | SBT_NOBORDERS, (LPARAM)"");

Через параметр wParam передается номер области, который может быть скомбинирован при помощи логической операции ИЛИ с одной из констант, определяющих внешний вид области:

Константа Описание
SBT_NOBORDERS Текст рисуется без рамки
SBT_POPOUT Текст рисуется с рамкой, которая выглядит приподнятой над поверхностью окна Statusbar
SBT_RTLREADING Текст отображается справа налево (такой способ отображения используется, например, в арабских странах)
SBT_OWNERDRAW Текст (или графическое изображение) рисуется родительским окном во время обработки сообщения WM_DRAWITEM

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

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

Рисование графического изображения в области Statusbar

Если в сообщении SB_SETTEXT указать константу SBT_OWNERDRAW , родительское окно, создавшее Statusbar, может нарисовать в соответствующей области любое изображение или написать текст любым шрифтом, используя всю мощь графического интерфейса GDI.

Ниже мы привели фрагмент кода, который загружает из ресурсов приложения битовое изображение и передает его идентификатор через параметр lParam сообщения SB_SETTEXT . При этом номер области, в которой будет нарисовано это изображения, комбинируется с константой SBT_OWNERDRAW :

hSbLogoBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SBLOGO));
SendMessage(hwndSb, SB_SETTEXT, 2 | SBT_OWNERDRAW,
  (LPARAM)hSbLogoBmp);

Когда область Statusbar должны быть перерисована, родительское окно получает сообщение WM_DRAWITEM . Параметр wParam этого сообщения содержит идентификатор органа управления, которое послало сообщение, или ноль, если сообщение пришло от меню. В нашем случае через wParam будет передаваться идентификатор органа управления Statusbar.

Параметр lParam содержит указатель на структуру типа DRAWITEMSTRUCT (описание полей приведено для Statusbar):

typedef struct tagDRAWITEMSTRUCT 
{ 
    UINT  CtlType;     // не используется
    UINT  CtlID;       // идентификатор окна Statusbar
    UINT  itemID; // номер области, которая будет перерисована
    UINT  itemAction;  // не используется
    UINT  itemState;   // не используется
    HWND  hwndItem;    // идентификатор окна Statusbar 
    HDC   hDC;         // идентификатор контекста отобаржения
    RECT  rcItem;      // координаты области
    DWORD itemData;    // значение lParam сообщения SB_SETTEXT
} DRAWITEMSTRUCT;

Обработчик сообщения WM_DRAWITEM должен проверить содержимое поля CtlID - в этом поле должен находится идентификатор Statusbar. Далее обработчик может выполнить рисование, пользуясь контекстом отображения hDC в области, координаты которой передаются через поле rcItem.

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

Ниже мы привели фрагмент исходного текста приложения Smart Application, который рисует в самой правой области Statusbar небольшое графическое изображение:

void WndProc_OnDrawItem(HWND hwnd, 
  const DRAWITEMSTRUCT * lpDrawItem)
{
  if(lpDrawItem->CtlID == IDS_STATUSBAR)
  {
    LPDRAWITEMSTRUCT lpDis;
    HDC hdcMem;
    HBITMAP hbmOld;
    BITMAP bm;
    lpDis = (LPDRAWITEMSTRUCT)lpDrawItem;
    hdcMem = CreateCompatibleDC(lpDis->hDC);
    hbmOld = SelectObject(hdcMem, hSbLogoBmp);
    GetObject(hSbLogoBmp, sizeof(bm), &bm);
    BitBlt(lpDis->hDC, lpDis->rcItem.left, lpDis->rcItem.top,
      bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
    SelectObject(hdcMem, hbmOld);
    DeleteDC(hdcMem);
  }
  return FORWARD_WM_DRAWITEM(hwnd, lpDrawItem, DefWindowProc);
}

Если вы незнакомы с понятиями контекста отображения, не умеете работать с битовыми графическими изображениями или никогда не пользовались функцией BitBlt, мы рекомендуем вам обратиться к 14 тому "Библиотеки системного программиста", который называется "Графический интерфейс GDI в Microsoft Windows".

Если вам нужно нарисовать непрямоугольное или частично прозрачное изображение, недостаточно выбрать в качестве цвета фона цвет окна Statusbar, так как пользователь может легко изменить цветовую гамму оболочки Microsoft Windows 95. В этом случае мы рекомендуем вам использовать более сложные процедуры рисования с использованием растровых операций ROP . Всю необходимую для этого информацию, а также пример приложения (которое называется BMPLOGO) вы найдете в 14 томе "Библиотеки системного программиста".

Сообщения для Statusbar

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

SB_SETMINHEIGHT

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

wParam = (WPARAM) minHeight; // минимальная высота в пикселах

Значение параметра lParam должно быть равно нулю.

SB_SETTEXT

Запись текста в заданную область окна Statusbar.

wParam = (WPARAM) iPart | uType;  // область и тип отображения
lParam = (LPARAM) (LPSTR) szText; // адрес строки

Через параметр iPart передается номер области. Этот номер может комбинироваться при помощи логической операции ИЛИ с одной из нескольких констант, описанной нами ранее в разделе " Запись текста в область Statusbar".

Через параметр szText передается адрес строки текста. Если используется константа SBT_OWNERDRAW, параметр сообщения lParam служит для передачи произвольного 32-разрядного значения, например, идентификатора битового изображения.

SB_SETPARTS

Установка количества областей и определение правой границы каждой области.

wParam = (WPARAM) nParts;          // количество областей
lParam = (LPARAM) (LPINT) aWidths; // границы

Это сообщение мы подробно описали в разделе " Разделение Statusbar на области".

SB_SIMPLE

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

wParam = (WPARAM) (BOOL); // флаг режима

Параметр lParam должен быть равен нулю.

Если флаг fSimple принимает значение TRUE, Statusbar переключается в упрощенный режим. если FALSE - возвращается в стандартный режим.

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

SB_GETBORDERS

Определение ширины горизонтальной и вертикальной рамки окна Statusbar.

lParam = (LPARAM) (LPINT) aBorders; // адрес массива

Параметр wParam должен быть равен нулю.

Перед тем как послать окну Statusbar сообщение SB_GETBORDERS, вы должны подготовить массив из трех переменных типа int. В первый элемент массива будет записана ширина горизонтальной рамки, во второй - ширина вертикальной рамки, и в третий - ширина рамки между прямоугольниками.

SB_GETPARTS

Определение количества областей в окне состояния и координат правых границ этих областей.

wParam = (WPARAM) nParts;              // количество областей
lParam = (LPARAM) (LPINT) aRightCoord; // массив координат

Через параметр nParts передается количество областей, информация о координатах правых границ которых записывается в массив aRightCoord.

Функция SendMessage, пославшая сообщение SB_GETPARTS, возвращает количество существующих в окне Statusbar областей или нуль при ошибке.

SB_GETRECT

Определение границ заданной области в окне Statusbar.

wParam = (WPARAM) iPart;         // номер области
lParam = (LPARAM) (LPRECT) lprc; // границы области

Границы области, номер которой задан через параметр iPart, передается приложению через структуру типа RECT. Адрес этой структуры должен быть указан в параметре lprc перед посылкой сообщения.

SB_GETTEXT

Извлечение текста из заданной области Statusbar.

wParam = (WPARAM) iPart;           // номер области
lParam = (LPARAM) (LPSTR) szText;  // адрес буфера для текста

Функция SendMesage возвращает в младшем 16-разрядном слове длину текста, в старшем, константу 0, SBT_NOBORDERS, SBT_POPOUT или SBT_RTLREADING. Если родительское окно само рисует внутри области при обработке сообщения WM_DRAWITEM, возвращается 32-разрядное значение, которое было передано при посылке сообщения SB_SETTEXT.

Перед тем как извлекать текст из области Statusbar, необходимо определить размер буфера для записи соответствующей текстовой строки. Это можно сделать при помощи сообщения SB_GETTEXTLENGTH, описанного ниже.

SB_GETTEXTLENGTH

Определение длины строки для заданной области окна Statusbar.

wParam = (WPARAM) iPart; // номер области

Значение параметра lParam должно быть равно нулю.

Функция SendMesage возвращает точно такое же значение, как и для сообщения SB_GETTEXT.

[Назад] [Содеожание] [Дальше]