Página 2 de 11

Gerador/criação de telas/executor

Enviado: 14 Ago 2023 20:20
por JoséQuintas
color.png
Anotado dentro dos testes mesmo kkkk

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 13:11
por JoséQuintas
Agora o browse.
Por enquanto meio gambiarra.

No botão view, chama método view.

Código: Selecionar todos

      AAdd( aList, { "View",     { || ::View() } } )
o método view chama o browse, passando o DBF atual

Código: Selecionar todos

   METHOD View()               INLINE frm_Browse( Self, "", "", ::cFileDbf, Nil )
uma rotina genérica de browse, que pega ::aEditList, que só tem a estrutura do arquivo atual

Código: Selecionar todos

/*
frm_browse - browse
*/

#include "frm_class.ch"

FUNCTION frm_Browse( Self, xDlg, xControl, cTable, cField )

   LOCAL oTBrowse := {}, aItem, aField, oBrw

   FOR EACH aField IN ::aEditList
      AAdd( oTBrowse, { aField[ CFG_CAPTION ], { || Transform( aField[ CFG_FNAME ], aField[ CFG_FPICTURE ] ) } } )
   NEXT

   INIT DIALOG xDlg TITLE cTable ;
      AT 0, 0 ;
      SIZE 1024, 768

   @ 0, 0 BROWSE oBrw DATABASE SIZE 800, 500 STYLE WS_BORDER + WS_VSCROLL + WS_HSCROLL

   oBrw:bOther := {|oBrw, msg, wParam, lParam| fKeyDown(oBrw, msg, wParam, lParam)}

   @ 500,540 OWNERBUTTON ON CLICK {|| xDlg:Close() } SIZE 180,36 FLAT TEXT "Close" COLOR hwg_ColorC2N("0000FF")

   FOR EACH aItem IN oTBrowse
      ADD COLUMN aItem[2] TO oBrw HEADER aItem[1] LENGTH Len( Eval( aItem[2] ) ) JUSTIFY LINE DT_LEFT
   NEXT

   ACTIVATE DIALOG xDlg

   (xControl)
   (cField)
   (Self)

   RETURN Nil

STATIC FUNCTION fKeyDown(oBrw, msg, wParam, lParam)

   LOCAL nKEY

   IF msg == WM_KEYDOWN
      nKey := hwg_PtrToUlong( wParam ) //wParam
      IF nKey = VK_RETURN
         hwg_Msginfo("RecNo(): " + Str(RecNo()) )
      ENDIF
   ENDIF
   ( lParam )
   ( oBrw )

   RETURN .T.
tela.png
E voilá.... um browse errado porque peguei o nome e não o conteúdo do campo kkkk

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 13:35
por JoséQuintas
browse.png
Agora sim.
Tá pronto um browse genérico, que usa a estrutura de um DBF qualquer.
Já pode ser usado pra pesquisar o DBF atual, ou aqueles códigos que vém de outros DBFs.

Tão entendendo o gerador?
o browse é um fonte simples, que ainda estou começando a fazer.
Mas já vou vê-lo em várias telas.
É a sensação de tudo pronto, mas não tem nada pronto.
Só dá vontade de continuar fazendo.

Depois é ver em minigui, pra ter em minigui também.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 14:03
por JoséQuintas
Ainda no quebra-galho....

Código: Selecionar todos

   METHOD View()               INLINE frm_Browse( Self, "", "", ::cFileDbf, Nil ), ::UpdateEdit()
Após o browse, que modifica posição do arquivo, atualiza a tela.
Pequeno aproveitamento do browse.

Código: Selecionar todos

STATIC FUNCTION fKeyDown(oBrw, msg, wParam, lParam, cField, xValue )

   LOCAL nKEY

   IF msg == WM_KEYDOWN
      nKey := hwg_PtrToUlong( wParam ) //wParam
      IF nKey = VK_RETURN
         IF ! Empty( cField )
            xValue := FieldGet( FieldNum( cField, xValue ) )
         ENDIF
         hwg_EndDialog()
      ENDIF
   ENDIF
