Отслеживание состояния команд
Функция GetParentFrame, полученная в наследство от класса CWnd, прбдвигаясь снизувверх, ищет среди родительских окон ближайшее окно-рамку. В нашем случае в этой цепи будет одно промежуточное окно типа MDICLIENT, управляемое классом cwnd. Отметим, что тип MDICLIENT не документирован, но известно, что он служит для управления окнами-рамками типа CMDlchildWnd, располагающимися в клиентской области главного окна приложения. Наши классы CTreeFrame и CDrawVrame являются потомками CMDlchildWnd, поэтому ими-то и управляет секретное окно типа MDICLIENT. Существует и другой способ получить адрес главного окна (CMainFrame). Это вызов глобальной функции MFC AfxGetMainWnd. Мы используем его во второй версии OnSetFocus только для того, чтобы продемонстрировать оба способа.
Если вы запустите приложение в этот момент, то получите сообщение об ошибках, к которым пора привыкнуть, так как они встречаются довольно часто и вызваны тривиальной причиной – отсутствием видимости класса. Вставьте строку #include "MainFrm.h" в оба файла реализации окон-рамок. Затем запустите приложение вновь и, выбрав шаблон Tree, дайте команду View › Geometry. Вместе с окном другого типа вы увидите и другую панель инструментов. Дайте команду Window › Tile Vertically и проверьте все способы поочередной активизации окон. Панель инструментов и меню должны мгновенно отслеживать переход фокуса.
При записи нового документа в текущую папку или удалении файла из текущей папки ситуация, которую призван отражать класс CRightView, меняется. Для синхронизации вида с изменившейся ситуацией была введена в меню IDR_TreeTYPE команда View › Refresh. Если мы хотим создать обработчик этой команды, то надо решить, в каком классе это лучше всего сделать. Тут есть проблема, которая может быть сначала и не видна. Вы помните, что мы поместили команду Refresh только в одно меню IDR__TreeTYPE. Поэтому она будет доступна только тогда, когда активно окно CTreeFrame, что соответствует логике изменения содержимого правого окна. Мы исходим из того, что изменяемое окно должно быть видно пользователю.
Если создать обработчик только в одном из классов, то команда будет не всегда доступна. Ее доступность зависит от того, в каком из окон находится фокус. Например, пусть обработчик находится в классе CLeftview. Если щелкнуть мышью правое окно, то команда будет недоступна. Она станет вновь доступной, если щелкнуть мышью левое окно. Рассмотрите самостоятельно варианты размещения обработчика В классах CTreeFrame, CMainFrame, (CDrawFrame?). Наряду с доступностью обсудите, как добывать адреса нужных объектов.
Мы решили поместить обработчик в класс документа, так как при этом команда будет относиться к окну CRightView активного документа, что логично. Известным вам способом создайте заготовку функции обработки команды ID_VIEW_ REFRESH и приведите ее в соответствие со следующим фрагментом:
void CTreeDoc::OnViewRefresh(void) { //====== Получаем адрес левого представления CLeftView *pView = dynamic_cast<CLeftview*> (GetView(RUNTIME_CLASS(CLeftView))); //====== Запускаем цепочку действий для освежения //====== содержимого правого окна FreeDocs(); pView › SearchForDocs (pView › GetPath(pView › m_Tree.GetSelectedItem())); ProcessDocs(); }
Запустив приложение, вы опять получите сообщения об ошибках, и причины будут теми же. Вставьте в TreeDoc.cpp строку #include "Lef tview.h", а в Lef tview.h уберите упреждающее объявление класса CTreeDoc, но вставьте внутрь объявления класса CLeftview декларацию односторонней дружбы:
friend class CTreeDoc;
Теперь запуск должен пройти гладко. Проверьте работу команды View › Refresh, предварительно сохранив документ Save as в ту же папку, которая выбрана в левом окне.