delphi – TPopupMenu作为子组件,序列化TMenuItems

delphi – TPopupMenu作为子组件,序列化TMenuItems,第1张

概述我试图将TPopupMenu作为子组件包含在自定义组件中,如下所示: interface TComp1 = class(TComponent) private FMenu: TPopupMenu; protected procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; pu 我试图将TPopupMenu作为子组件包含在自定义组件中,如下所示:

interface  TComp1 = class(TComponent)  private    FMenu: TPopupMenu;  protected    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); overrIDe;  public    constructor Create(AOwner: TComponent); overrIDe;  published    property Menu: TPopupMenu read FMenu;  end;implementation  constructor TComp1.Create(AOwner: TComponent);  begin    inherited Create(AOwner);    FMenu := TPopupMenu.Create(Self);    FMenu.name := 'Menu1';    //FMenu.SetSubComponent(True);  end;  procedure TComp1.GetChildren(Proc: TGetChildProc; Root: TComponent);  begin    Proc(FMenu);  end;

问题是TMenuItems没有保存到DFM.覆盖GetChildren使项目保存,但加载不起作用.

设置SetSubComponent(True)无效,TMenuItems不保存到DFM.

UPD:

我试过了:

procedure TComp1.definePropertIEs(filer: Tfiler);begin  inherited;  filer.defineProperty('Menu',ReadMenuItems,WriteMenuItems,True);end;procedure TComp1.WriteMenuItems(Writer: TWriter);begin  Writer.WriteComponent(FMenu);end;

WriteMenuItems给出“流读取错误”

解决方法 如果您按照 this answer中给出的步骤 *** 作,则代码将变为:

interfaceuses  System.Classes,Vcl.Menus;type  TMyComponent = class;  TMyPopupMenu = class(TPopupMenu)  private    FParent: TMyComponent;    procedure SetParent(Value: TMyComponent);  protected    procedure SetParentComponent(Value: TComponent); overrIDe;  public    destructor Destroy; overrIDe;    function GetParentComponent: TComponent; overrIDe;    function HasParent: Boolean; overrIDe;    property Parent: TMyComponent read FParent write SetParent;  end;  TMyComponent = class(TComponent)  private    FMenu: TPopupMenu;  protected    function GetChildOwner: TComponent; overrIDe;    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); overrIDe;  public    constructor Create(AOwner: TComponent); overrIDe;  published    property Menu: TPopupMenu read FMenu;  end;procedure Register;implementationprocedure Register;begin  RegisterComponents('Samples',[TMyComponent]);end;{ TMyComponent }constructor TMyComponent.Create(AOwner: TComponent);begin  inherited Create(AOwner);  FMenu := TMyPopupMenu.Create(Self);end;function TMyComponent.GetChildOwner: TComponent;begin  Result := Self;end;procedure TMyComponent.GetChildren(Proc: TGetChildProc; Root: TComponent);begin  inherited GetChildren(Proc,Root);  Proc(FMenu);end;{ TMyPopupMenu }destructor TMyPopupMenu.Destroy;begin  FParent := nil;  inherited Destroy;end;function TMyPopupMenu.GetParentComponent: TComponent;begin  Result := FParent;end;function TMyPopupMenu.HasParent: Boolean;begin  Result := FParent <> nil;end;procedure TMyPopupMenu.SetParent(Value: TMyComponent);begin  if FParent <> Value then  begin    if FParent <> nil then      FParent.FMenu := nil;    FParent := Value;    if FParent <> nil then      FParent.FMenu := Self;  end;end;procedure TMyPopupMenu.SetParentComponent(Value: TComponent);begin  if Value is TMyComponent then    SetParent(TMyComponent(Value));end;initialization  RegisterClass(TMyPopupMenu);end.

这解决了您的流媒体问题:菜单项被保存到表单文件中并从表单文件中读回.但是有一些缺点:

>您无法将PopupMenu分配给另一个PopupMenu属性,
>您只能通过双击组件的Menu属性来调用菜单设计器,
>您只能通过选择Object Inspector中的PopupMenu来获取PopupMenu的事件,这只能通过关闭菜单设计器来完成(由于’无法为未命名的组件创建方法’而无法分配这些事件’例外),
>然后你可以修改PopupMenu的名称(顺便说一句,没有任何后果.但你不能将它命名为’Menu’ – 属性的名称 – 因为这将导致’重复的组件名’异常.),
>结构视图将菜单项列为表单的直接子项而不是组件或PopupMenu,
> PopupMenu未显示在结构视图中,
>你不能在代码中命名子组件,也因为’重复组件名称异常'(我想知道为什么顺便说一下; TLabeledEdit中标签的命名工作得很好).

也许另一种方法更好.

我可以建议另类设计吗?添加ActionList属性而不是PopupMenu属性,并从ActionList内部创建PopupMenu:

interfaceuses  System.Classes,Vcl.ActnList,Vcl.Menus;type  TAwComponent = class(TComponent)  private    FActionList: TCustomActionList;    fdropDownMenu: TPopupMenu;    procedure ActionListChanged(Sender: TObject);    function HasActions: Boolean;    procedure SetActionList(Value: TCustomActionList);    procedure SetupDropDownMenu;  protected    procedure Loaded; overrIDe;  public    constructor Create(AOwner: TComponent); overrIDe;  published    property ActionList: TCustomActionList read FActionList write SetActionList;  end;implementationfunction SameEvent(A,B: TNotifyEvent): Boolean;begin  Result := (TMethod(A).Code = TMethod(B).Code) and    (TMethod(A).Data = TMethod(B).Data);end;{ TAwComponent }procedure TAwComponent.ActionListChanged(Sender: TObject);begin  if Sender = FActionList then    SetupDropDownMenu;end;constructor TAwComponent.Create(AOwner: TComponent);begin  inherited Create(AOwner);  fdropDownMenu := TPopupMenu.Create(Self);end;function TAwComponent.HasActions: Boolean;begin  Result := (FActionList <> nil) and (FActionList.ActionCount > 0);end;procedure TAwComponent.Loaded;begin  inherited Loaded;  SetupDropDownMenu;end;procedure TAwComponent.SetActionList(Value: TCustomActionList);begin  if FActionList <> Value then  begin    if FActionList is TActionList then      if SameEvent(TActionList(FActionList).OnChange,ActionListChanged) then        TActionList(FActionList).OnChange := nil;    FActionList := Value;    if FActionList is TActionList then      if not Assigned(TActionList(FActionList).OnChange) then        TActionList(FActionList).OnChange := ActionListChanged;    SetupDropDownMenu;  end;end;procedure TAwComponent.SetupDropDownMenu;var  I: Integer;  MenuItem: TMenuItem;begin  fdropDownMenu.Items.Clear;  if FActionList <> nil then  begin    fdropDownMenu.Images := FActionList.Images;    for I := 0 to FActionList.ActionCount - 1 do    begin      MenuItem := TMenuItem.Create(Self);      MenuItem.Action := FActionList[I];      fdropDownMenu.Items.Add(MenuItem);    end;  end;end;end.

或者在组件外部设置PopupMenu,并使属性可写.

您还可以尝试将MenuItems作为CollectionItems包装在临时Collection中,例如I have done here,但我还没有研究过是否可以从代码中调用菜单设计器.

总结

以上是内存溢出为你收集整理的delphi – TPopupMenu作为子组件,序列化TMenuItems全部内容,希望文章能够帮你解决delphi – TPopupMenu作为子组件,序列化TMenuItems所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1234168.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存