[RESUELTO]Control de foco en formulario
[RESUELTO]Control de foco en formulario
Buenas!
Hace tiempo intenté manejar esto para otras cosas y tuve que cerrar el proyecto. Ahora estoy intentando otra cosa, pero necesitaría la misma herramienta, y como no me eche alguien una mano, todo quedará encallado como la otra vez:
El sistema de búsqueda en base está bien cuando los registros son pocos, pero cuando nos vamos a 4 ó 5 mil registros se hace eterno (parece que va comprobando cada línea de formulario, comprobando si el registro de cada ciclo coincide con el texto propuesto -si es texto, claro-)
Si nos basásemos en SQL, de tal manera que si buscamos los registros que tienen el texto buscado, con un SQL con el mismo filtro y orden que el origen de datos, podríamos tener todos los registros con esos criterios. Si nos situamos en el primero (o en el último), podríamos saber el número de fila en la que se encuentra en el formulario, y con ello hacer un oForm.Absolute(), llegando con ello a mostrar en el formulario el registro deseado....
Bueno..., ya sé que es un tanto deslabazado, pero es perfectamente viable (de hecho ya lo tengo hecho en algún formulario). El reto es que, al clicar en un botón, te busque qué control tiene el foco, independientemente de que sea control de tabla, combobox, listbox, cuadro de texto, numérico, etc, y también independientemente de que sea un formulario prinipal, subformulario o subsubformulario.
Complejo ¿no?, pues por eso lo pregunto.
UnklDonald418, en los foros en Inglés, hilo https://forum.openoffice.org/en/forum/v ... it=copy%2A tiene una macro que recorre formularios y subformularios, pero no termino de conseguir su adaptación.
Con respecto al problema que plantea en este hilo, tengo alguna idea de como salvarlo (hace falta que luego funcione, y sería solo para los controles de tabla), pero necesitaría algo similar para recorrer todos los controles y ver en cual tengo el foco en el momento de apretar el botón.
Bueno!, que me enrollo un montón!
Gracias, y un saludo!
Hace tiempo intenté manejar esto para otras cosas y tuve que cerrar el proyecto. Ahora estoy intentando otra cosa, pero necesitaría la misma herramienta, y como no me eche alguien una mano, todo quedará encallado como la otra vez:
El sistema de búsqueda en base está bien cuando los registros son pocos, pero cuando nos vamos a 4 ó 5 mil registros se hace eterno (parece que va comprobando cada línea de formulario, comprobando si el registro de cada ciclo coincide con el texto propuesto -si es texto, claro-)
Si nos basásemos en SQL, de tal manera que si buscamos los registros que tienen el texto buscado, con un SQL con el mismo filtro y orden que el origen de datos, podríamos tener todos los registros con esos criterios. Si nos situamos en el primero (o en el último), podríamos saber el número de fila en la que se encuentra en el formulario, y con ello hacer un oForm.Absolute(), llegando con ello a mostrar en el formulario el registro deseado....
Bueno..., ya sé que es un tanto deslabazado, pero es perfectamente viable (de hecho ya lo tengo hecho en algún formulario). El reto es que, al clicar en un botón, te busque qué control tiene el foco, independientemente de que sea control de tabla, combobox, listbox, cuadro de texto, numérico, etc, y también independientemente de que sea un formulario prinipal, subformulario o subsubformulario.
Complejo ¿no?, pues por eso lo pregunto.
UnklDonald418, en los foros en Inglés, hilo https://forum.openoffice.org/en/forum/v ... it=copy%2A tiene una macro que recorre formularios y subformularios, pero no termino de conseguir su adaptación.
Con respecto al problema que plantea en este hilo, tengo alguna idea de como salvarlo (hace falta que luego funcione, y sería solo para los controles de tabla), pero necesitaría algo similar para recorrer todos los controles y ver en cual tengo el foco en el momento de apretar el botón.
Bueno!, que me enrollo un montón!
Gracias, y un saludo!
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Libreoffice 6.4.2, en Windows 10
Re: Control de foco en formulario
Como primer idea de una lluvia de ideas... ¿que tal una macro genérica que al obtener el foco del control, guarde su nombre en una variable global?... de todos modos voy a buscar en el API, si hay algo para esto.
Un abrazo
Un abrazo
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Re: Control de foco en formulario
Buenas!
Qué bueno que pierdas tu tiempo en estas cosas que a veces propongo y a las que pocas veces llego a buen puerto!
Te comento:
La idea es precisamente esa, localizar el control en el que está el foco y a partir de ahi, coger el número de fila del resultset que supone el formulario, el nombre del campo (o número de columna), y el texto (o número) del campo. Después, con estas condiciones, con el mismo filtro y mismo orden que el formulario, armar un SQL que nos dirá en qué puesto está el primer registro igual al que buscamos, determinando la fila en la que el SQL lo ha encontrado, y como el SQL es igual al ResultSet del formulario, con oForm.Absolute(), tendríamos el formulario en el primer registro deseado....
De todos modos el atasque es justo al principio, es decir, que no todos los controles tienen la propiedad 'hasfocus()', y la macro que comenté, en un principio hace un barrido por todos los formularios y sus controles, después por los subformularios y sus controles, etc.
El problema que tengo es que funciona solo para los que tienen la siguiente condición:, y después para los que tienen esta otra: .
El resultado es que cuando le dejas libremente recorrer todos los subformularios, la primera vez te localiza el control que tiene el foco (generalmente un control de texto), y parece que todo va sobre ruedas.
Cuando fijas el foco en otro subformulario (en un control con la propiedad 'hasfocus()') y lanzas la macro, entonces te reconoce el anterior que había marcado y el nuevo, y así sucesivamente al ir escogiendo otros subformularios.
En su día pregunté en el foro de Inglés si había manera de invalidar o poner a null el 'oFormController.CurrentControl' y me dijeron que no.
He intentado pararle los pies con exit for y exit function, pero los resultados no han sido los adecuados, ya que como paras el ciclo, cuando hay un subsubformulario, directamente no le dejas penetrar a investigar.
En definitiva, que estoy un tanto perdido!
Dejo aquí el código que he estado manejando para que os riais un poco de las burradas que hago.
Decir que estoy manejando libreOffice 5.4.7.2 en Windows 10, con HSQLDB 2.3 multiusuario, aunque creo que esto no tendría mayor importancia para que funcione o no el código propuesto.
También decir que la versión de LibreOffice es la última que no se me cuelga con esta base multiusuario, las demás (toda la saga de la versión 6) se cuelga al cargar el formulario de inicio, que entiendo que es algo completito, pero con esta versión no se cuelga y con las otras si (bueno, esto es otro tema para otra discusión!)
El código iría en un botón en un formulario, y considero que tendría que servir para cualquier formulario, por lo que se puede probar en cualquier base (no sé cómo lo admitiría Firebird, aunque en un principio no toca nada de SQL- de momento-)
Qué bueno que pierdas tu tiempo en estas cosas que a veces propongo y a las que pocas veces llego a buen puerto!
Te comento:
La idea es precisamente esa, localizar el control en el que está el foco y a partir de ahi, coger el número de fila del resultset que supone el formulario, el nombre del campo (o número de columna), y el texto (o número) del campo. Después, con estas condiciones, con el mismo filtro y mismo orden que el formulario, armar un SQL que nos dirá en qué puesto está el primer registro igual al que buscamos, determinando la fila en la que el SQL lo ha encontrado, y como el SQL es igual al ResultSet del formulario, con oForm.Absolute(), tendríamos el formulario en el primer registro deseado....
De todos modos el atasque es justo al principio, es decir, que no todos los controles tienen la propiedad 'hasfocus()', y la macro que comenté, en un principio hace un barrido por todos los formularios y sus controles, después por los subformularios y sus controles, etc.
El problema que tengo es que funciona solo para los que tienen la siguiente condición:
Código: Seleccionar todo
if not IsNull (oFormController.CurrentControl) Then
Código: Seleccionar todo
if oFormController.CurrentControl.hasfocus() Then
El resultado es que cuando le dejas libremente recorrer todos los subformularios, la primera vez te localiza el control que tiene el foco (generalmente un control de texto), y parece que todo va sobre ruedas.
Cuando fijas el foco en otro subformulario (en un control con la propiedad 'hasfocus()') y lanzas la macro, entonces te reconoce el anterior que había marcado y el nuevo, y así sucesivamente al ir escogiendo otros subformularios.
En su día pregunté en el foro de Inglés si había manera de invalidar o poner a null el 'oFormController.CurrentControl' y me dijeron que no.
He intentado pararle los pies con exit for y exit function, pero los resultados no han sido los adecuados, ya que como paras el ciclo, cuando hay un subsubformulario, directamente no le dejas penetrar a investigar.
En definitiva, que estoy un tanto perdido!
Dejo aquí el código que he estado manejando para que os riais un poco de las burradas que hago.
Decir que estoy manejando libreOffice 5.4.7.2 en Windows 10, con HSQLDB 2.3 multiusuario, aunque creo que esto no tendría mayor importancia para que funcione o no el código propuesto.
También decir que la versión de LibreOffice es la última que no se me cuelga con esta base multiusuario, las demás (toda la saga de la versión 6) se cuelga al cargar el formulario de inicio, que entiendo que es algo completito, pero con esta versión no se cuelga y con las otras si (bueno, esto es otro tema para otra discusión!)
El código iría en un botón en un formulario, y considero que tendría que servir para cualquier formulario, por lo que se puede probar en cualquier base (no sé cómo lo admitiría Firebird, aunque en un principio no toca nada de SQL- de momento-)
Código: Seleccionar todo
Sub CheckFocusB
Dim oDoc as object
Dim fname as string
oDoc = ThisComponent.DrawPage.Forms ' Formularios de la base de datos
fname = FocusNameListRecB(oDoc) ' Llamada a la función
End Sub
Function FocusNameListRecB(oDoc as object) as string
DIM oForm as object, oController as object, oGridControlView as object, oGCMP as object
Dim fName as string
Dim i as integer, j as integer, n as integer
oController = ThisComponent.CurrentController ' Controlador
n = oDoc.Count ' Número de elementos del formulario
For i=0 to n-1 ' i = Contador
If oDoc.hasElements() then ' Si el documento (en un principio formulario) tiene elementos
oForm = oDoc.getByIndex(i) ' Elemento en el documento (primer ciclo serían formularios, después controles y subformularios, después controles en los subformularios y subformularios
Select case oForm.ServiceName ' Comprobamos de qué servicio se trata
Case "stardiv.one.form.component.Form" ' Si es un formulario
fName = FocusNameListRecB(oForm) ' Variable de la función, que iguala a la función
oFormController=thiscomponent.currentController.getFormController(oForm) ' Vista o controlador del oForm
if not IsNull (oFormController.CurrentControl) Then ' Si oFormController.CurrentControl no es nulo
Nombre= oFormController.CurrentControl.model.name ' Nombre del control
Control = oForm.getByName(Nombre) ' Vista del control
if oFormController.CurrentControl.hasfocus() Then ' Si el control actual tiene foco
If not Control.SupportsService("stardiv.one.form.component.CommandButton") Then ' Y no es un botón
NombreCampo = Control.Datafield ' Obtenemos el nombre del campo
msgbox Control.ServiceName & " "& NombreCampo & " Tiene foco" ' Aviso para ir viendo si se hacen las cosas bien
Exit For ' Nos echa del ciclo
Exit function ' Nos echa de la función
End if ' Acabamos la condición de que no sea un botón
Else ' En caso de no tener foco
If Control.ServiceName= "stardiv.one.form.component.Edit" Then ' Hay veces que a pesar de ser este tipo de servicio y le pones el cursor encima, no marca que tenga foco
NombreCampo = Control.Datafield ' Obtenemos el nombre del campo
msgbox Control.ServiceName & " "& NombreCampo & " Es un campo tipo .Edit sin foco" ' Aviso para ir viendo si se hacen las cosas bien
Exit For ' Nos echa del ciclo
Exit function ' Nos echa de la función
End if ' Acabamos la condición de que sea un Edit sin foco
' Se seguirá investigando una vez resuelto el tema del exit for y exit function
' if Control.ServiceName="stardiv.one.form.component.ComboBox" or Control.ServiceName="stardiv.one.form.component.ComboBox" Then
' NombreCampo = Control.Datafield ' The name of the field in the ResultSet
' msgbox Control.ServiceName & " "& NombreCampo & " No tiene foco"
' Exit for
' Exit function
' End if
' End if
' If Control.ServiceName="stardiv.one.form.component.Grid" Then
' msgbox "Control de tabla"
'NombreCampo = Control.Datafield
'msgbox Control.ServiceName & " "& ControlName & " No tiene foco"
' Exit for
' End if
' Exit function
' End if
End if
End if
End Select
End if
next
End function
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Libreoffice 6.4.2, en Windows 10
Re: Control de foco en formulario
Ha vuelto a leer desde tu primer mensaje, y veo dos temas diferentes. No tengo claros lo siguiente que mencionas:
Por ultimo; ¿tiene que ser en Basic?
Un abrazo
¿El problema es el sistema de búsqueda?Si nos basásemos en SQL, de tal manera que si buscamos los registros que tienen el texto buscado, con un SQL con el mismo filtro y orden que el origen de datos, podríamos tener todos los registros con esos criterios
Voy a validarlo, pero según recuerdo, si estas en un registro, ya tienes la fila del resulset, no es necesario hacer nada más, pero puede ser que no este viendo algo que ya tienes. Prometo ponerme a estudiar.La idea es precisamente esa, localizar el control en el que está el foco y a partir de ahi, coger el número de fila del resultset que supone el formulario, el nombre del campo (o número de columna), y el texto (o número) del campo
Por ultimo; ¿tiene que ser en Basic?
Un abrazo
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Re: Control de foco en formulario
Buenas!
Voy a ver si consigo artellar un ejemplo sin subformularios y con un cuadro de diálogo o algo que se le parezca.
Pero necesito algo de tiempo.....
Y si, en basic (Python para cuando pueda, que no es por ahora)
Otro saludo!
Voy a ver si consigo artellar un ejemplo sin subformularios y con un cuadro de diálogo o algo que se le parezca.
Pero necesito algo de tiempo.....
Y si, en basic (Python para cuando pueda, que no es por ahora)
Otro saludo!
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Libreoffice 6.4.2, en Windows 10
Re: Control de foco en formulario
Buenas!
Supongo que lo que pongo aquí primero provocará una ligera sonrisa, y según se vayan viendo las burradas y cómo me lío para nada, terminareis partidos de risa o desesperados por que no hay manera de saber qué es lo que estoy persiguiendo (que por supuesto no lo consigo, claro está!).
Bien!, si, el asunto inicial es el de conseguir saber dónde está el foco en todo momento y lugar, para después hacer una búsqueda según dónde se encuentre el foco.
El tema de la búsqueda era muy sencillo, hasta que empecé a encontrarme con que los formularios pueden tener como origen SQL o Consultas con más de una tabla, las claves principales no tienen porqué ser autonuméricas, ni siquiera tienen que estar en el origen de datos del formulario, etc.
Vamos, que quería hacer algo para que fuese genérico (como una extensión), pero con mis conocimientos y mi empecinamiento solo podrá servir para un formulario concreto y nada más, a no ser que alguien vea que se puede hacer algo con lo que cuelgo.
A pesar de todo creo que es una vía a explorar para substituir el cuadro de diálogo de búsqueda tradicional, ya que es enórmemente pesado cuando los registros empiezan a ser numerosos.
Dejo un texo con explicaciones y una base con lo que he ido haciendo, que ya digo, seguro que hay métodos múcho más lógicos y cortos, pero qué le vamos a hacer?, uno es como es.
https://drive.google.com/file/d/1i_3nui ... sp=sharing
Un saludo!
Supongo que lo que pongo aquí primero provocará una ligera sonrisa, y según se vayan viendo las burradas y cómo me lío para nada, terminareis partidos de risa o desesperados por que no hay manera de saber qué es lo que estoy persiguiendo (que por supuesto no lo consigo, claro está!).
Bien!, si, el asunto inicial es el de conseguir saber dónde está el foco en todo momento y lugar, para después hacer una búsqueda según dónde se encuentre el foco.
El tema de la búsqueda era muy sencillo, hasta que empecé a encontrarme con que los formularios pueden tener como origen SQL o Consultas con más de una tabla, las claves principales no tienen porqué ser autonuméricas, ni siquiera tienen que estar en el origen de datos del formulario, etc.
Vamos, que quería hacer algo para que fuese genérico (como una extensión), pero con mis conocimientos y mi empecinamiento solo podrá servir para un formulario concreto y nada más, a no ser que alguien vea que se puede hacer algo con lo que cuelgo.
A pesar de todo creo que es una vía a explorar para substituir el cuadro de diálogo de búsqueda tradicional, ya que es enórmemente pesado cuando los registros empiezan a ser numerosos.
Dejo un texo con explicaciones y una base con lo que he ido haciendo, que ya digo, seguro que hay métodos múcho más lógicos y cortos, pero qué le vamos a hacer?, uno es como es.
https://drive.google.com/file/d/1i_3nui ... sp=sharing
Un saludo!
- Adjuntos
-
- Explicaciones.7z
- (22.12 KiB) Descargado 188 veces
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Libreoffice 6.4.2, en Windows 10
Re: Control de foco en formulario
ya voy entendiendo...
tienes razón, veo que, al buscar, hace el recorrido de todos los registros, algo que hace un simple SQL.
Entonces, la tares es hacer introspección en todos los campos de un formulario a todos los niveles para mostrarlos en el formulario de búsqueda personalizado, ¿correcto?
tienes razón, veo que, al buscar, hace el recorrido de todos los registros, algo que hace un simple SQL.
Entonces, la tares es hacer introspección en todos los campos de un formulario a todos los niveles para mostrarlos en el formulario de búsqueda personalizado, ¿correcto?
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Re: Control de foco en formulario
Primer problema, sabe donde esta el foco, la forma más sencilla para no recorrer todo cada vez que se ejecuta, es lo que te propuse al inicio, una macro al recibir el foco de cada control. Lo he probado con la siguiente macro en el evento al recibir el foco de todos los controles que sean campos y funciona correctamente.
Si, con Python podríamos autoreferenciar este evento en cada control, pero nos gusta sufrir...
Ahora, al mostrar el dialogo, ya sabemos con Source.Model.Parent, en que formulario estamos, y por lo tanto, que controles tiene. Supongo que, por el ejemplo, tienes en mente, cualquier combinación o complejidad u origen de datos del formulario. Pero, vayamos por partes y partamos de lo más sencillo.
Código: Seleccionar todo
Global g_ultimo_control As Object
Sub on_focus(event)
g_ultimo_control = event.Source
End Sub
Ahora, al mostrar el dialogo, ya sabemos con Source.Model.Parent, en que formulario estamos, y por lo tanto, que controles tiene. Supongo que, por el ejemplo, tienes en mente, cualquier combinación o complejidad u origen de datos del formulario. Pero, vayamos por partes y partamos de lo más sencillo.
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Re: Control de foco en formulario
Buenas de nuevo!
Veamos....., no soy una gran mente pensante, y aunque artello macros de una complejidad inusitada, no es precisamente por que sepa de programación, sino justo todo lo contrario, y porque hay muchas cosas que son de segundo y yo aún voy por el primer trimestre de primero.
La macro que propones, ¿cómo se aplica? y ¿cómo funciona?. ¿Hay que ponerla para cada control, o simplemente actúa desde un botón?
Siento ser tan cortito. Intentaré llegar al segundo trimestre, a ver si encuentro algo que me indique cómo va el asunto, pero si me adelantases algo se agradecería.
Ah!, en cuanto al tema que está en el texto 'Explicaciones' sobre que cuando hay más de un registro para buscar no era capaz de parar el ciclo y se buscaban todos los registros de una atacada ya lo tengo solucionado (o casi....Siempre empieza por el primero, no por el siguiente al registro en el que se inició la búsqueda, pero creo que es algo solucionable).
Gracias y otro saludo!
Veamos....., no soy una gran mente pensante, y aunque artello macros de una complejidad inusitada, no es precisamente por que sepa de programación, sino justo todo lo contrario, y porque hay muchas cosas que son de segundo y yo aún voy por el primer trimestre de primero.
La macro que propones, ¿cómo se aplica? y ¿cómo funciona?. ¿Hay que ponerla para cada control, o simplemente actúa desde un botón?
Siento ser tan cortito. Intentaré llegar al segundo trimestre, a ver si encuentro algo que me indique cómo va el asunto, pero si me adelantases algo se agradecería.
Ah!, en cuanto al tema que está en el texto 'Explicaciones' sobre que cuando hay más de un registro para buscar no era capaz de parar el ciclo y se buscaban todos los registros de una atacada ya lo tengo solucionado (o casi....Siempre empieza por el primero, no por el siguiente al registro en el que se inició la búsqueda, pero creo que es algo solucionable).
Gracias y otro saludo!
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Libreoffice 6.4.2, en Windows 10
Re: Control de foco en formulario
Si, hay que ponerlo en cada control, si, tengo en mente que puede haber formularios con decenas de controles, pero, primero; es solo una vez, al agregarlo, te lleva unos minutos relacionar esta macro a muchos controles, y dos; un formulario con decenas de controles, habría que revisarlo...
Por aquí puedes ver el archivo:
https://seafile.elmau.net/d/9d4d664604124c0daaef/
Aquí puede subir cualquier archivo (lo siento Google esta bloqueado en mi equipo):
https://seafile.elmau.net/u/d/86cfb32bfc4e4f5d9edc/
Usa el botón Mostrar control con foco, no use el botón Buscar que esta debajo, a menos que tengas instalado MRI.
Por aquí puedes ver el archivo:
https://seafile.elmau.net/d/9d4d664604124c0daaef/
Aquí puede subir cualquier archivo (lo siento Google esta bloqueado en mi equipo):
https://seafile.elmau.net/u/d/86cfb32bfc4e4f5d9edc/
Usa el botón Mostrar control con foco, no use el botón Buscar que esta debajo, a menos que tengas instalado MRI.
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Re: Control de foco en formulario
Buenas!
Estuve todo este tiempo rumiando el asunto, y pensé...(no se sorprendan, a veces lo hago), ¿y si uso la macro que recorre todos los controles no para ver qué control tiene el foco, sino para poner la macro en el evento ‘Al recibir el foco’ en los controles que me interesan?
Es un terreno pantanoso en el que nunca entré, pero había visto algunos posts al respecto, así que me lié la manta y me puse a ello, con idea de asignar esta macro a la carga del formulario para que me dejase todos los controles interesantes con la macro que me pusiste en el post anterior (on_focus).
Para las pruebas hice un nuevo formulario (Consulta81) y le puse dos botones, uno para cargar la macro y otro para vaciarla.
Aparentemente todo va muy bien, pero…..(tenía que haber un pero!) cuando en un control hay al menos un evento ocupado y distinto de ‘FocusGained’, parece que carga bien, pero selecciono la adjudicación de la macro, la borro con la tecla suprimir, y la borra, pero resulta que hay otra detrás, y habrá varias, según el número de ciclos que recorra y veces que hayas dado al botón (en las pruebas hechas llegué a borrar 57 veces!).
El asunto es que no he sido capaz de determinar un ‘IF Event.ScriptCode<>"" Then’, para no grabar, y si está vacío grabar.
Parece que Event.ScriptCode<>"" no se refiere al evento en el que quieres trabajar, sino al total de los eventos, de tal manera que, si tienes el evento de ‘Al mover el ratón’ ya ocupado (por ejemplo), entonces Event.ScriptCode ya es <>"".
De momento no se me ocurre mejor manera de explicarlo.
Espero que con el ejemplo se vea lo que ocurre y lo que pretendo.
A día de hoy, todo lo que he encontrado no me ha resuelto el asunto (evidentemente, si no, no preguntaría).
Gracias y un saludo!
Ah!, Mauricio, colgué la base de ejemplo en el enlace que me indicaste, pero por si alguien más está interesado lo colgué también aquí:
https://drive.google.com/file/d/1VjzhZj ... sp=sharing
Estuve todo este tiempo rumiando el asunto, y pensé...(no se sorprendan, a veces lo hago), ¿y si uso la macro que recorre todos los controles no para ver qué control tiene el foco, sino para poner la macro en el evento ‘Al recibir el foco’ en los controles que me interesan?
Es un terreno pantanoso en el que nunca entré, pero había visto algunos posts al respecto, así que me lié la manta y me puse a ello, con idea de asignar esta macro a la carga del formulario para que me dejase todos los controles interesantes con la macro que me pusiste en el post anterior (on_focus).
Para las pruebas hice un nuevo formulario (Consulta81) y le puse dos botones, uno para cargar la macro y otro para vaciarla.
Aparentemente todo va muy bien, pero…..(tenía que haber un pero!) cuando en un control hay al menos un evento ocupado y distinto de ‘FocusGained’, parece que carga bien, pero selecciono la adjudicación de la macro, la borro con la tecla suprimir, y la borra, pero resulta que hay otra detrás, y habrá varias, según el número de ciclos que recorra y veces que hayas dado al botón (en las pruebas hechas llegué a borrar 57 veces!).
El asunto es que no he sido capaz de determinar un ‘IF Event.ScriptCode<>"" Then’, para no grabar, y si está vacío grabar.
Parece que Event.ScriptCode<>"" no se refiere al evento en el que quieres trabajar, sino al total de los eventos, de tal manera que, si tienes el evento de ‘Al mover el ratón’ ya ocupado (por ejemplo), entonces Event.ScriptCode ya es <>"".
De momento no se me ocurre mejor manera de explicarlo.
Espero que con el ejemplo se vea lo que ocurre y lo que pretendo.
A día de hoy, todo lo que he encontrado no me ha resuelto el asunto (evidentemente, si no, no preguntaría).
Gracias y un saludo!
Ah!, Mauricio, colgué la base de ejemplo en el enlace que me indicaste, pero por si alguien más está interesado lo colgué también aquí:
https://drive.google.com/file/d/1VjzhZj ... sp=sharing
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Libreoffice 6.4.2, en Windows 10
Re: Control de foco en formulario
Manejar los eventos de foco, no es un tema menor, el foco puede ser "alterado" fácilmente, con la simple carga de un formulario, con el cambio de ventana, con enviar el foco a otro control y otras acciones "no visibles", en lo personal, prefiero dejarlo lo más sencillo posible. Pero es divertido... le doy una mirada a tu código.
No hay problema con el enlace, al contrario, te agradezco la consideración para mis manías.
Un abrazo
No hay problema con el enlace, al contrario, te agradezco la consideración para mis manías.
Un abrazo
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Re: Control de foco en formulario
Bueno....
Hice algunos progresos, y con ellos descubrí nuevas dificultades (no podía ser de otro modo).
Cambié el código y es capaz de colocar una sola macro en cada evento 'Al recibir el foco' que tiene libre, y parece que lo hace correctamente.
Me las ingenié para que en un msgbox me dijese cuales son los controles en los que no se instaló la macro, ya que estaba ocupado el evento por otra macro diferente, y pensé que tenía muy buena pinta.....Hasta que se me ocurrió ocupar con una macro distinta a la 'on_focus' un control de tablas que pertenecía a un subformulario que cuelga del formulario principal. Entonces encontré (lo que por otra parte era lógico) un msgbox para cada unidad del tipo Formulario/subformulario (en este caso 2, pero si tengo 10 subformularios, entonces tendría 10 msgbxes, por lo que no es totalmente práctico).
Supongo que después de unos meses se me ocurrirá alguna manera de juntarlos, pero por ahora estoy perdido.
También tendré que ingeniármelas para que, una vez modificadas las macros que salen en los informes (msgboxes), deje de salir el aviso....
En fin, todo esto como paso previo a intentar organizar una búsqueda basada en SQL que sé que es mucho más rápida que la búsqueda genérica que hay ahora.
Tendrían que mirarlo los desarrolladores, ya que filtrar una tabla de 50000 registros ocupa décimas de segundo, mientras que la búsqueda ocupa unos cuantos minutos, por lo que deduzco que el código que hay detrás de cada procedimiento tiene bases diferentes, aunque no entiendo el porqué.
Bueno!, diquisiciones aparte os dejo aquí el código de todo el módulo 'Module8' por si os apetece hacer pruebas, y si aportais algo sería fantástico.
Gracias y otro saludo!
Hice algunos progresos, y con ellos descubrí nuevas dificultades (no podía ser de otro modo).
Cambié el código y es capaz de colocar una sola macro en cada evento 'Al recibir el foco' que tiene libre, y parece que lo hace correctamente.
Me las ingenié para que en un msgbox me dijese cuales son los controles en los que no se instaló la macro, ya que estaba ocupado el evento por otra macro diferente, y pensé que tenía muy buena pinta.....Hasta que se me ocurrió ocupar con una macro distinta a la 'on_focus' un control de tablas que pertenecía a un subformulario que cuelga del formulario principal. Entonces encontré (lo que por otra parte era lógico) un msgbox para cada unidad del tipo Formulario/subformulario (en este caso 2, pero si tengo 10 subformularios, entonces tendría 10 msgbxes, por lo que no es totalmente práctico).
Supongo que después de unos meses se me ocurrirá alguna manera de juntarlos, pero por ahora estoy perdido.
También tendré que ingeniármelas para que, una vez modificadas las macros que salen en los informes (msgboxes), deje de salir el aviso....
En fin, todo esto como paso previo a intentar organizar una búsqueda basada en SQL que sé que es mucho más rápida que la búsqueda genérica que hay ahora.
Tendrían que mirarlo los desarrolladores, ya que filtrar una tabla de 50000 registros ocupa décimas de segundo, mientras que la búsqueda ocupa unos cuantos minutos, por lo que deduzco que el código que hay detrás de cada procedimiento tiene bases diferentes, aunque no entiendo el porqué.
Bueno!, diquisiciones aparte os dejo aquí el código de todo el módulo 'Module8' por si os apetece hacer pruebas, y si aportais algo sería fantástico.
Código: Seleccionar todo
Sub CheckFocus8 (oEvent)
Dim oDoc as object
Dim fname as string
oDoc = ThisComponent.DrawPage.Forms ' Formularios de la base de datos
fname = FocusNameListRec8(oDoc,oEvent) ' Llamada a la función
' If oEvent.Source.Model.Label= "Poner foco" Then ' Si apretamos el botón poner el foco
' msgbox "Se ha revisado la totalidad de los controles de cada formulario y subformulario, y en aquellos casos que no esté ocupado el evento ""Al recibir el foco"" coloca la macro ""on_focus""." & CHR(13) & "Si está ocupado y quier utilizar el control para la búsqueda tendrá que editar la macro en cuestión."
' End if ' Acabamos la condición
If oEvent.Source.Model.Label= "Quitar foco" Then ' Si apretamos el botón quitar el foco
msgbox "Se han eliminado las macros ""on_focus"" de todos los eventos ""Al recibir el foco"" de cada control."
End if ' Acabamos la condición
End Sub
Global oDoc
Function FocusNameListRec8(oDoc as object,oEvent) as string
DIM oForm as object, oController as object, oGridControlView as object, oGCMP as object
Dim fName as string
Dim i as integer, j as integer, n as integer
oController = ThisComponent.CurrentController ' Controlador
n = oDoc.Count ' Número de elementos del formulario
For L=0 to n-1 ' L= Contador
If oDoc.hasElements() then ' Si el documento (en un principio formulario) tiene elementos
oForm = oDoc.getByIndex(L) ' Elemento en el documento (primer ciclo serían formularios, después controles y subformularios, después controles en los subformularios y subformularios
If oForm.ServiceName = "stardiv.one.form.component.Form" Then ' Comprobamos de qué servicio se trata
fName = FocusNameListRec8(oForm,oEvent) ' Variable de la función, que iguala a la función
If oEvent.Source.Model.Label= "Poner foco" Then ' Si apretamos el botón Poner el foco
PonerMacroAlEnfocar(oForm) ' Ejecuta la macro para poner el evento
End if ' Acabamos la condición
If oEvent.Source.Model.Label= "Quitar foco" Then ' Si activamos el botón quitar el foco
RetirarFoco(oForm) ' Se llama a la macro que borra los códigos asignados a los eventos en cuestión
End if ' Acabamos la condición
End if ' Acabamos la condición de que sea un formulario
End if ' Acabamos la condición de que tenga más elementos
next ' Vamos al siguiente elemento
End function
Sub PonerMacroAlEnfocar (oForm)
Dim oEmptyArgs() as new com.sun.star.beans.PropertyValue
Dim oFormsCollection as Object
n= oForm.getCount-1 ' Controles totales del formulario
'---------------------------------------------------
' Ponemos en cada control que nos interesa la macro en el evento al recibir el foco
For i=0 to n ' Recorremos todos los controles
Control= oForm.getByIndex(i) ' El control del momento
If Control.ServiceName <> "stardiv.one.form.component.Form"and right(Control.ServiceName,6)<>"Button" and( Control.Servicename <> "stardiv.one.form.component.FixedText" and Control.Servicename<>"stardiv.one.form.component.FixedText" and Control.ServiceName<>"com.sun.star.form.component.DatabaseImageControl" and Control.ServiceName<>"com.sun.star.form.component.NavigationToolBar") Then
Dim oEvent as new com.sun.star.script.ScriptEventDescriptor ' Evento
oEvent.AddListenerParam = "" ' No añadimos ningún parámetro
oEvent.EventMethod = "focusGained" ' Al recibir el foco
oEvent.ListenerType = ".XFocusListener" ' Tipo de listener
oEvent.ScriptCode = "vnd.sun.star.script:Standard.Module5.on_focus?language=Basic&location=document" ' Ruta de la macro
oEvent.ScriptType = "Script" ' Tipo de script
'------------------------------------------------------
' Comprobamos si hay eventos con macros asignadas y cuales son
Dim Array1()
If ubound(oForm.getScriptEvents(i))>=0 then ' Si al menos hay un evento en el control que toca con macros
Clave=2 ' Constante
For each event in oForm.getScriptEvents(i) ' Recorremos todos los eventos del control en el que estamos
If Event.EventMethod= "focusGained"Then ' Si el evento es 'Al recibir el foco'
If Event.ScriptCode<> "vnd.sun.star.script:Standard.Module5.on_focus?language=Basic&location=document" Then ' Si la macro es distinta de la propuesta
Array1=Str(Control.Name) ' Rellenamos una matriz auxiliar
sTmp1= sTmp1 &" -Unidad """ & oForm.Name & """; control denominado """ & Array1(i)&"""" & Chr(13) ' Reunión de todos los controles con el evento ya ocupado con una macro distinta a la propuesta
Modelo1= Str(sTmp1)
End if ' Acabamos con la condición de que la macro sea distinta de la propuesta
Clave=1 ' Cambiamos el valor de la constante
End if ' Acabamos la condición de que el evento sea el de 'Al recibir el foco'
Next ' Vamos al siguiente evento
If Clave<>1 Then ' En caso de que la constante no sea uno
oForm.registerScriptEvent( i, oEvent ) ' Anexamos la macro al evento que habíamos preparado
End if ' Acabamos la condición de que la clave no sea uno
Clave=2 ' Modificamos el valor de la constante (distinto de 1)
End if ' Acabamos la condición de que al menos haya un evento ocupado
If ubound(oForm.getScriptEvents(i))= -1 then ' Si no hay ningún evento con macros
oForm.registerScriptEvent( i, oEvent ) ' Anexamos la macro al evento que habíamos preparado
End if ' Acabamos la condición de no tener ningún evento cubierto
End if ' Acabamos la condición de que no sean controles no deseados
Next ' Vamos al siguiente control
'-------------------------------------------------------
' Visualizamos el trabajo hecho
If len (Modelo1)>0 then
msgbox "Los siguientes controles tienen una macro diferente a la propuesta en el evento ""Al recibir el foco""" & CHR(13)&CHR(13)& Modelo1 & CHR(13) & CHR(13)& "Si qiere que la macro sea también aplicada en estos controles tendrá que editar el código que ya hay con una llamada a la macro ""on_focus"" en su interior"
End if
End Sub
Sub RetirarFoco (oForm)
Dim oEmptyArgs() as new com.sun.star.beans.PropertyValue
Dim oFormsCollection as Object
n= oForm.getCount-1 ' Controles totales del formulario
'---------------------------------------------------
' Ponemos en cada control que nos interesa la macro en el evento al recibir el foco
For i=0 to n ' Recorremos todos los controles
Control= oForm.getByIndex(i) ' El control del momento
If Control.ServiceName <> "stardiv.one.form.component.Form"and right(Control.ServiceName,6)<>"Button" and( Control.Servicename <> "stardiv.one.form.component.FixedText" and Control.Servicename<>"stardiv.one.form.component.FixedText" and Control.ServiceName<>"com.sun.star.form.component.DatabaseImageControl" and Control.ServiceName<>"com.sun.star.form.component.NavigationToolBar") Then
'------------------------------------------------------
' Comprobamos si hay eventos con macros asignadas y cuales son
If ubound(oForm.getScriptEvents(i))>=0 then ' Si al menos hay un evento en el control que toca con macros
For each event in oForm.getScriptEvents(i) ' Recorremos todos los eventos del control
If Event.EventMethod= "focusGained" Then ' Si es el evento 'al recibir el foco'
'------------------------------------------------------
' Comprobamos si la macro es la misma que estamos intentando instalar o es diferente
If Event.ScriptCode<>"" and Event.ScriptCode= "vnd.sun.star.script:Standard.Module5.on_focus?language=Basic&location=document" Then
oForm.revokeScriptEvent( i, "com.sun.star.awt.XFocusListener", "focusGained", "" )
End if ' Acabamos la condición de que sin estar vacío, resulta ser otra macro diferente
End if
Next ' Vamos al siguiente evento
End if ' Acabamos la condición de que al menos haya un evento ocupado
End if ' Acabamos la condición de que no sean controles no deseados
Next ' Vamos al siguiente control
End Sub
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Libreoffice 6.4.2, en Windows 10
Re: [RESUELTO]Control de foco en formulario
Bueno!
Lo daré por finalizado con este código lanzado desde botón:
Tened en cuenta que utilicé el 'Modulo3' como almacén de la macro. Si se utiliza otro nombre de módulo (áltamente recomendable), entonces hay que cambiarlo en el código.
Un saludo!
Ah! y con esta lo quitaríamos (al incluir la llamada en la recurrencia inicial)
Lo daré por finalizado con este código lanzado desde botón:
Código: Seleccionar todo
Sub CheckFocus (oEvent)
Dim oDoc as object
Dim fname as string
oDoc = ThisComponent.DrawPage.Forms ' Formularios de la base de datos
fname = FocusNameListRec(oDoc,oEvent) ' Llamada a la función
End Sub
Function FocusNameListRec(oDoc as object,oEvent) as string
DIM oForm as object, oController as object, oGridControlView as object, oGCMP as object
Dim fName as string
Dim i as integer, j as integer, n as integer
oController = ThisComponent.CurrentController ' Controlador
n = oDoc.Count ' Número de elementos del formulario
For L=0 to n-1 ' L= Contador
If oDoc.hasElements() then ' Si el documento (en un principio formulario) tiene elementos
oForm = oDoc.getByIndex(L) ' Elemento en el documento (primer ciclo serían formularios, después controles y subformularios, después controles en los subformularios y subformularios
If oForm.ServiceName = "stardiv.one.form.component.Form" Then ' Comprobamos de qué servicio se trata
fName = FocusNameListRec(oForm,oEvent) ' Variable de la función, que iguala a la función
PonerMacroAlEnfocar(oForm,L) ' Ejecuta la macro para poner el evento
End if ' Acabamos la condición de que sea un formulario
End if ' Acabamos la condición de que tenga más elementos
next ' Vamos al siguiente elemento
End function
Sub PonerMacroAlEnfocar (oForm,L)
Dim oEmptyArgs() as new com.sun.star.beans.PropertyValue
Dim oFormsCollection as Object
n= oForm.getCount-1 ' Controles totales del formulario
'---------------------------------------------------
' Ponemos en cada control que nos interesa la macro en el evento al recibir el foco
For i=0 to n ' Recorremos todos los controles
Control= oForm.getByIndex(i) ' El control del momento
If Control.ServiceName <> "stardiv.one.form.component.Form"and right(Control.ServiceName,6)<>"Button" and( Control.Servicename <> "stardiv.one.form.component.FixedText" and Control.Servicename<>"stardiv.one.form.component.FixedText" and Control.ServiceName<>"com.sun.star.form.component.DatabaseImageControl" and Control.ServiceName<>"com.sun.star.form.component.NavigationToolBar") Then
Dim oEvent as new com.sun.star.script.ScriptEventDescriptor ' Evento
oEvent.AddListenerParam = "" ' No añadimos ningún parámetro
oEvent.EventMethod = "focusGained" ' Al recibir el foco
oEvent.ListenerType = ".XFocusListener" ' Tipo de listener
oEvent.ScriptCode = "vnd.sun.star.script:Standard.Module3.on_focus?language=Basic&location=document" ' Ruta de la macro
oEvent.ScriptType = "Script" ' Tipo de script
'------------------------------------------------------
' Comprobamos si hay eventos con macros asignadas y cuales son
Dim Array1()
If ubound(oForm.getScriptEvents(i))>=0 then ' Si al menos hay un evento en el control que toca con macros
Clave=2 ' Constante
For each event in oForm.getScriptEvents(i) ' Recorremos todos los eventos del control en el que estamos
If Event.EventMethod= "focusGained"Then ' Si el evento es 'Al recibir el foco'
If Event.ScriptCode<> "vnd.sun.star.script:Standard.Module3.on_focus?language=Basic&location=document" Then ' Si la macro es distinta de la propuesta
Array1=Str(Control.Name) ' Rellenamos una matriz auxiliar
sTmp1= sTmp1 &" -Unidad """ & oForm.Name & """; control denominado """ & Array1(i)&"""" & Chr(13) ' Reunión de todos los controles con el evento ya ocupado con una macro distinta a la propuesta
Modelo1= Str(sTmp1)
End if ' Acabamos con la condición de que la macro sea distinta de la propuesta
Clave=1 ' Cambiamos el valor de la constante
End if ' Acabamos la condición de que el evento sea el de 'Al recibir el foco'
Next ' Vamos al siguiente evento
If Clave<>1 Then ' En caso de que la constante no sea uno
oForm.registerScriptEvent( i, oEvent ) ' Anexamos la macro al evento que habíamos preparado
End if ' Acabamos la condición de que la clave no sea uno
Clave=2 ' Modificamos el valor de la constante (distinto de 1)
End if ' Acabamos la condición de que al menos haya un evento ocupado
If ubound(oForm.getScriptEvents(i))= -1 then ' Si no hay ningún evento con macros
oForm.registerScriptEvent( i, oEvent ) ' Anexamos la macro al evento que habíamos preparado
End if ' Acabamos la condición de no tener ningún evento cubierto
End if ' Acabamos la condición de que no sean controles no deseados
Dim Array8()
Redim Preserve Array8(i)
Array8(i)= Modelo1
Next ' Vamos al siguiente control
for i= LBound (Array8()) to UBound(Array8())
if Len(Array8(i))>0 Then
sTmp8= sTmp8 & array8(i)
End if
Next
'-------------------------------------------------------
' Visualizamos el trabajo hecho
If len (Modelo1)>0 then
'msgbox "Los siguientes controles tienen una macro diferente a la propuesta en el evento ""Al recibir el foco""" & CHR(13)&CHR(13)& Modelo1 & CHR(13) & CHR(13)& "Si qiere que la macro sea también aplicada en estos controles tendrá que editar el código que ya hay con una llamada a la macro ""on_focus"" en su interior"
End if
End Sub
Sub on_focus(event)
g_ultimo_control = event.Source
End Sub
Un saludo!
Ah! y con esta lo quitaríamos (al incluir la llamada en la recurrencia inicial)
Código: Seleccionar todo
Sub RetirarFoco (oForm)
Dim oEmptyArgs() as new com.sun.star.beans.PropertyValue
Dim oFormsCollection as Object
n= oForm.getCount-1 ' Controles totales del formulario
'---------------------------------------------------
' Ponemos en cada control que nos interesa la macro en el evento al recibir el foco
For i=0 to n ' Recorremos todos los controles
Control= oForm.getByIndex(i) ' El control del momento
If Control.ServiceName <> "stardiv.one.form.component.Form"and right(Control.ServiceName,6)<>"Button" and( Control.Servicename <> "stardiv.one.form.component.FixedText" and Control.Servicename<>"stardiv.one.form.component.FixedText" and Control.ServiceName<>"com.sun.star.form.component.DatabaseImageControl" and Control.ServiceName<>"com.sun.star.form.component.NavigationToolBar") Then
'------------------------------------------------------
' Comprobamos si hay eventos con macros asignadas y cuales son
If ubound(oForm.getScriptEvents(i))>=0 then ' Si al menos hay un evento en el control que toca con macros
For each event in oForm.getScriptEvents(i) ' Recorremos todos los eventos del control
If Event.EventMethod= "focusGained" Then ' Si es el evento 'al recibir el foco'
'------------------------------------------------------
' Comprobamos si la macro es la misma que estamos intentando instalar o es diferente
If Event.ScriptCode<>"" and Event.ScriptCode= "vnd.sun.star.script:Standard.Module3.on_focus?language=Basic&location=document" Then
oForm.revokeScriptEvent( i, "com.sun.star.awt.XFocusListener", "focusGained", "" )
End if ' Acabamos la condición de que sin estar vacío, resulta ser otra macro diferente
End if
Next ' Vamos al siguiente evento
End if ' Acabamos la condición de que al menos haya un evento ocupado
End if ' Acabamos la condición de que no sean controles no deseados
Next ' Vamos al siguiente control
End Sub
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Libreoffice 6.4.2, en Windows 10