У меня есть приложение, которое загружает плагины в виде bpls. Каждый подключаемый модуль содержит форму для встраивания в другой пакет с именем CoreInf (имя формы ManageF), который является просто базовым графическим интерфейсом приложения, содержащего элемент управления TTabcontrol, известный как MTabcontrol1. Вот в основном что происходит
Список подключаемых модулей динамически загружается во время выполнения в последовательном порядке для макета интерфейса. Он загружает плагины на основе интерфейса IPluginFrame(Shared.bpl) . Если он содержит интерфейс, он пытается создать новую вкладку в MTabcontrol1 и внедрить форму. То, что я пытаюсь сделать, это сделать динамически созданную кнопку скорости onClick, сфокусировать поле TEdit на определенной встроенной форме, но она продолжает появляться как ошибки нарушения доступа.
Shared.bpl, содержащий интерфейс
unit PluginIntf;
interface
uses
FMX.Types, FMX.Controls;
type
IPluginFrame = interface
['{3B4943DB-951B-411B-8726-03BF1688542F}']
function GetBaseControl: TControl;
end;
implementation
end.
Форма и кнопка, которые должны быть встроены в интерфейс
InventoryInf.pas имеет форму для встраивания
var
InventoryF: TInventoryF;
implementation
{$R *.fmx}
function TInventoryF.GetBaseControl: TControl;
begin
Result := InvenLayout; //<---- This is a a TLayout which align
//to client this is the parent of every item on form
end;
//Below is the on click event for the TSpeedButton invBtn
//Which looks for the embedded form that is embedded
//in MTabcontrol1 as a TTabitem that has the name InventoryF
procedure TInventoryF.Look4Tabitem(Sender: TObject);
var
o : TTabitem;
s :TEdit;
begin
o := TTabitem(ManageF.MTabcontrol1.FindComponent('InventoryF'));
ManageF.MTabcontrol1.ActiveTab := o;
s := TEdit(ManageF.MTabcontrol1.FindComponent('VendorF').FindComponent('SearchEdit1')); <-- Dont think it actually found the TEdit
s.Setfocus; <------------------ Not focusing giving access violtaion error
with DataConModule1.InventoryQuery do
...
end;
TSpeedButton invBtn, который внедряется в Panel сбоку
unit InjectedInvBtn;
interface
implementation
uses
FMX.Types, InventoryInf, FMX.Controls, FMX.Forms, InjectedControlsHelper, FMX.StdCtrls,
ManageInf;
var
SysBtn: TSpeedButton;
initialization
SysBtn := TInjectedControl<TSpeedButton>.Create;
SysBtn.Align := TAlignLayout.Top;
SysBtn.Name := 'invBtn';
SysBtn.Text := 'INVENTORY';
ManageF.MenuPanel.AddObject(SysBtn);
SysBtn.OnClick := InventoryF.Look4Tabitem;
end.
**ManageF Показывает, как он загружает формы во вкладки MTabControl1 **
uses Shared;
function IsPluginFrameClass(AType: TRttiType; var AFormClass: TCustomFormClass): Boolean;
var
LClass: TClass;
begin
if not (AType is TRttiInstanceType) then Exit(False);
LClass := TRttiInstanceType(AType).MetaclassType;
Result := LClass.InheritsFrom(TCustomForm) and Supports(LClass, IPluginFrame);
if Result then
AFormClass := TCustomFormClass(LClass);
end;
function TSettingsF.LoadPluginTabs(const AFileName: string): HMODULE;
var
Context: TRttiContext;
Frame: TCustomForm;
FrameClass: TCustomFormClass;
LType: TRttiType;
Package: TRttiPackage;
Tab: TTabItem;
// Statusbar: TTabItem;
//Butz: TButton;
begin
Result := LoadPlugin(AFileName);
try
{ Cycle through the RTTI system's packages list to find the one we've just loaded. }
for Package in Context.GetPackages do
if Package.Handle = Result then
begin
{ Cycle through the package's types looking for implementors of the
IPluginFrameinterface defined in the shared package. }
for LType in Package.GetTypes do
if IsPluginFrameClass(LType, FrameClass) then
begin
{ For each frame, create a new tab to host its contents. In the case of
a VCL application, we could require an actual TFrame object, or failing
that, embed the form directly. FireMonkey has neither frames proper nor
supports embedded forms, so instead we ask the implementing form to
nominate a base control that will get embedded. }
Tab := TTabItem.Create(ManageF.MTabcontrol1);
Frame := FrameClass.Create(Tab);
Tab.Text := ' ' + Frame.Caption;
Tab.Name := Frame.Name;
MyTablist.Add(Tab);
(Frame as IPluginFrame).GetBaseControl.Parent := Tab;
{ Associate the tab with the plugin - since it owns the 'frame' form,
and that form owns its own components, freeing the tab will have the
effect of freeing all the actual plugin objects too. }
RegisterPluginComponent(Result, Tab);
ManageF.MTabcontrol1.AddObject(Tab);
Tab.Width := Tab.Canvas.TextWidth(Tab.Text + 'w');
end;
if IsStatusFrameClass(LType, FrameClass) then
begin
....
{ Associate the tab with the plugin - since it owns the 'frame' form,
and that form owns its own components, freeing the tab will have the
effect of freeing all the` actual plugin objects too. }
// RegisterPluginComponent(Result, Statusbar);
// ManageF.StatusMenuPanel1.AddObject(Statusbar);
//Statusbar.Width := Statusbar.Canvas.TextWidth(Statusbar.Name + 'w');
end;
Break;
end;
except
UnloadPlugin(Result);
raise;
end;
end;
Надеюсь, я правильно проиллюстрировал проблему. Пожалуйста, помогите =(