No ENTER do browse, pega campo chave.
Por enquanto fora de uso, mas vou usar para os campos relacionados a outras tabelas.

Lembram dos parâmetros do browse?

Código: Selecionar todos

FUNCTION frm_Browse( Self, xDlg, xControl, cTable, cField )
Vou ter exatamente qual o controle que devo atualizar o conteúdo após o browse.
Só preparando para o que vém depois, que ainda não sei como vai ser kkkk

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 14:20
por JoséQuintas
browse.png
Quase deu certo.
Não atualizou o campo.
Estou no cadastro de clientes, pesquisando o campo de vendedor.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 14:36
por JoséQuintas
Lógico... baguncei tudo, usei o nome da diálog original pra montar a dialog do browse.
Agora ok.

Lembram da rotina de validação?

Código: Selecionar todos

   IF ! Empty( aItem[ CFG_VTABLE ] )
      nSelect := Select()
      SELECT ( Select( aItem[ CFG_VTABLE ] ) )
      SEEK xValue
      lFound := ! Eof()
      xValue := FieldGet( FieldNum( aItem[ CFG_VSHOW ] ) )
      SELECT ( nSelect )
      IF ! lFound
         frm_Browse( Self, ::oDlg, @aItem[ CFG_FCONTROL ], aItem[ CFG_VTABLE ] )
         gui_SetFocus( ::oDlg, aItem[ CFG_FCONTROL ] ) // minigui need this
      ENDIF
      gui_SetLabelValue( ::oDlg, aItem[ CFG_VCONTROL ], xValue )
   ENDIF
Se não encontrar o código digitado, faz o browse com base nos parâmetros.

Código: Selecionar todos

   ACTIVATE DIALOG ThisDlg

   IF ! Empty( xValue ) .AND. ! Empty( xControl )
      xControl:Value := xValue
   ENDIF
   SELECT ( nSelect )
   (xControl)
Se a rotina recebeu o textbox, e se o browse retornou valor com ENTER, pronto, só atualizar o textbox.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 14:48
por JoséQuintas
Sabem o que isso significa?

Cadastro de clientes, vejam que tem o botão VIEW, o campo VENDEDOR, e o campo PORTADOR
cad0.png
Clicando no VIEW, browse de clientes
cad1.png
Digitando vendedor inválido, browse de vendedores
cad2.png
Digitando portador inválido, browse de portadores
cad3.png
E o mesmo acontece nas telas de produto, estoque, financeiro, etc.
O barato é doido.
Nem aprendi direito o browse, e já está em prática em todas as telas, já estou vendo funcionando em tudo que é lugar.
E vamos indo em frente.
Desse jeito, um pequeno avanço se multiplica ao máximo, e parece sempre faltar pouco.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 18:36
por JoséQuintas
Agora vamos melhorar um pouco, talvez....

Código: Selecionar todos

/*
frm_browse - browse
*/

#include "frm_class.ch"

FUNCTION frm_Browse( Self, xDlg, xControl, cTable )

#ifdef HBMK_HAS_HWGUI
   LOCAL oTBrowse := {}, aItem, aField, oBrw, xValue, cField, nSelect, nPos, oThisDlg

   nSelect := Select()
   SELECT ( cTable )

   nPos := hb_Ascan( ::aAllSetup, { | e | e[1] == cTable } )
   FOR EACH aField IN ::aAllSetup[ nPos, 2 ]
      AAdd( oTBrowse, { aField[ CFG_CAPTION ], { || Transform( FieldGet(FieldNum(aField[ CFG_FNAME ])), aField[ CFG_FPICTURE ] ) } } )
      IF aField[ CFG_ISKEY ]
         cField := aField[ CFG_FNAME ]
      ENDIF
   NEXT

   INIT DIALOG oThisDlg TITLE cTable ;
      AT 0, 0 ;
      SIZE 1024, 768

   @ 0, 0 BROWSE oBrw DATABASE SIZE 800, 500 STYLE WS_BORDER + WS_VSCROLL + WS_HSCROLL

   oBrw:bOther := {|oBrw, msg, wParam, lParam| fKeyDown(oBrw, msg, wParam, lParam, cField, @xValue ) }

   @ 500,540 OWNERBUTTON ON CLICK {|| oThisDlg:Close() } SIZE 180,36 FLAT TEXT "Close" COLOR hwg_ColorC2N("0000FF")

   FOR EACH aItem IN oTBrowse
      ADD COLUMN aItem[2] TO oBrw HEADER aItem[1] LENGTH Len( Eval( aItem[2] ) ) JUSTIFY LINE DT_LEFT
   NEXT

   ACTIVATE DIALOG oThisDlg

   IF ! Empty( xValue ) .AND. ! Empty( xControl )
      xControl:Value := xValue
   ENDIF
   SELECT ( nSelect )
   (xDlg)

   RETURN Nil

