Página 1 de 1

Travamento após browse

Enviado: 19 Dez 2023 12:26
por JoséQuintas
Identifiquei um travamento após o browse, mas não faço idéia como resolver.

Código: Selecionar todos

FUNCTION gui_Browse( xDlg, xControl, nRow, nCol, nWidth, nHeight, oTbrowse, cField, xValue, workarea )

   LOCAL aHeaderList := {}, aWidthList := {}, aFieldList := {}, aItem

   IF Empty( xControl )
      xControl := gui_newctlname( "BROW" )
   ENDIF
   FOR EACH aItem IN oTbrowse
      AAdd( aHeaderList, aItem[1] )
      AAdd( aFieldList, aItem[2] )
      AAdd( aWidthList, Max( Len( aItem[3] ), Len( Transform(FieldGet(FieldNum(aItem[1] ) ), "" ) ) ) * 10 + 10 )
   NEXT
   @ nRow, nCol GRID ( xControl ) ;
      OF ( xDlg ) ;
      WIDTH nWidth - 20 ;
      HEIGHT nHeight - 20 ;
      ON DBLCLICK gui_BrowseDblClick( xDlg, xControl, workarea, cField, @xValue ) ;
      HEADERS aHeaderList ;
      WIDTHS aWidthList ;
      ROWSOURCE ( workarea ) ;
      COLUMNFIELDS aFieldList

   (xDlg);(cField);(xValue);(workarea)

   RETURN Nil

FUNCTION gui_BrowseDblClick( xDlg, xControl, workarea, cField, xValue )

   IF ! Empty( cField )
      xValue := &(workarea)->( FieldGet( FieldNum( cField ) ) )
   ENDIF
   DoMethod( xDlg, "RELEASE" )
   (xControl)

   RETURN Nil
O problema é:
é chamado de um button. funciona normalmente, abre, no ENTER volta na dialog anterior.
é chamado de um edit. funciona normalmente, abre, no ENTER volta na dialog anterior.
E qual é o problema?
Depois que terminou tudo, ao fechar essa dialog que chamou o browse, não volta para o menu, fica travado.

Travamento após browse

Enviado: 20 Dez 2023 20:44
por Ana Mitoooo
POG do dia !

Código: Selecionar todos

Antes do Form.Release, mude o foco para outro objeto (Buttom, Edit, etc)

Travamento após browse

Enviado: 21 Dez 2023 12:48
por JoséQuintas
Nada feito.

Fiz a gambiarra acionando o button exit

Código: Selecionar todos

   IF ! Empty( xCmdExit )
      DoMethod( ::xDlg, xcmdExit[ CFG_FCONTROL ], "ACTION" )
   ENDIF
   //DoMethod( xDlg, "RELEASE" )

   RETURN Nil
o button exit muda o foco antes de sair, pra ele mesmo

Código: Selecionar todos

METHOD Exit() CLASS frm_Class

   LOCAL aControl

   // hmge extended
   FOR EACH aControl IN ::aControlList
      IF aControl[ CFG_CTLTYPE ] == TYPE_BUTTON .AND. aControl[ CFG_CAPTION ] == "Exit"
         gui_SetFocus( ::xDlg, aControl[ CFG_FCONTROL ] )
        EXIT
      ENDIF
   NEXT
   gui_DialogClose( ::xDlg )

   RETURN Nil
Continua o problema do menu ficar MODAL.

Recapitulando:

MENU chama CADASTRO MODAL, ok funciona

CADASTRO chama BROWSE MODAL, pode chamar várias vezes, ok funciona

Mas se o browse for acionado, ao sair do cadastro o menu está bloqueado.

Às vezes é o próprio cadastro que fica bloqueado e o menu fica liberado, o que é mais estranho ainda, ter dois comportamentos diferentes pra mesma coisa.
Parece problema no MODAL, por isso pensei em forçar a definição de PARENT, mas não recebi resposta pra isso.

Travamento após browse

Enviado: 21 Dez 2023 13:52
por JoséQuintas
Agora então..... sensacional....

Executei a primeira vez, nada travou.
Executei a segunda vez, janela travada.

