DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: tino0914
今日帖子: 31
在线用户: 8
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2022/4/17 10:36:37
标题:
Firemonkey中,如何把一个Form嵌入到另一个Form中的控件中? 浏览:1758
加入我的收藏
楼主: 我希望把Form2(无边框)嵌入到Form1.Layout1或Panel1中去。

网上搜到的方案,都是在Form2中放一个Align=client的Layout或Panel,再把Form2中的这个Layout或Panel的Parent指到Form1的Layout或Panel。

而我希望的是直接能把Form2嵌入到Form1.Layout1或Panel1中去。有办法么?
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/4/17 12:48:06
1楼: you can try my sample:

---------- Form1-- Caller!

type
  TForm1 = class(TForm)
    Layout1: TLayout;
    BtnCallsForm2InMyLayout: TButton;
    procedure BtnCallsForm2InMyLayoutClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses
  Unit2;

procedure TForm1.BtnCallsForm2InMyLayoutClick(Sender: TObject);
begin
  for var i: integer := 0 to (Layout1.ChildrenCount - 1) do
  begin
    if (Layout1.Children.Items[i] is TLayout) and (Layout1.Children.Items[i].Owner is TForm2) then
      Layout1.Children.Items[i].Owner.Free;
  end;
  //
  Form2 := TForm2.Create(Self); // self for usage "caFree" on Form2!
  //
  Layout1.AddObject(Form2.Layout1);
end;

end.


---------- Form2 -- Called!
type
  TForm2 = class(TForm)
    Label1: TLabel;
    BtnCloseMe: TButton;
    Layout1: TLayout;
    procedure BtnCloseMeClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

var
  MyText: string = '';

procedure TForm2.BtnCloseMeClick(Sender: TObject);
begin
  Close;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caFree; // if created with "SELF"
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  MyText      := 'Im Form2 at ' + DateTimeToStr(now);
  Label1.Text := MyText;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  ShowMessage('destroying form2...: ' + MyText);
end;

end.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/4/17 12:50:02
2楼: screenshot
此帖子包含附件:
PNG 图像
大小:32.4K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/4/17 12:52:09
3楼: screenshot2
此帖子包含附件:
PNG 图像
大小:26.4K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2022/4/17 20:10:19
4楼: Thanks @emailx45 for your reply. But your solution is still to put the Layout component in Form2 on top of the component in Form1. I wish I could embed Form2 directly into the Layout component of Form1.
----------------------------------------------
-
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2022/4/17 20:31:59
5楼: Please let me talk about the business requirements behind me: I need to play video on the Layout of Form1, my plan is to call ffplay.exe to play the video file, then embed the ffplay's playback window into Form2, and then embed Form2 into Form1.Layout1.

The following line of code is the key code used to embed the ffplay window into Form2. Only TForm can been got the Windows handle in Firemonkey.
Winapi.Windows.SetParent(ffPlayVideoWnd, Form2_Wnd);
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/4/18 0:39:52
6楼: Unfortunatelly, you CAN NOT put another "Form" into a "Form".
Because the forms particularity... 

Like a "root-container" it is like a application-in-live. 
You notice this when it takes over the screen in a modal window.

It has behaviors of its own, which would conflict with other forms within it.

Therefore, a "FRAME" is accepted, mainly because it does not inherit all the characteristics of a form, such as modal properties.

Therefore, the most common and accepted practice is to place a form inside a container such as a "TPanel" or a "TLayout/FMX" (or similar), however, note that the form must be of the "NOT MODAL" type, so we use "SHOW" or it can be embedded as an object inside the container, as I showed above.

On the other hand, you can, through more advanced techniques, redirect the output of one application, and capture it on the screen of another application.

I'm not very familiar with the operating system's nuances, but in summary, this can be done by capturing the "Handle" of the window you want to control, and sending it to another control. As you are indicating in the line of the Windows API "SetParent()".

NOTE: in VCL, a "FRAME" have a "handle" property... in FMX, does not!
TFrame FMX = TControl...
TFrame VCL = TWinControl... normally, will have a "handle"

To try to help you I would have to look at your code and see how you are making the calls from the external application, etc...

But I can't say much without something to actually analyze.

my email:  emailx45 @ yahoo com br

It is also worth analyzing, if FFplay provides access to its main library of functions (DLL/OS), above you could just "IMPORT" the calls from this library to Delphi, which would, in theory, be much easier to control.

For that, try using the following from Delphi:
--> Components -> Import Components -> Type Library -> .... and find the DLL of said software installed on your system.

Remembering that on the target device of the software installation, you must have the same DLL/OS installed or copied to your software folder.
此帖子包含附件:
PNG 图像
大小:15.7K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 net1999 (好人) ★☆☆☆☆ -
普通会员
2022/4/18 7:30:49
7楼: 指定 parent 属性行不行?
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/4/18 8:54:41
8楼: AddOject(...) already does it! = Layout1FromForm2.Parent = Layout1FromForm1

uses
  Unit2;

procedure TForm1.BtnCallsForm2InMyLayoutClick(Sender: TObject);
begin
  for var i: integer := 0 to (Layout1.ChildrenCount - 1) do
  begin
    if (Layout1.Children.Items[i] is TLayout) and (Layout1.Children.Items[i].Owner is TForm2) then
    begin
     ShowMessage( Layout1.Children.Items[i].Parent.Name);
     ShowMessage( Layout1.Children.Items[i].Parent.Parent.Name);
      //
      Layout1.Children.Items[i].Owner.Free;
    end;
  end;
  //
  Form2 := TForm2.Create(Self); // self for usage "caFree" on Form2!
  //
  Layout1.AddObject(Form2.Layout1);
