[RESUELTO]Control de foco en formulario

Discute sobre las herramientas de la base de datos
Responder
Longi
Mensajes: 804
Registrado: Dom Ene 20, 2013 9:05 pm
Ubicación: Ourense, Galicia, España

[RESUELTO]Control de foco en formulario

Mensaje por Longi »

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! ;)
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Avatar de Usuario
mauricio
Mensajes: 6092
Registrado: Sab Nov 22, 2008 5:36 am
Ubicación: CDMX
Contactar:

Re: Control de foco en formulario

Mensaje por mauricio »

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
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Longi
Mensajes: 804
Registrado: Dom Ene 20, 2013 9:05 pm
Ubicación: Ourense, Galicia, España

Re: Control de foco en formulario

Mensaje por Longi »

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:

Código: Seleccionar todo

if not IsNull (oFormController.CurrentControl) Then
, y después para los que tienen esta otra:

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
Avatar de Usuario
mauricio
Mensajes: 6092
Registrado: Sab Nov 22, 2008 5:36 am
Ubicación: CDMX
Contactar:

Re: Control de foco en formulario

Mensaje por mauricio »

Ha vuelto a leer desde tu primer mensaje, y veo dos temas diferentes. No tengo claros lo siguiente que mencionas:
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
¿El problema es el sistema de búsqueda?
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
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. :D

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
Longi
Mensajes: 804
Registrado: Dom Ene 20, 2013 9:05 pm
Ubicación: Ourense, Galicia, España

Re: Control de foco en formulario

Mensaje por Longi »

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!
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Longi
Mensajes: 804
Registrado: Dom Ene 20, 2013 9:05 pm
Ubicación: Ourense, Galicia, España

Re: Control de foco en formulario

Mensaje por Longi »

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! ;) ;) ;) ;)
Adjuntos
Explicaciones.7z
(22.12 KiB) Descargado 188 veces
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Avatar de Usuario
mauricio
Mensajes: 6092
Registrado: Sab Nov 22, 2008 5:36 am
Ubicación: CDMX
Contactar:

Re: Control de foco en formulario

Mensaje por mauricio »

ya voy entendiendo... :D

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
Avatar de Usuario
mauricio
Mensajes: 6092
Registrado: Sab Nov 22, 2008 5:36 am
Ubicación: CDMX
Contactar:

Re: Control de foco en formulario

Mensaje por mauricio »

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.

Código: Seleccionar todo

Global g_ultimo_control As Object

Sub on_focus(event)
	g_ultimo_control = event.Source
End Sub
Si, con Python podríamos autoreferenciar este evento en cada control, pero nos gusta sufrir... :lol: :lol: :lol:

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
Longi
Mensajes: 804
Registrado: Dom Ene 20, 2013 9:05 pm
Ubicación: Ourense, Galicia, España

Re: Control de foco en formulario

Mensaje por Longi »

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! ;)
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Avatar de Usuario
mauricio
Mensajes: 6092
Registrado: Sab Nov 22, 2008 5:36 am
Ubicación: CDMX
Contactar:

Re: Control de foco en formulario

Mensaje por mauricio »

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.
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Longi
Mensajes: 804
Registrado: Dom Ene 20, 2013 9:05 pm
Ubicación: Ourense, Galicia, España

Re: Control de foco en formulario

Mensaje por Longi »

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
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Avatar de Usuario
mauricio
Mensajes: 6092
Registrado: Sab Nov 22, 2008 5:36 am
Ubicación: CDMX
Contactar:

Re: Control de foco en formulario

Mensaje por mauricio »

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
______________________________________________
"Todo cuanto no podemos dar nos posee". - André Gide
LibreOffice 6.2 | ArchLinux | Gnome3
No respondo preguntas privadas, por favor, usa el foro
Longi
Mensajes: 804
Registrado: Dom Ene 20, 2013 9:05 pm
Ubicación: Ourense, Galicia, España

Re: Control de foco en formulario

Mensaje por Longi »

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.

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
Gracias y otro saludo! ;)
Openoffice 4.1.7, en Windows 10
Libreoffice 6.4.2, en Windows 10
Longi
Mensajes: 804
Registrado: Dom Ene 20, 2013 9:05 pm
Ubicación: Ourense, Galicia, España

Re: [RESUELTO]Control de foco en formulario

Mensaje por Longi »

Bueno!
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
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)

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
Responder