String en surbrillance dans une richtextbox wpf

Résolu
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 - 2 janv. 2012 à 16:10
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 - 12 janv. 2012 à 22:40
Bonjour tout le monde,

J'utilise ceci, mais aucune surbrillance n'apparait...
rtb est ma richtextbox.

string wordToSearch = "mot à sélectionner";
TextRange tr = new TextRange(rtb.Document.ContentStart,
rtb.Document.ContentEnd);

int index = tr.Text.IndexOf(wordToSearch);

var debut = rtb.Document.ContentStart;
var debutSel = debut.GetPositionAtOffset(index);
var finSel = debut.GetPositionAtOffset(index + wordToSearch.Length);

tr.Select(debutSel, finSel);

Quand je debug je vois bien que "tr" à prit comme valeur le mot "wordToSearch" mais dans la richtextbox rien à bougé...

moi
A voir également:

17 réponses

Tupad Messages postés 239 Date d'inscription lundi 5 décembre 2005 Statut Membre Dernière intervention 27 août 2012 5
4 janv. 2012 à 21:31
Une petite màj alors
private void SelectText(string p)
        {
            TextRange tr = new TextRange(this.rtb.Document.ContentStart, this.rtb.Document.ContentEnd);

            int startPosition = tr.Text.IndexOf(p);
            if (startPosition > -1)
            {

                int lines = this.GetLinesCount(tr.Text, startPosition);
                TextPointer startRtb = this.rtb.Document.ContentStart;
                TextPointer start = startRtb.GetPositionAtOffset(startPosition + lines);
                TextPointer end = start.GetPositionAtOffset(p.Length);

                this.rtb.Selection.Select(start, end);
                this.rtb.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, this.rtb.SelectionBrush);
            }
        }

        private int GetLinesCount(string str, int startPosition)
        {
            int lines = str
                // get Text up to startPosition
                .Take(startPosition)
                // Count "\n" and "\r"
                .Count(k => k == Environment.NewLine[0] || k == Environment.NewLine[1]);

            // lines + 1 because if not, missing lines with searched tring
            return lines + 1;
        }
3
Tupad Messages postés 239 Date d'inscription lundi 5 décembre 2005 Statut Membre Dernière intervention 27 août 2012 5
2 janv. 2012 à 22:27
Change ta dernière ligne par:

this.rtb.Selection.Select(start, end);
this.rtb.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, this.rtb.SelectionBrush);
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
3 janv. 2012 à 13:29
Re,
Et bien effectivement j'ai bien une surbrillance mais il se trouve qu'il y a une erreur de comptage...
J'explique; quand je debug:

L'index est bon, (quand je compte manuellement j'arrive sur la bonne position) mais dans les lignes:

var debutSel = debut.GetPositionAtOffset(index);
var finSel = debut.GetPositionAtOffset(index + wordToSearch.Length);

mon "index" est comme diminué... Dans le debugueur il est toujours bon mais la sélection est décalé d'un certain nombre de caractères qui varie selon le mot que je veux sélectionner et la ligne sur laquelle il est.

Dans mes souvenirs le saut de ligne est divisé en 2 (CR et LF) alors je compte le nombre de ligne (multiplié par ces 2 caractères ) et j'obtiens mon décalage...
D'où mes questions, comment récupérer le nombre de ligne dans une RTB et surtout, est-ce que j'ai bon?!?


En espérant que tu es une idée!!!
Merci d'avance et à bientôt.

moi
0
Tupad Messages postés 239 Date d'inscription lundi 5 décembre 2005 Statut Membre Dernière intervention 27 août 2012 5
4 janv. 2012 à 17:08
J'avais remarqué a même chose que toi pour le décalage.

tu peux alors utiliser la fonction suivante :

private void SelectText(string p)
{
            TextRange tr = new TextRange(this.rtb.Document.ContentStart, this.rtb.Document.ContentEnd);

            int startPosition = tr.Text.IndexOf(p);
            int lines tr.Text.Count(k> k == Environment.NewLine[0] || k == Environment.NewLine[1]);
            TextPointer startRtb = this.rtb.Document.ContentStart;
            TextPointer start = startRtb.GetPositionAtOffset(startPosition + lines);
            TextPointer end = start.GetPositionAtOffset(p.Length);

            this.rtb.Selection.Select(start, end);
            this.rtb.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, this.rtb.SelectionBrush);
        }
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
4 janv. 2012 à 18:09
Re,
Alors il y a un mieux mais j'ai quand-même quelques problèmes...
La variable "lines", quand je cherche un mot sur ma deuxième ligne, est égal à 857!!!
Ensuite, je ne comprends le rôle de l'expression lambda et plus particulièrement les "NewLine[]" (pourquoi sous forme de tableau) ...

Pour infos mon mot commence (en comptant les sauts de lignes) au 19e caractères.

Je te remercie de passer du temps pour m'aider!
Salut.
moi.
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
4 janv. 2012 à 18:23
PS:
Je viens de voir que mon fichier fait 857 ligne... Donc l'expression lambda compte toutes les lignes du fichier et non le nombre de lignes qu'il y a entre le début du fichier et le mot à surligner.

Je vais essayer de voir pourquoi, mais je ne promets rien!
moi
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
6 janv. 2012 à 14:22
Salut,
Donc cette fois ça marche (en n'oubliant pas que le saut de ligne est composé de 2 caractères "\r" et "\n")...

Ensuite j'ai été obligé d'étudier les expressions lambda en détail et les fonctions génériques de la classe "String" pour comprendre ton code.
Ce qui est donc particulièrement positif!!!

Bref, encore une fois merci!
moi
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
7 janv. 2012 à 12:17
Salut,
J'aurais quand-même une question...

Quand j'ai formatté mon texte (police ou couleur spéciale) et que je veux le mettre en surbrillance, je reviens au même problème qu'avant... A savoir que la surbrillance est décalée.
Le nombre de ligne et la position de départ (tr.Text.IndexOf(motATrouver)) sont pourtant corrects...

Je ne comprends pas, je ne sais pas comment on debug ce genre de problème...
J'aurais une erreur réelle (un compte faux ...) je pourrais essayer de comprendre pourquoi c'est faux, mais là c'est juste!!!

Bref, est-ce que tu aurais encore une idée?!?
Merci d'avance.
moi
0
Tupad Messages postés 239 Date d'inscription lundi 5 décembre 2005 Statut Membre Dernière intervention 27 août 2012 5
7 janv. 2012 à 17:29
Tu peux mettre copier ton code ici?
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
7 janv. 2012 à 21:05
Salut, Oui bien sûr (c'est le même que tu m'as donné, à une ou deux vaches près!):



//Evènement click d'un MenuItem (dans un ContextMenu)

RechercheRremplacement rR = new RechercheRremplacement(); //fenêtre pour
//la recherche
rR.Title = "Recherche simple";
if (rR.ShowDialog().Value == true)
{
string wordToSearch = rR.rechercheTextBox.Text;

//Déclaré plus haut
tr = new TextRange(this.rtb.Document.ContentStart,
this.rtb.Document.ContentEnd);

int startPosition = tr.Text.IndexOf(wordToSearch);
int lines = this.GetLinesCount(tr.Text, startPosition);

TextPointer startRtb = this.rtb.Document.ContentStart;
TextPointer start = startRtb.GetPositionAtOffset(startPosition + lines);
TextPointer end = start.GetPositionAtOffset(wordToSearch.Length);

this.rtb.Selection.Select(start, end);
this.rtb.Selection.ApplyPropertyValue(TextElement.BackgroundProperty,
this.rtb.SelectionBrush);
}

public int GetLinesCount(string str, int startPosition)
{
// Count "\n" and "\r"
int lines str.Take(startPosition).Count(k> k.Equals((char)13) ||
k.Equals((char)10));
return lines + 2; //lines + 2 because if not, missing lines with
//searched string (2 bacause two chars to jump a line
}



Tout ça fonctionne nickel pour un texte pur (sans formatage), mais dès que je change de police (mettre du "Lucida calligraphy" par exemple) ou changer la forme du texte (Italic) ou encore la couleur, le problème de décalage revient...
Pourtant les variables "startPosition" et "lines" donnent des valeurs correctes!!!

Voilà, comme dit, je ne sais pas comment chercher une erreur quand il n'y en a pas!!!
Sinon j'ai crut comprendre que le paramètre "offset" est est un compte d'octets et non de caractères... Mais là encore le décalage est présent quand le formatage change.

Je te remercie d'avance!
moi
0
Tupad Messages postés 239 Date d'inscription lundi 5 décembre 2005 Statut Membre Dernière intervention 27 août 2012 5
10 janv. 2012 à 22:44
Le code suivant fonctionne correctement (d'ailleurs, je n'ai pas compris ton erreur)

private void SelectText()
        {
            RechercheRemplacement rR = new RechercheRemplacement(); //fenêtre pour la recherche
            rR.Title = "Recherche simple";
            if (rR.ShowDialog().Value == true)
            {
                string wordToSearch = rR.rechercheTextBox.Text;

                TextRange tr = new TextRange(this.rtb.Document.ContentStart, this.rtb.Document.ContentEnd);

                int startPosition = tr.Text.IndexOf(wordToSearch);
                int lines = this.GetLinesCount(tr.Text, startPosition);

                TextPointer startRtb = this.rtb.Document.ContentStart;
                TextPointer start = startRtb.GetPositionAtOffset(startPosition + lines);
                TextPointer end = start.GetPositionAtOffset(wordToSearch.Length);

                this.rtb.Selection.Select(start, end);
                this.rtb.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, this.rtb.SelectionBrush);
                this.rtb.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
                this.rtb.Selection.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Italic);
                this.rtb.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Yellow));
            }
        }

        public int GetLinesCount(string str, int startPosition)
        {
            // Count "\n" and "\r"
            int lines str.Take(startPosition).Count(k> k.Equals((char)13) || k.Equals((char)10));
            //lines + 2 because if not, missing lines with
            //searched string (2 because two chars to jump a line)
            return lines + 2; 
        }
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
11 janv. 2012 à 12:45
Salut,
C'est là où c'est terrible, c'est que je ne comprends pas non plus...
Ci-joint une capture d'écran pour prouver qu'il y a effectivement un problème ("Yellow" est le mot que je veux surligner et "lue(" est la chaine surligner réellement):



Encore une fois quand je debug, le nombre de ligne est correcte, la position de départ "startPosition" est correcte aussi... Mais le sur-lignage est mauvais!
Comme dit je ne sais pas comment chercher une erreur alors que toutes les variables renvoient les valeurs correctes.

Je te remercie de m'aider!!!
A bientôt.

moi
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
11 janv. 2012 à 12:49
Ah oui, j'ai oublié, si je remets la police normale (Time new roman), et la couleur normale (noir), là ça remarche nickel...
Je crois que j'ai tout dit!
Salut.
moi
0
Tupad Messages postés 239 Date d'inscription lundi 5 décembre 2005 Statut Membre Dernière intervention 27 août 2012 5
11 janv. 2012 à 19:04
Je sèche complètement. Le code actuel fonctionne parfaitement chez moi, même si je change la police du texte sélectionné ou si j'applique une autre transformation de style.

Si tu es d'accord, on peut voir en message privé pour que tu m'envoies ton projet afin que je puisse regarder dedans.
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
11 janv. 2012 à 20:54
Salut,
Et bien ok, ça marche...


moi
0
Tupad Messages postés 239 Date d'inscription lundi 5 décembre 2005 Statut Membre Dernière intervention 27 août 2012 5
12 janv. 2012 à 21:14
J'ai testé ton truc hier soir.

Effectivement il y a un problème de positionnement mais, je n'ai pas encore identifié la cause.
Elle serait apparemment due à un mélange entre les couleurs et/ou police.
0
moi411 Messages postés 180 Date d'inscription samedi 22 novembre 2003 Statut Membre Dernière intervention 25 juin 2017 3
12 janv. 2012 à 22:40
Salut,
Alors voila, à force de chercher, j'ai trouvé quelque chose qui marche (formatage du texte ou non) mais je ne sais pas si c'est plus ou moins efficace (je découvre seulement les textrange & Co.!).
Le principe est de remplacer les "startPosition" et "lines" par des fonctions de la classe RegEx. Ci-jointe la fonction:

public void highLight(Color c)
{
  Regex reg = new Regex(word);
  TextPointer startRtb = rtb.Document.ContentStart;
  TextPointer start;
  TextPointer end;

  while ((startRtb != null) && startRtb.CompareTo(rtb.Document.ContentEnd) 
                                                                      < 0)
  {
      if (startRtb.GetPointerContext(LogicalDirection.Forward) == 
                                      TextPointerContext.Text)
      {
          Match match = reg.Match(startRtb.GetTextInRun(LogicalDirection.
                                                               Forward));

          //récupère la range avec l'index du mot et sa longueur
          start = startRtb.GetPositionAtOffset(match.Index, 
                                 LogicalDirection.Forward);
          end = startRtb.GetPositionAtOffset(match.Index + match.Length,
                                             LogicalDirection.Backward);

          //highlight du texte		
          tr = new TextRange(start, end);
          tr.ApplyPropertyValue(TextElement.BackgroundProperty, new 
                                               SolidColorBrush(c));

          //on rebascule à fin de la range pour parcourir la suite   
          startRtb = tr.End;
      }
      startRtb = startRtb.GetNextContextPosition(LogicalDirection.Forward);
  }
}


Donc maintenant mon programme fonctionne mais évidemment il reste le fait que j'ai fait une connerie quelque part et que je ne sais pas où...

Ensuite je ne me permettrait pas de te commander, mais est-ce que tu aurais une piste pour savoir où je me suis trompé?

Je te remercie.
Salut.
moi
0