1

我有一个加载 bpls 形式的插件的应用程序。每个插件都包含一个要嵌入到另一个名为 CoreInf 的包中的表单(表单名称 ManageF),它只是包含称为 MTabcontrol1 的 TTabcontrol 的应用程序的基本 gui。这里基本上发生了什么

插件列表在运行时按顺序动态加载以布局界面。它基于接口 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;

希望我正确地说明了这个问题。请帮忙=(

4

1 回答 1

0

通过遍历嵌入的 Tcustomform 的组件找到了解决方法。这就是我所做的。

而不是 TEdit 我使用了一个 tms 编辑框 TTMSFMXSearchEdit

procedure TVendorF.focuscheck;
var
  i: integer;
  j: integer;
  Fieldname: string;
  o : TTabitem;
  e : TTMSFMXSearchEdit;
begin
  if ManageF.MTabcontrol1.FindComponent('VendorF').Name = 'VendorF' then
    begin
    o  := TTabitem(ManageF.MTabcontrol1.FindComponent('VendorF'));

   //ShowMessage(IntToStr(o.ComponentCount)) ;
   // ShowMessage((o.Components[0].tostring));

      for i := 0 to ManageF.MTabcontrol1.ActiveTab.ComponentCount - 1 do
        if (ManageF.MTabcontrol1.ActiveTab.Components[i]) is TCustomForm then
          begin
         // ShowMessage('TCustomForm Recognized gonna look for child components now');
         // ShowMessage(IntToStr(ManageF.MTabcontrol1.ActiveTab.Components[i].ComponentCount));

        for j := 0 to ManageF.MTabcontrol1.ActiveTab.Components[i].ComponentCount - 1 do
                if (ManageF.MTabcontrol1.ActiveTab.Components[i].Components[j]) is TTMSFMXSearchEdit then
                   begin
                   // ShowMessage('Edit box found =)')
                        if (ManageF.MTabcontrol1.ActiveTab.Components[i].Components[j].Name = 'VenSearchEdit1') then
                           begin
                           //ShowMessage('Edit1 box found =)');
                           //ShowMessage('See if we can focus it');
                           e := TTMSFMXSearchEdit(ManageF.MTabcontrol1.ActiveTab.Components[i].Components[j]) ;
                           e.SetFocus;
                           end;

                end;
        end;
   end;
end;

它有点草率,但它有效=)。如果其他人有更好的方法,请告诉我

于 2014-07-03T04:27:16.823 回答