Search code examples
delphifiremonkey

Drawing on FMX canvas with WinApi functions


This question looks very simple, with VCL this is works fine (Image is TImage on VCL):

procedure TFormMain.btnDrawBackgroundClick(Sender: TObject);
var
  theme: HTHEME;
begin
  theme := OpenThemeData(0, 'TASKDIALOG');
  if theme <> 0 then
  try
    DrawThemeBackground(theme,
                        Image.Canvas.Handle,
                        TDLG_SECONDARYPANEL,
                        0,
                        Image.ClientRect,
                        nil);
  finally
    CloseThemeData(theme);
  end;
end;

Question: what I should change to get the same effect with FMX (on Windows)


Solution

  • Based on this answer you simply can't do that.

    The problem is that with Firemonkey, you only have a single device context for the form and not one for each component. When a component needs to be redrawn, it gets passed the forms canvas but with clipping and co-ordinates mapped to the components location.

    But there is always some workaround and you can try something like this.

    procedure TFormMain.btnDrawBackgroundClick(Sender: TObject);
    var
      lTheme : HTHEME;
      lStream : TMemoryStream;
      lBitmap : Vcl.Graphics.TBitmap;
    begin
      lTheme := OpenThemeData(0, 'TASKDIALOG');
      if lTheme <> 0 then
      try
        lBitmap := Vcl.Graphics.TBitmap.Create;
        try
          lBitmap.Width := Round(Image.Width);
          lBitmap.Height := Round(Image.Height);
          DrawThemeBackground(lTheme, lBitmap.Canvas.Handle, TDLG_SECONDARYPANEL, 0, 
                              Rect(0, 0, lBitmap.Width, lBitmap.Height), nil);
          lStream := TMemoryStream.Create;
          try
            lBitmap.SaveToStream(lStream);
            Image.Bitmap.LoadFromStream(lStream);
          finally
            lStream.Free;
          end;
        finally
          lBitmap.Free;
        end;
      finally
        CloseThemeData(lTheme);
      end;
    end;