Créer une bibliothèque graphique à partir de zéro - page 4

 
Реter Konow:
Qui sait pourquoi ça ne marche pas...

Il faut d'abord dessiner le schéma de la bibliothèque, puis écrire les codes. C'est généralement la façon de procéder.

fonctionne en C++

Qu'est-ce qui vous fait penser que le schéma n'a pas été établi, y avait-il un préalable à cela ? ??
 
Alexandr Andreev:

fonctionne en C++

Qu'est-ce qui vous fait penser qu'il n'y a pas de schéma, y avait-il un prérequis pour cela ?
Où se trouve-t-elle ? Je ne l'ai pas vu depuis trois pages.
 
Реter Konow:
Où se trouve-t-elle ? Je ne l'ai pas vu depuis trois pages.

Je pensais faire une base d'utilisation qui serait réduite à un style de code minimal New_Window<<<Window_Upper.Size ; New_Window<<Window_Upper.Position ; New_Window.Size<<0.5 (la taille devient automatiquement la moitié de ce qui précède) ; ...

Et cette classe tient déjà compte de la relation entre la position de la petite croix et la fenêtre supérieure (base).

On dirait que ça ne va pas se passer sans heurts... ça arrive.
 
Alexandr Andreev:

Je pensais faire une base d'utilisation qui serait réduite à un style de code minimal New_Window<<<Window_Upper.Size ; New_Window<<Window_Upper.Position ; New_Window.Size<<0.5 (la taille devient automatiquement la moitié de ce qui précède) ; ...

Et cette classe tient déjà compte de la relation entre la position de la petite croix et la fenêtre supérieure.

Ehhh, heh, heh.... "combien ça nous coûte de construire une maison, on va la dessiner, on va vivre..."

J'ai moi-même la même approche. Seulement, je le paie avec des années de dur labeur.
 
Алексей Барбашин:

...

J'ai déjà décrit à plusieurs reprises les "défauts" que, de mon point de vue, je vois dans la bibliothèque standard et dans la bibliothèque d'Anatoly.

Les deux bibliothèques présentent, à mon avis, un inconvénient de taille : l'interface est construite sur des objets graphiques discrets, c'est-à-dire que plus il y a de contrôles dans l'interface, plus il y a d'objets isolés dans le graphique lui-même. D'une part, ce n'est pas un problème en soi, mais d'autre part, c'est un problème avec les boîtes de dialogue glisser-déposer, car ce n'est pas un seul objet "formulaire avec éléments" qui est glissé, mais plusieurs éléments différents. Et cela consomme des ressources supplémentaires.

La bibliothèque d'Anatoly est très chic, mais elle est compliquée dans sa composition et difficile à intégrer dans le programme principal. Et la bibliothèque standard est limitée dans les contrôles eux-mêmes, bien que l'architecture originale soit très bonne à mon avis.

En fait, la meilleure solution serait ce que Petr Konov essaie de faire : un constructeur d'interface graphique avec génération de code d'interface graphique, mais avec un modèle d'événement étendu, de sorte que lors de l'intégration avec le programme principal, vous ne devez pas creuser dans un énorme code d'interface graphique (quelque chose comme MVVM analogique), et bien sûr avec des objets que les utilisateurs pourraient étendre eux-mêmes.

Bien entendu, il s'agit d'une vision très simplifiée du problème des bibliothèques graphiques. Il ne s'agit pas de glisser-déposer des formulaires et de l'absence de gestion des kanvas, qui limitent les possibilités et la fonctionnalité de l'interface graphique. En fin de compte, les objets MTont peu de propriétés, et les gestionnaires de bibliothèque ne sont pas suffisamment développés pour gérer les éléments dessinés et prendre en charge toutes leurs diverses capacités. La complexité des objets MT et la fonctionnalité de contrôle des bibliothèques n'atteignent pas le niveau minimum requis par kanvas.

Prendre ces bibliothèques et les réécrire pour kanvas signifie les élever à un niveau fondamentalement nouveau, ce qui a priori ne peut pas être facile et simple.


ZS. Anatoly a ouvert la voie aux kanvas dans sa bibliothèque et a été le premier à créer des tableaux dessinés en MKL. Cependant, la méthode pour les construire est imparfaite, du fait que les cellules sont des éléments semi-indépendants et qu'il est difficile de les traiter individuellement.

Je me souviens de ce que la transition a coûté à Anatoly et du temps qu'elle a pris.

 

C'est plus ou moins comme ça

#define  TEMPLATE(T) template<typename T>
#define  TEMPLATE2(T1,T2) template<typename T1, typename T2>

