如何创建一个类似组件的对话框,允许在其中放置其他控件?

爱德华多·埃里亚斯

它是一个Firemonkey组件,但是我可以看到,大多数组件库对于VCL和FMX都是相同的,因此,如果您知道如何在VCL中做到这一点,请分享您的知识,它最终可能是我的案例的解决方案。

我正在使用TPopup作为祖先。这对我来说很方便,因为它仍然保留在窗体/框架上,并且可以使用与父级相同的上下文/结构将其与LiveBindings相连,这对我来说非常方便。

我需要它的行为完全是作为容器的TPopup。但是我需要它看起来更好并且有我自己的特定按钮(我在其中为我的软件创建了一些属性和自动化功能)

问题是我创建了一些内部控件(如TLayouts,Tpanels和Tbuttons),使其看起来像这样:(空)

我的空弹出窗口

我想在其中的黑色区域放置TEdit等控件。

我已将所有内部创建的控件都设置为Store = false,因此不会将其存储在流系统中。举例来说,当我放下一个TEdit时,我得到的就是这个(带有aligned = top的Tedit我需要这个):

我的TEdit弹出窗口

但是我期望这样:

我的TEdit弹出窗口位于正确的位置

如果更改Store = true,则可以得到正确的效果,但是所有内部控件都显示在“结构”面板上,并且每次保存表单并重新打开时,所有内容都会重复。暴露的内部组件对我来说不是问题,但重复的是,如果我关闭并打开该组件10次,我将获得整个内部结构10次的复制。

I will try to show some code that is related to the design of the component:

Class declaration:

  [ComponentPlatformsAttribute(pidWin32 or pidWin64 or pidOSX32 or pidiOSSimulator or pidiOSDevice or pidAndroid)]
  TNaharFMXPopup = class(TPopup, INaharControlAdapter, INaharControl)
  private
  protected
    FpnlMain       : TPanel;
    FlytToolBar    : TLayout;
    FbtnClose      : TButton;
    FbtnSave       : TButton;
    FbtnEdit       : TButton;
    FpnlClientArea : TPanel;
    FlblTitle      : TLabel;
    procedure   Loaded; override;
    procedure   Notification(AComponent: TComponent; Operation: TOperation); override;

constructor Create:

    constructor TNaharFMXPopup.Create(AOwner: TComponent);
    begin
      inherited;

      FpnlMain         := TPanel.Create(Self);
      FlblTitle        := TLabel.Create(Self);
      FlytToolBar      := TLayout.Create(Self);
      FbtnEdit         := TButton.Create(Self);
      FpnlClientArea   := TPanel.Create(Self);
      FbtnClose         := TButton.Create(FlytToolBar);
      FbtnSave          := TButton.Create(FlytToolBar);

      Height         := 382;
      Placement      := TPlacement.Center;
      StyleLookup    := 'combopopupstyle';
      Width          := 300;

      ApplyControlsProp;

    end;

Setting properties of the internal controls:

procedure TNaharFMXPopup.ApplyControlsProp;
begin
  with FpnlMain do
  begin
    Parent         := Self;
    Align          := TAlignLayout.Client;
    StyleLookup    := 'grouppanel';
    TabOrder       := 0;
    Margins.Bottom := 10;
    Margins.Left   := 10;
    Margins.Right  := 10;
    Margins.Top    := 10;
    Stored         := false;
  end;
  with FlblTitle do
  begin
    Parent         := FpnlMain;
    Text           := 'Título';
    Align          := TAlignLayout.Top;
    Height         := 36;
    StyleLookup    := 'flyouttitlelabel';
    Stored         := false;
  end;
  with FpnlClientArea do
  begin
    Parent         := FpnlMain;
    Align          := TAlignLayout.Client;
    StyleLookup    := 'gridpanel';
    TabOrder       := 0;
    Margins.Bottom := 5;
    Margins.Left   := 5;
    Margins.Right  := 5;
    Margins.Top    := 5;
    Stored         := false;
  end;
  with FlytToolBar do
  begin
    Parent         := FpnlMain;
    Align          := TAlignLayout.Bottom;
    Height         := 50;
    Stored         := false;
  end;
  with FbtnClose do
  begin
    Parent         := FlytToolBar;
    Text           := 'Fecha';
    Align          := TAlignLayout.Left;
    Height         := 50;
    StyleLookup    := 'tilebutton';
    TabOrder       := 0;
    Width          := 70;
    ModalResult    := mrClose;
    Stored         := false;
  end;
  with FbtnEdit do
  begin
    Parent         := FlytToolBar;
    Text           := '';//'Edita';
    Align          := TAlignLayout.Left;
    Height         := 50;
    StyleLookup    := 'tilebutton';
    TabOrder       := 1;
    Width          := 70;
    ModalResult    := mrContinue;
    Stored         := false;
    Enabled        := false;
  end;
  with FbtnSave do
  begin
    Parent         := FlytToolBar;
    Text           := 'Salva';
    Align          := TAlignLayout.Left;
    Height         := 50;
    StyleLookup    := 'tilebutton';
    TabOrder       := 2;
    Width          := 70;
    ModalResult    := mrOk;
    Stored         := false;
  end;
