Página 1 de 1

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 18 Ago 2025 16:31
por JoséQuintas

Código: Selecionar todos

/*
h_HmgApp
*/

#include "hbclass.ch"

MEMVAR _HMG_SYSDATA

THREAD STATIC oApp

INIT PROCEDURE Init_oApp

   oApp := _hmg_AppClass():New()

   RETURN

CREATE CLASS _Hmg_AppClass

   VAR aList INIT {}
   METHOD AddItem( xValue )
   METHOD GetItemFromName( xValue )
   METHOD GetItemFromHandle( xValue )
   METHOD DelItem( xValue )

   ENDCLASS

METHOD AddItem( xValue ) CLASS _Hmg_AppClass

   LOCAL nIndex

   AAdd( ::aList, _hmg_ObjClass():New() )
   nIndex := Len( ::aList )
   ::aList[ nIndex ]:Name := xValue

   RETURN ::aList[ nIndex ]

METHOD GetItemFromName( xValue ) CLASS _hmg_AppClass

   LOCAL nIndex

   nIndex := hb_ASCan( ::aList, { | e | e:Name == xValue } )
   IF nIndex != 0
      RETURN ::aList[ nIndex ]
   ENDIF

   RETURN Nil

METHOD GetItemFromHandle( xValue ) CLASS _hmg_AppClass

   LOCAL nIndex

   nIndex := hb_ASCan( ::aList, { | e | e:Handle == xValue } )
   IF nIndex != 0
      RETURN ::aList[ nIndex ]
   ENDIF

   RETURN Nil

METHOD DelItem( xValue ) CLASS _hmg_AppClass

   LOCAL nIndex

   nIndex := hb_ASCan( ::aList, { | e | e:Name == xValue } )
   IF nIndex == 0 .OR. ValType( ::aList[ nIndex ] ) != "O"
      MsgInfo( "Can't remove " + xValue )
   ELSE
      ::aList[ nIndex ]:Destroy()
   ENDIF

   RETURN Nil

CREATE CLASS _hmg_ObjClass

   VAR _nIndex  INIT 0

   METHOD SetGet( xKey, xValue )
   METHOD Destroy() INLINE Nil
   METHOD Index( xValue )  INLINE ::SetGet( @::_nIndex, xValue )
   METHOD Name( xValue )   INLINE ::SetGet( @_HMG_SYSDATA[ 66, ::_nIndex ], xValue )
   METHOD Handle( xValue ) INLINE ::SetGet( @_HMG_SYSDATA[ 67, ::_nIndex ], xValue )
   METHOD Type( xValue )   INLINE ::SetGet( @_HMG_SYSDATA[ 69, ::_nIndex ], xValue )

   ENDCLASS

METHOD SetGet( xKey, xValue ) CLASS _hmg_ObjClass

   IF xValue != Nil
      xKey := xValue
   ENDIF

   RETURN xKey
Esta parte:

Código: Selecionar todos

   METHOD Index( xValue )  INLINE ::SetGet( @::_nIndex, xValue )
   METHOD Name( xValue )   INLINE ::SetGet( @_HMG_SYSDATA[ 66, ::nIndex ], xValue )
   METHOD Handle( xValue ) INLINE ::SetGet( @_HMG_SYSDATA[ 67, ::nIndex ], xValue )
   METHOD Type( xValue )   INLINE ::SetGet( @_HMG_SYSDATA[ 69, ::nIndex ], xValue )
Não sei como definir SETGET e INLINE ao mesmo tempo.
Seria susbtituir isto:

Código: Selecionar todos

		_HMG_SYSDATA [ 66 ]  [k] := FormName 
		_HMG_SYSDATA [ 67 ]  [k] := FormHandle 
		_HMG_SYSDATA [ 69 ]  [k] := cType
por isto:

Código: Selecionar todos

oForm:Name := FormName
oForm:Handle := FormHandle
oForm:Type := cType
Isso deixa compatível até terminar as mudanças, que podem demorar muito.
No final, seria substituir o array por variáveis da classe, o que pode até ser simultâneo antigo/novo ao mesmo tempo.
OOP sem mexer no controle central de tudo.

Nota:
Eu já disse por aqui, tem horas que parece mais fácil mexer nos fontes da LIB do que desenvolver com a LIB.
Se eu tiver que fazer uma tela em HMG Extended eu apanho.
Isso, de transformar em objetos parece mais simples - muito demorado pra fazer tudo, mas mais simples.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 18 Ago 2025 18:22
por JoséQuintas
O que me parece agora:

