Recherche et deplacement de ligne dans un memo

Signaler
Messages postés
12
Date d'inscription
jeudi 16 avril 2009
Statut
Membre
Dernière intervention
22 mai 2009
-
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
-
salut tt le monde
voila j'ai programé une interface delphi qui contient un memo et un  bouton
premierement je voudrai savoir comment lancer une recherche dans le memo?
et comment deplacer la ligne selectionner en haut on cliquant sur le bouton 
svp j'ai vremment besoin de votre réponse 
merci d'avance 

11 réponses

Messages postés
4719
Date d'inscription
dimanche 26 février 2006
Statut
Modérateur
Dernière intervention
1 février 2021
14
bonjour,
les pistes:
charger le memo dans un TStringList...
Faire une boucle et tester le mot à chercher..

des exemples il y en a beaucoup sur le site..

cantador
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
37
uses StrUtils; // Necessaire pour SoundEx!



{ FindAndSetFirst

  Cherche la chaine AStr dans la liste AStrings par correspondance   directe (Flash Flash) ou par similitude (Flash flach)
  et place cette chaine en début de liste.
  renvois l'index d'origine de la chaine






  AStr     [i]   string, chaine a chercher
  AStrings [i/o] TStrings, liste de chaine pouvant contenir AStr

  retour : integer, index d'origine de la chaine trouvée sinon est egal a -1
}

function FindAndSetFirst(const AStr: string; AStrings: TStrings): integer;
var N : integer;
    AStrSDX : string;
begin
 


AStrings


.BeginUpdate;
  try
    result :=


AStrings


.IndexOf(AStr);

    if result = -1 then
    begin
      AStrSDX := Soundex(AStr);
      for N := 0 to


AStrings


.Count-1 do
        if


AStr


SDX = Soundex(


AStrings


[N]) then
        begin
          result := N;
          Break;
        end;
    end;
   
    if result <> -1 then
    begin
     


AStrings


.Insert(0,


AStrings


[result]);
     


AStrings


.Delete(Result);
    end;                     
  finally
   


AStrings


.EndUpdate;
  end;
end;


Exemple :

procedure TForm8.Button1Click(Sender: TObject);
begin
  FindAndSetFirst('Flash', Memo1.Lines);
end;








<hr size="2" width="100%" />
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
14
Hello
Pas mal mais ne correspond pas à la demande de l'utilisateur
qui souhaite remonter en index 0 la ligne sur laquelle se trouve son
curseur ! Avec ta procédure, il faut passer en paramètre une string,
string que l'utilisateur ne sait pas trouver ...

Je propose donc en 1 ligne :

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Move(SendMessage(Memo1.Handle, EM_LineFromChar, Memo1.SelStart, 0), 0);
end;

Attention par défaut la ligne sélectionnée est la dernière (la ligne vide) !

@foxy :
      AStrings.Insert(0, AStrings[result]);
      AStrings.Delete(Result);
=
erreur car tu Insert puis Delete un index qui vient d'être décalé !
J'imagine que tu as dû le faire de tête sans tester, tu es tout
pardonné :p

Je propose la correction suivante :
function FindAndSetFirst(const AStr: string; AStrings: TStrings): integer;
var N : integer;
    AStrSDX : string;
begin
  AStrings.BeginUpdate;
  try
    result := AStrings.IndexOf(AStr);
    if result = -1 then
    begin
      AStrSDX := Soundex(AStr);
      for N := 0 to AStrings.Count-1 do
        if AStrSDX = Soundex(AStrings[N]) then
        begin
          result := N;
          Break;
        end;
    end
    else
      AStrings.Move(Result, 0);
  finally
    AStrings.EndUpdate;
  end;
end;

Pour utiliser la procédure de Foxy, nous allons donc faire :

procedure TForm1.Button2Click(Sender: TObject);
begin
  FindAndSetFirst(Memo1.Lines[SendMessage(Memo1.Handle, EM_LineFromChar, Memo1.SelStart, 0)], memo1.lines);
end;

Ou alors, on peut simplifier si l'utilisateur sélectionne le texte de la ligne (toujours avec la proc de foxy) :
procedure TForm1.Button3Click(Sender: TObject);
begin
  FindAndSetFirst(memo1.SelText, memo1.lines);
end;

Je rappelle que l'avantage de la procédure de foxy ne sert que si vous
cherchez "Flash" et que "Flach" est présent dans le mémo, donc, ma
première solution est la mieux adaptée.
Pour le cas du posteur, la proc de foxy est inutile
.
Voila !
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
14
Au fait foxy, contrairement à une ListBox, avec un Memo on ne peut pas
connaitre l'index de la ligne sous le curseur (c'est la raison de ce
post).

Comment puis je surcharger le composant Memo (sans recréer un compo, juste à la volée dans mon code) pour que je puisse faire :
Memo1.MonIndex

J'ai pensé à :
TMyMemo = class(TCustomMemo)
public
  function MonIndex: integer;
end;
...
Memo1: TMyMemo;
...
function TMyMemo.MonIndex: integer;
begin
  Result:= SendMessage(Handle, EM_LineFromChar, SelStart, 0);
end;

Mais je n'y parviens pas, tu saurais ? Merci
Messages postés
12
Date d'inscription
jeudi 16 avril 2009
Statut
Membre
Dernière intervention
22 mai 2009

