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

Composants VCL Delphi Discussion :

TntTreeView problème sous Delphi 7


Sujet :

Composants VCL Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif

    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Décembre 2008
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 36
    Par défaut TntTreeView problème sous Delphi 7
    Salut la communauté,

    Je suis en train de créer un outil de contrôle à distance sous Delphi 7, en utilisant les composants TNT pour gérer l'Unicode. J'ai un problème avec le composant TntTreeView : je n'arrive pas à obtenir le chemin complet lorsqu'un nœud est sélectionné.

    Notez que j'utilise TntTreeView pour lister les clés du registre de l'ordinateur distant. Dans le FormCreate, j'ai utilisé le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    MasterNode := TntTreeView1.Items.AddChildFirst(nil, 'Ordinateur');
    KeysNode := TntTreeView1.Items.AddChild(MasterNode, 'HKEY_LOCAL_MACHINE');
    Ensuite, dans l'événement TntTreeView1Click, j'appelle la fonction suivante pour obtenir le chemin complet :

    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
     
    function TUnitRegistryManager.WideGetPath(KeysTreeNode: TTntTreeNode): WideString;
    begin
      Result := '';
      if Assigned(KeysTreeNode) then
      begin
        if KeysTreeNode.Text = 'Ordinateur' then Exit;
        Result := KeysTreeNode.Text;
        while Assigned(KeysTreeNode.Parent) do
        begin
          KeysTreeNode := KeysTreeNode.Parent;
          if KeysTreeNode.Parent <> nil then
            Result := KeysTreeNode.Text + '\' + Result;
          Application.ProcessMessages;
        end;
      end;
    end;
    Exemple d'utilisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if TntTreeView1.Selected <> nil then
      TntEdit1.Text := WideGetPath(TntTreeView1.Selected);
    Je renvoie ensuite au serveur le résultat obtenu par WideGetPath.

    Jusqu'ici, tout va bien, mais mon problème survient lorsqu'il s'agit des sous-clés. Par exemple, lorsque je liste les clés sous HKEY_LOCAL_MACHINE (par exemple, Software, Hardware, etc.), et que je clique sur Software, je reçois le chemin complet dans le TntEdit, qui est bien HKEY_LOCAL_MACHINE\SOFTWARE.

    Cependant, lorsque je clique sur l'une des sous-clés de SOFTWARE (par exemple 7-Zip ou Avast), je ne reçois pas le chemin complet. Je reçois seulement HKEY_LOCAL_MACHINE\Software, sans ajouter la sous-clé sélectionnée.

    Voici un extrait de mon code serveur, où je traite les données envoyées par le serveur au thread :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    EXPLODE_REGISTRY_LIST :   // get registry keys and values list
    begin
      if FUserItem <> nil then
      begin
        FCallBackProcedure := TUnitRegistryManager(FUserItem.SubItems.Objects[1]).ParceRegistryManagerData;
        FCallBackProcedure(DecompMemory, DecompMemorySize, dwCommand, FUserItem.SubItems.Objects[1]);
      end;
    end;
    La fonction ParceRegistryManagerData est déclarée dans la forme UnitRegistry comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Public
       procedure ParceRegistryManagerData(var pMemory: Pointer; dwMemorySize: Integer; CmdParce: Byte; objFormObjet: TObject);
    end;
    J'ai utilisé FUserItem car c'est un système multitâche. Voici comment cela fonctionne dans la forme principale lorsque je clique sur le bouton Connecter cet utilisateur :

    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
     
    var
      UnitRegistryManager: TUnitRegistryManager;
    begin
      if lvConnections.Selected = nil then Exit;
      if lvConnections.Selected.SubItems.Objects[1] = nil then
      begin
        UnitRegistryManager := TUnitRegistryManager.Create(self);
        lvConnections.Selected.SubItems.Objects[1] := UnitRegistryManager;
        UnitRegistryManager.objFormObjet := lvConnections.Selected.SubItems.Objects[1];
        UnitRegistryManager.FSocket := TSocket(StrToInt(lvConnections.Selected.SubItems.Strings[12]));
        UnitRegistryManager.FUniqueID := lvConnections.Selected.SubItems.Strings[11];
        UnitRegistryManager.FUserID := lvConnections.Selected.SubItems.Strings[2];
        UnitRegistryManager.SetCallBackProcess(THandleConnection(lvConnections.Selected.Data).BuildPaCket);
        UnitRegistryManager.Show;
      end
      else
      begin
        TUnitRegistryManager(lvConnections.Selected.SubItems.Objects[1]).Show;
      end;
    end;
    Voici un aperçu de la fonction ParceRegistryManagerData :

    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
     
     
    procedure TUnitRegistryManager.ParceRegistryManagerData(var pMemory: Pointer; dwMemorySize: Integer; CmdParce: Byte; objFormObjet: TObject);
    var
      ParceStream: TMemoryStream;
      dwParseType, dwKeyLen, dwValueType: Integer;
      wszKeyName, wszValueName, wszSubValueName: WideString;
      _KeysNode: TTntTreeNode;
      RegistryItemValue: TTntListItem;
    begin
      if dwMemorySize = 0 then
      begin
        FEnableReply := True;
        Exit;
      end;
     
      ParceStream := TMemoryStream.Create;
      ParceStream.Write(pMemory^, dwMemorySize);
      ParceStream.Position := 0;
      FreeMem(pMemory, dwMemorySize);
      ParceStream.Read(dwParseType, SizeOf(Integer));
     
      case dwParseType of
        1:
          begin
            TntTreeView1.Enabled := False;
            TntTreeView1.Items.BeginUpdate;
            if SelectedTreeNode.HasChildren then
              SelectedTreeNode.DeleteChildren;
     
            while ParceStream.Position < ParceStream.Size do
            begin
              ParceStream.Read(dwKeyLen, SizeOf(Integer));
              SetLength(wszKeyName, dwKeyLen);
              ParceStream.Read(Pointer(wszKeyName)^, dwKeyLen * 2);
              _KeysNode := Self.TntTreeView1.Items.AddChild(SelectedTreeNode, wszKeyName);
              _KeysNode.Data := Pointer(wszKeyName);
              _KeysNode.ImageIndex := 1;
              _KeysNode.SelectedIndex := 0;
            end;
     
            TntTreeView1.Items.EndUpdate;
            SelectedTreeNode.Expand(False);
            TntTreeView1.Enabled := True;
            TntTreeView1.Update;
            SelectedTreeNode := nil;
          end;
      end;
    end;
    J'ai utilisé SelectedTreeNode comme référence au nœud sélectionné dans TntTreeView, qui est attribuée lors du clic sur l'arbre avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SelectedTreeNode := TntTreeView1.Selected;
    Si quelqu'un a une idée ou une solution à ce problème, je suis preneur. Merci d'avance !

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 933
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 933
    Par défaut
    Il faut croire que le bloc mémoire contient des chaînes à zéro terminal (zéro inclus dans la longueur). Le résultat de la concatenation est HKEY_LOCAL_MACHINE\Software#0\Avast#0 et puisque la fonction retourne une widestring (qui par définition est à zéro terminal) le traitement subséquent (l'affichage) est tronqué au premier #0.

    Donc soit dans WideGetPath Result := PWideChar(KeysTreeNode.Text) + '\' + Result; pour ne pas copier ce #0 (pour autant que ça fonctionne en D7),

    soit purement et simplement ignorer ce #0 à la lecture dans ParceRegistryManagerData :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SetLength(wszKeyName, dwKeyLen -1);
    ParceStream.Read(Pointer(wszKeyName)^, (dwKeyLen -1) * 2);
    ParceStream.Seek(soCurrent, 2);
    On pourrait aussi laisser tel quel et retailler la chaîne après chargement SetLength(wszKeyName, Length(wszKeyName) -1).

    A noter que l'utilité de passer par un stream est toute relative., un pointeur correctement indexé ferait tout aussi bien l'affaire.


    Attention aussi à _KeysNode.Data := Pointer(wszKeyName);, tu stockes un pointeur sur une variable temporaire qui ne pourra qu'être dans les choux par la suite.

  3. #3
    Membre actif

    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Décembre 2008
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 36
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Il faut croire que le bloc mémoire contient des chaînes à zéro terminal (zéro inclus dans la longueur). Le résultat de la concatenation est HKEY_LOCAL_MACHINE\Software#0\Avast#0 et puisque la fonction retourne une widestring (qui par définition est à zéro terminal) le traitement subséquent (l'affichage) est tronqué au premier #0.

    Donc soit dans WideGetPath Result := PWideChar(KeysTreeNode.Text) + '\' + Result; pour ne pas copier ce #0 (pour autant que ça fonctionne en D7),

    soit purement et simplement ignorer ce #0 à la lecture dans ParceRegistryManagerData :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SetLength(wszKeyName, dwKeyLen -1);
    ParceStream.Read(Pointer(wszKeyName)^, (dwKeyLen -1) * 2);
    ParceStream.Seek(soCurrent, 2);
    On pourrait aussi laisser tel quel et retailler la chaîne après chargement SetLength(wszKeyName, Length(wszKeyName) -1).

    A noter que l'utilité de passer par un stream est toute relative., un pointeur correctement indexé ferait tout aussi bien l'affaire.


    Attention aussi à _KeysNode.Data := Pointer(wszKeyName);, tu stockes un pointeur sur une variable temporaire qui ne pourra qu'être dans les choux par la suite.
    Effectivement mon ami, tu as tout à fait raison et merci pour ta réponse. Ça fait 3 jours que je galère avec ça. J'avais pensé un peu à ton idée, mais je ne l'avais pas mise en action car je me suis fait avoir avec le gestionnaire de fichiers que j'ai fait avant, et ça a marché. Du coup, je me suis fait avoir. Le fait que j'ai utilisé la même fonction pour le gestionnaire de fichiers et le gestionnaire du registre, et que pour le gestionnaire de fichiers ça marche mais pas pour le gestionnaire du registre, dans ce cas il faut que je me rende à la partie serveur pour corriger les données envoyées et envoyer une chaîne correcte sans #0. Merci Andnotor, tu m'as ouvert les yeux.

    Pour ça : _KeysNode.Data := Pointer(wszKeyName);, je l'ai juste fait temporairement, car quand j'essayais de régler ce problème, j'avais pensé que peut-être le WideGetPath trouvait le nœud nil et ne le copiait pas. Donc, j'ai tenté de lui attribuer un Data juste pour l'essayer. Merci encore.

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

Discussions similaires

  1. Corba sous Delphi et ORB alternatif
    Par Inpriser dans le forum CORBA
    Réponses: 4
    Dernier message: 18/08/2003, 18h42
  2. retrouver les compsants FASTNET sous Delphi 7
    Par fandor7 dans le forum Composants VCL
    Réponses: 4
    Dernier message: 11/06/2003, 18h11
  3. Comment créér une collection sous Delphi
    Par PsyKroPack dans le forum Langage
    Réponses: 6
    Dernier message: 11/02/2003, 13h20
  4. calcul sous delphi
    Par djedje-08 dans le forum Langage
    Réponses: 5
    Dernier message: 08/02/2003, 17h39
  5. Réponses: 4
    Dernier message: 27/03/2002, 11h03

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