Проект со злосчастным сплиттером - внутри
К ужасу или счастью, выпало мне снова взять в руки поделку MS. Ну теперь-то я уже не студентота копипастная, сейчас со всем разберусь! Первое, что удивляет - низкий полет над API, практически тонкие обертки над POD-структурами, которые, при некоторой доле фантазии отлично гоняются туда-сюда. Суть меняется от того слабо, ибо объекты ядра быть таковыми не перестали, а вот этот ООП-цирк - это лишь смена парадигм и использование перегрузок функций во все поля.
"Инструменты"
Вообще, общая организация - пародия на "как у людей": отдельный класс-приложение (да-да, WinMain скрыт в недрах MFC), минимум один класс окна, общий предок - класс CObject, возможность использовать архитектуру документ-вид (почти MV), метаинформация и даже (!!!) графический редактор форм (правда, только для диалогов). А вот дальше начинается ужас: единый файл с уникальными идентификаторами ресурсов (помимо ресурсов, контролы тоже помечаются ID), адовая кодогенерация с макросами той-самой метаинформации, обработчиков сообщений и черт знает чего еще. Еще и разделение на "диалоговые приложения" (dialog-based), одно- и многодокументные интерфейсы (SDI и MDI соответственно). Есть тонкие моменты, которые могут вам неожиданно кинуться в колеса. Например, моему маленькому мозгу так и не удалось ни найти, не придумать реально работающий вариант диалога с разделителем (Splitter). Пришлось идти по стопам вопиющих на 5-8 странице выдачи гугла, где советуют в диалоге уместить (!) фрейм (по сути, обычное окно), в котором сделать сплиттер, в части которого добавить вид (!!!). Ну, конечно, при этом нужно пробрасывать события (системые сообщения). Говорят, это самый простой способ. Еще и учитывая, что вид создается динамически где-то внутри.
// Мы в OnCreate диалога
// Создаем фрейм внутри диалога
frameWnd_ = new CFrameWnd;
frameWnd_->Create(strMyClass, L"", WS_CHILD, CRect(0,0,1,1), this, NULL, 0, NULL);
frameWnd_->ShowWindow(SW_SHOW);
frameWnd_->MoveWindow(0,0,600,600);
// Создаем сплиттер внутри фрейма внутри диалога
splitter_->CreateStatic(frameWnd_, 1, 2); // We need to go deeper...)
// Создаем одну из двух вьюх в сплиттере
// Обратите внимание на третий аргумент: в макрос мы передаем тип вьюхи, а ее экземпляр
// где-то там создается. Чтобы ей как-то управлять из диалога, нужно извернуться =)
splitter_->CreateView(0,0,RUNTIME_CLASS(CMyView), CSize(200,200), &cCreateContext);
//...
[caption id="attachment_618" align="center" width="478"]

ЗЫ
В общем, было весело =) Для сравнения, как это реализовано в Qt, любопытные могут заглянуть в референс. Но печаль в том, что это делается в две строки - создание и добавление дочерних элементов методом QSplitter::AddWidget(QWidget*).
QSplitter *splitter = new QSplitter(parent);
QListView *listview = new QListView;
QTreeView *treeview = new QTreeView;
QTextEdit *textedit = new QTextEdit;
splitter->addWidget(listview);
splitter->addWidget(treeview);
splitter->addWidget(textedit);
Складывается крайне устойчивое впечатление, что MFC писался под какую-то конкретную задачу, если приходится отступать от парадигмы, которую диктует фреймворк, то решить задачу иногда становится проще на голом API системы. Ко всему прочему MFC скудно документирован (даже справочник в MSDN уступает референсу Qt, что уж говорить о адекватных семплах).
Линк к проекту сплиттера в диалоге MFC для внимательных =)
[caption id="attachment_598" align="aligncenter" width="300"]

Комментариев нет:
Отправить комментарий