Recherche et deplacement de ligne dans un memo

lim3 Messages postés 12 Date d'inscription jeudi 16 avril 2009 Statut Membre Dernière intervention 22 mai 2009 - 13 mai 2009 à 00:00
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 - 20 mai 2009 à 13:57
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

cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
13 mai 2009 à 10:24
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
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
13 mai 2009 à 11:35
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%" />
0
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 14
13 mai 2009 à 14:11
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 !
0
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 14
13 mai 2009 à 17:17
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
0

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

Posez votre question
lim3 Messages postés 12 Date d'inscription jeudi 16 avril 2009 Statut Membre Dernière intervention 22 mai 2009
14 mai 2009 à 21:15
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. 
   
0
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 14
15 mai 2009 à 07:42
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+
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
15 mai 2009 à 17:07
@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 ="" />
0
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 14
15 mai 2009 à 17:12
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
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
20 mai 2009 à 12:18
@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="" />
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
20 mai 2009 à 12:58
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="" />
0
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 14
20 mai 2009 à 13:57
Nom de Zeus, pourquoi ai-je oublié CaretPos ...
Encore plus simple que mon SendMessage :/
Bravo Cirec pour avoir ENCORE simplifié ^^
0
Rejoignez-nous