Board index » cppbuilder » Having problems launching a property editor from a component editor

Having problems launching a property editor from a component editor

I am a tiny bit unsure where to post this question and since
cppbuilder.opentoolsapi is not begin used yet I will ask it here.

I have created a TComponentEditor descendant for a specific component and
registered it using RegisterComponentEditor().  When the user double clicks
on the component I would like to launch the property editor to edit a
"TPicture" property of the associated component.  The problem I am having is
in trying to write the correct code to find and launch the appropriate
property editor for the component's TPicture property.  My initial searches
on Google came up with the following scenario, which looked promising:

  void __fastcall TMyEditor::EnumerateProp(const _di_IProperty Property)
  {
    // Will eventually call the appropriate property editor here
  }

  void __fastcall TMyEditor::ExecuteVerb(int Index)
  {
    if (Index != 1)
      return;

    _di_IDesignerSelections list = CreateSelectionList();
    list->Add(Component);

    using Typinfo::TTypeKind;
    GetComponentProperties(list, tkProperties, Designer, &EnumerateProp);
  }

This compiles just fine.  When linked I receive the following error:

  [Linker Error] Unresolved external 'Designeditors::GetComponentProperties(
    const System::DelphiInterface<Designintf::IDesignerSelections>,
    System::Set<Typinfo::TTypeKind, 0, 17>,
    const System::DelphiInterface<Designintf::IDesigner>,
    __closure(*)(...'

My package has "designide.bpi, rtl.bpi, and vcl.bpi" in the requires
section.  GetComponentProperties is declared in DesignEditors.hpp.  When I
look at "designide.bpl" with Dependency Walker I can see
GetComponentProperties as an exported function:

@Designeditors@GetComponentProperties$qqrx58System@%DelphiInterface$t30Desig
nintf@IDesignerSelections%46System@%Set$t17Typinfo@TTypeKind$iuc$0$iuc$17%x4
8System@%DelphiInterface$t20Designintf@IDesigner%ynpqqrx48System@%DelphiInte
rface$t20Designintf@IPrope

So my questions are:

1. Has anyone gotten this to work before?  If so, how?
2. If I am on the right track what do I need to do to get the code to link?

BCB6 Patch2.
TIA,

Clayton

 

Re:Having problems launching a property editor from a component editor


Rather than enumerating the properties yourself, you could derive your
component editor from TDefaultEditor directly instead of TComponentEditor,
then simply override the inherited EditProperty() method, letting the VCL
handle the enumerating for you internally as normal.

Here is the code I use in my component to allow my component editor to bring
up the property editor for either one of two different properties based on
the user input's:

    #include <DesignEditors.hpp>

    class TRegExtensionItemsEditor : public TDefaultEditor
    {
    private:
        int PropIndex;
    protected:
        virtual void __fastcall EditProperty(const _di_IProperty Prop, bool
&Continue);
    public:
        __fastcall TRegExtensionItemsEditor(TComponent* AComponent,
_di_IDesigner ADesigner);
        virtual void __fastcall ExecuteVerb(int Index);
        virtual AnsiString __fastcall GetVerb(int Index);
        virtual int __fastcall GetVerbCount(void);
    };

    __fastcall
TRegExtensionItemsEditor::TRegExtensionItemsEditor(TComponent* AComponent,
 _di_IDesigner ADesigner)
        : TDefaultEditor(AComponent, ADesigner)
    {
        PropIndex = -1;
    }

    void __fastcall TRegExtensionItemsEditor::EditProperty(const
_di_IProperty Prop, bool &Continue)
    {
        AnsiString PropName = Prop->GetName();
        if( ((PropIndex == 0) || (PropIndex == -1)) &&
AnsiSameText(PropName, "Extensions") )
        {
            Prop->Edit();
            Continue = false;
        }
        else if( (PropIndex == 1) && AnsiSameText(PropName, "ProgIDs") )
        {
            Prop->Edit();
            Continue = false;
        }
    }

    void __fastcall TRegExtensionItemsEditor::ExecuteVerb(int Index)
    {
        PropIndex = Index;
        Edit();
        PropIndex = -1;
    }

    AnsiString __fastcall TRegExtensionItemsEditor::GetVerb(int Index)
    {
        switch( Index )
        {
            case 0:
                return "Extensions Editor";
            case 1:
                return "Prog IDs Editor";
        }
        return "";
    }

    int __fastcall TRegExtensionItemsEditor::GetVerbCount(void)
    {
        return 2;
    }

Gambit

Quote
"Clayton Arends" <claytonare...@hotmail.com> wrote in message

news:3e431118$1@newsgroups.borland.com...
Quote
> I have created a TComponentEditor descendant for a specific
> component and registered it using RegisterComponentEditor().
> When the user double clicks on the component I would like to
> launch the property editor to edit a "TPicture" property of the
> associated component.  The problem I am having is in trying to
> write the correct code to find and launch the appropriate property
> editor for the component's TPicture property.

Re:Having problems launching a property editor from a component editor


"Remy Lebeau (TeamB)" <gambi...@yahoo.com> wrote in message
news:3e4316c5$1@newsgroups.borland.com...

Quote
> Rather than enumerating the properties yourself, you could derive your
> component editor from TDefaultEditor directly instead of TComponentEditor

Many thanks, Remy.  That worked perfectly, with one adjustment but that's
due to how my property was defined.  The TPicture property is actually a
subproperty of a TPersistent descendant.  Fortunately, the code to retrieve
the sub properties of a property was straight-forward and actually linked ;)

