Please consider such scenerio:
I have component called TMenuItemSelector
which has two published properties: PopupMenu
- allows to pick an instance of TPopupMenu
from the form and MenuItem
which allows to pick any instance of TMenuItem
from the form.
I would like to modify property editor for MenuItem
property in a way that when PopupMenu
is assigned then only menu items from this PopupMenu
are visible in a drop down list.
I know that I need to write my own descendant of TComponentProperty
and override GetValues
method. The problem is that I do not know how to access the form on which TMenuItemSelector
is lying.
Original TComponentProperty
is using this method to iterate all available instances:
procedure TComponentProperty.GetValues(Proc: TGetStrProc);
begin
Designer.GetComponentNames(GetTypeData(GetPropType), Proc);
end;
However, Designer
seems to be precompiled so I have no idea how GetComponentNames
works.
This is what I have so far, I guess only thing which I am missing is the implementation of GetValues
:
unit uMenuItemSelector;
interface
uses
Classes, Menus, DesignIntf, DesignEditors;
type
TMenuItemSelector = class(TComponent)
private
FPopupMenu: TPopUpMenu;
FMenuItem: TMenuItem;
procedure SetPopupMenu(const Value: TPopUpMenu);
procedure SetMenuItem(const Value: TMenuItem);
published
property PopupMenu: TPopUpMenu read FPopupMenu write SetPopupMenu;
property MenuItem: TMenuItem read FMenuItem write SetMenuItem;
end;
type
TMenuItemProp = class(TComponentProperty)
public
function GetAttributes: TPropertyAttributes; override;
procedure GetValues(Proc: TGetStrProc); override;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterPropertyEditor(TypeInfo(TMenuItem), TMenuItemSelector, 'MenuItem', TMenuItemProp);
RegisterComponents('Test', [TMenuItemSelector]);
end;
{ TMenuItemSelector }
procedure TMenuItemSelector.SetMenuItem(const Value: TMenuItem);
begin
FMenuItem := Value;
end;
procedure TMenuItemSelector.SetPopupMenu(const Value: TPopUpMenu);
begin
FPopupMenu := Value;
end;
{ TMenuItemProperty }
function TMenuItemProp.GetAttributes: TPropertyAttributes;
begin
Result := inherited GetAttributes + [paValueList, paSortList];
end;
procedure TMenuItemProp.GetValues(Proc: TGetStrProc);
begin
//How to filter MenuItems from the form in a way that only
//MenuItems which belong to TMenuItemSelector.PopupMenu are displayed? \
//And how to get to that form?
//inherited;
end;
end.
Anyone could help?
Thanks.
When
TMenuItemProp.GetValues()
is called, you need to look at theTMenuItemSelector
object whoseMenuItem
property is currently being edited, see if that object has aPopupMenu
assigned, and if so then loop through its items as neded, eg:BTW, you need to implement
TMenuItemSelector
andTMenuItemProp
in separate packages. With the exception of theRegisterComponents()
function, (which is implemented in a runtime package), design-time code is not allowed to be compiled into run-time executables. It is against the EULA, and Embarcadero's design-time pacakges are not allowed to be distributed. You need to implementTMenuItemSelector
in a runtime-only package, and then implementTMenuItemProp
andRegister()
in a designtime-only package thatRequires
the runtime-only package anduses
the unit thatTMenuItemSelector
is declared in, eg:.