https://www.youtube.com/watch?v=hXREUQl_XPA



Funciona....
Mas não funciona....
Procurar um erro aonde funciona, porque não funciona.

Então....
Tá certo ? ou tá errado ?
Funciona ? ou não funciona ?
MESMO EXE, SEM NEM MESMO RECOMPILAR.
Funcionou sem travar.
Funcionou mas travou.

Tá certo ? porque no segundo uso trava ?
Tá errado ? porque no primeiro uso funciona ?

Pois é....

Fazer o que numa situação dessas ?

Vejam se detectam algo diferente entre as execuções que eu possa não ter percebido, na forma de uso.

Travamento após browse

Enviado: 21 Dez 2023 15:07
por JoséQuintas
DETECTEI... a diferença, não como resolver....

ENTER, ENTER, ENTER, ENTER pra browse, ok
ENTER, ENTER, ENTER, ENTER, shift-tab, ENTER pra browse, problema
ENTER, ENTER, ENTER, ENTER, shift-tab, shift-tab, ENTER, ENTER pra browse, ok.
Travou após usar shift-tab pra retornar no edit que faz o browse.
Se no EDIT do browse chegar com SHIFT_TAB, dá o problema.

Por enquanto sem idéia pra resolver.

Nota:
SET NAVIGATION EXTENDED, pra ENTER mudar de campo
Dialog do browse no LostFocus, na validação.
Sem problemas quando está indo em frente, mas problema se estiver voltando.

Nota2:
Por isso eu ficava confuso aqui de funcionar ou não. Depende de como chega no EDIT.
Acho que só alterando internamente na HMG Extended pra resolver.

Travamento após browse

Enviado: 22 Dez 2023 20:00
por ivanil
Ola Quintas;

Se você estiver usando Gotfocus ou Lostfocus; certamente o problema estará ai;
Estes eventos podem causar um travamento tendo em vista que um pode disparar o outro infinitamente;
imaginemos um cenário de validação com lostfocus... para disparar quer dizer que perdeu o foco, mas a validação o chama de volta, mas outro controle havia recebido o foco e se houver uma função em lostfocus nele, esta também será executada e temos ai o travamento. O mesmo vale para gotfocus...

Tem ainda o Onchange que deve ser usado com cuidado.
Você pode alterar um valor de um controle qualquer; este por sua vez tem um onchange atribuído que atualiza outros "N" controles... isso também pode levar a um travamento.

Grande Abraço.


Ivanil

Travamento após browse

Enviado: 24 Dez 2023 10:09
por JoséQuintas
Isso pode até tentar explicar, mas não justifica funcionar de vez em quando, conforme a última tecla acionada.
O problema não parece estar nesse ponto específico, o que complica tudo.

Uma miniatura de como uso no DlgAuto.

Código: Selecionar todos

#include "hmg.ch"
#include "i_altsyntax.ch"

PROCEDURE Main

   LOCAL xDlg := "win_Main"

   SET NAVIGATION EXTENDED
   SET WINDOW MODAL PARENT HANDLE ON

   IF ! File( "dbf.dbf" )
      dbCreate( "DBF", { ;
         { "A", "C", 10, 0 }, ;
         { "B", "C", 10, 0 } } )
      USE dbf
      APPEND BLANK
      REPLACE A WITH "A", B WITH "B"
      USE
   ENDIF
   USE dbf

	DEFINE WINDOW ( xDlg ) ;
	   AT        0,0 			;
	   WIDTH     640 			;
      HEIGHT    480 			;
	   TITLE     "EDIT Command Demo" 	;
      MAIN 				;
		BACKCOLOR GRAY

		DEFINE MAIN MENU OF ( xDlg )
         POPUP "test"
            ITEM "&Simple Edit test"   ACTION Eval( { || Dialog1() } )
        	   ITEM "E&xit"               ACTION DoMethod( xDlg, "RELEASE" )
         END POPUP
		END MENU

	END WINDOW

   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )
   USE

   RETURN

