4

I used the trick described in this question to display a FireMonkey form on a TPanel in a VCL application. My problem is that clicking (controls on) the embedded form causes the VCL form (containing that TPanel) to become deactivated. The most obvious consequence of that is the window border changing color all the time.

When displaying a VCL form on a TPanel of another, this doesn't happen; the forms apparently "merge". What should I do to reach a similar result with FireMonkey? I want controls on the FireMonkey form to be usable, but keep the parent form activated.

Update 1

VCL

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, FMX.Forms, Vcl.Forms,
  Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, FMX.Platform.Win;

type
  TMainForm = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

uses FireMonkeyForms;

procedure TMainForm.Button1Click(Sender: TObject);
var
  LFMForm: FireMonkeyForms.TForm1;
  LFMHWnd: HWND;
begin
  LFMForm := FireMonkeyForms.TForm1.Create(nil);
  LFMForm.Left := 0;
  LFMForm.Top := 0;
  LFMForm.Height := Panel1.ClientHeight;
  LFMForm.Width := Panel1.ClientWidth;
  LFMForm.BorderStyle := TFmxFormBorderStyle.bsNone;
  LFMForm.BorderIcons := [];
  LFMHWnd := FmxHandleToHWND(LFMForm.Handle);
  SetWindowLong(LFMHWnd, GWL_STYLE, GetWindowLong(LFMHwnd, GWL_STYLE) or WS_CHILD);
  Winapi.Windows.SetParent(LFMHWnd, Panel1.Handle);
  LFMForm.Visible := True;
end;

end.

FireMonkey

unit FireMonkeyForms;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Layouts, FMX.Memo;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Memo1: TMemo;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

end.
Community
  • 1
  • 1
Thijs van Dien
  • 6,516
  • 1
  • 29
  • 48

1 Answers1

3

The cause of the behavior is that the window manager does not know you have made your firemonkey window a child, hence it is deactivating the previously active window when you activate the firemonkey window. As is documented in SetParent function you have to set the child flag manually. An example usage could be:

var
  FMForm: TFMForm1;
  FMHWnd: HWND;
begin
  FMForm := TFMForm1.Create(nil);
  FMForm.Left := 0;
  FMForm.Top := 0;

  FMHWnd := FmxHandleToHWND(FMForm.Handle);
  SetWindowLong(FMHWnd, GWL_STYLE, GetWindowLong(FMHwnd, GWL_STYLE) or WS_CHILD);
  winapi.windows.SetParent(FMHWnd, Panel1.Handle);
  FMForm.Visible := True;

Update: If you have to remove the fmx form's borders, setting BorderStyle sets the WS_POPUP style which you cannot use with WS_CHILD. In that case set the styles you need explicitly instead of getting and 'or'ring them. F.i.

  ..
  LFMForm.BorderIcons := [];
  LFMForm.BorderStyle := TFmxFormBorderStyle.bsNone;
  LFMHWnd := FmxHandleToHWND(LFMForm.Handle);
  SetWindowLong(LFMHWnd, GWL_STYLE, WS_CHILDWINDOW or WS_BORDER);
  ..
Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
  • Tried exactly this, but the effect remains. – Thijs van Dien Oct 21 '12 at 23:47
  • 1
    @tvdien - I could duplicate your problem with a brand new project and this piece resolves it there. Your code is probably different, if you can include a simple duplicatable case in your question, it would help. – Sertac Akyuz Oct 21 '12 at 23:50
  • Posted the code. As far as I can tell, I'm doing exactly what you suggested. – Thijs van Dien Oct 22 '12 at 00:05
  • 1
    @tvdien - It's setting the 'BorderStyle' that breaks it, it sets the WS_POPUP style (WS_CHILD cannot be used with WS_POPUP). – Sertac Akyuz Oct 22 '12 at 00:20
  • 1
    I xor'ed with WS_POPUP, as an alternative to the update you posted. Either way, thanks a lot for your efforts! I didn't expect to have this resolved (for me) so quickly. – Thijs van Dien Oct 22 '12 at 00:36
  • 1
    Hmm, now a new problem came up, that keyboard input doesn't come through. Mouse clicks do work. Enabled TabStop, but that didn't change anything. With the border present, it does work. Your answer is accepted anyway, but if you feel like it, any further advice would be appreciated. – Thijs van Dien Oct 22 '12 at 00:44
  • 1
    @tvdien - Can't think of anything right now, if it were a VCL form probably InsertControl would help... Consider asking a new question. – Sertac Akyuz Oct 22 '12 at 00:52