Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Error al buscar cadena (https://www.clubdelphi.com/foros/showthread.php?t=85684)

danielmj 17-04-2014 18:47:21

Error al buscar cadena
 
Hola, trato de buscar una cadena dada en un TRichEdit, y funciona al 50% ¿como es eso? pues la cadena la busco a partir del texto seleccionado en un combobox, el problema viene cuando tiene que encontrar esa cadena a mitad del texto que se encuentre en el RichEdit, pongo unas capturas para explicarme mejor.

Captura 1


Captura 2


Captura 3


Como veis, en la captura 1, la cadena a buscar es "Usar mapas UV" cuando pulso el boton "Buscar entrada", selecciona texto mas o menos por donde está la cadena en cuestion, pero no selecciona a esta.

En la segunda captura, debe buscar "Editor de nodos" y si lo encuentra y selecciona correctamente, y por ultimo en la captura 3, debe buscar "Creando piedras manualmente", pero hace lo mismo que en la captura 1
¿Por que?

El código que tengo ahora para las busquedas es este:

Código Delphi [-]
rocedure TbNotas.Button3Click(Sender: TObject);
var
  posicion, desplazamiento, i: integer;

begin
  desplazamiento:= 0;
  for i:= 0 to editor.Lines.Count -1 do
    begin
      posicion:= pos(lista.Text,editor.Lines[i]);
      if posicion <> 0 then
        begin
          editor.SetFocus;
          editor.SelStart:= desplazamiento + Posicion -2;
          editor.SelLength:= Length(lista.Text);
          exit;
        end;
        inc(desplazamiento, 2 + length(editor.Lines[i]));
    end;
end;

En la linea del incremento de la variable desplazamiento, si cambio el valor numerico 2 por un valor menor o mayor a este, digamos que la busqueda empeora.

¿Alguna ayuda?

Gracias de antemano.

ecfisa 17-04-2014 22:06:08

Hola danielmj.

Aunque existen formas mas sofisticadas de búsqueda para un TRichEdit, usando FindDialog y FindText por ejemplo, creo que este modo se va a acomodar de forma simple al TComboBox de tu caso.

Fijate si te puede servir:
Código Delphi [-]
const
  EM_SCROLLCARET = $00B7;

var
  LastCase: Integer;

// Buscar primero
procedure TForm1.btnSearchClick(Sender: TObject);
begin
  with RichEdit1 do
  begin
    LastCase:= Pos(Lista.Text, Text);
    if LastCase <> 0 then
    begin
      SelStart:= Perform(EM_LINEINDEX, 0, 0) + LastCase-1;
      SelLength:= Length(Lista.Text);
      Perform(EM_SCROLLCARET, 0, 0);
      SetFocus
    end
    else MessageBox(0,PChar('No se encontró ' + Lista.Text), '', MB_OK);
  end;
end;

// Buscar siguientes
procedure TForm1.btnNextClick(Sender: TObject);
var
  Next: Integer;
begin
  with RichEdit1 do
  begin
    Next:= PosEx(Lista.Text, Text, LastCase+1);
    if Next <> 0 then
    begin
      SelStart:= Perform(EM_LINEINDEX, Next, 0) + Next ;
      SelLength:= Length(Lista.Text);
      Perform(EM_SCROLLCARET, 0, 0);
      LastCase:= Next;
    end;
    SetFocus;
  end;
end;

Saludos :)

danielmj 17-04-2014 22:43:47

Hola ecfisa,

gracias por tu ayuda, he probado el código y sigue dando el mismo error, por ejemplo si en el combobox selecciono "creando piedras manualmente" la busqueda selecciona a partir de la palabra "anualmente...", esta incluida.

"CREANDO PIEDRAS MANUALMENTE
Para crear pied
ras de forma manual, primero crearemos un cubo y este los subdividiremos al menos 3 veces..."

Lo que está en rojo, es lo que selecciona exactamente.

Voy a seguir mirando a ver que encuentro. Gracias otra vez.

ecfisa 18-04-2014 00:06:38

1 Archivos Adjunto(s)
Hola danielmj.

Ya que en mis pruebas funciona correctamente, no entiendo el comportamiento que mencionas.

Por favor revisa con tranquilidad este demo que adjunto y verás que destaca en el TRichEdit exáctamente lo seleccionado o escrito en el TComboBox como se espera:



Saludos :)

nlsgarcia 18-04-2014 00:56:23

danielmj,

Cita:

Empezado por danielmj
...trato de buscar una cadena dada en un TRichEdit...partir del texto seleccionado en un ComboBox...

Cita:

