Визуальное программирование и MFC

       

Синхронизация окон просмотра документа


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

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

К сожалению, окна просмотра одного документа несогласованны. Если в документ внести изменения через одно окно, они не появятся во втором до тех пор, пока содержимое второго окна не будет перерисовано. Чтобы избежать рассогласования между окнами просмотра одного и того же документа, необходимо сразу после изменения документа в одном окне вызвать метод UpdateAllViews, определенный в классе CDocument:

void UpdateAllViews(CView* pSender, LPARAM lHint=0l, CObject* pHint=NULL);

Метод UpdateAllViews вызывает метод CView::OnUpdate для всех окон просмотра данного документа, за исключением окна просмотра, указанного параметром pSender. Как правило, в качестве pSender используют указатель того окна просмотра, через которое был изменен документ. Его состояние изменять не надо, так как оно отображает последние изменения в документе.

Если изменение документа вызвано другими причинами, не связанными с окнами просмотра, в качестве параметра pSender можно указать значение NULL. В этом случае будут вызваны методы OnUpdate всех окон просмотра без исключения.

Параметры lHint и pHint могут содержать дополнительную информацию об изменении документа. Методы OnUpdate получают значения lHint и pHint и могут использовать их, чтобы сократить перерисовку документа.

Нужно отметить, что содержимое других окон при таком способе использования метода UpdateAllViews перерисовывается полностью, несмотря на то, что дорисовать нужно только одну фигуру. Перерисовка всех объектов может заметно замедлить работу приложения.

Выход из этого положения существует. При вызове метода UpdateAllViews можно указать, какой объект надо дорисовать.
А потом нужно переопределить метод OnUpdate так, чтобы приложение дорисовывало в окнах просмотра только новую фигуру. Для передачи информации от метода UpdateAllViews методу OnUpdate используют параметры lHint и pHint.

Рассмотрим более подробно, как работает метод OnUpdate:

virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);

Первый параметр pSender содержит указатель на объект класса окна просмотра, который вызвал изменение документа. Если обновляются все окна просмотра, этот параметр содержит значение NULL.

Второй и третий параметры - lHint и pHint - содержат дополнительную информацию, указанную во время вызова метода UpdateAllViews. Если дополнительная информация не определена, тогда эти параметры содержат соответственно значения 0l и NULL.

Метод OnUpdate вызывается, когда после изменения документа вызывается метод CDocument::UpdateAllViews. Метод OnUpdate также вызывается методом OnInitialUpdate (если он не переопределен в приложении).

Реализация OnUpdate из класса CView определяет, что внутренняя область окна просмотра подлежит обновлению и передает данному окну сообщение WM_PAINT (для этого вызывается функция InvalidateRect). Это сообщение обрабатывается методом OnDraw.

Параметр lHint имеет тип LPARAM и может содержать любое 32-битное значение. Параметр pHint является указателем на объект типа CObject. Поэтому, если есть необходимость его использовать, нужно определить собственный класс, наследованный от базового класса CObject, создать объект этого класса и передать указатель на него методу UpdateAllViews.

Указатель на объект класса, наследованного от CObject, можно присвоить указателю на объект класса CObject, поэтому такая операция разрешена. Следовательно, через этот указатель можно передавать объекты различных типов, наследованных от CObject.

При разработке метода OnUpdate необходимо проверять тип объекта, передаваемого через параметр pHint. Для этого можно воспользоваться методом IsKindOf класса CObject. Метод IsKindOf позволяет узнать тип объекта уже на этапе выполнения приложения.

Когда переопределяется метод OnUpdate, необходимо иметь в виду, что этот метод вызывается не только методом UpdateAllViews. В некоторых случаях он может быть вызван, если надо перерисовать все изображение в окне просмотра. В этом случае параметр lHint содержит 0, а параметр pHint - NULL. Необходимо обрабатывать эту ситуацию отдельно, вызывая метод CView::OnUpdate и обновляя все окно целиком.


Содержание раздела