На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> FireMonkey vs VCL , TPaintBox не пашет
    Пытаюсь перевести VCL код на FMX, застрял на отрисовке Паинтбоксов, в VCL прежний код выводил линии в 8 пайнтбоксов одновремено, а вот FMX версия не пашет, выводится в один пайнтбокс :wall:
    Кто уже прогет на FMX?
    Ниже привел мои эксперименты с пайнтбоксами, изучите плз эту портянку где то я накосячил :D
    ExpandedWrap disabled
      unit Unit1;
       
      interface
       
      uses
        System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
        FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
        System.SyncObjs, System.Threading;
       
      type
        TForm1 = class(TForm)
          PaintBox1: TPaintBox;
          PaintBox2: TPaintBox;
          PaintBox3: TPaintBox;
          PaintBox4: TPaintBox;
          PaintBox5: TPaintBox;
          PaintBox6: TPaintBox;
          PaintBox7: TPaintBox;
          PaintBox8: TPaintBox;
          procedure FormCreate(Sender: TObject);
          procedure FormDestroy(Sender: TObject);
        private
          FNumRunning: int64;
          FStop: boolean;    
        public
        
        end;
       
      var
        Form1: TForm1;
       
      implementation
       
      {$R *.fmx}
       
      {$IFDEF MSWINDOWS}
      uses Winapi.Windows;
      {$ENDIF}
       
      { TForm1 }
       
      procedure TForm1.FormCreate(Sender: TObject);
      var
        i: integer;
        pb: TArray<TPaintBox>;
      begin
        pb := [PaintBox1, PaintBox2, PaintBox3, PaintBox4,
               PaintBox5, PaintBox6, PaintBox7, PaintBox8];
       
        for i := 0 to High(pb) do
          TThread.CreateAnonymousThread((function (i: integer): TProc
            begin
              Result:= procedure
              var
                p1, p2: TPointF;
                d1, d2: TPointF;
                color: TAlphaColor;
       
                procedure CalcPoints(var point, delta: TPointF);
                begin            
                  if (point.X < 0) or (point.X >= pb[i].Width) then          
                    delta.X:= - delta.X;
                  
                  if (point.Y < 0) or (point.Y >= pb[i].Height) then        
                    delta.Y:= - delta.Y;
                  
                  point:= point + delta;
                end;
              begin
                TInterlocked.Increment(FNumRunning);
                p1 := PointF(50.0, 10.0); d1 := PointF(2.0, 3.0);
                p2 := PointF(10.0, 50.0); d2 := PointF(3.0, 2.0);
                color := $FF000000;
       
                while not FStop do
                begin
                  color:= color + $F0F8FF;
                  if color > $FFFFFFFF then color:= $FF000000;
                  // рисуем линии
                  pb[i].Canvas.BeginScene;
                  try
                    pb[i].Canvas.Stroke.Color:= color;
                    pb[i].Canvas.DrawLine(p1, p2, 1);
                  finally
                    pb[i].Canvas.EndScene;
                  end;
       
                  CalcPoints(p1, d1);
                  CalcPoints(p2, d2);
                  Sleep(10);
                end;
                TInterlocked.Decrement(FNumRunning);
              end;
            end)(i)).Start;
      end;
       
      procedure TForm1.FormDestroy(Sender: TObject);
      begin
        FStop := true;
        // ждем завершения все потоков
        while TInterlocked.Read(FNumRunning) > 0 do
           Application.ProcessMessages;
      end;
       
      end.
    Сообщение отредактировано: Cfon -
      Сам все порешал :D
      Как оказалось канва пайнтбокса это канва формы, т.е вот этот код
      ExpandedWrap disabled
        // рисуем линии
        pb[i].Canvas.BeginScene;
        try
          pb[i].Canvas.Stroke.Color:= color;
          pb[i].Canvas.DrawLine(p1, p2, 1);
        finally
          pb[i].Canvas.EndScene;
        end;

      на самом деле означает
      ExpandedWrap disabled
        // рисуем линии
        Form1.Canvas.BeginScene;
        try
          Form1.Canvas.Stroke.Color:= color;
          Form1.Canvas.DrawLine(p1, p2, 1);
        finally
          Form1.Canvas.EndScene;
        end;

      поэтому вся отрисовка шла начиная с координат (0,0)
      Короче добавил где надо смещение на расположение пайнтбоксов и...
      ВСЕ ЗАРАБОТАЛО! :D

      Как варик моно было закинуть каждый пейнтбокс в панельку и тогда не заморачиваться вапще с кодом смещения :huh: Гениально! :lool:
      Сообщение отредактировано: Cfon -
        Облом на MacOSX этот код не пашет :D
          Решил через обработку события OnPaint пайнтбокса и таймер :D
          ExpandedWrap disabled
            unit Unit1;
             
            interface
             
            uses
              System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
              FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
              System.Threading, System.SyncObjs, FMX.Controls.Presentation, FMX.StdCtrls;
             
            type
              TForm1 = class(TForm)
                PaintBox8: TPaintBox;
                PaintBox7: TPaintBox;
                PaintBox6: TPaintBox;
                PaintBox5: TPaintBox;
                PaintBox4: TPaintBox;
                PaintBox3: TPaintBox;
                PaintBox2: TPaintBox;
                PaintBox1: TPaintBox;
                Timer1: TTimer;
                procedure FormCreate(Sender: TObject);  
                procedure PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
                procedure Timer1Timer(Sender: TObject);  
              private
                p0, p1, p2, d1, d2: TPointF;
                color: TAlphaColor;
              end;
             
            var
              Form1: TForm1;
             
            implementation
             
            {$R *.fmx}
             
            {$IFDEF MSWINDOWS}
            uses Winapi.Windows;
            {$ENDIF}
             
            procedure TForm1.FormCreate(Sender: TObject);
            begin
              p1:= PointF(50.0, 10.0);
              p2:= PointF(10.0, 50.0);
              d1:= PointF(2.0, 3.0);
              d2:= PointF(3.0, 2.0);
              color := $FF000000;
              PaintBox1.OnPaint:= PaintBox1Paint;
              ...
              PaintBox8.OnPaint:= PaintBox1Paint;
            end;
             
            procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
            var pb: TPaintBox;
            procedure CalcPoints(pb: TPaintBox; var point, delta: TPointF);
            begin
              if (point.X < 0) or (point.X >= pb.Width) then
                delta.X:= - delta.X;
              if (point.Y < 0) or (point.Y >= pb.Height) then
                delta.Y:= - delta.Y;
              point:= point + 2 * delta;
            end;
            begin
              pb:= Sender as TPaintBox;
              color:= color + $F0F8FF;
              if color >= $FFFFFFFF then color:= $FF000000;
              // рисуем линию  
              Canvas.BeginScene;
              try
                Canvas.Stroke.Color:= color;
                Canvas.Stroke.Thickness:= 3;
                Canvas.Stroke.Kind:= TBrushKind.Solid;
                Canvas.DrawLine(p1, p2, 1);
              finally
                Canvas.EndScene;
              end;
              // пересчет координат
              CalcPoints(pb, p1, d1);
              CalcPoints(pb, p2, d2);
            end;
             
            procedure TForm1.Timer1Timer(Sender: TObject);
            begin
              Invalidate;
            end;
             
            end.

          Не очень красиво, но пашет на МАКАКЕ :D
          По поводу ошибки предыдущего кода, как я понял, на МакОСХ все более жестко :D там была ошибка обращения к залоченому монитором объекту с последующим эксепшеном, короче не стал копать дальше :wacko:
          Сообщение отредактировано: Cfon -
            Предлагаю вашему вниманию гениальное решение! :D
            Заюзал анонимную фунцию, убраны переменые из определения формы.
            Чтобы присвоить анонимку событию юзается одна хитрая структура :D
            ExpandedWrap disabled
              unit Unit1;
               
              interface
               
              uses
                System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
                FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
                System.Threading, System.SyncObjs, FMX.Controls.Presentation, FMX.StdCtrls;
               
              type
                TForm1 = class(TForm)
                  PaintBox8: TPaintBox;
                  PaintBox7: TPaintBox;
                  PaintBox6: TPaintBox;
                  PaintBox5: TPaintBox;
                  PaintBox4: TPaintBox;
                  PaintBox3: TPaintBox;
                  PaintBox2: TPaintBox;
                  PaintBox1: TPaintBox;
                  Timer1: TTimer;
                  procedure FormCreate(Sender: TObject);    
                  procedure Timer1Timer(Sender: TObject);
                private
                end;
               
              var
                Form1: TForm1;
               
              implementation
               
              {$R *.fmx}
               
              {$IFDEF MSWINDOWS}
              uses Winapi.Windows;
              {$ENDIF}
               
              type
                TProc = TProc<TObject, TCanvas>;
               
                TPaintEventAdapter = class
                strict private
                  FProc: TProc;
                public
                  constructor Create(AProc: TProc);
                  procedure EventHandler(Sender: TObject; Canvas: TCanvas);
                end;
               
              constructor TPaintEventAdapter.Create(AProc: TProc);
              begin
                FProc:= AProc;
              end;
               
              procedure TPaintEventAdapter.EventHandler(Sender: TObject; Canvas: TCanvas);
              begin
                FProc(Sender, Canvas);
              end;
               
              procedure TForm1.FormCreate(Sender: TObject);
              var
                i: integer;
                pbs: TArray<TPaintBox>;
                p1, p2, d1, d2: TPointF;
                color: TAlphaColor;
              begin
                pbs := [PaintBox1, PaintBox2, PaintBox3, PaintBox4, PaintBox5,
                        PaintBox6, PaintBox7, PaintBox8];
               
                p1:= PointF(50.0, 10.0);
                p2:= PointF(10.0, 50.0);
                d1:= PointF(2.0, 3.0);
                d2:= PointF(3.0, 2.0);
                color := $FF000000;
               
                for I := 0 to High(pbs) do
                begin
                  pbs[i].OnPaint := TPaintEventAdapter.Create(
                    procedure (Sender: TObject; Canvas: TCanvas)
                      procedure CalcPoints(var point, delta: TPointF);
                      var pb: TPaintBox;
                      begin
                        pb:= Sender as TPaintBox;
                        if (point.X < 0) or (point.X >= pb.Width) then
                          delta.X:= - delta.X;
                        if (point.Y < 0) or (point.Y >= pb.Height) then
                          delta.Y:= - delta.Y;
                        point:= point + 2 * delta;
                      end;
                    begin
                      color:= color + $F0F8FF;
                      if color >= $FFFFFFFF then color:= $FF000000;
                      // рисуем линию
                      Canvas.BeginScene;
                      try
                        Canvas.Stroke.Color:= color;
                        Canvas.Stroke.Thickness:= 3;
                        Canvas.Stroke.Kind:= TBrushKind.Solid;
                        Canvas.DrawLine(p1, p2, 1);
                      finally
                        Canvas.EndScene;
                      end;
                      // пересчет координат
                      CalcPoints(p1, d1);
                      CalcPoints(p2, d2);
                    end).EventHandler;
                end;
              end;
               
              procedure TForm1.Timer1Timer(Sender: TObject);
              begin
                Invalidate;
              end;
               
              end.

            Вот теперь красиво, как мне нравится :jokingly:
            Сообщение отредактировано: Cfon -
              Продолжаю улучшения кода, нет предела красивому :D
              вот список улучшений:
              -- добавил овнера в TPaintEventAdapter, чтобы избежать утечки памяти;
              -- ввел IIFE (Immediately Invoked Function Expression), чтобы перенести в локальную область видимости переменные p1,p2,d1,d2,color,pbs с тем чтобы каждый обработчик имел свою копию данных.
              На данном примере демонстрируется применение замыкания (closure), я там в коде пометил захваченые перемнные.

              ExpandedWrap disabled
                unit Unit1;
                 
                interface
                 
                uses
                  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
                  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
                  System.Threading, System.SyncObjs, FMX.Controls.Presentation, FMX.StdCtrls;
                 
                type
                  TForm1 = class(TForm)
                    PaintBox8: TPaintBox;
                    PaintBox7: TPaintBox;
                    PaintBox6: TPaintBox;
                    PaintBox5: TPaintBox;
                    PaintBox4: TPaintBox;
                    PaintBox3: TPaintBox;
                    PaintBox2: TPaintBox;
                    PaintBox1: TPaintBox;
                    Timer1: TTimer;
                    procedure FormCreate(Sender: TObject);
                    procedure Timer1Timer(Sender: TObject);
                  private
                 
                  end;
                 
                var
                  Form1: TForm1;
                 
                implementation
                 
                {$R *.fmx}
                 
                {$IFDEF MSWINDOWS}
                uses Winapi.Windows;
                {$ENDIF}
                 
                type
                  TPaintProc = TProc<TObject, TCanvas>;
                 
                  TPaintEventAdapter = class(TComponent)
                  strict private
                    FProc: TPaintProc;
                  public
                    constructor Create(AOwner: TComponent; AProc: TPaintProc);  
                    procedure EventHandler(Sender: TObject; Canvas: TCanvas);
                  end;
                 
                constructor TPaintEventAdapter.Create(AOwner: TComponent; AProc: TPaintProc);
                begin
                  inherited Create(AOwner);
                  FProc:= AProc;
                end;
                 
                procedure TPaintEventAdapter.EventHandler(Sender: TObject; Canvas: TCanvas);
                begin
                  FProc(Sender, Canvas);
                end;
                (**************************************************************************)
                procedure TForm1.FormCreate(Sender: TObject);
                var
                  i: integer;
                  pbs: TArray<TPaintBox>;
                begin
                  pbs := [PaintBox1, PaintBox2, PaintBox3, PaintBox4, PaintBox5,
                          PaintBox6, PaintBox7, PaintBox8];
                 
                  for I := 0 to High(pbs) do
                  begin
                    pbs[i].OnPaint := (function (i: integer): TPaintEvent //<--- iife
                      var
                        p1, p2, d1, d2: TPointF;
                        color: TAlphaColor;
                      begin
                        p1:= PointF(50.0, 10.0);
                        d1:= PointF(2.0, 3.0);
                        p2:= PointF(10.0, 50.0);
                        d2:= PointF(3.0, 2.0);
                        color := $FF000000;
                 
                        Result := TPaintEventAdapter.Create(self, //<--- owner
                          procedure (Sender: TObject; Canvas: TCanvas)  //<--- anonymous function
                            procedure CalcPoints(var point, delta: TPointF);
                            begin
                              if (point.X < 0) or (point.X >= pbs[i].Width) then  //<--- pbs captured
                                delta.X:= - delta.X;
                              if (point.Y < 0) or (point.Y >= pbs[i].Height) then //<--- pbs captured
                                delta.Y:= - delta.Y;
                              point:= point + 2 * delta;
                            end;
                          begin
                            color:= color + $F0F8FF;  //<--- color captured
                            if color >= $FFFFFFFF then color:= $FF000000;
                            // рисуем линию
                            Canvas.BeginScene;
                            try
                              Canvas.Stroke.Color:= color;
                              Canvas.Stroke.Thickness:= 3;
                              Canvas.Stroke.Kind:= TBrushKind.Solid;
                              Canvas.DrawLine(p1, p2, 1);  //<--- p1, p2 captured
                            finally
                              Canvas.EndScene;
                            end;
                            // пересчет координат
                            CalcPoints(p1, d1);  //<--- p1, d1 captured
                            CalcPoints(p2, d2);  //<--- p2, d2 captured
                          end).EventHandler;
                      end)(i);
                  end;
                end;
                 
                procedure TForm1.Timer1Timer(Sender: TObject);
                begin
                  Invalidate;
                end;
                 
                end.

              Все эти навороты пришлись мне по душе еще когда кодил на JS приятно что все это есть и в Delphi :D
              Сообщение отредактировано: Cfon -
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0322 ]   [ 16 queries used ]   [ Generated: 19.04.24, 04:04 GMT ]