Empezado por ecfisa
...existen formas mas sofisticadas de búsqueda para un TRichEdit, usando FindDialog y FindText...

Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    Button1: TButton;
    FindDialog1: TFindDialog;
    ComboBox1: TComboBox;
    procedure Button1Click(Sender: TObject);
    procedure FindDialog1Find(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   ComboBox1.Items.LoadFromFile('Search_Parameters.txt');
   RichEdit1.Lines.LoadFromFile('Search_File.txt');
end;

procedure TForm1.FindDialog1Find(Sender: TObject);
var
   FoundAt: LongInt;
   StartPos, ToEnd: Integer;

begin
   with RichEdit1 do
   begin
     if SelLength <> 0 then
        StartPos := SelStart + SelLength
     else
        StartPos := 0;

     ToEnd := Length(Text) - StartPos;

     FoundAt := FindText(FindDialog1.FindText, StartPos, ToEnd, [stMatchCase]);
     if FoundAt <> -1 then
     begin
        SetFocus;
        SelStart := FoundAt;
        SelLength := Length(FindDialog1.FindText);
     end
     else
        SelStart := 0;
   end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   FindDialog1.FindText := ComboBox1.Text;
   FindDialog1.Position := Point(0,0);
   FindDialog1.Execute;
end;

end.
El código anterior en Delphi 7 bajo Windows 7 Professional x32, realiza búsquedas de texto en un TRichEdit por medio de un TComboBox y un TFindDialog como se muestra en la siguiente imagen:



El código esta disponible en : FindText_RichEdit

Espero sea útil :)

Nelson.

danielmj 18-04-2014 09:16:29

Hola Ecfisa, he mirado tu demo y me pasa lo mismo, realmente no entiendo nada por que a ti te funciona y a mi no siendo el mismo codigo??



Hola nlsGarcía, tu código no lo he mirado aun, ahora me pongo con el. Sobre usar el findDialog, bueno, en realidad lo he pensado y lo he usado en un momento, pero sinceramente dado que la aplicación no es nada del otro mundo (y ademas de uso personal), prefiero no "salirme" de la interface de esta, es decir que si puedo prescindir del findDialog.execute... etc, mejor, de todos modos, como te digo, ahora me pongo con tu aporte.

Saludos y gracias a los dos.

danielmj 18-04-2014 09:45:58

Hola, ¿puede ser ese error provocado por delphi? uso la version XE4 y no funciona bien, pero acabo de probar con lazarus y si funciona el codigo de ecfisa.

¿?

Saludos.

ecfisa 18-04-2014 18:32:52

Hola danielmj.
Cita:

Empezado por danielmj (Mensaje 475289)
Hola Ecfisa, he mirado tu demo y me pasa lo mismo, realmente no entiendo nada por que a ti te funciona y a mi no siendo el mismo codigo??

Si, es muy posible ya que las versiones de TRichEdit son diferentes. Habría que revisar un poco sobre los valores de las constantes... En principio podrías intentar quitando la constante que redefine el valor de EM_SCROLLCARET (necesario para Delphi 7).

Voy a buscar un poco sobre el tema en XE4 y cualquier novedad te comento.

Saludos :)

danielmj 18-04-2014 19:30:11

Hola, gracias por la ayuda, sigo mirando a ver que consigo y quedo a la espera por si encuentras algo.

Saludos.

nlsgarcia 18-04-2014 20:23:39

danielmj,

Cita:

Empezado por danielmj
...Sobre usar el FindDialog...si puedo prescindir del FindDialog...mejor... :confused:

El código sugerido en el Msg #5 es una solución alternativa al problema planteado por medio de un TComboBox como interfaz de un TFindDialog, funcionando correctamente según lo esperado en Delphi 7, Delphi 2010 y Delphi XE4 bajo Windows 7 Professional x32.

Espero sea útil :)

Nelson.

ecfisa 18-04-2014 21:55:04

Hola danielmj.
Cita:

Empezado por danielmj (Mensaje 475308)
Hola, gracias por la ayuda, sigo mirando a ver que consigo y quedo a la espera por si encuentras algo.

Saludos.

No cuento con otra versión que Delphi 7 para comprobarlo (lo que me dificulta la taréa...), así que tengo que pedirte que verifiques si te funciona este modo en tu Delphi:
Código Delphi [-]
uses RichEdit;

const
  EM_SCROLLCARET = $00B7;

var
  LastCase: Integer;

procedure TForm1.btnSearchFirstClick(Sender: TObject);
begin
  with RichEdit1 do
  begin
    LastCase:= RichEdit1.FindText(Lista.Text, 0, Length(RichEdit1.Text), []);
    if LastCase <> -1 then
    begin
      SelStart:= Perform(EM_LINEINDEX, 0, 0) + LastCase;
      SelLength:= Length(Lista.Text);
      Perform(EM_SCROLLCARET, 0, 0);
      SetFocus
    end
  end
