Erstellen einer Grafikbibliothek von Grund auf - Seite 14

 
Versuchen Sie, ein vollwertiges Fenster zu erstellen. Wie ein Windows-Formular. Man kann es auch ohne Dynamik machen, aber da Sie es teilweise implementiert haben, denke ich, dass Sie ein Windows-ähnliches "Gummifenster" erhalten werden.
 
Реter Konow:
Versuchen Sie, ein vollwertiges Fenster zu erstellen. Wie ein Windows-Formular. Es geht auch ohne Dynamik, aber da Sie sie teilweise implementiert haben, werden Sie wohl ein Windows-ähnliches "Gummifenster" erhalten.
Der schwierigste Teil wird das Zeichnen der Knöpfe sein :))
 
Aliaksandr Hryshyn:
Der schwierigste Teil wird das Zeichnen der Knöpfe sein :))

Ja, ich dachte mir, dass das der schwierigste Teil ist, weil es keine gibt. ))))

 

Die Scrolls wurden separat erstellt, sie können auf eine bestimmte Fensterkonfiguration angewendet werden, der Rest (Ereignisse, Änderungen der erforderlichen Eigenschaften) wird automatisch durchgeführt. Die Verbindung zwischen ihnen ist sehr einfach:

   _scroll_v.Create(_main,_grid_cols,true,30);
   _scroll_h.Create(_main,_grid_cols,false,30);

Was dieSchwierigkeit , eine Tabelle zu erstellen, angeht: Die Engine ist sehr gut gelungen, so dass die Erstellung einer Tabelle mit ihr nicht so schwierig ist.

//+------------------------------------------------------------------+
//|                                                       V_grid.mqh |
//|                                               Aliaksandr Hryshyn |
//|                          https://www.mql5.com/ru/users/greshnik1 |
//+------------------------------------------------------------------+
#property copyright "Aliaksandr Hryshyn"
#property link      "https://www.mql5.com/ru/users/greshnik1"

#include  <Greshnik\\\Windows_engine\\Windows_engine_base.mqh>
#include <Greshnik\\\Windows_engine\\V_objects\\V_scrollbar.mqh>

enum eG_property
  {
   gp_=0,
  };
