Foro de elhacker.net

Programación => Programación Visual Basic => Mensaje iniciado por: VegaSys en 15 Abril 2019, 15:45 pm



Título: Recuperar posición del texto en un RichTextBox - VB6
Publicado por: VegaSys en 15 Abril 2019, 15:45 pm
Buenas tardes a todos:

Desearía saber si hay alguna forma de volver a posicionar el texto contenido en un RichTextBox en la misma forma en que estaba.
Me explico: necesito guardar un determinado archivo y, al volver a abrirlo, poner el texto y el cursor en la posición en la que estaba cuando fue guardado. "Recuperar la última vista", le dicen algunos.
De cada archivo puedo guardar cualquier dato necesario: tipo y tamaño de letra, posiciones de tabulación, tamaño y posición de la ventana, etc.
Me dedico a la programación embebida, y al realizar un proyecto utilizo muchos archivos distintos, y me sería muy útil poder recuperar la posición del texto y del cursor en cada uno.
Los archivos son de texto plano puro. Todos los settings que mencioné se guardan en otro lado.
Para esto, trabajo en VB6. He utilizado muchas veces las API del Windows así que si para esto se necesitan no hay ningún problema.

Desde ya agradezco sus opiniones.

Saludos cordiales,
Juan


Título: Re: Recuperar posición del texto en un RichTextBox - VB6
Publicado por: Serapis en 16 Abril 2019, 19:05 pm
El control richtextbox, no proporciona toda la infor precisa para reposicionarlo en exactamente el mismo punto, pero si de forma muy aproximada...

Tienes que usar el evento Selchange para ello...
Sea una ventana con un label1 y un richtextbox, llamado rTxt...

Cada vez que pulsas en el control, mueves el cursor, la propiedad SelStart mantiene precisamente el nº del carácter donde está localizado el cursor.

Y una función (GetLineFromChar), devuelve la línea (en el control), que contiene justamente el ese carácter... obviamente si haces el control de distinto tamaño el número de línea cambia, ya que la información de línea es relativa a la presentación no la absoluta al fichero de origen.
Código
  1. Private Sub rTxt_SelChange()
  2.    Dim Linea As Long
  3.  
  4.    Linea = rTxt.GetLineFromChar(rTxt.SelStart)
  5.    Label1.Caption = "Posición: " & CStr(rTxt.SelStart) & "     Linea: " & CStr(Linea)
  6. End Sub

Entonces una vez guardes el fichero, debes guardar el detalle que te faltaba: exactamente la posición del cursor (medidas, fuente y tal, no son necesarios en este caso).
Luego al cargar el fichero, invocas una función como la siguiente
Código
  1. Private Sub CargarFile(ByVal Ruta As String, ByVal Posicion As Long)
  2.    rTxt.FileName = Ruta
  3.    If ((Posicion < 0) Or (Posicion > Len(rTxt.Text))) Then
  4.        Posicion = 0
  5.    End If
  6.    rTxt.SelStart = Posicion
  7.    rTxt.SetFocus  ' activar el 'blink' del cursor, para que el usuario lo vea...
  8. End Sub
  9.  

Este método te proporciona que la posición donde estaba el cursor antes de cerrar el fichero, vuelva a ser la misma posición que contiene el cursor y que esté a la vista, pero la línea en el tope del control, puede no ser la misma, ya que forzado de dicho modo, serán scrolls enteros de la ventana...

...es decir pongamos que estaba en la posición 14546 y que era la línea 244, y que la línea en el top de la ventana era la 235, luego el cursor estaba en la 9º línea en dicha ventana y pongamos que caben 50 líneas en la ventana... al cargarlo, ahora la línea top será la 200 y por tanto el cursor estará ahora desde el tope, en la línea 44ª y no en la 9ª como antes.

El control richtextbox, tampoco tiene un método TextHeight, para calcular las línea de texto que caben en la ventana, ni las barras de scroll proporcionan dato alguno sobre que línea está al tope, que permitirían un mayor control para posicionar al tope la línea deseada...

Todavía podrías subclasificar el control para obtener los puntos de scroll y click, para saber la línea al tope, pero no considero que merezca la pena perder más tiempo ni esfuerzo en ello...

La forma que te proprociono lo ofrece con una exactitud aceptable... el cursor está exactamente en la misma posición donde estaba, si bien lo único que no se consigue es garantizar que la línea ocupe la misma posición que tenía antes.

La ventaja añadida al menos de este método es que tampoco precisas mantener las medias del control ni la fuente usada o su tamaño, ya que lo que se guarda es el índice del carácter que tiene el cursor en el texto, así que se autoajusta sea cual sea las medidas y fuente de la ventana, para que la página donde está el índice del cursor, esté a la vista.


Una imagen de ejemplo:

El cursor no se captura con la captura de pantalla, pero está justo al comienzo de 'Rosebud.en-us', en la línea justo encima del botón de scroll

(https://i.imgur.com/57Sp9YZ.png)


Título: Re: Recuperar posición del texto en un RichTextBox - VB6
Publicado por: VegaSys en 16 Abril 2019, 19:25 pm
Hola NEBIRE: muchas gracias por contestar.
Efectivamente, lo que estaba haciendo hasta ahora es prácticamente idéntico a lo que me sugerís, pero como decís, lo único que garantiza es que el cursor vuelva a la misma línea.
Lo que hacía antes era: guardar el valor de SelStart, luego simular un Ctl+PageDn (con SendInput), tomar el nuevo valor de SelStart, guardar ese valor y, al recargar el archivo, hacer todo a la inversa.
Con esto recuperaba todo: posición del texto y del cursor.
El problema nuevo apareció al querer guardar la posición si no usamos el margen derecho para que no haga un WordWrap, o sea, que una línea larga se "salga" del text box. Ahí empezó a pasar cualquier cosa. A grosso modo sigue respetando línea y posición del texto, pero solo a "grosso modo".
Ahora estaba justamente probando GetScrollInfo y SetScrollInfo (user32.dll), que parecen funcionar bien, para suplir las faltas del RichTextBox en VB6.
Cuando haga unas pruebas más comento qué pasó.

Nuevamente muchas gracias por tu interés.
Juan