PROCEDURE DIALOG1

   LOCAL xDlg := "Dialog1"
   LOCAL a := Space(10), b := Space(10), c := Space(10)
   LOCAL A1 := "edit1", A2 := "edit2", A3 := "edit3"

   DEFINE WINDOW ( xDlg ) ;
      AT 0, 0 ;
      WIDTH 640 ;
      HEIGHT 480 ;
      TITLE "dialog1" ;
      MODAL
   END WINDOW
      DEFINE TEXTBOX ( a1 )
        PARENT ( xDlg )
        ROW 10
        COL 10
        HEIGHT 20
        WIDTH 500
        VALUE A
     END TEXTBOX
      DEFINE TEXTBOX ( a2 )
        PARENT ( xDlg )
        ROW 40
        COL 10
        HEIGHT 20
        WIDTH 500
        VALUE B
        ON LOSTFOCUS Eval( { || Dialog2( xDlg, A2 ) } )
     END TEXTBOX
      DEFINE TEXTBOX ( a3 )
        PARENT ( xDlg )
        ROW 70
        COL 10
        HEIGHT 20
        WIDTH 500
        VALUE C
     END TEXTBOX

   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )

   RETURN

FUNCTION DIALOG2( xOldDlg, xEdit )

   LOCAL xDlg        := "Dialog2"
   LOCAL xControl    := "Grid1"
   LOCAL aHeaderList := { "A", "B" }
   LOCAL aWidthList  := { 100, 100 }
   LOCAL aColList    := { "A", "B" }
   LOCAL cArea       := "DBF"

   IF ! Empty( GetProPerty( xOldDlg, xEdit, "VALUE" ) )
      RETURN Nil
   ENDIF

   DEFINE WINDOW ( xDlg ) ;
      AT 0, 0 ;
      WIDTH 640 ;
      HEIGHT 480 ;
      TITLE xDlg ;
      MODAL
   END WINDOW
   @ 10, 10 GRID ( xControl ) ;
      OF ( xDlg ) ;
      WIDTH 600 ;
      HEIGHT 400 ;
      ON DBLCLICK BrowseDblClick( xDlg, xOldDlg, xEdit  ) ;
      HEADERS aHeaderList ;
      WIDTHS aWidthList ;
      ROWSOURCE ( cArea ) ;
      COLUMNFIELDS aColList

   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )

   RETURN .T.

FUNCTION BrowseDblClick( xDlg, xOldDlg, xEdit )

   SetProperty( xOldDlg, xEdit, "VALUE", field->a )
   DoMethod( xDlg, "RELEASE" )

   RETURN Nil
Ainda tentando fazer esse travar.

Travamento após browse

Enviado: 24 Dez 2023 10:13
por JoséQuintas
Pronto, consegui fazer travar.

Código: Selecionar todos

   SET WINDOW MAIN OFF
O fluxo normal de janelas não é obedecido com MAIN OFF.

O que tem a ver ? não sei.
janela chama janela que chama janela.

NÃO estou misturando nada.
Mas se levar em conta o comportamento da GTWVG... a execução a partir do menu não é exatamente a partir da janela.
Mas aí isso poderia afetar qualquer menu de qualquer janela.

Teste? talvez um setfocus() pra janela antes de executar.

Travamento após browse

Enviado: 24 Dez 2023 11:33
por JoséQuintas
Pra ficar mais parecido ainda com o dlgauto:

Código: Selecionar todos

#include "hmg.ch"
#include "i_altsyntax.ch"

PROCEDURE Main

   LOCAL xDlg := "win_Main"

   SET NAVIGATION EXTENDED
   SET WINDOW MAIN OFF
   SET WINDOW MODAL PARENT HANDLE ON


   IF ! File( "dbf.dbf" )
      dbCreate( "DBF", { ;
         { "A", "C", 10, 0 }, ;
         { "B", "C", 10, 0 } } )
      USE dbf
      APPEND BLANK
      REPLACE A WITH "A", B WITH "B"
      USE
   ENDIF
   USE dbf

	CreateWindow( xDlg, 0, 0, 640, 480, "Demo" )

   DEFINE MAIN MENU OF ( xDlg )
      POPUP "test"
         ITEM "&Simple Edit test"   ACTION Eval( { || DoMethod( xDlg, "setfocus" ), Dialog1() } )
        	ITEM "E&xit"               ACTION DoMethod( xDlg, "RELEASE" )
      END POPUP
   END MENU

   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )
   USE

   RETURN

PROCEDURE DIALOG1

   LOCAL xDlg := "Dialog1"
   LOCAL a := Space(10), b := Space(10), c := Space(10)
   LOCAL A1 := "edit1", A2 := "edit2", A3 := "edit3"

   CreateWindow( xDlg, 0, 0, 640, 480, "dialog1" )
   CreateTextbox( xDlg, a1, 10, 10, 500, 20, a )
   CreateTextbox( xDlg, a2, 40, 10, 500, 20, b, { || Dialog2( xDlg, A2 ) } )
   CreateTextbox( xDlg, a3, 70, 10, 500, 20, c )
   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )

   RETURN

FUNCTION DIALOG2( xOldDlg, xEdit )

   LOCAL xDlg        := "Dialog2"
   LOCAL xControl    := "Grid1"
   LOCAL aHeaderList := { "A", "B" }
   LOCAL aWidthList  := { 100, 100 }
   LOCAL aColList    := { "A", "B" }
   LOCAL cArea       := "DBF"

   IF ! Empty( GetProPerty( xOldDlg, xEdit, "VALUE" ) )
      RETURN Nil
   ENDIF

   CreateWindow( xDlg, 0, 0, 640, 480, xDlg )
   @ 10, 10 GRID ( xControl ) ;
      OF ( xDlg ) ;
      WIDTH 600 ;
      HEIGHT 400 ;
      ON DBLCLICK BrowseDblClick( xDlg, xOldDlg, xEdit  ) ;
      HEADERS aHeaderList ;
      WIDTHS aWidthList ;
      ROWSOURCE ( cArea ) ;
      COLUMNFIELDS aColList

   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )

   RETURN .T.

FUNCTION BrowseDblClick( xDlg, xOldDlg, xEdit )

   SetProperty( xOldDlg, xEdit, "VALUE", field->a )
   DoMethod( xDlg, "RELEASE" )

   RETURN Nil

FUNCTION CreateWindow( xDlg, nRow, nCol, nWidth, nHeight, cTitle )

   DEFINE WINDOW ( xDlg ) ;
      AT nCol, nRow ;
      WIDTH nWidth ;
      HEIGHT nHeight ;
      TITLE cTitle ;
      MODAL
   END WINDOW

   RETURN Nil

FUNCTION CreateTextbox( xDlg, xControl, nRow, nCol, nWidth, nHeight, xValue, bLostFocus )

   DEFINE TEXTBOX ( xControl )
      PARENT ( xDlg )
      ROW nRow
      COL nCol
      HEIGHT nHeight
      WIDTH nWidth
      VALUE xValue
      IF ! Empty( bLostFocus )
         ON LOSTFOCUS Eval( bLostFocus )
      ENDIF
   END TEXTBOX

   RETURN Nil

Travamento após browse

Enviado: 25 Dez 2023 01:24
por ivanil
Ola Quintas;

Para seu exemplo, o evento "ON ENTER" seria melhor empregado, embora o "ON LOSTFOCUS" não causaria problema pela validação simples, mas fica deselegante o salto, levando o usuário a pensar que está em um campo diferente;
Na modificação abaixo tudo ocorreu dentro dos conformes nos testes executados aqui;

Código: Selecionar todos

#include "hmg.ch"
Declare window (xDlg)
Declare window (xOldDlg)

PROCEDURE Main

   LOCAL xDlg := "win_Main"

   SET NAVIGATION EXTENDED

   IF ! File( "dbf.dbf" )
      dbCreate( "DBF", { ;
         { "A", "C", 10, 0 }, ;
         { "B", "C", 10, 0 } } )
      USE dbf
      APPEND BLANK
      REPLACE A WITH "A", B WITH "B"
      USE
   ENDIF
   USE dbf

   CreateWindow( xDlg, 0, 0, 640, 480, "Demo" )

   DEFINE MAIN MENU OF ( xDlg )
      POPUP "test"
         ITEM "&Simple Edit test"   ACTION Dialog1()
         ITEM "E&xit"               ACTION (xDlg).Release()
      END POPUP
   END MENU
   (xDlg).Center()
   (xDlg).Activate()
  
   USE

   RETURN

PROCEDURE DIALOG1

   LOCAL xDlg := "Dialog1"
   LOCAL a := Space(10), b := Space(10), c := Space(10)
   LOCAL A1 := "edit1", A2 := "edit2", A3 := "edit3"

   CreateWindow( xDlg, 0, 0, 640, 480, "dialog1" )
   CreateTextbox( xDlg, a1, 10, 10, 500, 20, a, { || Dialog2( xDlg, A1 ) }  )
   CreateTextbox( xDlg, a2, 40, 10, 500, 20, b, { || Dialog2( xDlg, A2 ) } )
   CreateTextbox( xDlg, a3, 70, 10, 500, 20, c , {|| Dialog2( xDlg, A3 ) } )
   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )

   RETURN

FUNCTION DIALOG2( xOldDlg, xEdit )

   LOCAL xDlg        := "Dialog2"+xEdit
   LOCAL xControl    := "Grid1"
   LOCAL aHeaderList := { "A", "B" }
   LOCAL aWidthList  := { 100, 100 }
   LOCAL aColList    := { "A", "B" }
   LOCAL cArea       := "DBF"

   IF ! Empty( (xOldDlg).(xEdit).Value )
      RETURN Nil
   ENDIF

   CreateWindow( xDlg, 0, 0, 640, 480, xDlg )
   
   
   @ 10, 10 GRID ( xControl ) ;
      OF ( xDlg ) ;
      WIDTH 600 ;
      HEIGHT 400 ;
      ON DBLCLICK ((xOldDlg).(xEdit).value := Field->a ,(xdlg).Release()) ;
      HEADERS aHeaderList ;
      WIDTHS aWidthList ;
      ROWSOURCE ( cArea ) ;
      COLUMNFIELDS aColList
      (xDlg).Center()
      (xDlg).Activate()

   RETURN .T.


FUNCTION CreateWindow( xDlg, nRow, nCol, nWidth, nHeight, cTitle )
    if !_HMG_MainActive
        DEFINE WINDOW ( xDlg ) ;
            AT nCol, nRow ;
            WIDTH nWidth ;
            HEIGHT nHeight ;
            TITLE cTitle ;
            MAIN
        END WINDOW
    else
        DEFINE WINDOW ( xDlg ) ;
            AT nCol, nRow ;
            WIDTH nWidth ;
            HEIGHT nHeight ;
            TITLE cTitle ;
            MODAL
        END WINDOW
    endif
   RETURN Nil

FUNCTION CreateTextbox( xDlg, xControl, nRow, nCol, nWidth, nHeight, xValue, bLostFocus )

   DEFINE TEXTBOX ( xControl )
      PARENT ( xDlg )
      ROW nRow
      COL nCol
      HEIGHT nHeight
      WIDTH nWidth
      VALUE xValue
      If !empty(bLostFocus)
         ON ENTER  Eval(bLostFocus)
      endif
   END TEXTBOX

   RETURN Nil

Travamento após browse

Enviado: 25 Dez 2023 01:34
por JoséQuintas
O Grigory respondeu.
Hello José,
Thanks for your bug report!
I confirm this issue with using SET WINDOW MAIN OFF and MODAL dialogs.
Please notice the above command was introduced for compatibility only.
It is not recommended for using usually.
BTW look at the updated example with a workaround below

Código: Selecionar todos

#include "hmg.ch"
//#include "i_altsyntax.ch"

PROCEDURE Main

   LOCAL xDlg := "win_Main"

   SET NAVIGATION EXTENDED
   SET WINDOW MAIN OFF
   SET WINDOW MODAL PARENT HANDLE ON


   IF ! File( "dbf.dbf" )
      dbCreate( "DBF", { ;
         { "A", "C", 10, 0 }, ;
         { "B", "C", 10, 0 } } )
      USE dbf
      APPEND BLANK
      REPLACE A WITH "A", B WITH "B"
      USE
   ENDIF

   USE dbf

	DEFINE WINDOW ( xDlg ) ;
	   AT        0,0 			;
	   WIDTH     640 			;
	   HEIGHT    480 			;
	   TITLE     "EDIT Command Demo" 	;
	   BACKCOLOR GRAY

		DEFINE MAIN MENU OF ( xDlg )
         POPUP "test"
            ITEM "&Simple Edit test"   ACTION ( DoMethod( xDlg, "setfocus" ), Dialog1() ) // <<=================
            ITEM "E&xit"               ACTION DoMethod( xDlg, "RELEASE" )
         END POPUP
		END MENU

	END WINDOW

   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )
   USE

   RETURN

PROCEDURE DIALOG1

   LOCAL xDlg := "Dialog1"
   LOCAL a := Space(10), b := Space(10), c := Space(10)
   LOCAL A1 := "edit1", A2 := "edit2", A3 := "edit3"

   DEFINE WINDOW ( xDlg ) ;
      AT 0, 0 ;
      WIDTH 640 ;
      HEIGHT 480 ;
      TITLE "dialog1" ;
      MODAL ;
      ON RELEASE DoMethod( "win_Main", "setfocus" ) // <<===============
      ON KEY ALT+F4 ACTION NIL // <<====================
   END WINDOW

      DEFINE TEXTBOX ( a1 )
        PARENT ( xDlg )
        ROW 10
        COL 10
        HEIGHT 20
        WIDTH 500
        VALUE A
     END TEXTBOX
      DEFINE TEXTBOX ( a2 )
        PARENT ( xDlg )
        ROW 40
        COL 10
        HEIGHT 20
        WIDTH 500
        VALUE B
        ON LOSTFOCUS Eval( { || Dialog2( xDlg, A2 ) } )
     END TEXTBOX
      DEFINE TEXTBOX ( a3 )
        PARENT ( xDlg )
        ROW 70
        COL 10
        HEIGHT 20
        WIDTH 500
        VALUE C
     END TEXTBOX

   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )

   RETURN

FUNCTION DIALOG2( xOldDlg, xEdit )

   LOCAL xDlg        := "Dialog2"
   LOCAL xControl    := "Grid1"
   LOCAL aHeaderList := { "A", "B" }
   LOCAL aWidthList  := { 100, 100 }
   LOCAL aColList    := { "A", "B" }
   LOCAL cArea       := "DBF"

   IF ! Empty( GetProPerty( xOldDlg, xEdit, "VALUE" ) )
      RETURN Nil
   ENDIF

   DEFINE WINDOW ( xDlg ) ;
      AT 0, 0 ;
      WIDTH 640 ;
      HEIGHT 480 ;
      TITLE xDlg ;
      MODAL ;
      ON RELEASE DoMethod( xOldDlg, "setfocus" ) // <<===============
      ON KEY ALT+F4 ACTION DoMethod( xOldDlg, "setfocus" ) // <<========================
   END WINDOW

   @ 10, 10 GRID ( xControl ) ;
      OF ( xDlg ) ;
      WIDTH 600 ;
      HEIGHT 400 ;
      ON DBLCLICK BrowseDblClick( xDlg, xOldDlg, xEdit  ) ;
      HEADERS aHeaderList ;
      WIDTHS aWidthList ;
      ROWSOURCE ( cArea ) ;
      COLUMNFIELDS aColList

   DoMethod( xDlg, "CENTER" )
   DoMethod( xDlg, "ACTIVATE" )

   RETURN .T.

FUNCTION BrowseDblClick( xDlg, xOldDlg, xEdit )

   SetProperty( xOldDlg, xEdit, "VALUE", field->a )
   DoMethod( xDlg, "RELEASE" )

   RETURN Nil
Nota:
Apesar do problema ter ocorrido após o browse, tem a ver com SET WINDOW MAIN OFF, e o uso de MODAL.
Só descobri no fonte isolado, criado primeiro normal sem travar, e depois com SET WINDOW MAIN OFF e travando.
Parece que o MODAL se perde desse jeito.