A. Для создания окна сплиттера в MFC служит класс CSplitterWnd. Этот класс предоставляет функции для создания вида (CreateView) и удаления вида DeleteView) в заданной панели, но не предоставляет функции, которая позволила бы перенести вид из одной панели в другую. Чтобы проделать это вручную, нужно понимать, каким образом связаны объект класса CSplitterWnd и объекты дочерних видов CView.

CSplitterWnd может иметь не более 16 панелей по горизонтали и столько же по вертикали. Таким образом, он может сожержать не более 256 панелей. Каждой панели соответствует уникальный идентификатор, который и назначается тому виду, который в этой панели находится. Отображение координат панели на её идентификатор выполняет функция int CSplitterWnd::IdFromRowCol(int row, int col);

На самом деле после целой серии ASSERT'ов она просто возвращает значение

AFX_IDW_PANE_FIRST + row * 16 + col

где AFX_IDW_PANE_FIRST — константа, объявленная в MFC.

Это подсказывает простой способ перемещения вида из одной панели в другую: нужно всего лишь подменить его идентификатор, после чего вызвать CSplitterWnd::RecalcLayout для обновления содержимого сплиттера. Если изначально вид не являлся дочерним окном сплиттера и требуется поместить его в одну из панелей, то необходимо также поменять ему родителя с помощью функции CWnd::SetParent. Таким образом функция, вставляющая вид в заданную панель, может выглядеть примерно так:

class CMySplitter : public CSplitterWnd {

 …

 void InsertView(int nRow, int nCol, CWnd *pView) {

  pView->SetParent(this);

  pView->SetDlgCtrlID(IdFromRowCol(nRow, nCol));

 }

 …

}

Аналогичным образом вид переносится "в юрисдикцию" главного окна приложения, порождённого от CFrameWnd:

class CMyFrame : public CFrameWnd {

 …

 void InsertView(CWnd *pView) {

  pView->SetParent(this);

  pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

 }

 …

}

Имея в руках эти две функции, можно без труда решить поставленную задачу, располагая виды как на рис. A, B, C или любым другим способом. Ещё раз замечу, что после всех перемещений необходимо вызывать CSplitterWnd::RecalcLayout и CFrameWnd::RecalcLayout.

Alexander Shargin
ОБРАТНАЯ СВЯЗЬ

Alexander Shargin, воистину герой сегодняшнего выпуска, в письме с ответом на предыдущий вопрос также недоумевал по поводу вопроса прошлого выпуска, где требовалось минимизировать CPropertySheet:

Перейти на страницу:

Похожие книги