//Таблица
class V_grid
  {
   int               _cols;//Количество столбцов
   int               _rows;//Количество строк
   int               _cell_width;//Ширина клетки
   int               _cell_height;//Высота клетки
   int               _scroll_width;//Ширина полосы прокрутки
   int               _size_caption;//Размер заголовков
   int               _size_fixing_col;//Размер фиксированного столбца
   bool              _is_captions;//Наличие заголовков
   bool              _is_cols_fixing;//Наличие первого фиксированного столбца
   bool              _is_scroll_bar_v;//Наличие вертикальной полосы прокрутки
   bool              _is_scroll_bar_h;//Наличие горизонтальной полосы прокрутки

   cV_object_base    *_main;//Основное окно
   cV_object_base    *_grid_view;//Окно отображения сетки
   V_scrollbar       _scroll_v;//Вертикалдьная прокрутка
   V_scrollbar       _scroll_h;//Горизонтальная прокрутка
   cV_object_base    *_caption_v;//Окно отображения заголовков
   cV_object_base    *_caption;//Окно с заголовками
   cV_object_base    *_col_fixing_v;//Окно отображения фиксированного столбца
   cV_object_base    *_col_fixing;//Фиксированный столбец
   cV_object_base    *_grid_cols;//Столбцы.Отсюда брать массивы столбцов

   //События, которые влияют на вертикальную прокрутку
   class Events_scroll_v_change: public iE_event_handler
     {
   public:
      V_grid         *_v_grid;
      void           On_event(sEvent &event);
     };
   Events_scroll_v_change scroll_v_change;

   //События, которые влияют на горизонтальную прокрутку
   class Events_scroll_h_change: public iE_event_handler
     {
   public:
      V_grid         *_v_grid;
      void           On_event(sEvent &event);
     };
   Events_scroll_h_change scroll_h_change;

   //События перемещения сетки
   class Events_grid: public iE_event_handler
     {
   public:
      V_grid         *_v_grid;
      void           On_event(sEvent &event);
     };
   Events_grid       events_grid;
public:
   //Создание таблицы
   bool              Create(
      cV_object_base &parent_object,
      string name=NULL
   );
   //Возвращает указатель на основной объект
   cV_object_base*   Get_main_v_object();

   //Изменение основных свойств таблицы
   void              Set_property(
      eG_property grid_property,
      long property_value
   );
   //Получение значения свойства
   long              Get_property(
      eG_property grid_property
   );//При ошибке возвращает LONG_MAX

   //Поучение объекта ячейки таблицы
   cV_object_base*   Get_cell_object(
      int pos_x,//Индекс столбца
      int pos_y//Индекс строки
   );//Возвращает объект ячейки или NULL при ошибке

   //Получение объекта столбца таблицы
   cV_object_base*   Get_col_object(
      int pos_x//Индекс столбца
   );//Возвращает объект ячейки или NULL при ошибке
  };

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
cV_object_base* V_grid::Get_col_object(int pos_x)
  {
   if((pos_x>=_grid_cols.Get_property(vop_s_childs_count).data_long)||(pos_x<0))
     {
      cLng_add_user(cV_object_base::lng_id,21,string(pos_x),"");
      return NULL;
     }
   return _grid_cols.Get_child(pos_x);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
cV_object_base* V_grid::Get_cell_object(int pos_x,int pos_y)
  {
   if((pos_x>=_grid_cols.Get_property(vop_s_childs_count).data_long)||(pos_x<0))
     {
      cLng_add_user(cV_object_base::lng_id,21,string(pos_x),"");
      return NULL;
     }
   cV_object_base *obj=_grid_cols.Get_child(pos_x);
   if((pos_y>=obj.Get_property(vop_s_childs_count).data_long)||(pos_y<0))
     {
      cLng_add_user(cV_object_base::lng_id,21,string(pos_x),"");
      return NULL;
     }
   return obj.Get_child(pos_y);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
long V_grid::Get_property(eG_property grid_property)
  {
   switch(grid_property)
     {
     }
   return 0;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void V_grid::Set_property(eG_property grid_property,long property_value)
  {
   switch(grid_property)
     {
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void V_grid::Events_grid::On_event(sEvent &event)
  {
   switch(event.id)
     {
      case CHARTEVENT_ON_PROPERTY_CHANGED_:
        {
         switch(eV_object_property(event.lparam))
           {
            case vop_position_x:
              {
               _v_grid._caption.Set_property(vop_position_x,event.dparam);
               break;
              }
            case vop_position_y:
              {
               _v_grid._col_fixing.Set_property(vop_position_y,event.dparam);
               break;
              }
           }
         break;
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void V_grid::Events_scroll_v_change::On_event(sEvent &event)
  {

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void V_grid::Events_scroll_h_change::On_event(sEvent &event)
  {

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool V_grid::Create(cV_object_base &parent_object,string name=NULL)
  {
   if(CheckPointer(_main))
     {
      cLng_add_user(cV_object_base::lng_id,20,"V_grid","");
      return false;
     }
   scroll_v_change._v_grid=GetPointer(this);
   scroll_h_change._v_grid=GetPointer(this);
   events_grid._v_grid=GetPointer(this);
   _cols=5;
   _rows=5;
   _cell_width=400;
   _cell_height=400;
   _scroll_width=20;
   _size_caption=30;
   _size_fixing_col=30;
   _is_captions=true;
   _is_cols_fixing=true;
   _is_scroll_bar_v=true;
   _is_scroll_bar_h=true;

   int width=850;
   int height=850;

   _main=new cV_object_base();
   _main.Set_property_info(vop_position_x,20);
   _main.Set_property_info(vop_position_y,20);
   _main.Set_property_info(vop_size_x,width);
   _main.Set_property_info(vop_size_y,height);
   _main.Create(parent_object,name);

   _caption_v=new cV_object_base();
   if(_is_cols_fixing)
     {
      _caption_v.Set_property_info(vop_position_x,_size_fixing_col);
      if(_is_scroll_bar_v)
        {
         _caption_v.Set_property_info(vop_size_x,width-_scroll_width-_size_fixing_col);
        }
      else
        {
         _caption_v.Set_property_info(vop_size_x,width-_cell_width);
        }
     }
   else
     {
      _caption_v.Set_property_info(vop_position_x,0);
      if(_is_scroll_bar_v)
        {
         _caption_v.Set_property_info(vop_size_x,width-_scroll_width);
        }
      else
        {
         _caption_v.Set_property_info(vop_size_x,width);
        }
     }
   _caption_v.Set_property_info(vop_position_y,0);
   _caption_v.Set_property_info(vop_size_y,_size_caption);
   _caption_v.Set_property_info(vop_is_hidden,!_is_captions);
   _caption_v.Set_property_info(vop_is_anchor_left,true);
   _caption_v.Set_property_info(vop_is_anchor_right,true);
   _caption_v.Create(_main);
   _caption_v.Add_event_handler(GetPointer(scroll_v_change));
   _caption_v.Set_property_change_event(vop_is_hidden);

   _caption=new cV_object_base();
   _caption.Set_property_info(vop_position_x,0);
   _caption.Set_property_info(vop_position_y,0);
   _caption.Set_property_info(vop_size_x,_cols*_cell_width);
   _caption.Set_property_info(vop_size_y,_size_caption);
   _caption.Set_property_info(vop_is_canvas,true);
   _caption.Create(_caption_v);
   for(int i1=0; i1<_cols; i1++)
     {
      cV_object_base *col_caption=new cV_object_base();
      col_caption.Set_property_info(vop_position_x,i1*_cell_width);
      col_caption.Set_property_info(vop_position_y,0);
      col_caption.Set_property_info(vop_size_x,_cell_width);
      col_caption.Set_property_info(vop_size_y,_size_caption);
      col_caption.Set_property_info(vop_color_back,clrWhiteSmoke);
      col_caption.Set_property_info(vop_color_borders,clrGray);
      col_caption.Set_property_info(vop_border_type,long(BORDER_FLAT));
      col_caption.Set_property_info(vop_text_anchor,TA_CENTER|TA_VCENTER);
      col_caption.Set_property_info(vop_border_line_width,1);
      col_caption.Set_property_info(vop_text,"Col "+string(i1));
      col_caption.Set_property_info(vop_is_canvas_from_parent,true);
      col_caption.Create(_caption);
     }

   _col_fixing_v=new cV_object_base();
   _col_fixing_v.Set_property_info(vop_position_x,0);
   if(_is_captions)
     {
      _col_fixing_v.Set_property_info(vop_position_y,_size_caption);
      if(_is_scroll_bar_h)
        {
         _col_fixing_v.Set_property_info(vop_size_y,height-_size_caption-_scroll_width);
        }
      else
        {
         _col_fixing_v.Set_property_info(vop_size_y,height-_size_caption);
        }
     }
   else
     {
      _col_fixing_v.Set_property_info(vop_position_y,0);
      if(_is_scroll_bar_h)
        {
         _col_fixing_v.Set_property_info(vop_size_y,height-_scroll_width);
        }
      else
        {
         _col_fixing_v.Set_property_info(vop_size_y,height);
        }
     }
   _col_fixing_v.Set_property_info(vop_size_x,_size_fixing_col);
   _col_fixing_v.Set_property_info(vop_is_anchor_top,true);
   _col_fixing_v.Set_property_info(vop_is_anchor_bottom,true);
   _col_fixing_v.Set_property_info(vop_is_hidden,!_is_cols_fixing);
   _col_fixing_v.Create(_main);

   _col_fixing=new cV_object_base();
   _col_fixing.Set_property_info(vop_position_x,0);
   _col_fixing.Set_property_info(vop_position_y,0);
   _col_fixing.Set_property_info(vop_size_x,_size_fixing_col);
   _col_fixing.Set_property_info(vop_size_y,_rows*_cell_height);
   _col_fixing.Set_property_info(vop_is_canvas,true);
   _col_fixing.Create(_col_fixing_v);
   for(int i1=0; i1<_rows; i1++)
     {
      cV_object_base *cell_fixing=new cV_object_base();
      cell_fixing.Set_property_info(vop_position_x,0);
      cell_fixing.Set_property_info(vop_position_y,i1*_cell_height);
      cell_fixing.Set_property_info(vop_size_x,_size_fixing_col);
      cell_fixing.Set_property_info(vop_size_y,_cell_height);
      cell_fixing.Set_property_info(vop_color_back,clrWhiteSmoke);
      cell_fixing.Set_property_info(vop_color_borders,clrGray);
      cell_fixing.Set_property_info(vop_border_type,long(BORDER_FLAT));
      cell_fixing.Set_property_info(vop_text_anchor,TA_CENTER|TA_VCENTER);
      cell_fixing.Set_property_info(vop_border_line_width,1);
      cell_fixing.Set_property_info(vop_text,string(i1));
      cell_fixing.Set_property_info(vop_is_canvas_from_parent,true);
      cell_fixing.Create(_col_fixing);
     }

   _grid_view=new cV_object_base();
   if(_is_cols_fixing)
     {
      _grid_view.Set_property_info(vop_position_x,_size_fixing_col);
      if(_is_scroll_bar_v)
        {
         _grid_view.Set_property_info(vop_size_x,width-_size_fixing_col-_scroll_width);
        }
      else
        {
         _grid_view.Set_property_info(vop_size_x,width-_size_fixing_col);
        }
     }
   else
     {
      _grid_view.Set_property_info(vop_position_x,0);
      if(_is_scroll_bar_v)
        {
         _grid_view.Set_property_info(vop_size_x,width-_scroll_width);
        }
      else
        {
         _grid_view.Set_property_info(vop_size_x,width);
        }
     }
   if(_is_captions)
     {
      _grid_view.Set_property_info(vop_position_y,_size_caption);
      if(_is_scroll_bar_h)
        {
         _grid_view.Set_property_info(vop_size_y,height-_size_caption-_scroll_width);
        }
      else
        {
         _grid_view.Set_property_info(vop_size_y,height-_size_caption);
        }
     }
   else
     {
      _grid_view.Set_property_info(vop_position_y,0);
      if(_is_scroll_bar_h)
        {
         _grid_view.Set_property_info(vop_size_y,height-_scroll_width);
        }
      else
        {
         _grid_view.Set_property_info(vop_size_y,height);
        }
     }
   _grid_view.Set_property_info(vop_is_anchor_left,true);
   _grid_view.Set_property_info(vop_is_anchor_right,true);
   _grid_view.Set_property_info(vop_is_anchor_top,true);
   _grid_view.Set_property_info(vop_is_anchor_bottom,true);
   _grid_view.Create(_main);
   _grid_view.Add_event_handler(GetPointer(scroll_v_change));
   _grid_view.Set_property_change_event(vop_size_y);

   _grid_cols=new cV_object_base();
   _grid_cols.Set_property_info(vop_position_x,0);
   _grid_cols.Set_property_info(vop_position_y,0);
   _grid_cols.Set_property_info(vop_size_x,_cols*_cell_width);
   _grid_cols.Set_property_info(vop_size_y,_rows*_cell_height);
   _grid_cols.Create(_grid_view);
   _grid_cols.Add_event_handler(GetPointer(events_grid));
   _grid_cols.Set_property_change_event(vop_position_x);
   _grid_cols.Set_property_change_event(vop_position_y);

   _scroll_v.Create(_main,_grid_cols,true,30);
   _scroll_h.Create(_main,_grid_cols,false,30);

   for(int i1=0; i1<_cols; i1++)
     {
      cV_object_base *col=new cV_object_base();
      col.Set_property_info(vop_position_x,i1*_cell_width);
      col.Set_property_info(vop_position_y,0);
      col.Set_property_info(vop_size_x,_cell_width);
      col.Set_property_info(vop_size_y,_rows*_cell_height);
      col.Create(_grid_cols);
      for(int i2=0; i2<_rows; i2++)
        {
         cV_object_base *cell=new cV_object_base();
         cell.Set_property_info(vop_position_x,0);
         cell.Set_property_info(vop_position_y,i2*_cell_height);
         cell.Set_property_info(vop_size_x,_cell_width);
         cell.Set_property_info(vop_size_y,_cell_height);
         cell.Set_property_info(vop_color_back,clrSlateGray);
         cell.Set_property_info(vop_color_text,clrBlack);
         cell.Set_property_info(vop_text_anchor,TA_CENTER|TA_VCENTER);
         cell.Set_property_info(vop_text,string(i1*_rows+i2));
         cell.Set_property_info(vop_color_back_mouse_moving,clrDimGray);
         cell.Create(col);
        }
     }
   return true;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
cV_object_base* V_grid::Get_main_v_object()
  {
   return GetPointer(_main);
  }
//+------------------------------------------------------------------+
 
Es wäre schön, wenn sich jemand daran machen würde, eine Grafikbibliothek für die Erstellung von Steuerelementen zu entwickeln
 
Реter Konow:

Ja, ich dachte mir, das ist der schwierigste Teil, weil es keine gibt. ))))

Eine Demo für Ihren Monitor. Für die untere rechte Ecke können Sie die Größe der Tabelle ändern

Dateien:
Test_v_grid.ex5  502 kb
 
Aliaksandr Hryshyn:

Eine Demo für Ihren Monitor. Für die untere rechte Ecke können Sie die Größe der Tabelle ändern

Danke für die Demo für meinen Monitor.

Und so:

  • Der "gummiartige" Fenstermechanismus wird zunächst eingeführt,

aber wenn Sie die Größe ändern:

  1. Die Fenster dürfen nicht blinken,
  2. Es sollten 8 Fenstergriffe für die Größenänderung vorhanden sein - für jede Seite und jede Ecke.
  • Das Fenster als Ganzes wird nämlich nicht gebildet. Es gibt noch keine Integrität.

Mit der Idee sollten Sie zu einer ähnlichen Option kommen:

Im Großen und Ganzen haben Sie sich gut geschlagen! Das hatte ich nicht erwartet. ))))

Weitermachen.
 

Ich habe mich erinnert!

Ich habe mich daran erinnert, woran mich das alles erinnert...

Demos von GVision (einem der Nachfahren von TVision).

Etwa 93-95 konnte man die oben erwähnten Demos (*wer weiß das nicht - die Software wurde im Einzelhandel verkauft) in der Buchhandlung "House of Tech Books" in der Leninsky Straße kaufen.
Es gab sogar einen separaten Monitor, auf dem die Demo lief, und man konnte sie "ausprobieren". Es war cool - die Schilder, die Knöpfe, die Kontroll-/Radioboxen und die Grafiken...

aber dann habe ich einen Zortec-C gekauft. Ein gewichtiger Karton mit 5 Bänden Dokumentation und einigen Disketten :-)

schön zu erinnern.

 
Реter Konow:

Danke für die Demo für meinen Monitor.

Und so:

  • Der "gummiartige" Fenstermechanismus wird zunächst eingeführt,

aber wenn Sie die Größe ändern:

  1. Die Fenster dürfen nicht blinken,
  2. Es sollten 8 Fenstergriffe für die Größenänderung vorhanden sein - für jede Seite und jede Ecke.
  • Das Fenster als Ganzes wird nämlich nicht gebildet. Es gibt noch keine Integrität.

Mit der Idee sollten Sie zu einer ähnlichen Option kommen:

Also, im Großen und Ganzen haben Sie sich gut geschlagen! Das hatte ich nicht erwartet. ))))

Weiter.

1. verwendet Rechtecke und kanvasses in großer Zahl mit Dynamik, vielleicht nicht blinken, wenn alles auf einem kanvass war, gibt es bereits Einschränkungen der Plattform, und zeichnen Sie alles auf einem kanvass ist nicht wünschenswert. Vielleicht nur, um alles auf einmal mit DirectX zu übersetzen...

2. Ich habe gerade eine kleine Komponente hinzugefügt, die die Streckung implementiert. Und es gibt keine Integrität, es sind nur zusammengesetzte Elemente, die nicht unbedingt grafisch sind.

Was haben Sie nicht erwartet? Dehnen? So einfach ist das für mich. Ich mache diese Dinge für mein Projekt, ich habe nicht vor, eine Bibliothek mit grafischen Steuerelementen zu erstellen, obwohl die Basis für ihre Erstellung sehr gut ist

#include  <Greshnik\\\Windows_engine\\Windows_engine_base.mqh>

//Элемент, который будет изменять размер родительского окна перетаскиванием мышки
//По умолчанию окошко будеи распологаться в правом нижнем углу
class cV_resizer
  {
   cV_object_base    *_main;//Основное окно
   class My_events: public iE_event_handler
     {
   public:
      cV_object_base *_e_my;
      void           On_event(sEvent &event);
     };
   My_events         ev;
public:
   //Создание таблицы
   bool              Create(
      cV_object_base &parent_object,
      string name=NULL
   );
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void cV_resizer::My_events::On_event(sEvent &event)
  {
   if(event.id==CHARTEVENT_ON_PROPERTY_CHANGED_)
     {
      if(event.lparam==vop_position_x)
        {
         cV_object_base *par=_e_my.Get_parent();
         long p=par.Get_property(vop_size_x).data_long;
         long pos=_e_my.Get_property(vop_position_x).data_long;
         long size=_e_my.Get_property(vop_size_x).data_long;
         long d=pos+size-p;
         par.Set_property(vop_size_x,p+d);
         _e_my.Set_property(vop_position_x,par.Get_property(vop_size_x).data_long-size);
        }
      else
        {
         cV_object_base *par=_e_my.Get_parent();
         long p=par.Get_property(vop_size_y).data_long;
         long pos=_e_my.Get_property(vop_position_y).data_long;
         long size=_e_my.Get_property(vop_size_y).data_long;
         long d=pos+size-p;
         par.Set_property(vop_size_y,p+d);
         _e_my.Set_property(vop_position_y,par.Get_property(vop_size_y).data_long-size);
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool cV_resizer::Create(cV_object_base &parent_object,string name=NULL)
  {
   int width=20;
   int height=20;
   long width_p=parent_object.Get_property(vop_size_x).data_long;
   long heigth_p=parent_object.Get_property(vop_size_y).data_long;

   _main=new cV_object_base();
   _main.Set_property_info(vop_size_x,width);
   _main.Set_property_info(vop_size_y,height);

   _main.Set_property_info(vop_position_x,width_p-width);
   _main.Set_property_info(vop_position_y,heigth_p-height);
   _main.Set_property_info(vop_is_movable,true);
   _main.Create(parent_object);
   _main.Add_event_handler(GetPointer(ev));
   _main.Set_property_change_event(vop_position_x);
   _main.Set_property_change_event(vop_position_y);

   ev._e_my=GetPointer(_main);
   return true;
  }
 
Aliaksandr Hryshyn:

1. Rechtecke und Kanvas werden in großen Mengen mit Dynamics verwendet, vielleicht würde es nicht auffallen, wenn alles auf einem Kanvas wäre, aber es gibt bereits Plattformbeschränkungen, und alles auf einem Kanvas zu zeichnen ist nicht wünschenswert. Vielleicht nur, um alles auf einmal mit DirectX zu übersetzen...

2. Ich habe gerade eine kleine Komponente hinzugefügt, die die Streckung implementiert. Und es gibt keine Integrität, es sind nur zusammengesetzte Elemente, die nicht unbedingt grafisch sind.

Was haben Sie nicht erwartet? Stretching? So einfach ist das für mich:

Es blinkt, weil Sie die Größe ALLER Leinwände ändern, was Ressourcen verbraucht, aber wenn Sie den Bereich des sichtbaren Bildes auf einer Leinwand mit MAXIMALER Größe ändern, wird dieser unangenehme Effekt beseitigt. Das heißt, Sie erstellen im Voraus eine Leinwand in der Größe des Bildschirms, verbinden das Bild mit dieser Leinwand (in derselben Größe) und "beschneiden" es dann. Und die Funktionen zur Größenänderung definieren nur den sichtbaren Bereich der Leinwand, ohne ihn neu zu erstellen.