salut a tous merci pour vos reponses
pour le deplacement de ligne oui ça marche mais c'est pas ce que je veux réelement
car quant je clique sur le bouton la ligne selectioné se deplace tout en haut mais moi ce que je veut est un deplacement d'une seul ligne si comme si on permute la ligne selectionné avec celle qui est juste avant 
par exemple si j'ai dans le memo les lignes suivantes:

code source.
application delphi .
question a poser.
 
 si je veux deplacer la ligne selectionné (en rose) en haut je clique une fois sur le bouton et j'aurai ce resultat :

code source.
question a poser.
application delphi.

et ainsi de suite
 merci d'avance. 
   
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
14
Tu as dit "comment deplacer la ligne selectionneren haut on cliquant sur le bouton", mon code déplace la ligne sélectionnée et la place en haut, le tout, en cliquant sur un bouton...
J'ai bon parfaitement bon :] Tu t'exprimes mal, bref voila ce que tu veux, tu aurais pu le faire toi meme avec tout ce qu'on vient de te donner ! Comprends tu le langage delphi ?

procedure TForm1.Button1Click(Sender: TObject);
var Ind: Integer;
begin
  Ind:= SendMessage(Memo1.Handle, EM_LineFromChar, Memo1.SelStart, 0);
  Memo1.Lines.Move(Ind, Ind-1);
end;

a+
Messages postés
3825
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
1 février 2021
38
@JulioDelphi:
"Au fait foxy, contrairement à une ListBox, avec un Memo on ne peut pas
connaitre l'index de la ligne sous le curseur (c'est la raison de ce
post)."

pas d'accord du tout

sur une fiche tu déposes:
1 TMemo
et tu ajoutes ce code ...

Function GetCaretPos(aCustomEdit : TCustomEdit): TPoint;
Begin
  Result.X := LongRec(SendMessage(aCustomEdit.Handle, EM_GETSEL, 0, 0)).Hi;
  Result.Y := SendMessage(aCustomEdit.Handle, EM_LINEFROMCHAR, Result.X, 0);
  Result.X := Result.X - SendMessage(aCustomEdit.Handle, EM_LINEINDEX, -1, 0);
End ;

Procedure SetCaretPos(aCustomEdit : TCustomEdit; Value: TPoint);
var
  CharIdx: Integer;
begin
  SetFocus(aCustomEdit.Handle);
  CharIdx : = SendMessage(aCustomEdit.Handle, EM_LINEINDEX, Value.y, 0) + Value.x;
  SendMessage(aCustomEdit.Handle, EM_SETSEL, CharIdx, CharIdx);
end;

// ... et ajoutes un évènement OnClick sur le TMemo
procedure TForm1.Memo1Click(Sender: TObject);
var aCP: TPoint;
begin
  aCP : = GetCaretPos(Memo1);
  Caption := Format('Ligne: %d  -  Col: %d', [aCP.Y, aCP.X]);
end ;

and run

Voilà ... avec SetCaretPos on peut, bien sur, positionner le curseur

ps: Fonctionne aussi avec TEdit et tous les descendants de TCustomEdit

 
@+
Cirec

<hr siz ="" />
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
14
Ce que je voulais dire c'est qu'avec une listbox tu fais :
ListBox.ItemIndex;
Avec un memo tu n'as pas ça !
Tu dois donc coder quelquechose.
Moi je fais :
SendMessage(Memo1.Handle, EM_LineFromChar, Memo1.SelStart, 0)
et toi tu fais tout ton bazar ... XD
Messages postés
3825
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
1 février 2021
38
@JulioDelphi:

c'est pas moi qui fait un bazar ...
c'est la méthode utilisé par Delphi dans la VCL ...
fais une recherche dans les sources sous "EM_LINEFROMCHAR"

donc si Delphi utilise ce code pour récupérer et définir la position du curseur dans le texte c'est qu'il doit y avoir une bonne raison ... ... non

et vu la différence de calcule de position entre les deux codes ... je ne serai pas étonné qu'à un moment le tiens nous retourne une position erronée !!

bon ensuite ... je reviens encore une fois sur
"... contrairement à une ListBox,
avec un Memo on ne peut pas connaitre l'index de la ligne sous le
curseur (c'est la raison de ce post)."

et encore une fois je suis pas d'accord ( Démonstration ):
On récupère la position grace à "CaretPos"
  Caption := Format('Ligne: %d  -  Col: %d', [Memo1.CaretPos.Y, Memo1.CaretPos.X]);

Et on peut même en définir une nouvelle
  Memo1.CaretPos : = Point(0,0);

et le tout sans une seule ligne de code ajoutée et avec la garantie d'une position exacte
 
@+
Cirec

<hr siz="" />
Messages postés
3825
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
1 février 2021
38
Interverti la ligne sur la quelle on clique avec sa précédente





à mettre dans le OnClick du Memo en question:

procedure TForm1.Memo1Click(Sender: TObject);
begin
  if (Memo1.Lines.Count > 1) and (Memo1.CaretPos.Y > 0) then
    Memo1.Lines.Exchange(Memo1.CaretPos.Y, Memo1.CaretPos.Y-1);
end;

 
@+
Cirec

<hr siz="" />
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
14
Nom de Zeus, pourquoi ai-je oublié CaretPos ...
Encore plus simple que mon SendMessage :/
Bravo Cirec pour avoir ENCORE simplifié ^^