No artigo de hoje, vamos demonstrar em como criar uma tela direto pelo programa inicial.
Pessoal, duas observações antes de iniciar o artigo:
- Para esse exemplo, é necessário baixar a zLogin (função que abre uma dialog para fazer login no Protheus) disponível em – https://terminaldeinformacao.com/2016/03/15/tela-de-autenticacao-customizada-protheus/
- Foi utilizado a classe MsNewGetDados apenas como exemplo, ela esta descontinuada, tente utilizar classes mais novas
No Protheus, nós temos dois tipos principais de janelas, as dialogs (TDialog, MsDialog, etc), e a janela principal (TWindow). A grande diferença delas, é que essa segunda se comporta como uma janela padrão do sistema operacional, ou seja com botões como maiximizar e minimizar.
Já a primeira, ela até pode ser aberta no programa inicial, mas existem algumas limitações.
Pensando nisso, construimos um fonte de exemplo para demonstrar em que, se o Protheus foi aberto a função direto no programa inicial (com u_zTstTela), ele usará a TWindow, agora se foi dentro do sistema usará a TDialog.
Em ambas usando os mesmos componentes e mesmo comportamento. Abaixo um gif demonstrando a abertura direto pelo programa inicial:
E abaixo o código fonte desenvolvido:
//Bibliotecas #Include "TOTVS.ch" /*/{Protheus.doc} User Function zTstTela Tela de exemplo sendo possível acionar no programa inicial @type Function @author Atilio @since 10/05/2022 /*/ User Function zTstTela() Local lContinua := .T. Local cEmprAux := "99" Local cFilAux := "" Private cUsrAux := "" Private cPswAux := "" Private lProgInic := .F. //Se a SX2 não tiver aberta, quer dizer que não veio pelo Protheus, logo é quiosque If Select("SX2")==0 //Montando uma seção, apenas para poder pegar os parâmetros da SX61 RPCSetEnv(cEmprAux, "", "", "", "") //Verificando se o login deu certo If u_zLogin(@cUsrAux, @cPswAux) RPCSetEnv(cEmprAux, cFilAux, cUsrAux, cPswAux, "SIGAEST") lContinua := .T. lProgInic := .T. Else lContinua := .F. EndIf EndIf If lContinua fMontaTela() EndIf Return Static Function fMontaTela() Local nLinObj := 0 Local nLargBtn := 85 Local nAltuBtn := 15 //Blocos de código chamados pelos botões Local bConfirm := {|| RptStatus({|| FWAlertInfo("Em Construção", "Atenção")}, "Processando Registros...", "Aguarde...")} Local bCancela := {|| fCancelar()} //Fontes Private cFontPad := "Tahoma" Private oFontBtn := TFont():New(cFontPad, , -14) Private oFontBtnN := TFont():New(cFontPad, , -14, , .T.) Private oFontMod := TFont():New(cFontPad, , -38) Private oFontMaior := TFont():New(cFontPad, , -68) Private oFontSub := TFont():New(cFontPad, , -20) //Objetos da Janela Private lCentered Private oBtConfirm Private oBtCancela Private oSayTitulo, cSayTitulo := 'Tela de Testes' Private oSayEtiqus, cSayEtiqus := '000' Private oDlgCentral //Tamanho da janela Private aTamanho Private nJanLarg Private nJanAltu Private nPosTop Private nPosLeft //Etiqueta Private cEspacProd := Space(TamSX3("B1_COD")[1]) Private oGetProdut Private cGetProdut := cEspacProd Private oGetBlank Private cGetBlank := "" //Grid Private oGridPro Private aHeaderPro := {} Private aColsPro := {} //Se vier do programa inicial, a dimensão será diferente If lProgInic aTamanho := GetScreenRes() nJanLarg := aTamanho[1] nJanAltu := aTamanho[2] - 80 lCentered := .F. nPosTop := 0 nPosLeft := -10 Else aTamanho := MsAdvSize() nJanLarg := aTamanho[5] nJanAltu := aTamanho[6] lCentered := .T. nPosTop := 0 nPosLeft := 0 EndIf //Cria o cabeçalho da grid // Titulo Campo Picture Tamanho Dec Valid Usado Tipo F3 aAdd(aHeaderPro, {"Produto", "XX_PROD", "", 15, 0, ".F.", ".F.", "C", "", ""} ) aAdd(aHeaderPro, {"Descrição", "XX_DESC", "", 30, 0, ".F.", ".F.", "C", "", ""} ) aAdd(aHeaderPro, {"SB1 RecNo", "XX_RECNUM", "@E 999,999,999,999,999,999", 18, 0, ".F.", ".F.", "N", "", ""} ) aAdd(aHeaderPro, {" ", "XX_BLANK", "", 01, 0, ".F.", ".F.", "C", "", ""} ) //Cria a janela If lProgInic oDlgCentral := TWindow():New(nPosTop, nPosLeft, nJanAltu, nJanLarg, cSayTitulo, , , , , , , , CLR_BLACK, RGB(250, 250, 250), , , , , , , .T.) Else oDlgCentral := TDialog():New(nPosTop, nPosLeft, nJanAltu, nJanLarg, cSayTitulo, , , , , CLR_BLACK, RGB(250, 250, 250), , , .T.) EndIf //Títulos e SubTítulos oSayTitulo := TSay():New(004, 003, {|| cSayTitulo}, oDlgCentral, "", oFontMod, , , , .T., RGB(149, 179, 215), , 200, 30, , , , , , .F., , ) oSayEtiqus := TSay():New(-003, (nJanLarg/2) - 120, {|| cSayEtiqus}, oDlgCentral, "", oFontMaior, , , , .T., RGB(255, 000, 000), , 100, 50, , , , , , .F., , ) //Get da Etiqueta nLinObj := 36 oGetProdut := TGet():New(nLinObj, 3, {|u| Iif( Pcount()>0, cGetProdut := u, cGetProdut)}, oDlgCentral, (nJanLarg/2)-3, 20, "@!", {|| fVldCodig()}, , , oFontMod, , , .T., , , , , , , .F., , , , , , , , , , , , , , , , ) oGetProdut:cPlaceHold := "< Código do Produto >" oGetBlank := TGet():New(-100, -100, {|u| Iif(PCount() > 0 , cGetBlank := u, cGetBlank)}, oDlgCentral, 10, 10, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontBtn, , , .T.) oGetBlank:bGotFocus := {|| oGetProdut:SetFocus()} //Botões nLinObj := 059 oBtConfirm := TButton():New(nLinObj + (nAltuBtn * 00), (nJanLarg/2) - (nLargBtn * 1), "Confirmar", oDlgCentral, bConfirm, nLargBtn, nAltuBtn, , oFontBtnN, , .T., , , , , , ) oBtCancela := TButton():New(nLinObj + (nAltuBtn * 01), (nJanLarg/2) - (nLargBtn * 1), "Cancelar", oDlgCentral, bCancela, nLargBtn, nAltuBtn, , oFontBtn, , .T., , , , , , ) //Abaixo cria a grid oGridPro := MsNewGetDados():New(; nLinObj,; //nTop 3,; //nLeft (nJanAltu/2) - 3,; //nBottom (nJanLarg/2) - 3 - nLargBtn,; //nRight ,; //nStyle "AllwaysTrue()",; //cLinhaOk ,; //cTudoOk "",; //cIniCpos {},; //aAlter ,; //nFreeze 99999999,; //nMax ,; //cFieldOK ,; //cSuperDel ,; //cDelOk oDlgCentral,; //oWnd aHeaderPro,; //aHeader aColsPro) //aCols oGridPro:oBrowse:SetCSS(u_zCSSGrid()) oGridPro:lActive := .F. //Ativa e exibe a janela If lProgInic oDlgCentral:Activate("MAXIMIZED") Else oDlgCentral:Activate(, , , lCentered, {|| .T.}, , ) EndIf Return Static Function fVldCodig() Local lRet := .T. Local aColsAux := oGridPro:aCols Local lAdiciona := .T. Local nPosProd := aScan(aHeaderPro, {|x| Alltrim(x[2]) == "XX_PROD"}) Local nLinha := 0 //Somente se tiver código de etiqueta If ! Empty(cGetProdut) //Validar se a etiqueta não foi inserida na grid ainda For nLinha := 1 To Len(aColsAux) If Alltrim(cGetProdut) == Alltrim(aColsAux[nLinha][nPosProd]) FWAlertError("O produto '" + cGetProdut + "' já foi adicionado na linha '" + cValToChar(nLinha) + "'!", "Falha") lAdiciona := .F. Exit EndIf Next //Se deu tudo certo If lAdiciona DbSelectArea("SB1") SB1->(DbSetOrder(1)) //Se conseguir posicionar no produto If SB1->(MsSeek(FWxFilial('SB1') + cGetProdut)) //Se tiver apenas 1 linha e a coluna do produto estivar vazia If Len(aColsAux) == 1 .And. Empty(aColsAux[1][nPosProd]) aColsAux := {} EndIf //Adiciona uma linha na grid aAdd(aColsAux, {; SB1->B1_COD,; SubStr(SB1->B1_DESC, 1, 30),; SB1->(RecNo()),; "",; .F.; }) oGridPro:SetArray(aColsAux) oGridPro:Refresh() //Atualiza produtos lidos cSayEtiqus := Soma1(cSayEtiqus) oSayEtiqus:Refresh() Else FWAlertError("O produto '" + cGetProdut + "' não encontrado!", "Falha") EndIf EndIf //Zera o Get, para ser inserida uma nova etiqueta cGetProdut := cEspacProd EndIf Return lRet Static Function fCancelar() Local aColsAux := oGridPro:aCols //Somente se a pergunta for confirmada If FWAlertYesNo("Deseja cancelar?", "Continua?") aColsAux := {} oGridPro:SetArray(aColsAux) oGridPro:Refresh() cSayEtiqus := '000' oSayEtiqus:Refresh() EndIf Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.
boa noite. Especificamente usando uma tdialog tem jeito de mesmo passando as coordenadas ela execute completamente maximizada na tela? Obrigado
Bom dia Mauricio, tudo joia?
Tanto a TDialog como TWindow, você pode abrir com a tela 100% cheia, desde que você acione no programa inicial (no lugar de SIGAMDI, SIGAADV, etc).
A partir do momento que você aciona dentro do Protheus, existem alguns limites (por causa da barra que fica acima com informações do usuário logado, por causa das abas que ficam abertas no SIGAMDI, etc).
Segue um exemplo de utilização da função MsAdvSize, que retorna as informações que podemos usar para criar uma dialog em tela cheia: https://terminaldeinformacao.com/2024/03/11/buscando-o-tamanho-do-monitor-com-getscreenres-e-msadvsize-maratona-advpl-e-tl-286/
Tenha uma ótima e abençoada sexta feira.
Um grande abraço.