_HMG_SYSDATA é a variável pública com tudo.
Digamos assim, cada nova variável que a HMG precisa, é adicionada uma nova coluna a esse array.
De certa forma, é o que fazemos com classes, a diferença é que está tudo nesse array público.
O array é multidimensional.
Compare com uma tabela, pode ficar mais fácil de entender.
&nbspindex&nbsp&nbspnome&nbsp&nbsphandle&nbsp&nbspsetfocus&nbsp
&nbsp1&nbsp&nbspmain&nbsp&nbsph3ED&nbsp&nbsp&nbsp
&nbsp2&nbsp&nbspclientes&nbsp&nbspjfgfht&nbsp&nbsp&nbsp
Acima criei duas classes: uma representa as linhas dessa tabela, cada controle.
A outra representa o controle da linha, direcionando o nome pra coluna

Ou seja, passam a ser usadas como classes nos fontes, mas trabalham com a mesma tabela.

Qual a vantagem ?

É uma transformação sem limite de tempo.
Pode alterar qualquer coisa a qualquer momento.
Compatibilidade total, já que é sempre a mesma _HMG_SYSDATA.
O tempo mostrará o que poderá ser melhorado, mas pode continuar tudo passando por uma mesma classe.

Será que não pensaram nisso ?
Às vezes não, porque quem trabalha com C pode não estar habituado com possibilidades do harbour, é difícil mas não impossível.
E às vezes, um programador de alto nível pode pensar só em soluções de alto nível, deixando de considerar alternativas simples.
E entre uma solução definitiva, e alternativas possíveis, existe muita coisa no meio, que cada um pode enxergar uma possibilidade diferente.
Lembrando que posso estar errado: pode ser que não se aplica a tudo, ou pode ser que entendi tudo errado.

Uma vez tudo passando pela classe, só alterar a classe pra forma definitiva, sem mexer mais nos outros fontes.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 18 Ago 2025 21:15
por JoséQuintas
Tem estes casos também

Código: Selecionar todos

         _HMG_SYSDATA [ 271 ] := .F.   // _HMG_IsModalActive
         _HMG_SYSDATA [ 167 ] := 0     // _HMG_ActiveModalHandle
esses ficariam na classe principal.

Código: Selecionar todos

oHmgApp():IsModalActive  := .F.
oHmgApp():ActiveModalHandle := 0
E na classe principal mesmo estilo:

Código: Selecionar todos

METHOD IsModalActive( xValue ) INLINE ::SetGet( @_HMG_SYSDATA[ 271 ], xValue )
METHOD ActiveModalHandle( xValue ) INLINE ::SetGet( @_HMG_SYSDATA[ 167 ], xValue )
Estou avaliando, porque chega em partes como esta.... muito mais trabalho envolvido.

Código: Selecionar todos

Function GetWindowDataByIndex (k)
*-----------------------------------------------------------------------------*
LOCAL aWinData := {}
      AADD ( aWinData, _HMG_SYSDATA [ 66 ]  [k] )   // FormName
      AADD ( aWinData, _HMG_SYSDATA [ 67 ]  [k] )   // FormHandle
      AADD ( aWinData, _HMG_SYSDATA [ 68 ]  [k] )   // .f.
      AADD ( aWinData, _HMG_SYSDATA [ 69 ]  [k] )   // cType
      AADD ( aWinData, _HMG_SYSDATA [ 70 ]  [k] )   // If ( panel , Parenthandle , 0 )
      AADD ( aWinData, _HMG_SYSDATA [ 71 ]  [k] )   // ReleaseProcedure
      AADD ( aWinData, _HMG_SYSDATA [ 72 ]  [k] )   // InitProcedure
Aqui é criado outro array, com numeração totalmente diferente.
Tudo bem, a rotina acaba nem mais sendo necessária, porque dá pra pegar direto da classe
Mas.... precisa ajustar os fontes que chamam essa função.

É como eu disse: é um trabalho demorado.
É ir "catando milho" pelos fontes, e alterar um elemento de cada vez.
No caso desta rotina, envolve outras.

Alterar direto... ferrou... nesse esquema de compatibilidade que mostrei... talvez melhor.

E uma alteração dessas, não dá pra ficar de fora dos fontes oficiais, porque qualquer alteração na oficial pode invalidar todo trabalho.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 19 Ago 2025 09:23
por Ana Mitoooo
A criação de uma classe OOP para a hmg3 seria diferente da implementação usada na oohg ?
hmg3 tem algum controle a mais que oohg ?

Os comandos nessa tela oohg me parecem idênticos a hmg3
Imagem

*Ainda não fiz testes com oohg

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 19 Ago 2025 10:38
por JoséQuintas
Não faço a menor idéia e não interessa no momento.
Compare os fontes
Antes de alterar

Código: Selecionar todos

*--------------------------------------------------------------------*
Function GetSplitChildWindowHandle (cFormName, cParentForm)
*--------------------------------------------------------------------*
LOCAL i, hWnd := GetFormHandle (cParentForm)
   FOR i = 1 TO HMG_LEN (_HMG_SYSDATA [ 66 ])
       IF (_HMG_SYSDATA [ 66 ] [i] == cFormName) .AND. (_HMG_SYSDATA [ 69 ] [i] ==  'X') .AND. (_HMG_SYSDATA [ 70 ]  [i] == hWnd) 
           Return _HMG_SYSDATA [ 67] [i]
       ENDIF
   NEXT
Return 0
Depois de alterar

Código: Selecionar todos

FUNCTION GetSplitChildWindowHandle (cFormName, cParentForm)

   LOCAL oForm, hWnd := GetFormHandle (cParentForm)
   
   FOR EACH oForm IN oHmgApp():aList
       IF oForm:Name == cFormName .AND. oForm:Type ==  'X' .AND. oForm:ParentHandle == hWnd
           RETURN oForm:Handle
       ENDIF
   NEXT

   RETURN 0
É disso que estou falando.
Alterando interno, aí fica disponível pra qualquer fonte.
É só o começo ainda.
Estou alterando o 66 = NAME

Só pra efeito DESSE BLOCO, alterei também
66 = NAME
67 = HANDLE
69 = TYPE
70 = PARENTHANDLE

Mas tem que alterar um número de cada vez, em todos os fontes.
São mais de 500 números.
Só depois vém as funções.

Mais de 500 números, usados pelo menos 20 vezes.... isso dá 10.000 alterações
Depois vém os métodos... talvez mais 50.000 alterações.

Quer saber como vai ficar depois de 60.000 alterações ?

Se continuar funcionando já vai estar muito bom.....
Se eu não desistir antes de acabar também já vai estar muito bom...
Daí pra frente... é pra se ver depois.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 19 Ago 2025 14:22
por JoséQuintas
Então.....
Essas coisas acontecem.....
hmg3.png
Por descuido, estava alterando hmg3 e testando hmg extended.

Joguei todas as alterações fora.
O pior disso, é que original também não funciona.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 19 Ago 2025 15:24
por Ana Mitoooo
Mudar _HMG_SYSDATA para hash seria opção (intenção de melhorar a legibilidade) ?

Código: Selecionar todos

*--------------------------------------------------------------------*
Function GetSplitChildWindowHandle (cFormName, cParentForm)
*--------------------------------------------------------------------*
LOCAL i, hWnd := GetFormHandle (cParentForm)

   FOR i = 1 TO HMG_LEN (_HMG_SYSDATA [ 'cFormName' ])

       IF (_HMG_SYSDATA [ 'cFormName' ] [i] == cFormName) .AND. (_HMG_SYSDATA [ 69 ] [i] ==  'X') .AND. (_HMG_SYSDATA [ 70 ]  [i] == hWnd) 
           Return _HMG_SYSDATA [ 67] [i]
       ENDIF

   NEXT

Return 0

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 20 Ago 2025 11:20
por JoséQuintas
Hash não vai mudar nada, só vai piorar as coisas.
Quanto mais alternativas pior, mais difícil consertar depois.
HMG Extended acho que vai ser difícil refazer, por tantas opções alternativas que foram criadas e ainda são mantidas.
Manter compatibilidade com tudo que inventaram torna tudo cada vez mais difícil de alterar.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 20 Ago 2025 12:42
por JoséQuintas
Olhe este bloco, ok, está parcialmente alterado:

Código: Selecionar todos

    For i := 1 To oHmgApp():FormCount
        If _HMG_SYSDATA [ 65 ] [i] == .F.
            If _HMG_SYSDATA [ 69  ] [i] != 'X'
                If oHmgApp():FormByIndex( i ):Handle != ModalHandle
                    DisableWindow ( oHmgApp():FormByIndex( i ):Handle )
                EndIf
            EndIf
        EndIf
    Next i
Com hash:

Código: Selecionar todos

    For i := 1 To Len( _HMG_SYSDATA[ "form_name" ] )
        If ! _HMG_SYSDATA [ "form_deleted" ] [i] 
         IF _HMG_SYSDATA [ "form_handle"  ] [i] != 'X' 
         IF _HMG_SYSDATA[ "form_handle", i ) != ModalHandle
                    DisableWindow ( _HMG_SYSDATA[ "form_handle", i ] )
                EndIf
            EndIf
        EndIf
    Next i
Agora totalmente alterado com classe:

Código: Selecionar todos

FOR EACH oForm IN oHmgApp():aList
   IF ! oForm:Deleted .AND. oForm:Type != "X" .AND. oForm:Handle != ModalHandle 
      DisableWindow( oForm:Handle )
   ENDIF
NEXT
Sinceramente
Qual deles tem mais chances de erro ?
Qual deles tá mais fácil de fazer manutenção para os próximos anos ?
Multiplique isso por centenas de vezes nos fontes.

E considere que isso pode se multiplicar nos fontes dos usuários.

Nisso também dá pra perceber que conforme a mudança vai acontecendo, dá pra melhorar os fontes ainda mais.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 20 Ago 2025 18:32
por Ana Mitoooo
Sem dúvida que o Array da forma que está, precisa a todo tempo consultar a tabela de referencia dos elementos (saber sua função).

Mudar _HMG_SYSDATA para Hash vai quebrar compatibilidade com qualquer código de usuário que utilize o Array diretamente.
Mudar _HMG_SYSDATA para Static idem, pois muda a forma de acesso ao Array.

Essa nova codificação sem dúvida mantêm a compatibilidade sem gerar novos problemas, com o bônus de facilitar em muito a leitura dos fontes.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 21 Ago 2025 13:11
por JoséQuintas
erro.png
Isto mostra que as alterações estão surtindo efeito.

O erro era esperado.

Hoje achei melhor alterar form:Active pra form:IsActive.
Esqueci de alterar na classe, então deu falta.

Também alterei form:Deleted pra form:IsDeleted

O importante do erro é: é erro esperado, fácil de resolver, só alterar o nome.

Por isso seria interessante vários usuários pra testar, encima de aplicativos prontos.
Pra usar o máximo de opções possíveis.
Seria só compilar e rodar o aplicativo, nada mais, sem mexer em fontes.

Uma alteração recente é mais fácil de localizar.
Em caso extremo, só anular a alteração recente e fazer de novo.

Precisa muuuito cuidado.
Estou encontrando possíveis bugs, mas nem estou mexendo nisso ainda.
Considerando que, se estão usando, o bug não é problema.

Numa determinada rotina, testa se GraphTasks é array, mas em outras não tem esse teste.
Provavelmente em algum tempo deu erro, e corrigiram só a parte que deu erro.

Mas uma vez isso na classe, depois dá pra colocar a validação na classe, e limpar todos os testes de outros fontes.

Uma idéia de como isso vai longe, oForm é onde já alterei

Código: Selecionar todos

         oForm := oHmgApp():FormByIndex( i )
			oForm:IsDeleted := .T.
			oForm:Handle := 0
			oForm:Name := ""
			oForm:IsActive := .f.
			oForm:Type := ""
			oForm:ParentHandle := 0
			_HMG_SYSDATA [ 72 ] [i]	:= ""
			oForm:ReleaseProcedure := ""
			_HMG_SYSDATA [ 73 ] [i]	:= 0
			_HMG_SYSDATA [ 74 ] [i]	:= 0
			_HMG_SYSDATA [ 75 ] [i]	:= ""
			_HMG_SYSDATA [ 76 ] [i]	:= ""
			_HMG_SYSDATA [ 77 ] [i]	:= ""
			_HMG_SYSDATA [ 78 ] [i]	:= ""
         _HMG_SYSDATA [ 79 ] [I]	:= Nil
			_HMG_SYSDATA [ 80 ] [i]	:= ""
			_HMG_SYSDATA [ 81 ] [i]	:= .F.
			oForm:NotifyIconName := ''
			_HMG_SYSDATA [ 83 ] [i] := ''
			_HMG_SYSDATA [ 84 ] [i] := ''
			_HMG_SYSDATA [ 87 ] [i] := 0
			_HMG_SYSDATA [ 88 ] [I] := 0
			_HMG_SYSDATA [ 89 ] [i] := {}
			_HMG_SYSDATA [ 90 ] [i] := {}
			oForm:VirtualHeight := 0
			_HMG_SYSDATA [ 85 ] [i] := ""
			_HMG_SYSDATA [ 86 ] [i] := ""
			oForm:VirtualWidth := 0
			_HMG_SYSDATA [ 93 ] [i] := .f.
			_HMG_SYSDATA [ 94 ] [i] := ""
			_HMG_SYSDATA [ 95 ] [i] := ""
			_HMG_SYSDATA [ 96 ] [i] := ""
			_HMG_SYSDATA [ 97 ] [i] := ""
			_HMG_SYSDATA [ 98 ] [i] := ""
			_HMG_SYSDATA [ 99 ] [i] := ""
			_HMG_SYSDATA [ 100 ] [i] := 0
			_HMG_SYSDATA [ 101 ] [i] := 0
			oForm:GraphTasks := {}
			_HMG_SYSDATA [ 103 ] [i] := Nil
			_HMG_SYSDATA [ 104 ] [i] := Nil
			oForm:AutoRelease := .F.
			_HMG_SYSDATA [ 106 ] [i] := ""
			_HMG_SYSDATA [ 107 ] [i] := 0
			_HMG_SYSDATA [ 108 ] [i] := NIL
         _HMG_SYSDATA [ 504 ] [i] := { NIL, NIL, NIL, NIL}
         _HMG_SYSDATA [ 511 ] [i] := 0
         _HMG_SYSDATA [ 512 ] [i] := { NIL, NIL, NIL, NIL, NIL, NIL, NIL }
e deixando este pra depois

Código: Selecionar todos

      oHmgApp():AddForm( oHmgApp():FormCount + 1 )

		aAdd ( _HMG_SYSDATA [ 66 ]	, FormName ) // don't change
		aAdd ( _HMG_SYSDATA [ 67 ]	, FormHandle )
		aAdd ( _HMG_SYSDATA [ 68 ]	, .f. )
		aAdd ( _HMG_SYSDATA [ 69 ]	, cType )
		aAdd ( _HMG_SYSDATA [ 70 ]	, If ( panel , Parenthandle , 0 ) )
		aAdd ( _HMG_SYSDATA [ 71 ]	, ReleaseProcedure )
		aAdd ( _HMG_SYSDATA [ 72 ]	, InitProcedure )
		aAdd ( _HMG_SYSDATA [ 73 ]	, htooltip )
		aAdd ( _HMG_SYSDATA [ 74 ]	, 0 )
		aAdd ( _HMG_SYSDATA [ 75 ]	, MouseDragProcedure )
		aAdd ( _HMG_SYSDATA [ 76 ]	, SizeProcedure )
		aAdd ( _HMG_SYSDATA [ 77 ]	, ClickProcedure )
		aAdd ( _HMG_SYSDATA [ 78 ]	, MouseMoveProcedure )
		aAdd ( _HMG_SYSDATA [ 65 ]	, .f. )
		aAdd ( _HMG_SYSDATA [ 79 ]	, aRGB )
		aAdd ( _HMG_SYSDATA [ 80 ]	, PaintProcedure )
		aAdd ( _HMG_SYSDATA [ 81 ]	, noshow )
		aAdd ( _HMG_SYSDATA [ 82 ]	, NotifyIconName 	)
		aAdd ( _HMG_SYSDATA [ 83 ]	, NotifyIconToolTip 	)
		aAdd ( _HMG_SYSDATA [ 84 ]	, NotifyIconLeftClick 	)
		aAdd ( _HMG_SYSDATA [ 85 ]	, GotFocus )
		aAdd ( _HMG_SYSDATA [ 86 ]	, LostFocus )
		aAdd ( _HMG_SYSDATA [ 87 ]	, 0 )
		aAdd ( _HMG_SYSDATA [ 88 ]	, 0 )
		aAdd ( _HMG_SYSDATA [ 89 ]	, {} )
		aAdd ( _HMG_SYSDATA [ 90 ]	, {} )
		aAdd ( _HMG_SYSDATA [ 91 ]	, VirtualHeight )
		aAdd ( _HMG_SYSDATA [ 92 ]	, VirtualWidth )
		aAdd ( _HMG_SYSDATA [ 93 ]	, .f. )
		aAdd ( _HMG_SYSDATA [ 94 ]	, ScrollUp )
		aAdd ( _HMG_SYSDATA [ 95 ]	, ScrollDown )
		aAdd ( _HMG_SYSDATA [ 96 ]	, ScrollLeft )
		aAdd ( _HMG_SYSDATA [ 97 ]	, ScrollRight )
		aAdd ( _HMG_SYSDATA [ 98 ]	, HScrollBox )
		aAdd ( _HMG_SYSDATA [ 99 ]	, VScrollBox )
		aAdd ( _HMG_SYSDATA [ 100 ]	, BrushHandle )
		aAdd ( _HMG_SYSDATA [ 101 ]	, 0 )
		aAdd ( _HMG_SYSDATA [ 102 ]	, {} )
		aAdd ( _HMG_SYSDATA [ 103 ]	, MaximizeProcedure )
		aAdd ( _HMG_SYSDATA [ 104 ]	, MinimizeProcedure )
		aAdd ( _HMG_SYSDATA [ 105 ]	, .Not. NoAutoRelease )
		aAdd ( _HMG_SYSDATA [ 106 ]	, InteractiveCloseProcedure )
		aAdd ( _HMG_SYSDATA [ 107 ]	, 0 )
		aAdd ( _HMG_SYSDATA [ 108 ]	, NIL )
      aAdd ( _HMG_SYSDATA [ 504 ]   , {x, y, w, h})
      aAdd ( _HMG_SYSDATA [ 511 ] , hWnd_ToolTip )
      aAdd ( _HMG_SYSDATA [ 512 ] , { NIL, NIL, NIL, NIL, NIL, NIL, NIL } )
