On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru








 

Глава_18. Панель состояния

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

Для управления панелями состояния в состав библиотеки MFC включен класс CStatusBar . Как и классы CToolBar и CDialogBar , предназначенные для работы с панелями управления, класс CStatusBar также наследуется от базового класса CControlBar .

По умолчанию все приложения с оконным интерфейсом, построенные с помощью средства MFC AppWizard, имеют панель состояния (но можно при создании шаблона приложения и отказаться от этой возможности). В ней отображается текущее состояние приложения или краткая подсказка для выбранных строк меню, а также текущее положение клавиш <Caps Lock>, <Scroll Lock> и <Num>.

К сожалению, нет специальных ресурсов, предназначенных для разработки панелей состояния. Панель состояния создается 'вручную ', каждый элемент панели должен быть описан в специальным массиве (создание панели состояния на этапе разработки шаблона приложения осуществляет MFC AppWizard).

Создание пане ли состояния

Процесс создания панели состояния во многом схож с процессом создания панелей управления.

Сначала надо создать объект класса CStatusBar - он будет представлять панель состояния и управлять ею. Обычно для этого включают объект класса CStatusBar непосредственно в класс окна приложения, в котором будет размещена эта панель состояния :

	class CMainFrame : public CMDIFrameWnd
	{
	protected:
		CStatusBar m_wndStatusBar; // панель состояния
	// другие описания класса

	.......
	};

В некоторых случаях вместо использования класса CStatusBar от него предварительно наследуется дополнительный класс. В этом случае для создания панели состояния используют именно этот класс.

Следующим шагом является создание самой панели состояния и связывание ее с объектом, ее представляющим. Панель состояния создается вызовом метода Create класса CStatusBar:

	BOOL Create( CWnd* pParentWnd, DWORD dwStyle = 
		WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, 
		UINT nID = AFX_IDW_STATUS_BAR );

Через первый параметр указывается окно (родительское окно), для которого создается панель состояния.

Второй параметр позволяет задать характеристики панели управления, в том числе ее расположение внутри окна. Панель состояния является дочерним окном, поэтому в параметре стиля следует указать атрибут WS_CHILD. Атрибут WS_VISIBLE также следует указать, так как при его отсутствии панель не появится на экране, хотя и будет создана.

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

Последний параметр метода Create определяет идентификатор дочернего окна панели состояния. По умолчанию используется идентификатор AFX_IDW_STATUS_BAR.

Следует заметить, что приложения, созданные MFC AppWizard, имеют меню View, содержащие строки 'Toolbar' и 'Status bar'. Эти строки позволяют показывать и скрывать панели управления и состояния в главном окне приложения. Для обработки сообщений о выборе строки меню 'Status bar' используется метод OnUpdateControlBarMenu класса CFrameWnd. Причем этот метод может управлять отображением панели состояния, если только она имеет идентификатор AFX_IDW_STATUS_BAR.

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

Каждый элемент панели состояния (индикатор) должен иметь отдельный идентификатор, например :

	static UINT BASED_CODE indicators[] =
	{
		ID_SEPARATOR,		// индикатор информации о состоянии 

		ID_INDICATOR_CAPS,
		ID_INDICATOR_NUM,
		ID_INDICATOR_SCRL,
	};

Для того, чтобы связать каждый индикатор панели состояния с идентификатором текстовой строки (со строковым ресурсом), необходимо вызвать метод SetIndicators класса CStatusBar , передавая ему подготовленный массив идентификаторов . Этот метод загружает строковые ресурсы, соответствующие идентификаторам индикаторов, и размещает их на панели состояния. Через первый параметр передается указатель на массив идентификаторов индикаторов панели состояния. Общее количество индикаторов панели состояния, определенных в массиве идентификаторов, передается во втором параметре.

Обычно создание панели состояния производят при обработке сообщения WM_CREATE для главного окна приложения, например :

	int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
	{
		// вызов метода базового класса для корректного создания окна

		if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;

		// создание панели управления (процесс создания рассматривался выше)

		:::
		// создание панели состояния

		if (!m_wndStatusBar.Create(this) ||
			!m_wndStatusBar.SetIndicators(indicators,
				sizeof(indicators)/sizeof(UINT))) return -1;

		..........
		return 0;
	}

Метод SetIndicators отображает в панели состояния строки, идентификаторы которых представлены в массиве indicators. При этом первый элемент массива определяет крайнюю левую строку в панели состояния. По умолчанию, строки в панели состояния выравниваются по правой границе. Можно получить доступ к любому элементу панели состояния по его индексу или идентификатору.

Для того, чтобы определить, какой идентификатор имеется у того или другого индикатора, можно воспользоваться методом GetItemID. Этот метод возвращает идентификатор индикатора по его индексу (порядковому номеру в панели состояния). Обратная операция выполняется при помощи метода CommandToIndex.

Изменение характеристик индикаторов

После того, как при помощи метода SetIndicators индикаторы панели состояния созданы, можно изменить некоторые их характеристики, воспользовавшись методом SetPaneInfo:

	void SetPaneInfo( int nIndex, UINT nID, UINT nStyle, int cxWidth );

Параметр nIndex определяет порядковый номер индикатора в панели управления (его индекс). Характеристики этого индикатора будут меняться. Метод SetPaneInfo позволяет изменить расположение индикаторов на панели или даже заменить существующий индикатор на новый. Для этого можно указать новый идентификатор через параметр nID.

Внешний вид индикатора, заданного параметрами nIndex и nID, определяется параметрами nStyle и cxWidth. В качестве nStyle можно указать один или несколько атрибутов, объединенных логической операцией ИЛИ.

  • SBPS_NOBORDERS - убрать трехмерную рамку вокруг индикатора.
  • SBPS_POPOUT - обычная рамка вокруг индикатора создает впечатление, что индикатор расположен в углублении. Если указать атрибут SBPS_POPOUT, рамка изменятся таким рбразом, что индикатор будет располагаться выше общего уровня панели состояния.
  • SBPS_DISABLED - если указать этот атрибут, то в индикаторе не будет отображаться текст из соответствующего строкового ресурса.
  • SBPS_STRETCH - один из индикаторов панели состояния может менять свой размер в зависимости от размера окна. Атрибут SBPS_STRETCH предназначен для выбора этого индикатора.
  • SBPS_NORMAL - стандартный индикатор.

Если первый элемент массива идентификаторов, переданного методу SetIndicators, содержит константу ID_SEPARATOR, то для первого индикатора панели состояния по умолчанию устанавливаются атрибуты SBPS_NOBORDERS и SBPS_STRETCH.

Параметр cxWidth определяет ширину индикатора. Когда создается панель состояния и устанавливаются индикаторы при помощи вызова метода SetIndicators, размер индикаторов определяется автоматически исходя из ширины текста индикатора.

Узнать текущие характеристики индикатора можно при помощи метода GetPaneInfo . Он позволяет определить идентификатор, стиль и ширину идндикатора с индексом nIndex.

Если требуется определить или установить только стиль индикатора панели состояния, то вместо методов GetPaneInfo и SetPaneInfo лучше использовать два других метода класса CStatusBar: GetPaneStyle и SetPaneStyle.

Отображение текста в панели состояния

Для изменения текста в самом первом индикаторе панели состояния, который имеет идентификатор ID_SEPARATOR, можно воспользоваться методом SetWindowText . Этот метод определен в классе CWnd, и его можно использовать, так как класс панели состояния наследуется от класса CWnd. Строку, которую надо вывести в панели состояния, следует передать через параметр этого метода.

Метод SetTextWindow изменяет текст в панели состояния, передавая ему сообщение WM_SETTEXT. Самый первый индикатор панели состояния, который имеет идентификатор ID_SEPARATOR, отличается от остальных индикаторов панели состояния. В нем отображаются подсказки для выбранных строк меню, кнопок панели управления и в некоторых других случаях. Фактически этот индикатор используется различными объектами библиотеки MFC для отображения своего состояния или кратких подсказок.

Объекты MFC устанавливают текст первого индикатора, который имеет идентификатор ID_SEPARATOR, непосредственного передавая окну панели состояния сообщение WM_SETTEXT. Отсюда, кстати, следует один вывод : текст, который программист самостоятельно выводит методом SetWindowText, может быть изменен в любой момент без ведома программиста. Чтобы исправить такое положение, можно наследовать класс, в котором определить обработчик для сообщения WM_SETTEXT. Этот обработчик, например, может полностью игнорировать сообщения WM_SETTEXT или обрабатывать их только в особых случаях.

Если необходимо изменить текст не только в первом индикаторе, но и в других индикаторах панели состояния, можно воспользоваться методом SetPaneText , который определен в классе CStatusBar. Текст, который отображается в индикаторе в данный момент, можно определить при помощи метода GetPaneText , определенного в класса CStatusBar:

Еще один метод изменения индикаторов панели состояния основан на обработке сообщения ON_UPDATE_COMMAND_UI. Во время, когда приложение 'простаивает', сообщение ON_UPDATE_COMMAND_UI передается для всех индикаторов панели состояния (также как и для всех строк меню и всех кнопок панели управления).

Дополнительные возможности панели состояния

Если во время работы приложения выполняется какой-либо длительный процесс, то в панели состояния можно вывести линейный индикатор progress bar, чтобы показать ход данного процесса.

Методика размещения полосы progress bar достаточно проста. В тот момент, когда понадобится вывести полосу progress bar, просто нужно создать ее, указав в качестве родительского окна панель состояния. Координаты линейного индикатора желательно выбрать так, чтобы он отображался на месте одного из индикаторов (например, на месте индикатора с идентификатором ID_INDICATOR_PRBAR). Предварительно можно убрать рамку с этого индикатора и заблокировать его так, чтобы в нем не отображался текст.

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

	void CMainFrame::OnItemMenu() 
	{
		// получаем индекс индикатора ID_INDICATOR_
PRBAR
		int index=m_wndStatusBar.CommandToIndex(ID_INDICATOR_PRBAR);

		// устанавливаем характеристики индикатора ID_INDICATOR_
PRBAR
		m_wndStatusBar.SetPaneInfo(index,ID_INDICATOR_PRBAR, 
			SBPS_DISABLED|SBPS_NOBORDERS,150);

		// определяем координаты индикатора ID_INDICATOR_
PRBAR
		RECT r; m_wndStatusBar.GetItemRect(index,&r);

		// создаем линейный индикатор

		CProgressCtrl progress;
		if(!progress.Create(WS_CHILD|WS_VISIBLE,r,&m_wndStatusBar,1)) return;

		// устанавливаем границы для линейного индикатора

		progress.SetRange(0,100);

		// устанавливаем шаг приращения для линейного индикатора

		progress.SetStep(1);

		// плавно увеличиваем положение линейного индикатора

		for(int i=0; i<100; i++)
		{
			Sleep(10); // здесь можно выполнять действия


			// выполняем шаг приращения линейного индикатора

			progress.StepIt();
		}

		// отображаем текст в самом первом индикаторе

		m_wndStatusBar.SetWindowText("Progress completed");
	}
Назад       Содержание       Вперёд