Forum > Android

Application.processmessages does not seem to work

(1/2) > >>

Kostas:
Hi!
I have managed to run Graphics32 in Android and the speed for stretching etc is very good!!

Now i have the following problem:
I am trying to do some animations.
I am calling for every frame of the animation 'Application.processmessages'.
But the GUI is not getting refreshed.
The code is the following:

  for i := 1 to 40 do
  begin
    aDice.Roll;
    DrawDice(aDice); // This will draw the correct Dice bitmaps (TBitmap32) on a Graphics32 Image
    Application.ProcessMessages;
    sleep(25); // Wait 25 ms for this frame
  end;

The animation works right in Custom Drawn Interface when running on Win32

Am i doing something wrong?
How to get the Gui refreshed in android?

2. Is it possible to play sounds in Android and how?


Thanks in advance

felipemdc:
Android does not support Application.ProcessMessages by design, so it cannot be implemented in the LCL. In general you cannot take too long to exit a event handler in Android or else it will ask the user to kill the process as it is not responding, so using Sleep() in the main thread is a bad idea.

What you should do instead is handle the OnPaint event of your form, or other control, and draw 1 frame there.

Add a TTimer which calls Form.Invalidate or Control.Invalidate periodically to get an animation.

About sound, first research which APIs are available in the SDK and NDK. You can access SDK Java APIs via JNI. NDK APIs can be accessed via C headers converted to Pascal.

meanderix:
Hi Kostas,


--- Quote from: Kostas on June 14, 2012, 08:25:51 am ---Now i have the following problem:
I am trying to do some animations.
I am calling for every frame of the animation 'Application.processmessages'.

--- End quote ---

As Felipe suggested, you need to use timers for animations. If you're using a TPaintBox32 instance then you can call TPaintBox32.Repaint inside the OnTimer event handler (and then you can redraw your frame in the TPaintBox32.OnPaint handler.)

A different option, which might be slightly faster (if you want to control the whole screen via Graphics32), would be to use TForm.OnPaint and a separate paint buffer. Below are some of the changes I did to Graphics32's GradLinesEx example in order to get good performance:


--- Code: ---uses
  LazCanvas, customdrawnint, LCLProc, ... ;

procedure TFormGradientLines.FormPaint(Sender: TObject);
var
  LazCanvas: TLazCanvas;
  W, H: Integer;
begin
  LazCanvas := TLazCanvas(Canvas.Handle);
  W := LazCanvas.Width;
  H := LazCanvas.Height;
  Buffer.SetSize(W, H);
  RepaintBuffer;
  Buffer.DrawTo(Canvas.Handle, 0, 0);
end;

procedure TFormGradientLines.Timer1Timer(Sender: TObject);
begin
  Repaint;
end;

function TFormGradientLines.MyDisableFormBackgroundDrawingProc(AForm: TCustomForm): Boolean;
begin
  Result := AForm = Self; // disable drawing only for self
end;

procedure TFormGradientLines.FormCreate(Sender: TObject);
begin
  Buffer := TBitmap32.Create;
  FadeCount := 0;
  DrawPasses := 2;
  CDWidgetset.DisableFormBackgroundDrawingProc := @MyDisableFormBackgroundDrawingProc;
end;

procedure TFormGradientLines.RepaintBuffer;
var
  I, J: Integer;
  P: PColor32;
begin
  for J := 0 to DrawPasses - 1 do
    for I := 0 to High(Lines) do
    begin
      Lines[I].Advance(1);
      Lines[I].Paint;
    end;

  if FadeCount > 0 then
  begin
    if Pass = 0 then with Buffer do
    begin
      P := @Bits[0];
      for I := 0 to Width * Height -1 do
      begin
        BlendMem($10000000, P^);
        Inc(P);
      end;
      EMMS;
    end;
    Dec(Pass);
    if (Pass < 0) or (Pass > FadeCount) then Pass := FadeCount;
  end;
end;

--- End code ---

Edit: I also made some changes to GR32_Backends_LCL_CustomDrawn. The problem here is that you get the wrong colors (BGRA instead of ARGB.) This has been discussed a bit in the GR32 newsgroups and it seems this is a problem with some other backends as well. A solution might be to have conditional defines that would adjust the TColor32Entry record to either ARGB or BGRA memory layout.


--- Code: ---procedure TransferBits(Src, Dst: TLazIntfImage; X, Y, XSrc, YSrc,
  SrcWidth, SrcHeight: Integer); overload;
var
  I, H: Integer;
  Depth: Integer;
  X1, Y1, X2, Y2, SrcLine, DstLine, CopyBytes: Integer;
  PSrc, PDst: PByte;
begin
  Depth := Src.DataDescription.Depth shr 3;
  SrcLine := Src.Width * Depth;
  DstLine := Dst.Width * Depth;
  PSrc := Src.PixelData;
  PDst := Dst.PixelData;

  if (X >= Dst.Width) or (Y >= Dst.Height) then Exit;

  X1 := X;
  Y1 := Y;
  X2 := Min(X + SrcWidth, Dst.Width);
  Y2 := Min(Y + SrcHeight, Dst.Height);
  CopyBytes := (X2 - X1) * Depth;

  Inc(PSrc, XSrc * Depth + SrcLine * YSrc);
  Inc(PDst, X * Depth + DstLine * Y);
  for I := 0 to SrcHeight - 1 do
  begin
    System.Move(PSrc^, PDst^, CopyBytes);
    Inc(PSrc, SrcLine);
    Inc(PDst, DstLine);
  end;
end;

procedure TransferBits(Src, Dst: TLazIntfImage); overload;
begin
  TransferBits(Src, Dst, 0, 0, 0, 0, Src.Width, Src.Height);
end;

procedure TLCLBackend.DoPaint(ABuffer: TBitmap32; AInvalidRects: TRectList;
  ACanvas: TCanvas; APaintBox: TCustomPaintBox32);
var
  Src, Dst: TLazCanvas;
begin
  Dst := TLazCanvas(ACanvas.Handle);
  Src := TLazCanvas(Canvas.Handle);
  if Dst.Image is TLazIntfImage then
    TransferBits(TLazIntfImage(Src.Image), TLazIntfImage(Dst.Image))
  else
    Dst.CopyRect(0, 0, Src, Rect(0,0,Src.Width,Src.Height));
end;

--- End code ---

Kostas:
Thanks a lot for your detailed answer!!
I will look at a later point at your changes to Graphics32.
I have actually no problem with the library.
Everything seems to draw right and also alpha blending works fine.
Also on my Smartphone. And it is really fast... :)


--- Quote from: meanderix on June 14, 2012, 03:00:37 pm ---A different option, which might be slightly faster (if you want to control the whole screen via Graphics32), would be to use TForm.OnPaint and a separate paint buffer.

--- End quote ---
Yes i already was into this way.
My Problem for the moment is that my OnPaint handler of my Form is never called...
Invalidate or Repaint does not call the FormPaint handler...
Neither on Win32 nor on Android.
I am still on testing and looking around in order to find the problem.

Any idea?

felipemdc:

--- Quote from: Kostas on June 14, 2012, 07:26:59 pm ---My Problem for the moment is that my OnPaint handler of my Form is never called...
Invalidate or Repaint does not call the FormPaint handler...
Neither on Win32 nor on Android.
I am still on testing and looking around in order to find the problem.

Any idea?

--- End quote ---

Do you have controls which completely cover the form? LCL-CustomDrawn will attempt to auto-detect this situation and if it is so, it will skip drawing the form (or for that matter any completely covered control).

Navigation

[0] Message Index

[#] Next page

Go to full version