end;

end.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/4/18 9:10:59
9楼: procedure TForm1.BtnCallsForm2InMyLayoutClick(Sender: TObject);
begin
  (* for var i: integer := 0 to (Layout1.ChildrenCount - 1) do
    begin
    if (Layout1.Children.Items[i] is TLayout) and (Layout1.Children.Items[i].Owner is TForm2) then
    begin
    ShowMessage( Layout1.Children.Items[i].Parent.Name);
    ShowMessage( Layout1.Children.Items[i].Parent.Parent.Name);
    Layout1.Children.Items[i].Owner.Free;
    end;
    end;
  *)
  //
  Form2 := TForm2.Create(Self); // self for usage "caFree" on Form2!
  // Form2.Parent := Layout1;
  // Form2.Show;  // show does not works like expected!
  Layout1.AddObject(Form2.Layout1);
  // Form2.Show;  // show does not works like expected!
end;

按此在新窗口浏览图片
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
2022/4/18 10:30:06
10楼: FMX里将Form嵌入其他东西是做不到的
你只能将Layout嵌入其他东西(Panel你可以看作只是一个带了一个背景的Layout)

所以, 放弃Form嵌入,将Form里的东西都摆在一个Layout里,然后将这个Layout嵌入其他东西

又或者, 你动态创建一个Layout, 然后枚举Form里面的Children,将它们嵌到你创建的Layout里,然后再将父Layout替代原来的Form嵌入其他东西里
----------------------------------------------
-
作者:
男 wenyue0811 (wenyue0811) ★☆☆☆☆ -
普通会员
2022/4/18 10:30:47
10楼: FMX 和 VCL 不一样, 有很多地方不要用 VCL 的方式来想像 FMX 也会这样操作.
所以就是多看 DELPHI 的帮助, 帮助中有提到这方面.
所以只能间接的来进行 FORM 的嵌入,别的就不表要想了.
记住这一点就行了.
----------------------------------------------


美国国务卿蓬佩奥回答大学生提问时说,“我曾担任美国中央情报局(CIA)的局长。我们撒谎、我们欺骗、我们偷窃。我们还有一门课程专门来教这些。这才是美国不断探索进取的荣耀
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/4/18 11:10:02
11楼: to end this topic:

ONLY "TCONTROLS" can be "ParentED" to appears on root-object
FMX.Controls.pas, line 2210: if AObject is TControl then

a form (TFmxObject) is a root-object, then, form-in-form does not works!
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2022/4/18 18:55:38
12楼: It's clear. Thanks!
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/4/18 19:50:43
13楼: 其实楼主的问题,不是简单的把 Form2 放到 Form1 上面去  --- 在 VCL 底下很简单。

在 FireMonkey 底下,楼主的问题是一个外部的播放器,要放到 Form1 上面。

如果是 WINDOWS 底下,可能还有办法。在 WINDOWS 底下,外部的播放器窗口也有一个 WINDOWS 的 Handle 的。

但如果是 Android 或者 iOS APP,估计难搞了。

视频播放,如果使用外部播放器,在手机上,目前我只能让外部播放器最大化占据整个屏幕。如果想让它在我的 Form 的窗口里面,目前我只能自己做视频的显示。其实就是解码后的数据拿去不停地画图。
----------------------------------------------
-
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2022/4/18 22:15:27
14楼: @pcplayer,是的。就是把外部播放器的窗口,嵌入到FMX TForm上的一个局部区域。我今天已经想到办法了,只是还没空去做实现。等有空了尝试一下再来说。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/4/18 23:02:15
15楼: 楼上你是在 Windows 底下做?

还是想做安卓或者苹果?
----------------------------------------------
-
作者:
男 sxqwhxq (步惊云) ★☆☆☆☆ -
普通会员
2022/4/19 10:04:12
16楼: 在fmx的form里嵌套frame是可行的
----------------------------------------------
-
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2022/4/19 19:23:40
17楼: @pcplayer, 是Windows下。我现在的计划仍是把外部播放器的窗口嵌入到Form上,取得Form的Handle转成Windows句柄,然后通过WinAPI设置调整播放窗口的大小到合适的区域。要花时间研究一下,应该是可行的。

@步惊云,Frame应该不行吧?没有Windows句柄。
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/4/19 21:15:01
18楼: In VCL it's more easy have the "external-app-window" into "Form1" because we have "HANDLEs" to identify each window: external-app and Form-handle in RAD.

you can use some MS Windows API functions:
-- Winapi.ShellAPI.ShellExecuteEx() // run external-app
-- Winapi.Windows.WaitForInputIdle() // wait external-app-works
-- Winapi.Windows.FindWindow() // find external-app-window
-- Winapi.Windows.SetParent() // define external-app-window parent
-- Winapi.Windows.ShowWindow() // show the external-app-window
-- Winapi.Windows.SetWindowPos() // to resize your new-window-app

NOTE: this technic does not works with all external-application, of course!

.
此帖子包含附件:
PNG 图像
大小:53.4K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 bjlg (蓝天) ★☆☆☆☆ -
盒子活跃会员
2022/4/29 16:48:57
19楼: 好像出了form,其他的还行吧
----------------------------------------------
http://delphi.icm.edu.pl/ftp/http://delphi-z.ru
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行125毫秒 RSS