Во-первых, основная проблема заключается в том, что в вашем слое "абстракции" нет абстракции.
Реализация тех же элементов управления, которые предоставляются ОС, и простое добавление префикса «Win32» к их именам не является абстракцией.
Если вы на самом деле не собираетесь упрощать и обобщать структуру, зачем вообще писать слой абстракции?
Чтобы это действительно было полезно , вы должны написать классы, представляющие понятия , которые вам нужны. И затем внутренне сопоставьте их с необходимым кодом Win32. Не создавайте класс Form
или Window
только потому, что в Win32 он есть.
Во-вторых, если вам нужны точные типы, я бы сказал, что отказываюсь от ООП-подхода и использую шаблоны.
Вместо функции
Form::addControl(Control &ctrl)
определить
template <typename Ctrl_Type>
Form::addControl(Ctrl_Type &ctrl)
теперь функция знает точный тип элемента управления и может выполнять любые специфичные для типа действия. (Конечно, если он должен сохранить элемент управления в списке в элементе управления, вы снова потеряете информацию о типе. Но информация о типе распространяется, по крайней мере, намного дальше, что может помочь.
Коллекция может хранить даже что-то вроде boost::variant
объектов, что позволит вам сохранять некоторую информацию о типах даже там.
В противном случае, если вы идете по маршруту ООП, по крайней мере, сделайте это правильно . Если вы собираетесь скрыть и EditBoxes, и CheckBoxes за общим IControl
интерфейсом, то это должно быть потому, что вам не нужен точный тип. Интерфейс должен быть всем, что вам нужно. В этом смысл интерфейсов.
Если этот контракт не соблюдается, если вы собираетесь все время понижать до фактических типов, то ваша хорошая иерархия ООП имеет недостатки.
Если вы не знаете, чего пытаетесь достичь, добиться успеха будет сложно. Какова цель этого Попытка написать «абстракцию пользовательского интерфейса, предоставляемого Windows», вы ничего не добиваетесь, поскольку именно это Windows уже предоставляет. Напишите уровни абстракции, если абстракция, предоставляемая Windows, не соответствует вашим потребностям. Если вам нужна другая иерархия, или вообще нет иерархии, или иерархия, в которой все не является формой или элементом управления, тогда имеет смысл написать слой абстракции. Если вам просто нужен слой, «такой же, как Win32, но с моим соглашением об именах», вы теряете время.
Итак, мой совет: начните с того, как бы вы хотели, чтобы ваш GUI-слой работал. И затем беспокоятся о том, как это должно быть сопоставлено с базовыми примитивами Win32. Забудьте, что вы когда-либо слышали о формах, диалоговых окнах, окнах редактирования или даже элементах управления или окнах. Все это концепции Win32. Определите понятия, которые имеют смысл в вашем приложении. Нет правила, согласно которому каждый объект в графическом интерфейсе должен происходить из общего класса или интерфейса Control. Нет правила, что должно быть одно «Окно» или «Холст» для всего, что нужно разместить. Это соглашение, используемое Windows. Напишите API, который имел бы смысл для you .
А затем выясните, как реализовать это с точки зрения доступных примитивов Win32.