10
votes

Delphi - appeler de manière dynamique des fonctions différentes

J'ai une arborescence (virtualtree) qui a des nœuds. Lorsqu'un utilisateur clique sur un nœud, je dois exécuter une fonction spécifique, en passant le nom de texte du nœud. Cette fonction est l'un des attributs du nœud. Par exemple, supposons deux nœuds.

nœud 1, nom = myhouse, fonction = buildhouse
Node 2, nom = mycar, fonction = runcar

Lorsque je clique sur le nœud 1, je dois appeler la fonction buildhouse ('myhouse');
Lorsque je clique sur le nœud 2, j'ai besoin d'appeler Runcar ('mycar');

Les arguments sont toujours des cordes. Il convient de noter que ce sont des fonctions vraies, pas des membres d'une classe.

Il y a trop de nœuds pour avoir une affaire ou si / puis le type de structure de code. J'ai besoin d'un moyen d'appeler les différentes fonctions de manière dynamique, c'est-à-dire sans le code du comportement. Comment puis-je faire cela? Comment puis-je appeler une fonction lorsque je dois rechercher le nom de la fonction à l'exécution, pas compilez l'heure?

merci, Gs


4 commentaires

Les sous-classes et les méthodes virtuelles sont la meilleure approche, si pratique. Sinon, les pointeurs de fonctions Pascal / Delphi vont bien. Larry Lustig donne un excellent exemple ci-dessous.


Désolé pour l'offtopic mais j'ai vu que Virtualtree est très populaire où puis-je obtenir ce composant?


@ opc0de au code de Google: code.google.com/p/virtual-treeview


Je déteste nécromance mon poteau ... mais une autre alternative (selon le scénario) est simplement de déclarer votre pointeur de méthode comme un pointeur de méthode. Exemple: Type TnodeFunction = Procédure (Ainput: String) de l'objet; . Plus de détails ici: docwiki.embarcadero.com/radstudio/xe3/fr/... < / a>


3 Réponses :


15
votes

Delphi permet de créer des variables pointant sur les fonctions, puis appelez la fonction via la variable. Ainsi, vous pouvez créer vos fonctions et attribuer une fonction à un attribut correctement typé du nœud (ou vous pouvez attribuer des fonctions à, par exemple, la propriété pratique de données code> de nombreuses classes d'articles de collecte).

interface

type
  TNodeFunction = function(AInput: String): String;

implementation

function Func1(AInput: String): String;
begin
   result := AInput;
end;

function Func2(AInput: String): String;
begin
   result := 'Fooled You';
end;

function Func3(AInput: String): String;
begin
   result := UpperCase(AInput);
end;

procedure Demonstration;
var
  SomeFunc, SomeOtherFunc: TNodeFunction;
begin

     SomeOtherFunc = Func3;

     SomeFunc := Func1;
     SomeFunc('Hello');   // returns 'Hello'
     SomeFunc := Func2;
     SomeFunc('Hello');   // returns 'Fooled You'

     SomeOtherFunc('lower case'); // returns 'LOWER CASE'

end;


0 commentaires

2
votes

Je n'utilise jamais virtualtree, mais je peux vous dire 2 façons de cela.

première méthode: p>

Si vous utilisez Delphi 2009 ou la version supérieure, essayez d'utiliser RTTI pour une méthode d'appel de l'appel dynamique p >

Ceci est un exemple pour RTTI P>

uses rtti;

function TVLCVideo.Invoke(method: string; p: array of TValue): TValue;
var
  ctx     : TRttiContext;
  lType   : TRttiType;
  lMethod : TRttiMethod;

begin
  ctx := TRttiContext.Create;
  lType:=ctx.GetType(Self.ClassInfo); // where is the your functions list ? if TFunctions replace the Self with TFunctions class
  Result := nil;
  try
    if Assigned(lType) then
      begin
       lMethod:=lType.GetMethod(method);

       if Assigned(lMethod) then
        Result := lMethod.Invoke(Self, p);  // and here is same replace with your functions class
      end;
  finally
    lMethod.Free;
    lType.Free;
    ctx.Free;
  end;
end;


1 commentaires

Faites que TPROC = procédure (var p1: chaîne; p2: entier); comme User1009073 disent spécifiquement qu'ils ne sont pas des méthodes d'une classe.



19
votes

Larry a écrit un bel exemple sur la manière d'utiliser les pointeurs de la fonction, mais il reste encore le problème de les stocker de manière à ce que Virtualtree puisse y accéder. Il y a au moins deux approches que vous pouvez utiliser ici.

1. Magasinez les pointeurs de fonction avec les données h2>

Si le nom et la fonction appartiennent ensemble dans toute votre application, vous voulez généralement les mettre en une seule structure. P>

procedure vtTreeFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
  TNode(VTGetNodeData(vtTree, node, 0)).Free;
end;


0 commentaires