Был у меня удачный опыт запуска GUI microwindows в связке с RTOS TNKernel на STM32F4 и дисплее от Samsung S5233. Всё вроде бы хорошо: рисует на экране окна и контролы, и всё это работает с тачскрином, но сделать богатый интерфейс на WinAPI очень сложно (по крайней мере для меня). Поэтому я решил пойти по пути Microsoft и написать оболочку над WinAPI по типу Windows Forms в .Net Framework. Ну, написать это сильно сказано, я просто беру исходники .Net Framework и тупо переделываю их с C# на C++. Сделал базовый класс Object, и классы Control, Form, Button, CheckBox, RadioButton и др. Всё это замечательно работало, пока не приступил к реализации меню MenuStrip из Windows Forms, и столкнулся с операторами языка C# “is” и ”as”, которых естественно в С++ нет.
Начнём с оператора проверки типа “is”. Использую компилятор IAR, в котором вроде бы есть RTTI, думал использовать typeid и type_info, но, то ли IAR их не поддерживает, то ли у меня ума не хватило использовать их, я решил пойти по другому пути. В базовом классе Object добавил член класа int id, в который заносится идентификатор в конструкторе класса, и метод bool Is(int id), который как раз и реализует оператор “is”:
Спойлер
Код: Выделить всё
namespace System {
class Type
{
public:
const static int TypeObject = 0;
const static int TypeString = 1;
const static int TypeControl = 2;
const static int TypeScrollableControl = 8;
const static int TypeForm = 3;
const static int TypeButtonBase = 4;
const static int TypeButton = 5;
const static int TypeCheckBox = 6;
const static int TypeLabel = 7;
const static int TypeRadioButton = 9;
const static int TypeListBox = 10;
const static int TypeComboBox = 11;
const static int TypeTextBoxBase = 12;
const static int TypeTextBox = 13;
const static int TypeMainMenu = 14;
const static int TypeMenuItem = 15;
const static int ArrangedElementCollection = 16;
const static int LayoutEngine = 17;
const static int EventArgs = 18;
const static int IArrangedElement = 19;
const static int FlowLayout = 20;
const static int DefaultLayout = 21;
const static int ControlEventArgs = 22;
const static int IMessageFilter = 23;
const static int IMessageModifyAndFilter = 24;
const static int ToolStripItemCollection = 200;
const static int ToolStripSplitStackLayout = 201;
const static int ToolStrip = 202;
const static int ToolStripItem = 203;
const static int ToolStripDropDownItem = 204;
const static int ToolStripMenuItem = 205;
const static int MenuStrip = 206;
const static int ToolStripItemRenderEventArgs = 207;
const static int ToolStripItemTextRenderEventArgs = 208;
const static int ToolStripRenderer = 209;
const static int ToolStripSystemRenderer = 210;
const static int ToolStripDropDown = 211;
const static int ToolStripLayoutData = 212;
const static int ToolStripItemLayoutOptions = 213;
const static int ToolStripItemInternalLayout = 214;
const static int ToolStripDropDownMenu = 215;
const static int ToolStripDropDownLayoutEngine = 216;
const static int ModalMenuFilter = 217;
};
class String;
class Object
{
public:
int id;
Object():
id(Type::TypeObject)
{ }
bool Is(int id)
{
return id == this->id;
}
virtual String ToString();
};
class String : public Object
{
public:
String()
{id = Type::TypeString;}
.
.
.
};
};
namespace System { namespace Windows{ namespace Forms{
class Control : public virtual Object, public IArrangedElement
{
public:
Control()
{id = Type::TypeControl;}
.
.
.
};
class ScrollableControl : public Control
{
.
.
.
};
class Form : public ScrollableControl
{
public:
Form ()
{id = Type::TypeForm;}
.
.
.
};
};};};Спойлер
Код: Выделить всё
bool res;
Object* o = new Object();
Control* c = new Control();
Form* f = new Form();
res = o->Is(Type::Object); //true
res = o->Is(Type::Control); //false
res = o->Is(Type::Form); //false
res = c->Is(Type::Object); //false - ошибка
res = c->Is(Type::Control); //true
res = c->Is(Type::Form); //false
res = f->Is(Type::Object); //false - ошибка
res = f->Is(Type::Control); //false - ошибка
res = f->Is(Type::Form); //trueСпойлер
Код: Выделить всё
namespace System {
class Type
{
public:
Type* BaseType;
Type(Type* baseType=0) :
BaseType(baseType)
{
}
static Type* Object;
static Type* Control;
static Type* Form;
};
Type* Type::Object = new Type();
Type* Type::Control = new Type(Type::Object);
Type* Type::Form = new Type(Type::Control);
class Object
{
public:
Type* type;
Object()
{ type = Type::Object; }
bool Is(Type* type)
{
Type* t = this->type;
while (t)
{
if (type == t) return true;
t = t->BaseType;
}
return false;
}
};
};
namespace System { namespace Windows{ namespace Forms{
class Control : public Object
{
public:
Control()
{ type = Type::Control; }
.
.
.
};
class Form : public Control
{
public:
Form()
{ type = Type::Form; }
.
.
.
};
};};};Спойлер
Код: Выделить всё
bool res;
Object* o = new Object();
Control* c = new Control();
Form* f = new Form();
res = o->Is(Type::Object); //true
res = o->Is(Type::Control); //false
res = o->Is(Type::Form); //false
res = c->Is(Type::Object); //true
res = c->Is(Type::Control); //true
res = c->Is(Type::Form); //false
res = f->Is(Type::Object); //true
res = f->Is(Type::Control); //true
res = f->Is(Type::Form); //trueА теперь собственно вопрос. Можно ли реализовать аналог оператора “is” из .Net на С++ каким ни будь другим способом, или автоматизировать мой вариант, чтобы не нужно было вручную прописывать каждый объект Type для каждого нового класса, а ведь их будет в будущем дофига.
Второй вопрос: реализация аналога оператора “as”, я даже не представляю как это сделать. Простое приведение типов не подходит потому как, например, следующие строки будут срабатывать не правильно:
Спойлер
Код: Выделить всё
Object* obj = new Object();
Control* c = new Control();
Form* f = new Form();
Control* temp;
//C# temp = obj as Control; //тут temp должен быть равен 0
temp = (Control*) obj; //а он равен obj
//C# temp = f as Control; //а тут temp равен f
temp = (Control*)f; //здесь верноЗаранее благодарен.
only pure true norwegian blackx 

