Mudando FWFormStruct em tempo de execução

oi pessoal, é possivel mexer no FWFormStruct antes de abrir a tela ? digamos que eu faça uma pergunta ao usuario antes de abrir a tela de inserçao pedindo o tipo de lancamento, e conforme o tipo de lancamento eu mostro determinados campos na tela, digamos que eu tenha os campos: codigo, descrição da fruta, descrição da sobremesa, quando eu mandar inserir eu peço o tipo de descrição se eu escolher fruta o sistema mostra apenas o codigo e o campo descrição da fruta, nem mostra o campo descrição da sobremesa.

seria algo com se eu estivesse testando dentro do modeldef a situação a seguir

If nOpc == MODEL_OPERATION_INSERT -- monto o struct conforme resposta da pergunta

nao sei se ficou claro mas quero abrir meu formulario limitando a exibição de campos em determinadas situações. (nao é desabilitar, é nao mostrar mesmo)

em segundos d

Olá.

Segue solução que eu uso e me atende bem.

Crie uma User Function para realizar a chamada de sua view, utilizando a função FwExecView.

Chame essa User Function no MenuDef do seu programa, na opção desejada (incluir, alterar, etc). Exemplo:


User Function ESTM09HS
Local aButtons  As Array

    aButtons := {{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.T.,Nil},{.T.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil}}

    FwExecView('HISTÓRICO', 'ELESTM09', MODEL_OPERATION_VIEW, , { || .T. } , , , aButtons)

Return

No modelo, utilizando a função FwIsInCallStack, verifique se a User Function está na stack de chamadas (isso é, o modelo foi chamado por a view aberta dentro dessa User Function), e faça as alterações desejadas na estrutura dos campos:


If(FwIsInCallStack('U_ESTM09HS'))

     oStructDsp:AddField('', '', 'ZDR_MRK', 'L', 01, 0, Nil, Nil, Nil, Nil, { || .F. }, Nil, Nil, .T.)
     oStructLin:AddField('', '', 'ZDR_MRK', 'L', 01, 0, Nil, Nil, Nil, Nil, { || .F. }, Nil, Nil, .T.)

     oStructDsp:SetProperty('*', MODEL_FIELD_OBRIGAT, .F.)
     oStructLin:SetProperty('*', MODEL_FIELD_OBRIGAT, .F.)

EndIf

Outra solução, caso não for possível trabalhar apenas com a FwIsInCallStack, é criar variáveis Private dentro da User Function e utilizar elas dentro do modelo, só tendo cuidado para verificar a existência delas antes da utilização para evitar error log caso o modelo seja chamado por outras rotinas.

Exemplo:


User Function ESTM09HS
Local aButtons            as Array
Private lObrigAll        as Logical // variável Private que será usada dentro do modelo

    aButtons := {{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.T.,Nil},{.T.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil},{.F.,Nil}}

    lObrigAll := MsgYesNo('Tornar todos os campos obrigatórios?')

    FwExecView('HISTÓRICO', 'ELESTM09', MODEL_OPERATION_VIEW, , { || .T. } , , , aButtons)

Return

No modelo:


If(Type('lObrigAll') == 'L' .and. lObrigAll) // verifico se a variável existe antes de utilizar

     oStructDsp:SetProperty('*', MODEL_FIELD_OBRIGAT, .T.)
     oStructLin:SetProperty('*', MODEL_FIELD_OBRIGAT, .T.)

Else

     oStructDsp:SetProperty('*', MODEL_FIELD_OBRIGAT, .F.)
     oStructLin:SetProperty('*', MODEL_FIELD_OBRIGAT, .F.)

EndIf

Documentações:

FwExecView: https://tdn.totvs.com/display/public/framework/FWExecView

FwIsInCallStack: https://tdn.totvs.com/display/public/framework/FWIsInCallStack

Olá!

Talvez seja mais interessante você ter dois modelos, uma para cada caso, e usar a função FwExecView para instanciar o modelo correto de acordo com os seus parâmetros.