Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
65-96.doc
Скачиваний:
5
Добавлен:
11.11.2019
Размер:
340.99 Кб
Скачать

Создание средств разделения окна

Разделяемое окно — это особая разновидность окна-рамки. Каждая его часть (pane — панель) содержит свое представление документа. Разбить окно на части может сама программа при его создании или пользователь, выбрав соответствующую команду меню, либо переместив маркер разбивки на полосе прокрутки. Границу между двумя панелями называют линией разбивки. Маркер разбивки позволяет корректировать размеры панелей, для этого его перемещают мышью.

Разделяемое окно является объектом класса CSplitterWnd, оно занимает всю клиентскую область окна-рамки класса CFrameWnd. В панелях разделяемого окна располагаются окна представления. Активное окно представления на панели разделяемого окна логически связано непосредственно с окном-рамкой. Разделенное окно является дочерним по отношению к главному окну приложения. В свою очередь, каждая панель — дочернее окно разделенного окна.

Окна могут разделяться динамически или статически. Динамически разделяемое окно (dynamic splitter window) можно разделять в любой момент. Панели в динамически разделяемом окне обычно связаны с одним классом представления. Поэтому при запуске приложения создается единственный объект представления. Когда пользователь разделяет окно-рамку, создаются другие объекты представления, которые уничтожаются при соединении панелей в единое окно-рамку. Статически разделяемое окно используется для нескольких классов представления. Все объекты представления конструируются при создании окна-рамки и удаляются при его уничтожении. Панели статически разделяемого окна определяются при первом создании окна, можно менять их размеры, но не количество. У каждой панели имеются свои полосы прокрутки.

Для создания разделяемого окна определяют объект класса CSplitterWnd. При создании главного окна библиотека MFC вызывает виртуальную функцию CFrameWnd::OnCreateClient(). Заданная по умолчанию версия этой функции, определенная в классе CFrameWnd, создает единственное окно представления, заполняющее область главного окна. Переопределенная версия этой функции вызывает функцию CSplitterWnd::Create() для объекта класса CSplitterWnd, чтобы создать разделяемое окно, а оно формирует первое окно представления. Разделяемое окно содержит одну панель. Вторая панель создается при выполнении двойного щелчка на маркере разбивки. Класс представления известен объекту класса CSplitterWnd, поскольку имя этого класса внедрено в структуру CCreateContext, которая передается в функцию CSplitterWnd::Create() в качестве параметра. Структура CCreateContext содержит указатели на окно-рамку, документ, окно представления и шаблон документа. Она также содержит указатель на CRuntimeClass, который идентифицирует создаваемый тип представления. Эта информация и указатель на текущий документ используются при создании нового представления динамически.

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

Однако MFC не вызывает функцию CMуPaintView::OnDraw() для второго объекта представления автоматически. Напомним, что при изменении документа необходимо обновить все представления его данных. Для этого в классе документа существует функция CDocument::UpdateAllViews(), которую вызывают в случае, если изменился документ и об этом надо уведомить все объекты представления, чтобы те обновили представления данных. Следовательно, после прорисовки линии в одном окне представления необходимо явно вызвать функцию CDocument::UpdateAllViews() для объекта документа, чтобы MFC вызвала CMуPaintView::OnDraw() для другого окна представления. Если в функцию UpdateAllViews() класса CDocument передан параметр 0, то все окна представлений будут перерисованы. При включении горизонтального и вертикального маркеров разбивки программа с однодокументным (однооконным) интерфейсом может иметь до четырех представлений данного документа.

Функция CDocument::UpdateAllViews() вынуждает программу вызывать функцию OnDraw() класса представления для всех связанных с документом представлений, кроме указанного в первом параметре. В программе MуPaint передача параметра this в функцию CDocument::UpdateAllViews() вызывает функцию CMуPaintView::OnDraw() только для второго и других представлений. Текущее окно представления не нуждается в перерисовке, так как новая линия в нем уже отображается. Таким образом, если линия нарисована в одной панели, то она появится и в другой.

Функция CView::OnDraw() не вызывается до тех пор, пока пользователь не изменит размеров окна вида, не прокрутит изображение в нем или не сделает его активным, выведя его на передний план после его перекрывания другими окнами. Область окна представления, которая перекрывается другими окнами или становится невидимой в результате прокрутки либо изменения размеров окна, называется недействительным прямоугольником. Недействительная часть окна представления называется областью обновления. При возникновении недействительного прямоугольника окно представления должно перерисовываться.

Для объявления области окна представления недействительной явно вызываются функция CWnd::InvalidateRect() или CWnd::Invalidate(). Класс представления приложения наследует эти функции из класса CWnd. При вызове функции CWnd::InvalidateRect() недействительная прямоугольная область добавляется к текущей области обновления, т.е. отмечается как требующая перерисовки. Когда окно представления получает непустую область обновления, то после обработки любых сообщений с более высоким приоритетом вызывается функция CView::OnDraw(), и область обновления становится пустой. Функция CView::OnDraw() вызывается в ответ на Windows-сообщение WM_PAINT, которое посылается функциями CWnd::InvalidateRect() или CWnd::Invalidate(). Область становится недействительной также вследствие ответа Windows на событие, требующее перерисовки некоторой части рисунка (например, передвинуто верхнее из перекрывающихся окон). При необходимости CView::OnDraw() может получить доступ к параметру недействительного прямоугольника, переданному функции CWnd::InvalidateRect().

Для оптимизации процесса перерисовки необходимо учесть следующее.

Windows обновляет пиксели только внутри недействительного прямоугольника. Поэтому, чем меньшего размера будет недействительный прямоугольник, тем быстрее он будет перерисован. Исполнение команд перерисовки за пределами недействительного прямоугольника не имеет смысла. Функция CView::OnDraw() могла бы вызывать для определения недействительного прямоугольника функцию-член CDC::GetClipBox() и тем самым избегать перерисовки объектов за пределами этого прямоугольника.

Функция CView::OnDraw() вызывается не только в ответ на вызов CWnd::InvalidateRect(), но и в тот момент, когда пользователь изменяет размер окна или делает его видимым. Таким образом, функция CView::OnDraw() отвечает за все виды перерисовки в окне и должна обрабатывать любые недействительные прямоугольники, о которых ей сообщают. Рисовать вне клиентской области обычно не разрешается и большинство сообщений, связанных с мышью, принимается, только когда курсор мыши находится в этой области.

В функцию CWnd::InvalidateRect() передаются координаты устройства. Если эти координаты не принадлежат области окна представления (например, одно окно представления в настоящее время не отображает часть рисунка, измененную в другом окне), часть окна представления не становится недействительной.

Если окно представления нуждается в перерисовке из-за внешнего события, например, перемещения перекрывающего окна, то Windows также признает недействительной только ту область окна, которая нуждается в перерисовке. Функция CView::OnDraw() перерисовывает только изображение, попавшее в эту область.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]