STATIC FUNCTION fKeyDown(oBrw, msg, wParam, lParam, cField, xValue )

   LOCAL nKEY

   IF msg == WM_KEYDOWN
      nKey := hwg_PtrToUlong( wParam ) //wParam
      IF nKey = VK_RETURN
         IF ! Empty( cField )
            xValue := FieldGet( FieldNum( cField, xValue ) )
         ENDIF
         hwg_EndDialog()
      ENDIF
   ENDIF
   (oBrw)
   (lParam)
#endif

   RETURN .T.
Tá com um owner button embaixo pra close.
Mais interessante deixar encima, igual as outras telas.

Eu já não tenho a classe dos cadastros que diz o default?
E uma rotina de dialogs?
E uma rotina de buttons?
Vamos usar o que já existe pra ver o que dá, pode complicar ou não.

Código: Selecionar todos

/*
frm_browse - browse
*/

#include "frm_class.ch"

FUNCTION frm_Browse( Self, xDlg, xControl, cTable )

#ifdef HBMK_HAS_HWGUI
   LOCAL oTBrowse := {}, aItem, aField, oBrw, xValue, cField, nSelect, nPos, oThisDlg

   nSelect := Select()
   SELECT ( cTable )

   nPos := hb_Ascan( ::aAllSetup, { | e | e[1] == cTable } )
   FOR EACH aField IN ::aAllSetup[ nPos, 2 ]
      AAdd( oTBrowse, { aField[ CFG_CAPTION ], { || Transform( FieldGet(FieldNum(aField[ CFG_FNAME ])), aField[ CFG_FPICTURE ] ) } } )
      IF aField[ CFG_ISKEY ]
         cField := aField[ CFG_FNAME ]
      ENDIF
   NEXT

   oThisDlg := frm_Class():New()
   oThisDlg:cOptions := ""
   gui_CreateDialog( @oThisDlg:oDlg, 0, 0, ::nDlgWidth, ::nDlgHeight, cTable, { || Nil } )
   frm_Buttons( oThisDlg, .F. )

   @ 5, 70 BROWSE oBrw DATABASE SIZE oThisDlg:nDlgWidth - 10, oThisDlg:nDlgHeight - 80 STYLE WS_BORDER + WS_VSCROLL + WS_HSCROLL

   oBrw:bOther := {|oBrw, msg, wParam, lParam| fKeyDown(oBrw, msg, wParam, lParam, cField, @xValue ) }

   FOR EACH aItem IN oTBrowse
      ADD COLUMN aItem[2] TO oBrw HEADER aItem[1] LENGTH Len( Eval( aItem[2] ) ) JUSTIFY LINE DT_LEFT
   NEXT

   gui_ActivateDialog( oThisDlg:oDlg )

   IF ! Empty( xValue ) .AND. ! Empty( xControl )
      xControl:Value := xValue
   ENDIF
   SELECT ( nSelect )
   (xDlg)

   RETURN Nil

STATIC FUNCTION fKeyDown(oBrw, msg, wParam, lParam, cField, xValue )

   LOCAL nKEY

   IF msg == WM_KEYDOWN
      nKey := hwg_PtrToUlong( wParam ) //wParam
      IF nKey = VK_RETURN
         IF ! Empty( cField )
            xValue := FieldGet( FieldNum( cField, xValue ) )
         ENDIF
         hwg_EndDialog()
      ENDIF
   ENDIF
   (oBrw)
   (lParam)
#endif

   RETURN .T.
Até que o fonte não mudou muito
browse.png
Tamanho padronizado, button padronizado, cores padronizadas.
Pronto. Tudo padronizado, só falta o padrão que ainda não existe kkkk

Como é função padrão.... já temos dialog e button pra HMG Extended e OOHG, fica pendente o browse.
Não é louco isso ? fiz pra hwgui e já adiantou pras outras LIBs !!!

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 18:53
por JoséQuintas
teste.png
Isto é uma coisa que não pode esquecer.
HWGUI é objeto, MINIGUI é texto.

Código: Selecionar todos

   oThisFrm := frm_Class():New()
   oThisFrm:cOptions := ""
   oThisFrm:oDlg := "browse"
Faltou colocar um nome na dialog pra minigui.
Vai ser bom colocar algum tipo de alerta, porque posso esquecer disso.
O erro foi no button, porque não dava pra definir o PARENT dele, tava vazio.
Agora ok
browse.png
Já temos janela de browse pra HMG Extended e OOHG, só falta o browse no meio dela.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 19:08
por JoséQuintas

Código: Selecionar todos

/*
frm_browse - browse
*/

#include "frm_class.ch"

FUNCTION frm_Browse( Self, xDlg, xControl, cTable )

   LOCAL oTBrowse := {}, aItem, aField, oBrw, xValue, cField, nSelect, nPos, oThisFrm

   nSelect := Select()
   SELECT ( cTable )

   nPos := hb_Ascan( ::aAllSetup, { | e | e[1] == cTable } )
   FOR EACH aField IN ::aAllSetup[ nPos, 2 ]
      AAdd( oTBrowse, { aField[ CFG_CAPTION ], { || Transform( FieldGet(FieldNum(aField[ CFG_FNAME ])), aField[ CFG_FPICTURE ] ) } } )
      IF aField[ CFG_ISKEY ]
         cField := aField[ CFG_FNAME ]
      ENDIF
   NEXT

   oThisFrm := frm_Class():New()
   oThisFrm:cOptions := ""
   oThisFrm:oDlg := "browse"
   gui_CreateDialog( @oThisFrm:oDlg, 0, 0, ::nDlgWidth, ::nDlgHeight, cTable, { || Nil } )
   frm_Buttons( oThisFrm, .F. )

#ifdef HBMK_HAS_HWGUI
   @ 5, 70 BROWSE oBrw DATABASE SIZE oThisFrm:nDlgWidth - 10, oThisFrm:nDlgHeight - 80 STYLE WS_BORDER + WS_VSCROLL + WS_HSCROLL

   oBrw:bOther := {|oBrw, msg, wParam, lParam| fKeyDown(oBrw, msg, wParam, lParam, cField, @xValue ) }

   FOR EACH aItem IN oTBrowse
      ADD COLUMN aItem[2] TO oBrw HEADER aItem[1] LENGTH Len( Eval( aItem[2] ) ) JUSTIFY LINE DT_LEFT
   NEXT
#endif

   gui_ActivateDialog( oThisFrm:oDlg )

#ifdef HBMK_HAS_HWGUI
   IF ! Empty( xValue ) .AND. ! Empty( xControl )
      xControl:Value := xValue
   ENDIF
#endif
   SELECT ( nSelect )
   (xDlg)

   RETURN Nil

#ifdef HBMK_HAS_HWGUI
STATIC FUNCTION fKeyDown(oBrw, msg, wParam, lParam, cField, xValue )

   LOCAL nKEY

   IF msg == WM_KEYDOWN
      nKey := hwg_PtrToUlong( wParam ) //wParam
      IF nKey = VK_RETURN
         IF ! Empty( cField )
            xValue := FieldGet( FieldNum( cField, xValue ) )
         ENDIF
         hwg_EndDialog()
      ENDIF
   ENDIF
   (oBrw)
   (lParam)

   RETURN .T.
#endif
E o fonte ganhou as exceções.
Parte dele funciona em qualquer LIB, mas parte dele só em HWGUI.
Antes era inteiro da hwgui, agora só algumas partes.

Provavelmente é fazer o browse diferente pra cada LIB, passando coordenadas, array, e retorno.
Isso vai deixar esse fonte universal, apenas chamando gui_browse( row, col, width, height, array, retorno )
E cada LIB vai fazer do seu jeito.

De um modo geral, o fonte vai ficar mais simples.
O fonte não precisa saber que hwgui usa FKeyDown(), quem precisa saber disso é o browse da hwgui.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 19:35
por JoséQuintas
Uia:

Código: Selecionar todos

   gui_Browse( 70, 5, oThisFrm:nDlgWidth - 10, oThisFrm:nDlgHeight - 80, oTbrowse, cField, @xValue )
e na lib hwgui:

Código: Selecionar todos

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

   LOCAL oBrw, aItem

   @ nCol, nRow BROWSE oBrw DATABASE SIZE nWidth, nHeight STYLE WS_BORDER + WS_VSCROLL + WS_HSCROLL

   oBrw:bOther := { |oBrw, msg, wParam, lParam| fKeyDown( oBrw, msg, wParam, lParam, cField, @xValue ) }

   FOR EACH aItem IN oTBrowse
      ADD COLUMN aItem[2] TO oBrw HEADER aItem[1] LENGTH Len( Eval( aItem[2] ) ) JUSTIFY LINE DT_LEFT
   NEXT

   RETURN Nil

STATIC FUNCTION fKeyDown(oBrw, msg, wParam, lParam, cField, xValue )

   LOCAL nKEY

   IF msg == WM_KEYDOWN
      nKey := hwg_PtrToUlong( wParam ) //wParam
      IF nKey = VK_RETURN
         IF ! Empty( cField )
            xValue := FieldGet( FieldNum( cField, xValue ) )
         ENDIF
         hwg_EndDialog()
      ENDIF
   ENDIF
   (oBrw)
   (lParam)

   RETURN .T.
O fonte do browse ficou legal:

Código: Selecionar todos

/*
frm_browse - browse
*/

#include "frm_class.ch"

FUNCTION frm_Browse( Self, xDlg, xControl, cTable )

   LOCAL oTBrowse := {}, aField, xValue, cField, nSelect, nPos, oThisFrm

   nSelect := Select()
   SELECT ( cTable )

   nPos := hb_Ascan( ::aAllSetup, { | e | e[1] == cTable } )
   FOR EACH aField IN ::aAllSetup[ nPos, 2 ]
      AAdd( oTBrowse, { aField[ CFG_CAPTION ], { || Transform( FieldGet(FieldNum(aField[ CFG_FNAME ])), aField[ CFG_FPICTURE ] ) } } )
      IF aField[ CFG_ISKEY ]
         cField := aField[ CFG_FNAME ]
      ENDIF
   NEXT

   oThisFrm := frm_Class():New()
   oThisFrm:cOptions := ""
   oThisFrm:oDlg := "browse"
   gui_CreateDialog( @oThisFrm:oDlg, 0, 0, ::nDlgWidth, ::nDlgHeight, cTable, { || Nil } )
   frm_Buttons( oThisFrm, .F. )

   gui_Browse( 70, 5, oThisFrm:nDlgWidth - 10, oThisFrm:nDlgHeight - 80, oTbrowse, cField, @xValue )

   gui_ActivateDialog( oThisFrm:oDlg )

   IF ! Empty( xValue ) .AND. ! Empty( xControl )
      SetTextboxValue( xDlg, xControl, xValue )
   ENDIF

   SELECT ( nSelect )
   (xDlg)

   RETURN Nil
E o fonte pra hwgui é o que mostrei acima, vai ficar em lib_hwgui.prg
Ficou tudo mais limpo, e menos variáveis em cada um.
O que é de hwgui na hwgui, o que é do aplicativo (gerador) no aplicativo.

Usei funções que já existem pra dialog e button, e criei uma nova pra browse.

É pra estes testes, uso limitado de recursos, mas está atendendo o que precisa.
A idéia é que funcione a parte normal de um aplicativo.

Também já sei de um possível problema pra minigui:
Não poderão existir duas telas com o nome de "browse" ativas ao mesmo tempo.
Já sei disso, mas não é importante no momento, porque por enquanto isso não acontece.
Talvez uma variável na classe como CLASSVAR começando no zero, e no New() ir somando um, e usar isso no nome... mas vejo depois. Só preciso lembrar quando acontecer o erro de janela já existente.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 19:40
por Itamar M. Lins Jr.
Olá!
Vc vai fazendo isso o Ron Pinkas liberou a xIDE e vamos indo... No final ficou tudo como era para ter ficado.
Quer dizer atrasou o mundo Harbour em uns 13 anos ? quem sabe ?
Pq poderia está tudo unificado mas cada um puxa daqui e dali e vamos vivendo.
No final o Open Source vence e vencerá sempre.
O dinheiro que cada um ganhou, poderia ter ganho muito mais... Consultoria vale muito mais que códigos e mais códigos.

Saudações,
Itamar M. Lins Jr.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 19:47
por JoséQuintas
Mais fácil ainda pra isso de dialog.
Lembram? Dialog recebe variável por referência.

Código: Selecionar todos

FUNCTION gui_CreateDialog( xDlg, nRow, nCol, nWidth, nHeight, cTitle, bAction )

   STATIC nNumDialog := 1

   IF Empty( xDlg )
      xDlg := "Dialog" + StrZero( nNumDialog, 4 )
      nNumDialog += 1
   ENDIF

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

   RETURN Nil
Pronto.
Acabou o problema de nome repetido em dialog.
Também acabou o problema de esquecer de colocar nome, nem precisa mais nome.

E vamos extender isso a buttons, labels, textbox, e tudo mais.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 20:27
por JoséQuintas
Tudo certo.
Nada mais precisa de nome.
Por precaução deixei como StrZero(x,10).
Usar a ponto de precisar mais de 10 bilhões de controles durante o uso vai ser difícil.
Mas 10.000 era pouco.
Clientes, 30 campos, textbox e label e extra pode subir pra 90, mais buttons, etc. 100
Abre e fecha 100 vezes por dia, pronto 10.000

Já pensaram o quanto isso também pode movimentar imagens?
Esquecer de destruir imagens pode ser uma catástrofe.
Quando o Windows não faz, a LIB precisa fazer, e quando a LIB não faz, é o programador.
Carregar imagem do disco não altera isso, pelo contrário, pode até piorar.
Não tinha pensado nisso, mas pode derrubar um aplicativo, além de comprometer muita memória.
É, porque se não destruir, vai acumulando cada vez mais memória em uso.
A otimização do Windows vale pra resource, não pra arquivo em disco.
E depende da LIB, mas tem uma opção LR_SHARED onde o Windows não precisa carregar uma imagem já existente, e já descarta as fora de uso.

O negócio de GUI é complicado.
Muita coisa acontece além do que estamos vendo na tela.

Gerador/criação de telas/executor

Enviado: 16 Ago 2023 21:52
por JoséQuintas
Itamar M. Lins Jr. escreveu:Vc vai fazendo isso o Ron Pinkas liberou a xIDE e vamos indo... No final ficou tudo como era para ter ficado.
Quer dizer atrasou o mundo Harbour em uns 13 anos ? quem sabe ?
Pq poderia está tudo unificado mas cada um puxa daqui e dali e vamos vivendo.
No final o Open Source vence e vencerá sempre.
O dinheiro que cada um ganhou, poderia ter ganho muito mais... Consultoria vale muito mais que códigos e mais códigos.
Sabe a parte mais legal disso que estou fazendo?
O Harbour vém se dividindo em grupos cada vez menores...
E isso está mostrando que os grupos podem ficar juntos.

hwgui com classe, minigui sem classe, estou usando as LIBs originais sem alterações.

Open Source.... depende de alguém que mexa, não adianta fontes se não souber mexer.

O editor de textos que eu uso, tá tudo lá em Open Source.
Mas quem vai mexer?
Vai ser usar enquanto der.