end;

Loaded:

procedure TNaharFMXPopup.Loaded;
begin
  inherited;

  ApplyControlsProp;
  SetEvents;
end;

I have tried the following with notification, trying to make the inserted control a parent for my intenal "clientarea"

procedure TNaharFMXPopup.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (Operation = opInsert) and (csDesigning in ComponentState) then
  begin
    if AComponent.Owner = self then
      if AComponent is TFmxObject then
      begin
        (AComponent as TFmxObject).Parent := FpnlClientArea;
      end;
  end;

end;

But that made nothing change.

I have asked similar question before, but I was not aware of many things on creating such a component and the answer I got gave little help, I was missing the Parent of each internal component.

Now I am trying to really show where is my need: I need to drop controls on my TPopup dialog that will be parented of the ClientArea inside it.

Sebastian Z

Take a closer look at TTabControl / TTabItem in the unit FMX.TabControl. This is your perfect example because it basically needs to solve the same problem.

以下功能是您需要覆盖的功能:

procedure DoAddObject(const AObject: TFmxObject); override;

当控件添加到您的控件时,将调用此方法。重写此函数,以便将您的控件添加到FpnlClientArea控件中。您将获得类似于以下内容的信息:

procedure TNaharFMXPopup.DoAddObject(const AObject: TFmxObject);
// ...
begin
  if (FpnlClientArea <> nil) and not AObject.Equals(FpnlClientArea) and not AObject.Equals(ResourceLink) then
  begin
    FpnlClientArea.AddObject(AObject);
  end
  else
    inherited;
end;

确保这AObject.Equals还排除了其他“未存储”控件。

没有DoAddObject覆盖,FMX TabControl将显示与您的组件当前相同的问题。


TPopup不能接受控件。因此,还需要一些技巧。这是对我有用的单位的修改版本。我添加了一些评论:

unit NaharFMXPopup;

interface

uses
  System.UITypes,
  System.Variants,
  System.SysUtils, System.Classes, FMX.Types, FMX.Controls, FMX.Layouts, FMX.StdCtrls;

type
  [ComponentPlatformsAttribute(pidWin32 or pidWin64 or pidOSX32 or pidiOSSimulator or pidiOSDevice or pidAndroid)]
  TNaharFMXPopup = class(TPopup)
  private
    procedure   ApplyControlsProp;
  protected
    FpnlMain       : TPanel;
    FlytToolBar    : TLayout;
    FbtnClose      : TButton;
    FbtnSave       : TButton;
    FbtnEdit       : TButton;
    FpnlClientArea : TContent; // change to TContent. 
    // For TPanel we'd have to call SetAcceptControls(False), 
    // but that is not easily possible because that is protected
    FlblTitle      : TLabel;
    procedure   Loaded; override;
    procedure   Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure   DoAddObject(const AObject: TFmxObject); override;
  public
    procedure   InternalOnClose(Sender: TObject);
    procedure   InternalOnSave(Sender: TObject);
    procedure   InternalOnEdit(Sender: TObject);
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
    procedure   SetEvents;
  published
  end;

implementation


{ TNaharFMXPopup }

constructor TNaharFMXPopup.Create(AOwner: TComponent);
begin
  inherited;

  FpnlMain         := TPanel.Create(Self);
  FlblTitle        := TLabel.Create(Self);
  FlytToolBar      := TLayout.Create(Self);
  FbtnEdit         := TButton.Create(Self);
  FpnlClientArea   := TContent.Create(Self); // change to TContent
  FbtnClose         := TButton.Create(FlytToolBar);
  FbtnSave          := TButton.Create(FlytToolBar);

  Height         := 382;
  Placement      := TPlacement.Center;
  StyleLookup    := 'combopopupstyle';
  Width          := 300;

  // A TPopup is not intended to accept controls
  // so we have to undo those restrictions:
  Visible := True;
  SetAcceptsControls(True);

  ApplyControlsProp;