end;

procedure TForm1.btnNextClick(Sender: TObject);
var
  Next: Integer;
begin
  with RichEdit1 do
  begin
    Next:= RichEdit1.FindText(Lista.Text, SelStart+SelLength, Length(RichEdit1.Text), []);
    if Next <> -1 then
    begin
      SelStart:= Perform(EM_LINEINDEX, Next, 0) + Next + 1;
      SelLength:= Length(Lista.Text);
      Perform(EM_SCROLLCARET, 0, 0);
      LastCase:= Next
    end;
    SetFocus;
  end
end;
Insisto en este modo de búsqueda, por que en principio entendí que respeta la estética que queres darle a tu aplicación.

Saludos :)

nlsgarcia 18-04-2014 22:51:40

danielmj,

Cita:

Empezado por ecfisa
...No cuento con otra versión que Delphi 7 para comprobarlo...así que tengo que pedirte que verifiques si te funciona este modo en tu Delphi...

El código sugerido en el Msg #11 funciona correctamente según lo esperado en Delphi 7, Delphi 2010 y Delphi XE4 bajo Windows 7 Professional x32.

Espero sea útil :)

Nelson.

nlsgarcia 18-04-2014 23:05:57

danielmj,

Cita:

Empezado por danielmj
...Sobre usar el FindDialog...si puedo prescindir del FindDialog...mejor... :confused:

Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    Button1: TButton;
    ComboBox1: TComboBox;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   ComboBox1.Items.LoadFromFile('Search_Parameters.txt');
   RichEdit1.Lines.LoadFromFile('Search_File.txt');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  FoundAt: LongInt;
  StartPos, ToEnd: Integer;

begin
   with RichEdit1 do
   begin
     if SelLength <> 0 then
        StartPos := SelStart + SelLength
     else
        StartPos := 0;

     FoundAt := FindText(ComboBox1.Text, StartPos, Length(RichEdit1.Text), []);
     if FoundAt <> -1 then
     begin
        SetFocus;
        SelStart := FoundAt;
        SelLength := Length(ComboBox1.Text);
     end
     else
        SelStart := 0;
   end;
end;

end.
El código anterior es la versión 2 del código sugerido en el Msg #5 sin la utilización del componente TFindDialog y con la capacidad de hacer Búsquedas Cíclicas de tipo Case Insensitive, funcionando correctamente según lo esperado en Delphi 7, Delphi 2010 y Delphi XE4 bajo Windows 7 Professional x32.

Espero sea útil :)

Nelson.

ecfisa 18-04-2014 23:25:56

Gracias por probar el código Nelson ^\||/
Cita:

Empezado por nlsgarcia (Mensaje 475321)
...
Cita:

Empezado por ecfisa
...Sobre usar el FindDialog...si puedo prescindir del FindDialog...mejor... :confused:


Pero... ¿ En que mensaje escribí esa opinión ? :rolleyes:

Saludos :)

nlsgarcia 18-04-2014 23:28:32

ecfisa,

Corregido Maestro :D

Nelson.

ecfisa 18-04-2014 23:38:01

Cita:

Empezado por nlsgarcia (Mensaje 475324)
ecfisa,

Corregido Maestro :D

Nelson.

No te preocupes :).

Por otro lado, estoy totalmente de acuerdo en las bondades que ofrece FinDialog, de echo siempre lo he incluido en mis editores. Pero me pareció que en este caso puntual, danielmj prefería que no apareciera la ventana emergente de búsqueda.

Saludos :)

danielmj 20-04-2014 20:53:32

Hola, perdonad por no contestar antes, pero estuve fuera a parte que no me habia llegado notificacion al correo de que había respuestas. Ahora me pongo a mirar todo y a probar.

Gracias y saludos.

Edito: Hola de nuevo, he probado tu codigo ecfisa (mensaje #11) y si va bien, como dice nlsgarcia, funciona en XE4 y en mi caso bajo 64bit.
En cuanto al findDialog, ecfisa tiene razón, prefiero no usarlo mas que nada para no romper la estetica del formulario, máxime cuando es una aplicación de uso personal y si puedo conseguir el mismo resultado a base de codigo, pues me ahorro ventanas emergentes.

Gracias a los dos y una vez más siento no haber respondido antes, normalmente me llega un aviso al correo cuando hay respuestas, pero esta vez no sé que pasó.


La franja horaria es GMT +2. Ahora son las 21:08:44.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi