Page 1 of 1

Detectar click fuera de un diálogo

PostPosted: Sun Sep 09, 2012 3:43 pm
by quique
¿Es posible detectar cuando se da click fuera de un diálogo?

Me explico, tengo un diálogo común y corriente, pero necesito detectar si el usuario da click en la ventana del programa que está detras del diálogo. No quiero un diálogo nomodal, porque estoy esperando una respuesta del diálogo, simplemente necesito detectar el click de cualquiera de los botones del mouse.

Re: Detectar click fuera de un diálogo

PostPosted: Sun Sep 09, 2012 6:51 pm
by Antonio Linares
Quique,

Puedes capturar el ratón pero el primer click tendría que ser sobre el diálogo:

SetCapture( oDlg:hWnd )

Otra opción es crear una ventana o diálogo que ocupe todo el escritorio y que sea transparente. Asi al hacer click recibirías el evento.

Re: Detectar click fuera de un diálogo

PostPosted: Mon Sep 10, 2012 4:33 am
by quique
No me funciona el capturar el click si tengo que dar click primero en el diálogo, porque es muy común que el capturista no utilice mouse para llegar al diálogo, y tome el ratón hasta el momento en el que quiero detectar el click, y por consiguiente no de click sobre el diálogo.

Por otro lado, tampoco me convence el diálogo en toda la ventana porque entonces tengo que detectar si fue clic en otra ventana o en la que está detras del diálogo, y además, en que parte es, si es que da en la ventana anterior, pero se me hace interesante el crear un diálogo transparente para colocarlo en otra parte ¿como puedo crear un diálogo transparente? intente con oDlg:lTransparent := .t. y no funcionó.

Re: Detectar click fuera de un diálogo

PostPosted: Mon Sep 10, 2012 6:12 am
by Antonio Linares
Quique,

La utilidad Spy de Microsoft te permite seleccionar una ventana de otra aplicación, pero primero te pide hacer click en Spy y ahi cambia el cursor del ratón indicando que estas en modo selección.

Re: Detectar click fuera de un diálogo

PostPosted: Tue Sep 11, 2012 2:47 am
by quique
Lo que pasa es que en este caso, la opción de capturar el ratón es algo extra, se trata de un proceso de captura, pero es posible que el usuario cambie de opinión y quera abandonar la captura sin terminar el proceso normal, pero no se quiere agregar un botón para no invitar al usuario a salir, pero como se vió que es un proceso relativamente frecuente, se quiere dar la oportunidad.

La solución fue cambiar el diálogo por una ventana y con ella lógicamente hubo que hacer algo de programación por el cambio de ventana, pudimos resolver la necesidad que se tenía.

Re: Detectar click fuera de un diálogo

PostPosted: Tue Sep 11, 2012 10:24 am
by antolin
Quique, cuando despliego alguna ventana NOMODAL para capturar datos, normalmente tienen un sólo control, por ejemplo un LISTBOX, lo que hago es que cierro el dialogo cuando el LISTBOX pierde el foco. Si tiene más de un control, en cada bLostfocus de cada control le digo que si nadie tiene el control, que se cierre el dialogo (desde un función común).

A lo mejor puedes aplicar algo de eso en tu programa.

Otra solución sería decirle al bMMoved de la pantalla principal que si había un dialogo abierto, que lo cierre (al crear el dialogo guarda su hWnd en una variable así sabrás que está abierto, al cerrarlo vuelve a ponerla en 0 y sabrás que está cerrado).

Hay más soluciones, pero depende de qué es lo que quieres, y de cómo quieres que ocurrate.

Re: Detectar click fuera de un diálogo

PostPosted: Tue Sep 11, 2012 2:39 pm
by quique
Si antolin, es algo como lo que comentas, pero no funcionaba con el bLostFocus, porque si le das click a la ventana anterior no lo acepta, asi que esa solución no funcionó, de hecho, así la tuve algún tiempo antes de preguntar, el bMMoved tampoco me funciona, aunque no lo probé, porque eso sería si se mueve el mouse, en este caso, solo se quiere si se da click fuera del diálogo, porque en el diálogo, dependiendo de la opción, llego a tener hasta 3 contoles, entonces puede haber oportunidad de que el usuario escoja un botón y le de click, si uilizo el bMMoved para la ventana posterior, con cualquier movimiento podría avandonar la captura.

Ya quedó solucionado con utilizar una ventana en lugar de un diálogo, ahi si se puede utilizar bLostFocus, porque con la venana si puedo detectar si pierde el foco al hacer click en la ventana anterior.

Re: Detectar click fuera de un diálogo

PostPosted: Fri Sep 21, 2012 8:53 am
by antolin
Quique, he estado buscando algunas soluciones, pero ahora no tengo tiempo de ponerlas en práctica, pero a lo mejor tu sí.

Windows se comunica con nuestras ventanas/dialogos mediante mensajes (como todo el mundo sabe). Cuando una ventana/dialogo recibe o pierde el flujo de nuestra aplicación recibe el mensaje WM_ACTIVATE via HandleEvent(). Consulta esta página, a lo mejor ahí hay una solución efectiva:

http://winapi.conclase.net/curso/?winms ... ATE#inicio

Significa que cuando una ventana se desactiva recibe el mensaje WA_INACTIVE (en teoría), eso se podría controlar modificando TDIALOG para procesar ese evento.

Suerte.

Re: Detectar click fuera de un diálogo

PostPosted: Fri Sep 21, 2012 8:55 am
by antolin
Por cieto, en ese mismo enlace también habla del mensaje WM_KILLFOCUS que a lo mejor tambien funciona. Es cuestión de probar.

Saludos

Re: Detectar click fuera de un diálogo

PostPosted: Wed Jan 22, 2014 1:29 pm
by emotta_no

Re: Detectar click fuera de un diálogo

PostPosted: Wed Jan 22, 2014 1:30 pm
by emotta_no
Code: Select all  Expand view

    #include "FiveWin.ch"

    function Teste()

   local oDlg

   DEFINE DIALOG oDlg STYLE WS_POPUP

   oDlg:bStart = { || SetCapture( oDlg:hWnd ) }

   ACTIVATE DIALOG oDlg CENTERED ;
      ON CLICK If( nRow < 0 .or. nCol < 0 .or. ;
                   nRow > oDlg:nHeight - 0 .or. nCol > oDlg:nWidth,;
                   (MsgStop("clicked outside"),SetCapture( oDlg:hWnd )),)
return nil

 

Re: Detectar click fuera de un diálogo

PostPosted: Fri Jan 24, 2014 5:44 am
by quique
Gracias por la ayuda, el problema es que ya no me acuerdo donde necesitaba esa solución, si recuerdo el programa, pero no la opción, voy a tratar de hacer memoria y cuando recuerde lo pruebo.

Re: Detectar click fuera de un diálogo

PostPosted: Wed Aug 14, 2019 2:01 am
by leandro
Buenas noches para todos, compile el ejemplo que esta aqui y funciona, pero al colocarlo en mi codigo nada de nada. No se si tenga que ver con el tema de los recursos.

Code: Select all  Expand view

********************************************************************************
FUNCTION buscarArticulo(oDlg,oGet)
Local vGbus := space(100)

local nTopR, nLeftR, nAltura
local aPoint

nTopR     := oGet:nTop      
nLeftR    := oGet:nLeft
nAltura   := oGet:nHeight

aPoint := { nTopR+nAltura, nLeftR }
aPoint = ClientToScreen( oDlg:hWnd, aPoint )

oVar:="SELECT i_articu,i_nombre FROM " + oLamcla:tArti +" ORDER BY i_articu"
oRsBar := FW_OPENRECORDSET(oLamcla:oServer,oVar,adLockOptimistic,adOpenKeyset)  
Define Font oFont Name "Calibri" Size 0,-12 Bold
Define Font oFont1 Name "Calibri" Size 0,-13
DEFINE DIALOG oDlgBar RESOURCE "ORFACT3" OF oDlg

    REDEFINE GET oGbus VAR vGbus ID 4002 OF oDlgBar UPDATE VALID (hacefiltro(cBrw,vGbus),.T.)

    cBrw := TXBrowse():New( oDlgBar )
    cBrw:nMarqueeStyle         := MARQSTYLE_HIGHLROW
    cBrw:nRowDividerStyle      := LINESTYLE_LIGHTGRAY
    cBrw:nColDividerStyle      := LINESTYLE_LIGHTGRAY
    cBrw:nHeaderLines          := 1
    cBrw:lColDividerComplete   := .t.
    cBrw:lRecordSelector       := .t.
    cBrw:nStretchCol           := STRETCHCOL_LAST
    cBrw:l2007                 := .f.
    cBrw:oFont                 := oFont1
    cBrw:bKeyDown              := {|nKey|iif(nKey == 13,oDlgBar:end(),)}
    cBrw:blDblClick            := {|| oDlgBar:end()}
   
    oCol          = cBrw:AddCol()
    oCol:bStrData = { || If( oRsBar:Eof, Space( nWidth ), oRsBar:Fields( "i_articu" ):Value ) }
    oCol:cHeader  = "Artículo"
    oCol:nWidth   = 90
    oCol:nHeadStrAlign = AL_LEFT
    oCol:nDataStrAlign = AL_LEFT   
    oCol:oHeaderFont = oFont
    oCol:bLClickHeader := {|r,c,f,o| organiza(1) }

    oCol          = cBrw:AddCol()
    oCol:bStrData = { || If( oRsBar:Eof, Space( nWidth ), oRsBar:Fields( "i_nombre" ):Value ) }
    oCol:cHeader  = "Descripción"
    oCol:nWidth   = 250
    oCol:nHeadStrAlign = AL_LEFT
    oCol:nDataStrAlign = AL_LEFT   
    oCol:oHeaderFont = oFont   
    oCol:bLClickHeader := {|r,c,f,o| organiza(2) }

    cBrw:SetADO( oRsBar )
    cBrw:CreateFromResource( 102 )

    oDlgBar:cTitle := "Buscar Artículo"
    oDlgBar:bPostEnd := { || oRsBar:Close() }
    oDlgBar:nOpacity    := 240
    oDlgBar:bStart := { || SetCapture( oDlgBar:hWnd ) }

ACTIVATE DIALOG oDlgBar ON INIT (oDlgBar:SetPos( aPoint[ 1 ], aPoint[ 2 ] ) ) ;
            ON CLICK If( nRow < 0 .or. nCol < 0 .or. ;
            nRow > oDlgBar:nHeight - 0 .or. nCol > oDlgBar:nWidth,;
            (MsgStop("clicked outside"),SetCapture( oDlgBar:hWnd )),)


oItem:hDatos["articulo"] := oRsBar:Fields( "i_articu" ):Value
oItem:hDatos["nombre"] := oRsBar:Fields( "i_nombre" ):Value
return nil