Разделить вид на две с помощью кнопки меню? (МФЦ)
У меня написана программа MFC, которая читает файлы, сохраняет данные и рисует их в виде текста в представлении клиента.
Я хочу сделать кнопку меню View->Split, которая разбивает клиентскую область на два, отдельно прокручивающихся вида, отображающих одни и те же данные.
Я видел некоторые вещи о CWndSplitter онлайн и прочитал некоторую документацию, но ни одна из них не оказалась полезной, потому что они говорят об использовании OnCreate и удалении представления по умолчанию, чтобы заставить его работать. Это не вариант. Я хочу сохранить вид по умолчанию, но разделить его на две части, если пользователь нажимает кнопку.
В настоящее время я создал переменную-член CWndSplitter и определил обработчик события кнопки меню в моем SDI-1View.cpp. При вызове он делает абсолютно ничего, только заставляет экран мерцать, а второй щелчок вызывает сбой программы.
void CSDI1View::OnViewSplit32778()
{
// TODO: Add your command handler code here
/*
int rows = 2;
int columns = 1;
if (!m_wndSplitter.CreateStatic(this, rows, columns))
return;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CSDI1View), CSize(100, 100), NULL) ||
(!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CSDI1View), CSize(100, 100), NULL)))
{
m_wndSplitter.DestroyWindow();
return;
}
*/
}
Может кто-нибудь сказать мне, каков нормальный подход к разделению клиентского представления пополам? Я просто хочу интегрировать это в обработчик событий. Любая помощь будет принята с благодарностью.
Благодарю.
--------------------------------РЕДАКТИРОВАТЬ----------------- -----------------
Теперь у меня есть следующий код в моем обработчике событий кнопки Split, благодаря схеме, предоставленной xMRi, но он все еще не работает должным образом...
void CMainFrame::OnViewSplit()
{
// TODO: Add your command handler code here
//calculate client size
CRect cr;
GetClientRect(&cr);
if (!m_mainSplitter.CreateStatic(this, 2, 1))
{
MessageBox(_T("Error setting up splitter frames! (CreateStatic)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
// Set the parent of the splitter window to the current view
CSDI1View * view = CSDI1View::GetView();
m_mainSplitter.SetParent(this);
view->SetParent(&m_mainSplitter);
// Create a CCreateContext
CCreateContext cc;
CRuntimeClass* prt = RUNTIME_CLASS(CSDI1View);
cc.m_pNewViewClass = prt;
cc.m_pCurrentDoc = view->GetDocument();
cc.m_pNewDocTemplate = NULL;
cc.m_pLastView = NULL;
cc.m_pCurrentFrame = this;
if (!m_mainSplitter.CreateView(0, 0,
cc.m_pNewViewClass,
CSize(cr.Width(), cr.Height()/2), &cc))
{
MessageBox(_T("Error setting up splitter frames! (CreateView 1)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
if (!m_mainSplitter.CreateView(1, 0,
cc.m_pNewViewClass,
CSize(cr.Width(), cr.Height()/2), &cc))
{
MessageBox(_T("Error setting up splitter frames! (CreateView 2)"),
_T("Init Error!"), MB_OK | MB_ICONERROR);
return;
}
m_bInitSplitter = TRUE;
}
После нажатия кнопки view->split я получаю всплывающее окно "Ошибка отладки утверждения", и первый вызов CreateView возвращает FALSE, отображая мое сообщение: "Ошибка при настройке разделителей! (CreateView 1)"
2 ответа
Статический разделитель предназначен для статического разделения, то есть окна, которое всегда разделено. Вы обычно используете его, когда вы хотите иметь разные представления на каждой панели разделения (например, отображать столбец чисел на одной панели и график на другой панели).
Для ситуации, подобной вашей, вы хотите иметь возможность иметь окно, а затем разбить его и получить два по существу идентичных представления, и вы (по крайней мере обычно) захотите использовать динамический разделитель.
По крайней мере, обычно вы создаете сплиттер при создании представления. Это создаст окно с ручкой в правом верхнем углу, который пользователь тянет вниз, чтобы разделить вид:
Чтобы разделить окно, пользователь нажимает на ручку:
Когда разделение происходит там, где они этого хотят, они отпускают кнопку мыши, и представление разделяется на две отдельно прокручиваемые секции:
Поскольку вы не указали, хотите ли вы вертикальное или горизонтальное разбиение, я настроил это, чтобы разрешить одно или оба:
Код для этого выглядит примерно так:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) {
return my_splitter.Create(this,
2, 2, // 2 rows, 2 columns
CSize(20, 20), // minimum pane size
pContext);
}
где my_splitter
определяется примерно так:
CSplitterWnd my_splitter;
Если вы хотите использовать окно сплиттера по требованию, вам нужно изменить родительский элемент текущего представления. Итак, шаги:
- создать простое приложение SDI
- По запросу создайте окно сплиттера
- Используйте SetParent для текущего представления и установите его в качестве родителя в окне разделителя.
- Создайте другое окно во втором сплиттере.
И обратный путь.
- Используйте SetParent и прикрепите обычный вид назад к основному кадру.
- Уничтожить сплиттер
Существуют активные примеры того, как переключить представление в текущем документе ( MSDN). Это поможет вам, как идентификаторы должны быть заменены и изменены.