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, воистину герой сегодняшнего выпуска, в письме с ответом на предыдущий вопрос также недоумевал по поводу вопроса прошлого выпуска, где требовалось минимизировать CPropertySheet: