Программисту-профессионалу
Строка состояний - одна из особенностей, по достоинству оцененных пользователями прикладных программ Windows. Она представляет собой расположенную вдоль нижнего края окна программы маленькую рамку, в которой выводится полезная информация о ходе выполнени текущей операции. Одно из назначений строки состояний - вывод контекстно-чувствительных подсказок по командам меню, другое - в том, чтобы показать пользователю, в каком режиме - вставки или замены текста - работает в данный момент программа. Некоторые строки состояний имеют даже индикаторы ("градусники"), которые при выполнении длительных операций визуально отображают степень завершенности задания.
Используемая при программировании библиотека классов Си++ - Microsoft Foundation Classes (MFC) - позволяет с легкостью создавать строки состояний, для чего используется класс CStatusBar. Однако если вы все еще разрабатываете свои программы с помощью комплекта SDK, то создание строк состояний потребует большой работы. Для этого раньше вам были нужны либо готовые, либо запрограммированные вами элементы управления. Помимо прочего, это означало, что каждая строка состояний отличалась от других и не было двух одинаковых.
Система Windows 95 предоставляет стандартную строку состояний в файле Comctl32.dll, библиотеке типовых элементов управления. Использование типового элемента строки состояний лишь чуть труднее, чем применение класса CStatusBar, и намного проще, чем самостоятельное составление программы. Даже если вам трудно удержатьс от соблазна перенести фрагменты старой программы в новую, стоит принять во внимание и другие варианты, чтобы ваша программа была похожа на другие прикладные программы Windows 95. А если старая программа у вас 16-разрядная, этот метод позволит избежать проблем при подготовке ее 32-разрядной версии.
Давайте начнем с краткого обзора того, как работают строки состояний и интерфейсы, которыми система Windows обеспечивает их. Затем мы вместе составим пару простых программ, демонстрирующих два варианта реализации наиболее удобных строк состояний. Все исходные тексты программ и файлы, упомянутые в этой статье, можно загрузить из оперативной службы PC Magazine Online.
Если вы хотите снабдить строкой состояний свою программу в среде Windows 95, то ваш первый шаг - это добавление предложения #include для заголовочного файла Commctrl.h и подключение компонуемой библиотеки Comctl32.lib. Затем, чтобы обеспечить загрузку и инициализацию библиотеки Comctl32.dll, в обработчик WM_CREATE вашей программы вы вводите следующее выражение:
InitCommonControls ();
Следующий шаг - добавить команды, формирующие строку состояний. Для этого можно воспользоваться одним из двух вариантов: использовать API-функцию метода CreateStatusWindow или старые надежные функции CreateWindow либо CreateWindowEx, передавая им им класса STATUSCLASSNAME. Более простой из этих двух методов - применение CreateStatusWindow, потому что ему необходимы только четыре параметра: стиль строки состояния, текст, ссылка на родительское окно и идентификатор элемента управления. При выполнении следующего предложения создается строка состояний, на которую изначально выводится текст "Ready"; ее родительское окно - hwndParent, а ее идентификатор - IDC_STATUS_BAR:
hwndStatusBar = CreateStatusWindow (WS_CHILD | WS_VISIBLE, "Ready",
hwndParent, IDC_STATUS_BAR);
Строка состояний в итоге содержит одну панель (pane), имеющую объемное "утопленное" изображение. Строка состояний автоматически располагается вдоль нижней границы родительского окна (для размещения ее вверху можно добавить стиль CCS_TOP к параметрам WS_CHILD и WS_VISIBLE) и имеет захват (grip) дл изменения размера окна в правом углу - похожие на след протектора линии, расположенные под углом 45'.
Если вы не хотите использовать строку состояний такого типа, существует множество способов ее изменения. Можно добавлять панели (до 255), посыла строке состояний сообщения SB_SETPARTS. Можно указать, будет ли изображение отдельных панелей "утопленным", выступающим или плоским, задавая текст на панелях с помощью сообщения SB_SETTEXT. При выполнении следующего фрагмента программы строка состояний делится на три панели примерно равной ширины:
RECT rect;
int nPaneWidth, nPanes [3];
GetWindowRect(hwndStatusBar, &rect);
nPaneWidth = (rect.right - rect.left) / 3;
nPanes [0] = nPaneWidth;
nPanes [1] = nPaneWidth * 2;
nPanes [2] = -1;
SendMessage(hwndStatusBar, SB_SETPARTS, 3, (LPARAM) nPanes);
Параметр wParam, сопровождающий сообщение SB_SETPARTS, задает число панелей. lParam указывает на целочисленный массив, определяющий положение правого пиксела каждой панели. Значение -1 для крайней правой панели сообщает строке состояний, что последняя панель должна заполнять все пространство до правой границы.
Ссылки на конкретные панели на многопанельной строке состояний осуществляются по индексу. Крайняя панель слева имеет индекс 0, первая панель справа от нее - 1 и т.д. Текст выводится на панель с помощью сообщени SB-SETTEXT строке состояний, задающего строку текста, индекс панели и ее стиль: "утопленный", плоский или выпуклый. При выполнении следующего фрагмента программы инициализируется трехпанельная строка состояний, текст на которых указывает номера панелей и их стиль:
SendMessage (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) "\tPane 0;
indented");
SendMessage (hwndStatusBar, SB_SETTEXT, 1 | SBT_NOBORDERS,
(LPARAM) "\tPane 1; flush");
SendMessage (hwndStatusBar, SB_SETTEXT, 2 | SBT_POPOUT, (LPARAM)
"\tPane 2; protruding");
Номер и стиль панели указываются с помощью объединения логическим ИЛИ индекса и идентификатора SBT в параметре wParam сообщения: при отсутствии флага SBT получается "утопленная" панель. lParam содержит указатель на строку. Расположенные в начале строки символы табуляции (\t) сообщают строке состояний о необходимости центрирования текста в панели. Текст, в начале которого нет символа табуляции, выравнивается по левому, а текст, начинающийся с двух символов табуляции, - по правому краю.
Вероятно, SB_SETPARTS и SB_SETTEXT - это два наиболее часто используемых сообщения строке состояний, но есть и другие сообщения (см. таблицу ниже). Одно из наиболее интересных сообщений - SB_SIMPLE, которое включает и отключает "простой" режим строки состояний. В этом режиме все панели временно заменяются одной. Отключение этого режима восстанавливает исходные панели и их содержимое. Одно из назначений простого режима состоит в выводе контекстно-чувствительной подсказки для пунктов меню без использования отдельной панели. Достаточно переключиться в простой режим, когда раскрывается меню, вывести текст подсказки на панель 0 и отменить простой режим при закрытии меню. Именно так в программе Word for Windows 7.0 реализован вывод подсказок для пунктов меню. Включение и выключение простого режима осуществляются просто. Следующее предложение включает этот режим,
SendMessage (hwndStatusBar, SB_SIMPLE, TRUE, 0);
а выражение
SendMessage (hwndStatusBar, SB_SIMPLE, FALSE, 0);
выключает его.
При использовании строки состояний в окне с изменяющимися размерами важно не забыть передать сообщения WM_SIZE строке состояний, чтобы она могла перестроиться при смене размеров окна. Для этого в процедуру работы с окном достаточно ввести следующий обработчик сообщений:
case WM_SIZE:
SendMessage (hwndStatusBar, WM_SIZE, wParam, lParam);
return 0;
Этот обработчик, если он есть в программе, обеспечит автоматическую привязку строки состояний к нижнему краю родительского окна изнутри.
Теперь давайте посмотрим, как все это перевести в команды, составив простую программу, использующую однопанельную строку состояний для вывода справок по пунктам меню. Исходный текст приведен на лист. 1. Обработчик WM_CREATE программы SBDemo1 создает строку состояний с помощью процедуры CreateStatusWindow, а ее обработчик WM_SIZE передает сообщения об изменении размеров окна, так что строка состояний всегда будет иметь надлежащие размеры и положение относительно родительского окна.
Сообщения линейке состояний | |
---|---|
Сообщение | Описание |
SB_GETBORDERS | Сообщает информацию о ширине границ строки состояний: верхней/нижней, левой/правой и между панелями. |
SB_GETPARTS | Сообщает информацию о числе панелей в строке состояний и положении правого края каждой из них. |
SB_GETRECT | Передает ссылку на ограничивающий панель прямоугольник. |
SB_GETTEXT | Сообщает текст и стиль панели. |
SB_GETTEXTLENGTH | Сообщает длину текста панели. |
SB_SETMINHEIGHT | Задает минимальную высоту панелей строки состояний. |
SB_SETPARTS | Задает число панелей, ширину и положение каждой из них. |
SB_SETTEXT | Задает текст и стиль панели. |
SB_SIMPLE | Включает и отключает "простой" режим строки состояний. |
Файл SBDemo1.rc содержит шаблон меню программы, включающий в себя четыре пункта меню верхнего уровня и связанных с ними раскрывающихся меню: File, Edit, View и Help. В rc-файле также имеется строковая таблица, идентификаторы строк которой отражают пункты меню-шаблона. В этой таблице определяется текст подсказки по каждому пункту меню. Например, идентификатор пункта меню File | New обозначен как IDM_FILE_NEW. Текст соответствующей справки ("Create a new document" - Создать новый документ) можно найти, отыскав идентификатор IDM_FILE_NEW в строковой таблице.
Функции "клея", связывающего текст подсказки со строкой состояний, выполняет обработчик WM_MENUSELECT модуля SBDemo1.c. Используя идентификатор выделенного в данный момент пункта меню, WM_MENUSELECT загружает соответствующий строковый ресурс и выводит его в строке состояний с помощью сообщения SB_SETTEXT. Сообщени WM_MENUSELECT посылаются при выборе пункта меню верхнего уровня, при выделении пункта раскрывающегос меню и при закрытии меню. Младшее слово параметра wParam содержит идентификатор пункта меню, если сообщение относится к пункту всплывающего меню, или индекс пункта меню, если сообщение касается пункта меню верхнего уровня. Старшее слово содержит двоичные флажки с дополнительной информацией, относящейся к этому пункту.
Обработчик WM_MENUSELECT модуля SBDemo1 сначала проверяет, равно ли старшее слово wParam - 0xFFFF, а lParam - нулю, если - да, значит, меню только что закрыто. В этом случае обработчик снова выводит на экран строку "Ready":
uItem = LOWORD (wParam);
fuFlags = HIWORD (wParam);
if ((fuFlags == 0xFFFF) && (lParam == 0))
SendMessage (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) "Ready");
Затем он сопоставляет значение параметра uItem с идентификатором пункта меню и, если они совпали, выводит на экран соответствующую строку. Чтобы облегчить сравнение, пунктам меню в модуле SBDemo1 присваиваются последовательные значения идентификаторов от 100 до 114:
else if ((uItem >=IDM_FILE_NEW) && (uItem <=IDM_HELP_ABOUT)) {
LoadString (hInstance, uItem, szHelpText, sizeof (szHelpText));
SendMessage (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) szHelpText);
}
Если ни одна из упомянутых выше проверок не дает положительного результата, обработчик выводит на экран пустую строку. Тем самым учитывается случай, когда с помощью указателя мыши выделяется пункт меню верхнего уровня или когда выделение попадает на разделительную полосу всплывающего меню:
else
SendMessage (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) "");
Результаты вы можете увидеть сами, раскрыв одно из меню программы SBDemo1 и наблюдая за строкой состояний при перемещении курсора вверх и вниз.
Единственный действующий пункт меню - это View|StatusBar, он включает и отключает строку состояний. Выполняющий эту задачу обработчик WM_COMMAND действует очень просто. Сначала он вызывает процедуру IsWindowVisible, чтобы выяснить, видна ли в настоящий момент строка состояний. Затем он использует процедуру ShowWindow, чтобы показать или скрыть строку состояний, и метод CheckMenuItem, чтобы выбрать или отменить выбор этого пункта меню.
Лист. 1. Исходный текст программы на языке Си++.//***************************************************** // // SBDemo1.h // //***************************************************** #define IDC_STATUS_BAR 100 #define IDM_FILE_NEW 100 #define IDM_FILE_OPEN 101 #define IDM_FILE_SAVE 102 #define IDM_FILE_SAVE_AS 103 #define IDM_FILE_PRINT 104 #define IDM_FILE_PRINT_PREVIEW 105 #define IDM_FILE_PRINT_SETUP 106 #define IDM_FILE_EXIT 107 #define IDM_EDIT_UNDO 108 #define IDM_EDIT_CUT 109 #define IDM_EDIT_COPY 110 #define IDM_EDIT_PASTE 111 #define IDM_VIEW_TOOLBAR 112 #define IDM_VIEW_STATUS_BAR 113 #define IDM_HELP_ABOUT 114 //***************************************************** // // SBDemo1.c // //***************************************************** #define <windows.h> #include <commctrl.h> #include "SBDemo1.h" LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { static char szWndClass[] = "SBDemo1"; WNDCLASS wc; HWND hwnd, MSG msg; wc.style = 0 ; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbWndExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wc.lpszMenuName = "MainHenu"; wc.lpszClassName = szWndClass; RegisterClass (&wc); hmnd = CreateWindow (szWndClass, "Status Bar Demo 1", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWNDESKTOP, NULL, hInstance, NULL); ShowWindow (hwnd, nCmdShow); UpdateWindow (hwnd); while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HMENU hMenu: static HINSTANCE hInstance; static HWND hwndStatusBar; UINT uItem, fuFlags; char szHelpText[64]; switch (message) { case WM_CREATE: // // Создание строки состояний. // InitCommonControls (); hwndStatusBar = CreateStatusWindow (WS.CHILD | WS_VISIBLE, "Ready", hwnd, IDC_STATUS_BAR); hInstance = ((LPCREATESTRUCT) lparam)->hInstance; return 0; case WH_SIZE; // // Пересылка сообщений WM_SIZE строке состояний. // SendMessage (hwndStatusBar, WM_SIZE, wParam, lParam); return 0; Case WM_MENUSELECT: // // Обновление информации в строке состояний при просмотре // пользователем меню. // uItem = LOWORD (wParam); fuFlags = HIWORD (wParam); if ((fuFlags == 0x FFFF) && (lParam == 0)) SendMessage (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) "Ready"); else if ((uItem >= IDM_FILE_NEW) && (uItem <= IDM_HELP_ABOUT)) { LoadString (hInstance, uItem, szHelpText, sizeof (szHelpText)); SendMessaae (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) szHelpText); } else SendMessage (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) ""); return 0; Case WM_COMMAND: // // Обработка сообщений о выбранных пунктах меню. // switch (LOWORD (wParam)) { case IDM_VIEW_STATUS_BAR: // // Вывести или убрать строку состояний. // hMenu = GetMenu (hwnd): If (IsWindowVisible (hwndStatusBar)) { ShowWindow (hwndStatusBar, SW_HIDE); CheckMenuItem (hMenu, IDM_VIEW_STATUS_BAR, MF_UNCHECKED) } else ( // Not visible ShowWindow (hwndStatusBar, SW.SHOW); CheckMenuItem (hMenu, IDM_VIEW_STATUS_BAR, MF_CHECKED); } return 0; } break Case WM_DESTROY: // // Закончить работу программы. // PostQuitMessage (0); return 0; } return DefWindowProc (hwnd, message, wParam, lParam); } //*************************************************** // // SBDemo1.rc // //*************************************************** #include "SBDemo1.h" MainMenu MENU BEGIN POPUP "&Flle" { MENUITEM "&New\tCtrl+N", IDM_FILE_NEW MENUITEM "&Open...\tCtrl+O", IDM_FILE-OPEN MENUITEM "&Save\tCtrl+S", IDM_FILE_SAVE MENUITEM "Save&As...", IDM_FILE_SAVE_AS MENUITEM SEPARATOR MENUITEM "&Print...\tCtrl+P", IDM_FILE_PRINT MENUITEM "Print Pre&view", IDM_FILE_PRINT_PREVIEW MENUITEM "P&rint Setup...", IDM_FILE_PRINT_SETUP MENUITEM SEPARATOR MENUITEM "E&xit", IDM_FILE_EXIT } POPUP "&Edit" { MENUITEM "Undo\tCtrl+Z", IDM_EDIT_UNDO MENUITEM SEPARATOR MENUITEM "Cu&t\tCtrl+X", IDM_EDIT_CUT MENUITEM "&Copy\tCtrl+C", IDM_EDIT_COPY MENUITEM "&Paste\tCtrl+V", IDM_EDIT_PASTE } POPUP "&View" MENUITEM "&Toolbar", IDM_VIEW_TOOLBAR MENUITEM "&Status Bar", IDM_VIEW_STATUS_BAR, CHECKED } POPUP "&Help" { MENUITEM "&About SBDemol...", IDM_HELP_ABOUT } END STRINGTABLE BEGIN IDM_FILE_NEW "Создать новый документ" IDM_FILE_OPEN "Открыть существующий документ" IDM_FILE_SAVE "Сохранить текущий документ" IDM_FILE_SAVE_AS "Сохранить текущий документ под другим именем" IDM_FILE_PRINT "Напечатать текущий документ" IDM_FILE_PRINT_PREVIEW "Показать, как будет напечатан документ" IDM_FILE_PRINT_SETUP "Изменить параметры печати" IDM_FILE_EXIT "Завершить работу программы" IDM_EDIT_UNDO "Отменить последнюю операцию" IDM_EDIT_CUT "Вырезать текущее выделение и поместить его в буфер обмена" IDM_EDIT_COPY "Скопировать текущее выделение в буфер обмена" IDM_EDIT_PASTE "Вставить содержимое буфера обмена в текущий документ" IDM_VIEW_TOOLBAR "Показать или спрятать инструментальную панель" IDM_VIEW_STATUS_BAR "Показать или спрятать строку состояний" IDM_HELP_ABOUT "Отображает информацию об этой программе" END
Пример программы SBDemo1 вполне хорош для начала, но можно сделать и значительно больше. Расширение возможностей SBDemo1 осуществляет программа SBDemo2, создающая многопанельную строку состояний. Она отображает подсказку по меню на плоской, а не на "утопленной" панели 0, а текущее состояние переключателей CapsLock, NumLock и ScrollLock на "утопленных" панелях в правой части строки состояний. Она также показывает, как лучше провести сопряжение строки состояний с рамкой окна, ограничив эффективную площадь пользовательской части окна - рабочая площадь за вычетом места, занятого строкой состояний, - с помощью "запавшего" прямоугольника стил WS_EX_CLIENTEDGE. Этот новый стиль используется в диалоговых окнах Windows 95, чтобы придать объемность средствам управления. В MFC он находит применение при обрамлении просмотровых окон, которые служат контейнерами для данных. Исходный текст SBDemo2 можно загрузить из PC Magazine Online.
После создания строки состояний в обработчике WM_CREATE программа SBDemo2 вызывает локальную функцию InitStatusBar и инициализирует ее. InitStatusBar посылает сообщение SB_SETPARTS, чтобы разделить строку состояний на четыре панели, с последующей отправкой четырех сообщений SB_SETTEXT, определяющих размеры панелей, их положение и первоначальный текст. Информацию о состоянии переключателей CapsLock, NumLock и ScrollLock предоставляет функция Windows - GetKeyboardState, которая копирует в локальный буфер массив из 256 байт с данными о состоянии отдельных клавиш. Нулевые разряды элементов VK_CAPITAL, VK_NUMLOCK и VK_SCROLL массива принимают значение 1, если включены переключатели CapsLock, NumLock и ScrollLock, и 0 - в противном случае. Заметим, что дл выравнивания по центру строк Caps, Num и Scroll в соответствующих панелях используются символы табуляции. Слово "Ready" на панели 0 выравнивается по левому краю, потому что перед ним нет символа табуляции.
Справка по меню на панели 0 обновляется обработчиком WM_MENUSELECT оконной процедуры точно так же, как это происходило в примере SBDemo1. Панели 1, 2 и 3 обновляются обработчиком WM_KEYDOWN, реагирующим на нажатие клавиш CapsLock, NumLock и ScrollLock. Когда нажимается любая из указанных клавиш, этот обработчик при помощи функции GetKeyState определяет новое состояние переключателя и соответствующим образом настраивает текст на строке состояний.
Размеры и положение панелей определяет функци PositionPanes, вызов которой осуществляется из обработчика WM_SIZE так, чтобы при изменении размеров окна три крайние правые панели оставались бы в том же положении по отношению к правому краю строки состояний. Важно, чтобы функция PositionPanes была вызвана после передачи сообщения WM_SIZE строке состояний, иначе размер этой строки не изменится. Первое сообщение WM_SIZE поступает до того, как окно впервые выводитс на экран, поэтому оконному обработчику WM_CREATE нет необходимости вызывать PositionPanes отдельно.
Функция PositionPanes использует сообщение SB_SETPARTS для конфигурирования панелей строки состояний. Размер и положение каждой панели определяются средней шириной символа шрифта строки состояний, причем по умолчанию используется 8-пунктовый шрифт MS Sans Serif. Название шрифта передается в сообщении WM_GETFONT. Затем этот шрифт выбирается во временный контекст устройства и для определения средней ширины символа вызывается функция GetTextMetrics. Шрифт, определяющий таким способом размеры и положение панелей на строке состояний, обеспечивает сохранение относительных пропорций панелей даже в случае изменени размеров экрана. Расчет пикселов, в зависимости от аппаратуры, хорош при значениях разрешения 640х480 и 1024х768, но в один прекрасный день, когда мы все запустим Windows с разрешением 2048х2048, вы будете рады, что связали размер панели строки состояний с размером шрифта. И даже если шрифт, используемый в строке состояний, когда-нибудь изменится, ваша программа автоматически настроит панели.
И наконец, рассмотрим последний аспект SBDemo2 - команды обработчика WM_PAINT, прорисовывающего "утопленную" рамку окна:
GetModifiedClientRect (hwnd, hwndStatusBar, &rect);
DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT);
GetModifiedClientRect - это локальная функция, которая рассчитывает эффективную площадь прямоугольного окна клиента, вычитая высоту линейки состояний из прямоугольника, размеры которого сообщаются функцией GetClientRect. DrawEdge - это новая функция Win32, которая прорисовывает разностильные рамки. Комбинаци параметров EDGE_SUNKEN и BF_RECT позволяет получить прямоугольник со стилем рамки WS_EX_CLIENTEDGE.
Вместо самостоятельной прорисовки рамки можно использовать подход, принятый в MFC, и перекрыть эффективное окно клиента окном просмотра WS_CHILD, тоже оформленным в стиле WS_EX_CLIENTEDGE. Теперь рамка прорисовывается автоматически, но необходимо изменить вашу программу таким образом, чтобы введенна информация либо обрабатывалась процедурой окна просмотра, либо передавалась для обработки "наверх" - главному окну. Главное окно должно также позаботитьс об изменениях размера окна просмотра при изменении собственных размеров.
Последнее различие между SBDemo1 и SBDemo2 заключается в процедуре обработки команд View|StatusBar. Эта процедура была изменена дл обеспечения гарантии правильности перерисовки границ окна, когда строка состояний видна или спрятана. При включении и выключении режима показа строки состояний обработчик аннулирует несколько рядов пикселов в нижней части окна, с тем чтобы соответствующая часть рамки также была перерисована.
Если вы хотите узнать больше о строках состояний Windows 95, попробуйте изменить программы-примеры, чтобы реализовать следующие функции.
Панель строки состояний, содержащая индикатор выполнения программы. Сделать это просто: создайте панель с помощью сообщения SB_SETPARTS и воспользуйтесь сообщением SB_GETRECT для получения соответствующего прямоугольника. Затем создайте индикатор выполнени программ в этом прямоугольнике и с помощью функции SetParent назначьте ему в родители строку состояний, а не главное окно программы. Это свяжет два объекта вместе так, что, когда перемещается строка состояний, индикатор выполнения программ будет передвигаться с ней.
Индикаторы CapsLock, NumLock и ScrollLock, выводящие на экран светло-серый текст вместо пустых строк, когда соответствующие переключатели выключены. Совет: в сообщении SB_SETTEXT можно передать другой стиль - SBT_OWNERDRAW, создающий нарисованную пользователем панель. Вы можете перехватить сообщения WM_DRAWITEM и начертить на панели такого типа все что угодно, в том числе и светло-серый текст.
Дополнительную информацию о строках состояний и их сообщениях можно найти в Windows 95 SDK.
ОБ АВТОРЕ: Джефф Просис - внештатный редактор PC Magazine.