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

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

Votre réponse

17 réponses

Meilleure réponse
Messages postés
239
Date d'inscription
lundi 5 décembre 2005
Dernière intervention
27 août 2012
3
Merci
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;
        }

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 95 internautes nous ont dit merci ce mois-ci

Commenter la réponse de Tupad
Messages postés
239
Date d'inscription
lundi 5 décembre 2005
Dernière intervention
27 août 2012
0
Merci
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
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
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
Messages postés
239
Date d'inscription
lundi 5 décembre 2005
Dernière intervention
27 août 2012
0
Merci
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
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
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
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
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
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
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
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
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
Messages postés
239
Date d'inscription
lundi 5 décembre 2005
Dernière intervention
27 août 2012
0
Merci
Tu peux mettre copier ton code ici?
Commenter la réponse de Tupad
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
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
Messages postés
239
Date d'inscription
lundi 5 décembre 2005
Dernière intervention
27 août 2012
0
Merci
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
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
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
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
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
Messages postés
239
Date d'inscription
lundi 5 décembre 2005
Dernière intervention
27 août 2012
0
Merci
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
Messages postés
180
Date d'inscription
samedi 22 novembre 2003
Dernière intervention
25 juin 2017
0
Merci
Salut,
Et bien ok, ça marche...


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