end;

destructor TNaharFMXPopup.Destroy;
begin

  inherited;
end;

procedure TNaharFMXPopup.ApplyControlsProp;
begin
  with FpnlMain do
  begin
    Parent         := Self;
    Align          := TAlignLayout.Bottom;
    StyleLookup    := 'grouppanel';
    TabOrder       := 0;
    Height         := 50;
    Margins.Bottom := 10;
    Margins.Left   := 10;
    Margins.Right  := 10;
    Margins.Top    := 10;
    Stored         := false;
  end;
  with FpnlClientArea do
  begin
    Parent         := Self; // we have to change this to Self (it refuses working if the parent is FPnlMain)
    Align          := TAlignLayout.Client;
    Margins.Left   := 3;
    Margins.Right  := 3;
    Margins.Top    := 3;
    Margins.Bottom := 3;
    Stored         := false;
  end;
  with FlytToolBar do
  begin
    Parent         := FpnlMain;
    Align          := TAlignLayout.Bottom;
    Height         := 50;
    Stored         := false;
  end;
  with FbtnClose do
  begin
    Parent         := FlytToolBar;
    Text           := 'Close';
    Align          := TAlignLayout.Left;
    Height         := 50;
    StyleLookup    := 'tilebutton';
    TabOrder       := 0;
    Width          := 70;
    ModalResult    := mrClose;
    Stored         := false;
  end;
  with FbtnEdit do
  begin
    Parent         := FlytToolBar;
    Text           := '';//'Edita';
    Align          := TAlignLayout.Left;
    Height         := 50;
    StyleLookup    := 'tilebutton';
    TabOrder       := 1;
    Width          := 70;
    ModalResult    := mrContinue;
    Stored         := false;
    Enabled        := false;
  end;
  with FbtnSave do
  begin
    Parent         := FlytToolBar;
    Text           := 'Save';
    Align          := TAlignLayout.Left;
    Height         := 50;
    StyleLookup    := 'tilebutton';
    TabOrder       := 2;
    Width          := 70;
    ModalResult    := mrOk;
    Stored         := false;
  end;
end;

procedure TNaharFMXPopup.Loaded;
begin
  inherited;

  ApplyControlsProp;
//  SetEvents;

end;

procedure TNaharFMXPopup.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;

end;

procedure TNaharFMXPopup.InternalOnClose(Sender: TObject);
begin
end;

procedure TNaharFMXPopup.InternalOnEdit(Sender: TObject);
begin
end;

procedure TNaharFMXPopup.InternalOnSave(Sender: TObject);
begin
end;

procedure TNaharFMXPopup.SetEvents;
begin
  FbtnClose.OnClick := InternalOnClose;
  FbtnSave.OnClick := InternalOnSave;
  FbtnEdit.OnClick := InternalOnEdit;
end;


procedure TNaharFMXPopup.DoAddObject(const AObject: TFmxObject);
begin
//inherited; try commenting the block bellow and uncommenting this one
//Exit;

  if (FpnlClientArea <> nil)
    and not AObject.Equals(FpnlClientArea)
    and not AObject.Equals(ResourceLink)
    and not AObject.Equals(FpnlMain)
    and not AObject.Equals(FlblTitle)
    and not AObject.Equals(FlytToolBar)
    and not AObject.Equals(FbtnEdit)
    and not AObject.Equals(FpnlClientArea)
    and not AObject.Equals(FbtnClose)
    and not AObject.Equals(FbtnSave) then

  begin
    FpnlClientArea.AddObject(AObject);
  end
  else
    inherited;
end;

end.

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在GTK的主窗口中居中放置一个对话框窗口?

来自分类Dev

如何在模态对话框右下角的 <form> 中放置一个 div?

来自分类Dev

如何创建一个无边框对话框?

来自分类Dev

在视图中创建文件夹,我可以在其中放置其他视图

来自分类Dev

如何创建一个对话框,在后台打开我的 SharePoint 网站的同时在其内部打开一个网站?

来自分类Dev

MFC:如何在一个函数中捕获对话框的每个控件的设置焦点

来自分类Dev

我如何递归跟踪空文件夹并在其中放置一个 .keep 文件?