#define  TEMPL(T) TEMPLATE(T)
#define  TEMPL1(T) TEMPLATE(T)
#define  TEMPL2(T,T1) TEMPLATE2(T,T1)
//whats TD (template define)? because TT is busy
//почемуто этот код в шаблонах на мкл не хочет компилироваться поэтому через дефайн - это Плохо надо бы через шаблоны как то придумать.... привет метаквотам
#define  TD1 int
#define  TD2 double 
#define  EMPY -1 
#define  GET this.operator>> 
#define  SET this.operator<< 
class CCoordD; 
class CSizeD;
class CCoordBaseD //полностью внутрений класс
   {
   private:
   #define  ME CCoordBaseD 
   TEMPL1(T)
   bool Chek(T *a)                  {return CheckPointer(a)!=POINTER_INVALID;}
   TEMPL1(T)
   bool Chek(T a)                   {return a!=(T)EMPY;}
   TD1 Error()                      {Print(__FUNCTION__," ",__LINE__," POINTER_INVALID size"); int a[]; a[0]=0; return (TD1)EMPY;};//wtf??? =P CRASH Error
   TD1 GetA()                       {return c.GetA()+ar;}
   TD1 GetP()                       {return c.Result() + size.GetP()*(TD1)pr;}
   public:
   ME()                                   {Init();} 
   ME(TD1 a)                              {Init(a);} 
   ME(TD1 a,CCoordD &b)                   {Init(a,b);} 
   ME(TD1 a,CCoordD &b,CSizeD &x)         {Init(a,b,x);} 
   ME(TD2 a,CSizeD &b)                    {Init(a,b);} 
   ME(TD2 a,CCoordD &b,CSizeD &x)         {Init(a,b,x);} 
   CCoordD *c;//one coord
   CSizeD *size;//size 
   TD1 ar;
   TD2 pr;//percent проценты
   void Init()                            {ar=(TD1)EMPY; pr=(TD2)EMPY; }  
   TD1 Result()                           {return Chek(ar)?Chek(c)?GetA():ar:Chek(pr)?Chek(size)?GetP():Error():(TD1)EMPY;}
   ME *GetMe()                            {return &this;}
   ME *GetCoorBase()                      {return c;}
   ME *GetSizeBase()                      {return size;} 
   CCoordD *GetCoor()                     {return c;}
   CSizeD *GetSize()                      {return size;} 
   void Init(TD1 a)                       {Init(); SET(a);}
   void Init(TD1 a,CCoordD &b)            {Init(); SET(a); SET(b);}
   void Init(TD1 a,CCoordD &b,CSizeD &x)  {Init(); SET(a); SET(b); SET(x);}
   void Init(TD1 a,CSizeD &b,CCoordD &x)  {Init(); SET(a); SET(b); SET(x);}
 //  void Init(TD2 p)                     {Init(); pr=p_;}
   void Init(TD2 a,CSizeD &b)             {Init(); SET(a); SET(b);}
   void Init(TD2 a,CCoordD &b,CSizeD &x)  {Init(); SET(a); SET(b); SET(x);}
   void Init(TD2 a,CSizeD &b,CCoordD &x)  {Init(); SET(a); SET(b); SET(x);}
   void operator >> (TD1 a)               {a=ar;} 
   void operator >> (TD2 a)               {a=pr;}  
   void operator >> (CCoordD &a)          {a=GetPointer(c);}  
   void operator >> (CSizeD &s)           {s=GetPointer(size);}  
   void operator << (TD1 a)               {ar=a;} 
   void operator << (TD2 a)               {pr=a;}  
   void operator << (CCoordD &a)          {c=GetPointer(a);}  
   void operator << (CSizeD &s)           {size=GetPointer(s);}  
   void operator << (ME &a)               {a>>c; a>>ar; a>>pr; a>>size;}  
   void operator = (CCoordD &a)           {SET(a);}
   void operator = (CSizeD &a)            {SET(a);}
   void operator = (ME &a)                {SET(a);} 
   TD1 operator ~ ()                      {return Result();} 
   #undef  ME
   #undef  GET 
   #undef  SET
   };
   
class CSizeD : public CCoordBaseD
   {
   public:
   CSizeD(){};
   };
   
class CCoordD : public CCoordBaseD
   {
   public:
   CCoordD(){};
   };

class CCoord;

class CTX {public:CTX(){}}; 
class CTY {public:CTY(){}};
class CTZ {public:CTZ(){}};
TEMPL(T)
class CCoordA : public T
   {
   public:
   CCoordD ar; 
   CSizeD size;
   CCoordA()                                                {}; 
   CCoordA(TD1 a1,TD1 a2=(TD1)0)                            {Init(a1,a2);} 
   CCoordA(TD1 a1,CCoordD &c1, CSizeD &c2,TD1 a2)           {Init(a1,c1,c2,a2);}  
   CCoordA(TD1 a1,CCoordD &c1, CSizeD &c2,TD2 a2=(TD2)1)    {Init(a1,c1,c2,a2);}  
   CCoordA(TD2 a1,CCoordD &c1, CSizeD &c2,TD1 a2)           {Init(a1,c1,c2,a2);}  
   CCoordA(TD2 a1,CCoordD &c1, CSizeD &c2,TD2 a2=(TD2)1)    {Init(a1,c1,c2,a2);}   
   void Init()                                              {} 
   void Init(TD1 a1,TD1 a2=(TD1)0)                          {ar.Init(a1);        size.Init(a2);} 
   void Init(TD1 a1,CCoordD &c1, CSizeD &c2,TD1 a2)         {ar.Init(a1,c1,c2);  size.Init(a2,c1,c2);}  
   void Init(TD1 a1,CCoordD &c1, CSizeD &c2,TD2 a2=(TD2)1)  {ar.Init(a1,c1,c2);  size.Init(a2,c1,c2);}  
   void Init(TD2 a1,CCoordD &c1, CSizeD &c2,TD1 a2)         {ar.Init(a1,c1,c2);  size.Init(a2,c1,c2);}  
   void Init(TD2 a1,CCoordD &c1, CSizeD &c2,TD2 a2=(TD2)1)  {ar.Init(a1,c1,c2);  size.Init(a2,c1,c2);}  
   void operator <<(CSizeD &a)   {return ;}
   void operator <<(CCoordD &a)  {return ;} 
   bool Chek(int px)             {return (px-=(int)~ar) < 0 && px<(int)~size;}                   
   };
   
class CCoord
   {  
   public: 
   CCoordA<CTX> X;
   CCoordA<CTY> Y; 
   CCoord ()                              {} 
   void operator >> (CCoordA<CTX> &a)     {a=GetPointer(X);}
   void operator >> (CCoordA<CTY> &a)     {a=GetPointer(Y);}
   void operator << (CCoord &a)           {a>>X; a>>Y;}
   bool MouseOn(CMouse &mouse)//px
      {
      return X.Chek(mouse.X) && Y.Chek(mouse.Y);
      }
   };  
CCoord Pro1; 

void Func()
   {
   TD1 bi;//buf int
   TD1 bd;//buf double
   CCoord general;//создали класс координат некого объекта - к примеру окна дженерал
   general.X.Init((int)0,(int)1000); //установили размер
   general.Y.Init((int)0,(int)1000); 
   
   CCoord next;//создали класс координат следующего окна
   next<<general;//сделали его зависимым от главного окна
   next.X.ar<<(double)0.25;//старт по оси Х 25%, если значение типа дабл автоматически считается процент
   next.X.size<<(double)0.5;//размер окна равен 50% от главного.
   }
   #undef  TD1
   #undef  TD2
 
 

C'est la fin de la classe de coordonnées. Je ne sais même pas ce qui va suivre.

Je pense que nous devrions ajouter le positionnement, cependant.

Dans le style de next, in, left, top. cent.....

 
Alexandr Andreev:

Ça donne quelque chose comme ça.


#define  TEMPLATE(T) template<typename T>
#define  TEMPLATE2(T1,T2) template<typename T1, typename T2>

#define  TEMPL(T) TEMPLATE(T)
#define  TEMPL1(T) TEMPLATE(T)
#define  TEMPL2(T,T1) TEMPLATE2(T,T1)

Vous avez aussi oublié ceci :

#define  TE(T) TEMPL(T)
#define  TE1(T) TEMPL1(T)
#define  TE2(T,T1) TEMPL2(T,T1)
 
Alexandr Andreev:

Ça donne quelque chose comme ça.

#define  TD1 int
#define  TD2 double 

Et c'est ce qui manque :

#define  TD3 bool
#define  TD4
 void 
 
Aliaksandr Hryshyn:

Et c'est ce qui manque :

Je voulais utiliser des modèles mais ils ne compilent pas, l'exemple simplifié de la page précédente

Et il n'est pas sûr que ce sera exactement int et pas un certain enum, et alors vous ne voulez pas corriger le code

Et pourquoi avons-nous besoin d'un bool ici ?

Idéalement, il devrait en être ainsi

enum EPX{}//px
enum EPR{}//процент
#define  TD1 EPX
#define  TD2 EPR

Et pas de TD3 (en fait, la classe entière est écrite pour deux valeurs). Pourquoi j'ai appelé la TD également écrite dans le code

Raison: