String en surbrillance dans une richtextbox wpf [Résolu]

moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 2 janv. 2012 à 16:10 - Dernière réponse : moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention
- 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
Afficher la suite 

17 réponses

Répondre au sujet
Tupad 239 Messages postés lundi 5 décembre 2005Date d'inscription 27 août 2012 Dernière intervention - 4 janv. 2012 à 21:31
+3
Utile
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;
        }
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Tupad
Tupad 239 Messages postés lundi 5 décembre 2005Date d'inscription 27 août 2012 Dernière intervention - 2 janv. 2012 à 22:27
0
Utile
Change ta dernière ligne par:

this.rtb.Selection.Select(start, end);
this.rtb.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, this.rtb.SelectionBrush);
Commenter la réponse de Tupad
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 3 janv. 2012 à 13:29
0
Utile
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
Commenter la réponse de moi411
Tupad 239 Messages postés lundi 5 décembre 2005Date d'inscription 27 août 2012 Dernière intervention - 4 janv. 2012 à 17:08
0
Utile
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);
        }
Commenter la réponse de Tupad
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 4 janv. 2012 à 18:09
0
Utile
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.
Commenter la réponse de moi411
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 4 janv. 2012 à 18:23
0
Utile
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
Commenter la réponse de moi411
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 6 janv. 2012 à 14:22
0
Utile
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
Commenter la réponse de moi411
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 7 janv. 2012 à 12:17
0
Utile
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
Commenter la réponse de moi411
Tupad 239 Messages postés lundi 5 décembre 2005Date d'inscription 27 août 2012 Dernière intervention - 7 janv. 2012 à 17:29
0
Utile
Tu peux mettre copier ton code ici?
Commenter la réponse de Tupad
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 7 janv. 2012 à 21:05
0
Utile
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
Commenter la réponse de moi411
Tupad 239 Messages postés lundi 5 décembre 2005Date d'inscription 27 août 2012 Dernière intervention - 10 janv. 2012 à 22:44
0
Utile
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; 
        }
Commenter la réponse de Tupad
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 11 janv. 2012 à 12:45
0
Utile
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
Commenter la réponse de moi411
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 11 janv. 2012 à 12:49
0
Utile
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
Commenter la réponse de moi411
Tupad 239 Messages postés lundi 5 décembre 2005Date d'inscription 27 août 2012 Dernière intervention - 11 janv. 2012 à 19:04
0
Utile
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.
Commenter la réponse de Tupad
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 11 janv. 2012 à 20:54
0
Utile
Salut,
Et bien ok, ça marche...


moi
Commenter la réponse de moi411
Tupad 239 Messages postés lundi 5 décembre 2005Date d'inscription 27 août 2012 Dernière intervention - 12 janv. 2012 à 21:14
0
Utile
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.
Commenter la réponse de Tupad
moi411 180 Messages postés samedi 22 novembre 2003Date d'inscription 25 juin 2017 Dernière intervention - 12 janv. 2012 à 22:40
0
Utile
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
Commenter la réponse de moi411

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.