来自分类Dev

在对话框中选择文件,在文本框中放置路径,还有一个按钮作为表格导入

来自分类Dev

WinAPI单击第一个对话框上的按钮控件并销毁第一个对话框后,创建第二个对话框

来自分类Dev

如何从另一个组件打开对话框?

来自分类Dev

通过在bot框架v4中跳过第一个对话框的第一步,将第一个对话框的瀑布步骤调用到其他对话框中

来自分类Dev

在活动顶部创建一个透明对话框

来自分类Dev

在活动顶部创建一个透明对话框

来自分类Dev

在页面内创建一个小对话框

来自分类Dev

在WPF中放置对话框窗口

来自分类Dev

如何在其他树枝+模式对话框Symfony2中渲染视图

来自分类Dev

如何使用Winapi创建一个对话框来选择多个文件?

来自分类Dev

如何创建一个显示当前网页截图的打印对话框

来自分类Dev

如何创建一个包含下拉列表的HTML对话框?

来自分类Dev

XPages:如何创建一个带有回调到调用方的对话框

来自分类Dev

如何防止在按ESC键后关闭基于MFC对话框的应用程序,而是允许其他控件对其进行处理?

来自分类Dev

在另一个对话框上创建对话框

来自分类Dev

创建一个字段,在其中放置URL的结尾,单击提交,然后将其添加到已编码的父URL中

来自分类Dev

如何制作一个多重搜索对话框?

来自分类Dev

KivyMD // Python如何创建一个加载对话框(弹出窗口),该对话框在后台运行代码的同时显示一个旋转的轮子

来自分类Dev

其他路径组件中的“渲染超时”对话框

来自分类Dev

单击“如何防止此页面创建其他对话框”时如何检测

来自分类Dev

如何创建一个单独的类来处理android常见任务(如创建进度对话框)?

来自分类Dev

第一个活动中显示的对话框,而不是创建片段的对话框

Related 相关文章

  1. 1

    如何在GTK的主窗口中居中放置一个对话框窗口?

  2. 2

    如何在模态对话框右下角的 <form> 中放置一个 div?

  3. 3

    如何创建一个无边框对话框?

  4. 4

    在视图中创建文件夹,我可以在其中放置其他视图

  5. 5

    如何创建一个对话框,在后台打开我的 SharePoint 网站的同时在其内部打开一个网站?

  6. 6

    MFC:如何在一个函数中捕获对话框的每个控件的设置焦点

  7. 7

    我如何递归跟踪空文件夹并在其中放置一个 .keep 文件?

  8. 8

    在对话框中选择文件,在文本框中放置路径,还有一个按钮作为表格导入

  9. 9

    WinAPI单击第一个对话框上的按钮控件并销毁第一个对话框后,创建第二个对话框

  10. 10

    如何从另一个组件打开对话框?

  11. 11

    通过在bot框架v4中跳过第一个对话框的第一步,将第一个对话框的瀑布步骤调用到其他对话框中

  12. 12

    在活动顶部创建一个透明对话框

  13. 13

    在活动顶部创建一个透明对话框

  14. 14

    在页面内创建一个小对话框

  15. 15

    在WPF中放置对话框窗口

  16. 16

    如何在其他树枝+模式对话框Symfony2中渲染视图

  17. 17

    如何使用Winapi创建一个对话框来选择多个文件?

  18. 18

    如何创建一个显示当前网页截图的打印对话框

  19. 19

    如何创建一个包含下拉列表的HTML对话框?

  20. 20

    XPages:如何创建一个带有回调到调用方的对话框

  21. 21

    如何防止在按ESC键后关闭基于MFC对话框的应用程序,而是允许其他控件对其进行处理?

  22. 22

    在另一个对话框上创建对话框

  23. 23

    创建一个字段,在其中放置URL的结尾,单击提交,然后将其添加到已编码的父URL中

  24. 24

    如何制作一个多重搜索对话框?

  25. 25

    KivyMD // Python如何创建一个加载对话框(弹出窗口),该对话框在后台运行代码的同时显示一个旋转的轮子

  26. 26

    其他路径组件中的“渲染超时”对话框

  27. 27

    单击“如何防止此页面创建其他对话框”时如何检测

  28. 28

    如何创建一个单独的类来处理android常见任务(如创建进度对话框)?

  29. 29

    第一个活动中显示的对话框,而不是创建片段的对话框

热门标签

归档