Just in case anyone is interested, here is my code:

  class PACKAGE TMyEditor : public TDefaultEditor
  {
    typedef TDefaultEditor inherited;
    private:
      virtual void __fastcall EditProperty(
        const _di_IProperty Prop, bool& Continue);

      void __fastcall SubProperty(const _di_IProperty Prop);

    public:
      virtual __fastcall TMyEditor(TComponent* AComponent,
        _di_IDesigner ADesigner);

      virtual void __fastcall ExecuteVerb (int Index);
      virtual String __fastcall GetVerb(int Index);
      virtual int __fastcall GetVerbCount ();
  };

  __fastcall TMyEditor::TMyEditor(TComponent* AComponent,
    _di_IDesigner ADesigner) : inherited(AComponent, ADesigner)
  {
  }

  void __fastcall TMyEditor::EditProperty(
    const _di_IProperty Prop, bool& Continue)
  {
    if (AnsiSameText(Prop->GetName(), "BackgroundImage"))
    {
      Prop->GetProperties(&SubProperty);
      Continue = false;
    }
  }

  void __fastcall TMyEditor::ExecuteVerb(int Index)
  {
    if (Index == 0)
      Edit();
  }

  String __fastcall TMyEditor::GetVerb(int Index)
  {
    return "Picture Chooser ...";
  }

  int __fastcall TMyEditor::GetVerbCount()
  {
    return 1;
  }

  void __fastcall TMyEditor::SubProperty(const _di_IProperty Prop)
  {
    if (AnsiSameText(Prop->GetName(), "Picture"))
      Prop->Edit();
  }

- Clayton

Re:Having problems launching a property editor from a component editor


Quote
"Clayton Arends" <claytonare...@hotmail.com> wrote in message

news:3e431118$1@newsgroups.borland.com...

Quote
> When I look at "designide.bpl" with Dependency Walker I can see
> GetComponentProperties as an exported function:

@Designeditors@GetComponentProperties$qqrx58System@%DelphiInterface$t30Desig
Quote

nintf@IDesignerSelections%46System@%Set$t17Typinfo@TTypeKind$iuc$0$iuc$17%x4
Quote

8System@%DelphiInterface$t20Designintf@IDesigner%ynpqqrx48System@%DelphiInte

Quote
> rface$t20Designintf@IPrope

After getting Remy's suggestion to work I wanted to learn more about why the
other solution would not work.  If you take a look at the above mangled name
you will notice that it ends abruptly at "IPrope" which should continue as
"IProperty ...".  The number of characters happens to be 255.  To make sure
that the problem didn't lay with Dependency Walker I opened the BPL in
notepad and searched for the signature.  Sure enough, the name ends at the
255 byte mark.

So, I created a test using the same declaration in DesignEditors.hpp but
with the function name much smaller (just G).  Here is what I got:

@G$qqrx58System@%DelphiInterface$t30Designintf@IDesignerSelections%46System@
%Set$t17Typinfo@TTypeKind$iuc$0$iuc$17%x48System@%DelphiInterface$t20Designi
ntf@IDesigner%ynpqqrx48System@%DelphiInterface$t20Designintf@IProperty%$vynp
qqrx48System@%DelphiInFmAe

If you'll notice the name is exactly the same up until "IPrope" and then the
signature continues and ends at 255 bytes.  It appears to me that the
compiler/linker has a 255 byte limit for all exported names.  Is this limit
a Windows limit or is it a bug in Borland products?  I am assuming that
Delphi was used to create DesignIde60.bpl so I therefore assume the problem
exists in both products (if it is a Borland problem).

After removing parameters from my function I found that the actual length of
the mangled name needs to be 288.  Which means that the mangled name for
Borland's function needs to be 320 characters.  Here is what the signature
"should" look like for Borland's GetComponentProperties if the full 320
characters were used:

@Designeditors@GetComponentProperties$qqrx58System@%DelphiInterface$t30Desig
nintf@IDesignerSelections%46System@%Set$t17Typinfo@TTypeKind$iuc$0$iuc$17%x4
8System@%DelphiInterface$t20Designintf@IDesigner%ynpqqrx48System@%DelphiInte
rface$t20Designintf@IProperty%$vynpqqrx48System@%DelphiInterface$t20Designin
tf@IProperty%$o

- Clayton

Other Threads