Иллюстрированный самоучитель по Visual Studio .NET

Отслеживание состояния команд

Текущее состояние команды меню или кнопки на панели инструментов легко определяется по их облику: недоступная команда или кнопка имеет блеклый (grayed) вид. Кроме того, бывают команды, работающие по принципу переключателя (включен – выключен). Их состояние определяется по наличию – отсутствию флажка слева от команды меню или утопленному – нормальному облику кнопки.

Отслеживание состояния команд производится каркасом приложения в паузах между обработкой сообщений. В эти моменты вызывается виртуальная функция Onldle, и если вы ее переопределите для выполнения какой-либо своей фоновой задачи, то можете нарушить или замедлить процесс отслеживания состояния команд. Логика перехода между состояниями определяется специальными функциями т – обработчиками событий UPDATE_COMMAND_UI. Мы должны создать такой обработчик для отслеживания состояния команды ID_EDIT_NEWPOLY. Схема создания точно такая же, как и для самой команды, за исключением того, что вы вместо строки COMMAND выбираете строку UPDATE_COMMAND_UI:

void CDrawView::OnUpdateEditNewpoly(CCradUI *pCmdUI)
{
pCmdUI › SetCheck(m_bNewPoints);
}

Метод SetCheck вспомогательного класса ccmdui устанавливает флажок рядом с командой меню, если параметр имеет значение TRUE, или снимает его, если параметр имеет значение FALSE. Состояние кнопки на инструментальной панели синхронизировано с состоянием команды меню, имеющей тот же идентификатор.

Следующим шагом в развитии приложения будет введение в действие второй панели инструментов IDR_Draw_TYPE. Загрузка из ресурсов панели инструментов осуществляется методом LoadToolBar класса CToolBar. Так как объект этого класса (m_wndToolBar) хранится в классе главного окна (CMainFrame), то и смену панелей инструментов целесообразно выполнять в этом же классе. Введите в него новый метод:

void CMainFrame::ChangeToolbar(UINT tb)
{
//=== в параметре tb будет передан идентификатор панели
m_wndToolBar.LoadToolBar (tb);
//=== Перерисовка toolbar
RecalcLayout();
}

Метод CFrameWnd::RecalcLayout занимается перерисовкой панели инструментов и пересчетом размеров клиентской области окна, так как панель инструментов хоть и управляется классом главного окна, но расположена в клиентской области окна, отнимая у нее часть полезной площади.

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

Примечание
Здесь важно понять, что фокус на самом деле попадает в одно из дочерних окон CLeftView или CRightView или CDrawView. Но это происходит после того, как он попадет в родительское окно-рамку. В принципе, возможны и другие варианты решения проблемы своевременной смены панелей инструментов. Например, переопределить в каждом из трех представлений виртуальную функцию OnActivateView и в ней вызывать ChangeToolbar
.

Заметьте, что фокус может быть переведен в окно четырьмя разными способами:

  • активизация представления или его рамки при помощи левой кнопки мыши;
  • ввод клавишной комбинации (accelerator) CTRL + F6, которая обрабатывается каркасом приложения и по очереди в цикле активизирует окна;
  • системная активизация следующего окна при закрытии одного из окон;
  • системная активизация окна при создании одного из окон (вспомните вызов CreateNewFrame В теле CTreeDoc::MakeView) или открытии существующего документа.

Во всех четырех случаях окну-рамке будет послано сообщение WM_SETFOCUS, что нам и надо. Создайте известным вам способом обработчики рассматриваемого сообщения в двух классах окон-рамок CTreeFrame и CDrawFrame и наполните заготовки кодами, как показано ниже:

void CTreeFrame::OnSetFocus(CWnd* pOldWnd)
//====== Родитель делает свое дело,
CMDIChildWnd::OnSetFocus(pOldWnd);
//====== а мы делаем свое
((CMainFrame*)GetParentFrame())
 › ChangeToolbar(IDRJTreeTYPE);
void CDrawFrame::OnSetFocus(CWnd* pOldWnd)
CMDIChildWnd::OnSetFocus(pOldWnd);
((CMainFrame*)AfxGetMainWnd())
 › ChangeToolbar(IDR_DrawTYPE);
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.