IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

VitualTreeView et IVTEditLink


Sujet :

C++Builder

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par défaut VitualTreeView et IVTEditLink
    Bonjour,

    J'utilise un virtualtreeview et j'ai besoin d'éditer plusieurs colonnes.
    Une d'elle est une combobox, j'ai créé ma classe dérivée de IVTEditLink que j'appelle via l'événement CreateEditor et ça fonctionne très bien.
    Problème, ce mode d'édition s'applique sur toutes les colonnes éditables alors que je ne souhaite la combo que sur une seule. Sur les autres je voudrais laisser l'édition de base.
    J'ai essayé dans CreateEditor ne faire appel à ma class que si je suis sur la colonne qui m’intéresse, mais du coup j'obtiens le message d'erreur suivant lorsque j'essaye d'éditer une autre colonne :
    Edit Link must not be nil

    Quelqu'un sait il comment faire pour obtenir 2 modes d'édition différents ?

    merci !
    Pascale38

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 081
    Par défaut
    Je ne connais pas VirtualTreeView, il semble que le OnCreateEditor fourni des paramètres, un Sender évidemment ainsi qu'un paramètre Column.

    Pourquoi ne pas créer un IVTEditLink par défaut, il doit bien y avoir une classe par défaut pour implémenter cette interface ?
    Regarde dans le code source Delphi de DoCreateEditor, il doit y avoir un code genre :
    Code delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function TVirtualTreeView.DoCreateEditor(Column): IVTEditLink 
    begin
      if FOnCreateEditor then
        FOnCreateEditor(Self, Column, Result)
      else
        Result := LaClasseParDéfaut.Create();  
    end;



    Sinon, pour une simple ComboBox dans une colonne il n'y a rien de plus simple ?
    Tu n'aurais pas une propriété PickList comme on pourrait le voir dans la TDBGrid ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par défaut
    Salut ShaiLeTroll,

    pas trouvé plus simple que le IVTEditLink malheureusement ! Tout ce que j'ai trouvé c'est de devoir créer la classe qui dérive donc de IVTEditLink.
    Autant les checkBox sont présentes nativement dans le composant, autant rien concernant les combo...

    J'ai cherché du côté de la classe par défaut bien sûr, mais je n'ai pas trouvé, d'où le post...

    j'ai trouvé ça dans les sources
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    function TCustomVirtualStringTree.DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink;
     
    begin
      Result := inherited DoCreateEditor(Node, Column);
      // Enable generic label editing support if the application does not have own editors.
      if Result = nil then
        Result := TStringEditLink.Create;
    end;
    mais je ne sais pas trop comment m'en servir et en c++ en plus...???
    (je connais rien au delphi !!!)

    Il semblerait que la solution soit dans ma classe dérivée de gérer les différentes éditions possibles selon ma colonne... pfff quel boulot juste pour une combo !

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 081
    Par défaut
    Eh bien mon LaClasseParDéfaut correspond donc à TStringEditLink
    Le code devrait gérer l'utilisation du NULL (nil) et fournir une instance par défaut, tu as une étrange erreur !

    il te suffit de faire

    Tu as bien utiliser OnCreateEditor (via l'inspecteur d'objet) ? tu n'as pas fait un héritage de TVirtualTreeView et redéfini DoCreateEditor ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void TForm1::VirtualTreeView1CreateEditor(TObject* Sender, TColumnIndex Column, IVTEditLink* &EditLink)
    {
      if (Column == IndexDELaColonneAvecCombo)
        EditLink = new TComboLinkDePascale38();
      else
        EditLink = new TStringEditLink();
    }
    cherche dans le code un raise avec le message "Edit Link must not be nil"
    Soit c'est une Exception spécifique au TVirtualTreeView
    Soit c'est une Assertion (EAssertionFailed) avec la fonction Assert()

    Lorsque l'on fait du C++Builder, il est important de savoir lire du Delphi, surtout lorsque l'on utilise des composants externes avec des documentations souvent légères !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par défaut
    on a donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    function TCustomVirtualStringTree.DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink;
     
    begin
      Result := inherited DoCreateEditor(Node, Column);
      // Enable generic label editing support if the application does not have own editors.
      if Result = nil then
        Result := TStringEditLink.Create;
    end;
    et TCustomVirtualStringTree hérite de TBaseVirtualTree :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     TCustomVirtualStringTree = class(TBaseVirtualTree)
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    function TBaseVirtualTree.DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink;
     
    begin
      Result := nil;
      if Assigned(FOnCreateEditor) then
      begin
        FOnCreateEditor(Self, Node, Column, Result);
        if Result = nil then
          ShowError(SEditLinkIsNil, hcTFEditLinkIsNil);
      end;
    end;
    c'est de la que vient le message, et du coup il apparaît avant l'appel de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    TStringEditLink.Create
    suis un peu perdue là...

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 081
    Par défaut
    As-tu essayé mon exemple de code de 13h16, en créant manuellement un TStringEditLink dont le Gestionnaire d'évèmenent OnCreateEditor

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void TForm1::VirtualStringTree1CreateEditor(TObject* Sender, PVirtualNode Node, TColumnIndex Column, IVTEditLink* &EditLink)
    {
      if (Column == IndexDELaColonneAvecCombo)
        EditLink = new TComboLinkDePascale38();
      else
        EditLink = new TStringEditLink();
    }
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par défaut
    oui désolée, me revoilà !!!
    alors j'ai testé ça (il faut passer par un QueryInterface) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void __fastcall TLabelForm::VirtualStringTreeCreateEditor
    	(TBaseVirtualTree *Sender,
    	PVirtualNode Node, TColumnIndex Column, IVTEditLink *EditLink){
    	if (Column == IndexDELaColonneAvecCombo){
    		TMyEditLink *NewEditLink = new TMyEditLink(true);
    		NewEditLink->QueryInterface(__uuidof(IVTEditLink), (void**)EditLink);
    	}
    	else{
    		TStringEditLink *NewEditLink = new TStringEditLink();
    		NewEditLink->QueryInterface(__uuidof(IVTEditLink), (void**)EditLink);
    	}
    }
    et ça a l'air de bien fonctionner !!
    Je continue mes tests, et si je ne trouve pas de problème majeur je mettrai le post en résolu !!

    encore une fois, merci à toi !!!
    Pascale38

  8. #8
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 081
    Par défaut
    Fait attention tout de même, l'utilisation d'interface implique probablement un compteur de référence et une libération automatique par les DelphiInterface !

    TMyEditLink et TStringEditLink n'implémente pas IVTEditLink directement ?

    IVTEditLink est-ce un __interface ou un DelphiInterface ?

    vérifie l'exactitude du prototype entre les différentes possibilités

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    IVTEditLink *EditLink
    IVTEditLink **EditLink
    IVTEditLink* &EditLink
    _di_IVTEditLink &EditLink
    la dernière syntaxe étant en réalité la plus proche de celle des interfaces Delphi !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    229
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 229
    Par défaut
    En ce qui concerne IVTEditLink , je n'ai pas trouvé les sources en C++, mais voilà le bout de code delphi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
      IVTEditLink = interface
        ['{2BE3EAFA-5ACB-45B4-9D9A-B58BCC496E17}']
        function BeginEdit: Boolean; stdcall;                  // Called when editing actually starts.
        function CancelEdit: Boolean; stdcall;                 // Called when editing has been cancelled by the tree.
        function EndEdit: Boolean; stdcall;                    // Called when editing has been finished by the tree.
        function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
                                                               // Called after creation to allow a setup.
        function GetBounds: TRect; stdcall;                    // Called to get the current size of the edit window
                                                               // (only important if the edit resizes itself).
        procedure ProcessMessage(var Message: TMessage); stdcall;
                                                               // Used to forward messages to the edit window(s)-
        procedure SetBounds(R: TRect); stdcall;                // Called to place the editor.
      end;
    quand au compteur de référence, c'est gérer dans TMyEditLink dont voici le code (récupéré sur internet)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
     
    class TMyEditLink : public IVTEditLink
    {
    private:
    	TComboBox *FComboBox;
    	TBaseVirtualTree* FTree;
    	PVirtualNode FNode;
    	TColumnIndex FColumn;
    	TNodeLabel *FNodeData;
    	unsigned long m_RefCount;
     
    public:
    	/* general */
    	__fastcall TMyEditLink() : IVTEditLink()
    	{
    		// initialise
    		FComboBox = new TComboBox(HWND(NULL));
    		FComboBox->Style = csDropDownList;
    		FComboBox->Visible = false;
    		m_RefCount = 0;
    	}
     
    	__fastcall ~TMyEditLink()
    	{
    		// free memory
    		delete FComboBox;
    	}
     
    	/* IVTEditLink */
    	virtual bool __stdcall BeginEdit(void)
    	{
    		// show combo
    		FComboBox->Show();
    		FComboBox->SetFocus();
     
    		return true;
    	}
     
    	virtual bool __stdcall CancelEdit(void)
    	{
    		// hide combo
    		FComboBox->Hide();
    		FTree->SetFocus();
     
    		return true;
    	}
     
    	virtual bool __stdcall EndEdit(void)
    	{
    		// set new data
    		FNodeData->type = FComboBox->Text;
    		if (FNodeData->usage != NULL)
    		{
    			FNodeData->usage->type = FComboBox->Text;
    		}
     
    		// hide combo
    		FComboBox->Hide();
    		FTree->SetFocus();
     
    		return true;
    	}
     
    	virtual bool __stdcall PrepareEdit(TBaseVirtualTree* Tree,
    		PVirtualNode Node,
    		TColumnIndex Column)
    	{
    		// set ptrs
    		FTree = Tree;
    		FNode = Node;
    		FColumn = Column;
     
    		// get data for node
    		FNodeData = (TNodeLabel*)(FTree->GetNodeData(FNode));
     
    		// init combobox
    		FComboBox->Parent = FTree;
    		FComboBox->Items->CommaText = "Setting,Measure,Fault,State";
    		FComboBox->ItemIndex =
    			FComboBox->Items->IndexOf(FNodeData->type);
     
    		return true;
    	}
     
    	virtual TRect __stdcall GetBounds(void)
    	{
    		return FComboBox->BoundsRect;
    	}
     
    	virtual void __stdcall ProcessMessage(TMessage &Message)
    	{
    		FComboBox->WindowProc(Message);
    	}
     
    	virtual void __stdcall SetBounds(const TRect R)
    	{
    		FComboBox->BoundsRect =
    			FTree->GetDisplayRect(FNode, FColumn, false, true);
    	}
     
    	/* IUnkown */
    	virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv)
    	{
    		if (iid == IID_IUnknown || iid == __uuidof(IVTEditLink))
    		{
    			*ppv = static_cast<IVTEditLink*>(this);
    		}
    		else
    		{
    			*ppv = 0;
    			return E_NOINTERFACE;
    		}
     
    		(reinterpret_cast<IUnknown*>(*ppv))->AddRef();
    		return S_OK;
    	}
     
    	virtual unsigned long __stdcall AddRef(void)
    	{
    		return static_cast<unsigned long>(InterlockedIncrement(
    			reinterpret_cast<long*>(&m_RefCount)));
    	}
     
    	virtual unsigned long __stdcall Release(void)
    	{
    		if (m_RefCount == 1)
    		{
    			delete this;
    			return 0;
    		}
    		else
    		{
                            return static_cast<unsigned long>(InterlockedDecrement(
    				reinterpret_cast<long*>(&m_RefCount)));
    		}
    	}
    };

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. VirtualTreeView et IVTEditLink
    Par Pascale38 dans le forum Composants VCL
    Réponses: 1
    Dernier message: 21/11/2011, 11h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo