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

 Delphi Discussion :

Gérer un autocomplete de combobox manuellement


Sujet :

Delphi

  1. #1
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 20
    Points
    20
    Par défaut Gérer un autocomplete de combobox manuellement
    Bonjour à tous,
    Voilà mon problème : j'ai un Combobox auquel je dois affecter un système d'autocomplete sur une liste de valeurs en base de données.

    Exemple : Quand je tape "mat" dans ma combobox, je dois avoir une liste déroulante qui s'alimente avec "matériel", "dématérialisation" .. etc .. un like %chaine% quoi.

    Problème, quand je mets cela en place sur le onchange ou onkeydown/keypress, dès que je tape ma première lettre, mon curseur reviens toujours à la position 0 et impossible de taper entièrement ma chaine.

    Des idées pour m'éclairer ?

  2. #2
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Bonjour,

    Regardes du côté de la propriété SelStart et SelLength du composant...

    --
    Philippe.
    Philippe.

  3. #3
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par 2nd Floor Voir le message
    Bonjour à tous,
    Voilà mon problème : j'ai un Combobox auquel je dois affecter un système d'autocomplete sur une liste de valeurs en base de données.

    Exemple : Quand je tape "mat" dans ma combobox, je dois avoir une liste déroulante qui s'alimente avec "matériel", "dématérialisation" .. etc .. un like %chaine% quoi.

    Problème, quand je mets cela en place sur le onchange ou onkeydown/keypress, dès que je tape ma première lettre, mon curseur reviens toujours à la position 0 et impossible de taper entièrement ma chaine.

    Des idées pour m'éclairer ?
    Salut Floor,

    Perso je l'ai fais dans un de mes champs également, d'ailleur j'ai ajouteré également la création lorsque à la fin de l'autocompletion du mot n'est pas trouvé.

    J'utilise si je me souviens bien uniquement le Onchange.

    Dés mon retour chez moi, je t'en dirais plus.

    bye

  4. #4
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 20
    Points
    20
    Par défaut
    Merci, j'attend de tes nouvelles.
    Concernant le SelStart et SelLength je vais regarder mais je ne crois pas que ça influe la-dessus.

  5. #5
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par 2nd Floor Voir le message
    Merci, j'attend de tes nouvelles.
    Concernant le SelStart et SelLength je vais regarder mais je ne crois pas que ça influe la-dessus.
    Re,

    Alors en fait je n'utilise pas du tout l'évement OnChange.

    1) Mettre la propriété Style du combobox en csDropDown et Sorted à True

    2) Dans la Oncreate j'alimente une première fois mon ComboBox
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TFTaches.FormCreate(Sender: TObject);
    begin
    //... PassageParam.PPObjet permet d'initialisé le combox avec une valeur passée en paramètre a toi de voire si cela peux être utilisé pour ton cas.
      LectureDesObjets(ComboBoxObjet,PassageParam.PPObjet);
    // ...
    Procedure LecturesDesObjets
    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
    procedure TFTaches.LectureDesObjets(Combo:TComboBox;sText:String);
    begin
      With FData.TblObjets do
      Begin
        Try
          Open;
          First;
          Combo.Clear;
          while not Eof do
          begin
            Combo.items.add(FieldByName('Libelle').AsString);
            next;
          end;
          Combo.Sorted := True;
          ComboBoxObjet.Text := sText;
        Finally
          Close;
        end;
      end;
    end;
    En fait à ce moment précis tu pourrais t'arrêter là, car la propriété du combo suffit à lui-même

    Voilà les 2 évenements que j'utilise en plus

    3) OnEnter
    ValeurEnterCombo est déclarer en public evidement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TFTaches.ComboBoxObjetEnter(Sender: TObject);
    begin
      ValeurEnterCombo := TComboBox(Sender).Text;
    end;
    4) OnExit
    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
    procedure TFTaches.ComboBoxObjetExit(Sender: TObject);
    begin
      if TComboBox(Sender).Text <> ValeurEnterCombo then
      Begin
        with FData do
        Begin
          Try
      // On verifie si le text tapé n'existe déjà pas
            QryTravail2.Active := False;
            QryTravail2.SQL.Clear;
            QryTravail2.SQL.Add('Select * From Objets ');
            QryTravail2.SQL.Add('Where Libelle=:xLibelle');
            QryTravail2.Parameters.ParamByName('xLibelle').Value := TComboBox(Sender).Text;
            QryTravail2.Active := True;
            if QryTravail2.Recordset.RecordCount = 0 then
            Begin
              //  ------Ajout d'un Objet
              With TblObjets do
              Begin
                Try
                  Open;
                  Insert;
                  FieldByName('Libelle').AsString := TComboBox(Sender).Text;
                  Post;
                Finally
                  Close;
                end;
              end;
            end;
          Finally
            QryTravail2.Close;
          end;
        end;
      end;
    end;
    Tu pourrais rappeler la procédure LectureObject une fois un nouvel élément créé, si jamais l'utilisateur reviens dans le combobox... a toi d'améliorer....

    Voilà j'espere que cet exemple t'aidera.

    a+

    [Ce que je viens de trouver sur le net]

    Méthode 1

    Tu alimente toujours de la même manière que je t'ai montré ci-dessus (oncreate), ensuite j'ai trouvé cela en me demandant ce que d'autre delphiste aurait fait et je suis tombé la dessus :

    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
    var
      LastKey: Word;
     
    procedure TForm1.ComboBox1KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      LastKey := Key;
    end;
     
    procedure TForm1.ComboBox1Change(Sender: TObject);
    var
      Srch: string;
      ix: Integer;
    begin
      Srch := combobox1.Text;
      if LastKey = $08 then
      begin
        LastKey := 0;
        Exit;
      end;
      LastKey := 0;
      ix := combobox1.Perform(CB_FINDSTRING, - 1, Longint(PChar(Srch)));
      if ix > CB_ERR then
      begin
        combobox1.ItemIndex := ix;
        combobox1.SelStart  := Length(Srch);
        combobox1.SelLength := (Length(combobox1.Text) - Length(Srch));
      end;
    end;
    Méthode 2
    Tu alimente toujours de la même manière que je t'ai montré ci-dessus (oncreate).

    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
      const    
       wm_changecombolistitems = WM_USER+101;
       ...    
       procedure Message_UpdateComboBoxListItems(var Msg: TMessage); message wm_changecombolistitems;
       ... 
     
    procedure TForm1.ComboBox1Change(Sender: TObject);
    begin  
       PostMessage(self.handle, wm_changecombolistitems, 0, 0);
    end;
     
    procedure TForm1.Message_UpdateComboBoxListItems(var Msg: TMessage);
    var  
      i: integer;  
      selstart_, sellength_: integer;  
      text_: string;
    begin  
      selstart_ := ComboBox1.SelStart;  
      sellength_ := ComboBox1.SelLength;  
      text_ := ComboBox1.Text;   
     
      ComboBox1.Items.Clear;  
      for i := 0 to ComboStrings.Count - 1 do  
      begin    
         if (text_ = '') or (Pos(text_, ComboStrings[i]) <> 0) then      
           ComboBox1.Items.Add(ComboStrings[i]);  
      end;  
     
      i := ComboBox1.Items.Count;  
     
      if i > 10 then i := 10;  
      ComboBox1.DroppedDown:=False;  
     
      ComboBox1.DropDownCount := i;  
      ComboBox1.DroppedDown:=True;  
      ComboBox1.Text := text_;  
      ComboBox1.SelStart := selstart_;  
      ComboBox1.SelLength := sellength_;
    end;
    PH. B. proposais ce genre de chose d'ailleur...

  6. #6
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 20
    Points
    20
    Par défaut
    Alors Buzz, t'a solution a du bon, mais ça ne marche pas avec un %chaine%. Tu marques que ta solution avec les bonnes propriétés se suffit à elle même mais en fait non.

    Et pour la solution du PostMessage(self.handle, wm_changecombolistitems, 0, 0); ça ne marche carrément pas. Il faut juste que la procédure appelée soit intégrée dans le OnChange. Mais même avec ça le résultat est instable, on vois le curseur se balader de gauche à droite, ça fait peur en fait.

    Et moi qui croyais qu'un sélect de %chaine% tout simple était pris en charge en affichage. Dur dur ...

    Si vous avez des nouvelles merci de me le faire savoir, je cherche de mon coté aussi

  7. #7
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Salut

    C'est étonnant ton histoire...

    tu es sur d'alimenter au départ ton combox ? car ensuite tu n'as pas besoin de gérer ton onchange...

    Affiche tes evenements :
    - remplissage combobox
    - et ton onchange que tu cherche a faire.

    a+

  8. #8
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 20
    Points
    20
    Par défaut
    Je n'ai pas ma machine avec moi le soir là, mais j'ai quand meme une question :
    Le autocomplete que les combobox gèrent, ce sont des autocomplete direct, car quand je tape "le m", j'ai tous les résultats commençant par "le m".
    Si j'ai une valeur "débute le mardi", logiquement je n'aurais pas cette valeur dans le autocomplete non ?

    C'est quand même dommage qu'on soit obligé de jouer avec le selstart, car de 1) ce n'est pas esthétique de repositionner le curseur, et 2) je trouve que c'est du bidouillage.

    Merci

  9. #9
    Membre chevronné

    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 935
    Points : 1 765
    Points
    1 765
    Par défaut
    Citation Envoyé par 2nd Floor Voir le message
    Le autocomplete que les combobox gèrent, ce sont des autocomplete direct, car quand je tape "le m", j'ai tous les résultats commençant par "le m".
    Si j'ai une valeur "débute le mardi", logiquement je n'aurais pas cette valeur dans le autocomplete non ?
    Ca dépends.

    Avec la méthode 2 de Buzz, le test effectué est Pos(text_, ComboStrings[i]) <> 0, ce qui signifie que toutes les chaines de caractere contenant text_ vont être choisies.
    Pour obtenir le comportement inverse, il suffit de mettre Pos(text_, ComboStrings[i]) = 1, ce qui choisira seulement les items commencant par text_

  10. #10
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 20
    Points
    20
    Par défaut
    Oui merci j'avais compris cela
    Je dis juste que je suis étonné que nativement le combobox ne le fasse pas.

    Avec la méthode des seltext/selstart, j'ai des soucis de curseurs, ce n'est pas super pratique dans une application ou on saisie très rapidement.

    Après il y a aussi le problème que la combobox réagis mal, mais je vais tenter des choses demain et vous tenir au courant.

    Bonne soirée

  11. #11
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Salut,

    Je comprends mieux ce que tu cherche a faire.

    Pourquoi ne pas utiliser un TEdit avec une Tform (dans la forme tu mets un TListBox en alClient et tu laisse juste les bords de la Tform) .

    je m'explique :
    Tu tapes dans le TEdit et dés la première lettre tapée tu affiche la form juste en dessous "qui à la meme longueur" avec l'ensemble des mots qui répondent à ta requete dans ton TListBox, ensuite, soit l'utilisateur continue à taper et la tu balance systématiquement ta requête, soit l'utilisateur clique sur un mot et tu affiche le mot en fermant la form.

    J'ai déjà réalisé cela, ça ressemble un peu comme dans delphi : tu tape un mot ensuite tu tape le point et tu as toutes les possibilités qui apparaissent.

    tu vois ce que je veux dire ?

  12. #12
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 20
    Points
    20
    Par défaut
    Oui merci je vois ce que tu veux dire.
    C'est dommage d'en arriver là alors qu'on a un composant Combobox qui gère le semi-autocomplete mais bon.

    je vais m'orienter vers ça, ça sera plus simple je pense.
    Merci

  13. #13
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    64
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 64
    Points : 20
    Points
    20
    Par défaut
    Ton astuce est bonne, sauf que je dois plus gérer le clavier que la souris.
    Du coup quand on tape un mot, ça fais un like %chaine% et on doit pouvoir descendre avec les flèches pour choisir.
    Et ça c'est galère avec un tform.

    Est-ce qu'il n'y a pas d'autre moyens ??? style mettre une listbox caché sous le composant combobox et afficher la listbox a true ?

  14. #14
    Membre éprouvé Avatar de BuzzLeclaire
    Homme Profil pro
    Dev/For/Vte/Ass
    Inscrit en
    Août 2008
    Messages
    1 606
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Dev/For/Vte/Ass

    Informations forums :
    Inscription : Août 2008
    Messages : 1 606
    Points : 1 113
    Points
    1 113
    Par défaut
    Citation Envoyé par 2nd Floor Voir le message
    Ton astuce est bonne, sauf que je dois plus gérer le clavier que la souris.
    Du coup quand on tape un mot, ça fais un like %chaine% et on doit pouvoir descendre avec les flèches pour choisir.
    Et ça c'est galère avec un tform.

    Est-ce qu'il n'y a pas d'autre moyens ??? style mettre une listbox caché sous le composant combobox et afficher la listbox a true ?
    Pourquoi pas,

    Peut-être avec un TMemo ? où tu afficherai par dessus la première ligne ton Combobox.

  15. #15
    Membre chevronné

    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 935
    Points : 1 765
    Points
    1 765
    Par défaut
    A choisir, un listbox est plus propre je pense.

    Joue avec les effets de bordure pour avoir un résultat voulu. Apres, le plus dur, c'est de modifier l'effet du clic sur la fleche du combobox. Il faut jouer avec la propriété DroppedDown.

    Bonne chance

Discussions similaires

  1. gérer manuellement le scroll d'un flowlayoutpanel ?
    Par cf1109 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 12/11/2007, 20h04
  2. Réponses: 1
    Dernier message: 16/10/2007, 20h21
  3. [VB6] ComboBox autocompletion
    Par ninjabui dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 05/07/2007, 11h40
  4. Combobox autocompletion
    Par fixfix dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 08/03/2007, 11h46
  5. [Excel] Gérer des combobox dynamiques
    Par VBall dans le forum Macros et VBA Excel
    Réponses: 12
    Dernier message: 11/09/2006, 14h23

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