Parece igual, mas não é.
O primeiro apenas atribui valor ao que já existe.
O segundo adiciona elemento em cada array, são variáveis diferentes adicionando elemento que não existe.
Tem isso pelo menos 3 vezes em forms, o if/else adicionando ou não.

Talvez mover pra classe pra adicionar elementos, mas precisa ser com conteúdo válido, mesmo que "vazio"
zero aonde número, {} aonde array, "" aonde string, etc.

Pois é... mais de 500 elementos, pra alterar um por um em todo fonte....
Tem que ser um por vez, senão os nomes começam a se bagunçar na cabeça.

Vai fazer o 67 handle... é procurar 67 em todos os fontes.
é procurar em todos os fontes, alterar, procurar de novo, alterar, procurar de novo... sempre passa algum.

E depois que terminar... não significa que terminou... podem ter rotinas dependentes do SYSDATA ainda.

Nessa primeira fase de mudança, tanto faz, tá sempre compatível.
Só nos blocos acima poderão ser meses pra mexer.

Se fosse mudar pra HASH... vixe... já acabaria toda compatibilidade logo na primeira alteração.


Entendeu ?
É alterar uma coisa em qualquer fonte, e continuar usando.
Não tem nenhum tempo de espera pra usar minigui alterada.
Tudo correndo bem, ninguém nem vai notar diferença.
A qualquer momento pode parar ou continuar as alterações, não perde nada, tá tudo sempre rodando.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 21 Ago 2025 19:09
por JoséQuintas
change.png
E olhando assim, dá até pra agilizar.
Tá procurando um form com essas características...
Pra isso existe AScan()

Código: Selecionar todos

nPos := hb_AScan( oHmgApp():AllForms(),
   { | e | e:Name == cFormName .AND. e:Type == "X" .AND. e:ParentHandle == hWnd } )
IF nPos != 0
   RETURN oHmgApp():FormByIndex( nPos ):Handle 
ENDIF
RETURN 0
Deve agilizar a velocidade.

Não parece, mas cada informação dessas está num array em _HMG_SYSDATA.
O fonte nem sabe mais que _HMG_SYSDATA existe, quando sumir - esse é o objetivo - nem vai sentir falta.

Só uma idéia que veio na cabeça pra OOP na HMG3

Enviado: 21 Ago 2025 19:27
por JoséQuintas
É incrível.
Variáveis da classe App

Código: Selecionar todos

CREATE CLASS _HmgAppClass STATIC

   VAR aFormList INIT {}
Variáveis da classe do form

Código: Selecionar todos

CREATE CLASS _HmgFormClass

   VAR    _nIndex                   INIT 0
É só isso.
O array tem todos os forms, todos os forms disponíveis em uma única variável.
E no form, tem o Index, toda informação dos forms disponíveis a partir do Index.

E pelos métodos acessa todos os detalhes, de toda a HMG.
Mas por enquanto só dos forms.

Depois... futuramente.... acabar com HMG_SYSDATA, e acrescentar maismétodos pro form, como activate() por exemplo.
Aliás... dá pra fazer a qualquer momento. oForm:Activate(), é só questão de colocar lá.

É engraçado... praticamente quase nada pronto, ao mesmo tempo que está tudo pronto.
É só questão de trabalho braçal mesmo.