Nesse vídeo demonstraremos a utilização da classe DBTree, que serve para criar uma árvore de navegação em uma Dialog.
Abaixo o código fonte desenvolvido para o exemplo em vídeo acima:
//Bibliotecas
#Include "TOTVS.ch"
/*/{Protheus.doc} User Function zExe134
Cria uma navegação de níveis em árvore
@type Function
@author Atilio
@since 15/12/2022
@see https://tdn.totvs.com/display/public/framework/DBTree
@obs
**** Apoie nosso projeto, se inscreva em https://www.youtube.com/TerminalDeInformacao ****
/*/
User Function zExe134()
Local cBmp1 := "PMSEDT3"
Local cBmp2 := "PMSDOC"
Local aArea := GetArea()
Local aAreaSBM := SBM->(GetArea())
Local aAreaSB1 := SB1->(GetArea())
Local nJanAltu := 500
Local nJanLarg := 700
Local oBtnFec
Local nAtu := 1
Local nAtuGrp := 1
Local nAtuPrd := 1
Local nCorFundo := RGB(240, 240, 240)
Local lDimPixels := .T.
Local cFontNome := 'Tahoma'
Local oFontPadrao := TFont():New(cFontNome, , -12)
Private aDados := {}
Private cCadastro := "Grupo de Produtos"
Private oDlgTree
Private oDBTree
Private oSayGCod, oGetGCod, cGetGCod := Space(TamSX3('BM_GRUPO')[01])
Private oSayGDes, oGetGDes, cGetGDes := Space(TamSX3('BM_DESC')[01])
Private oSayPCod, oGetPCod, cGetPCod := Space(TamSX3('B1_COD')[01])
Private oSayPDes, oGetPDes, cGetPDes := Space(TamSX3('B1_DESC')[01])
Private oSayPTip, oGetPTip, cGetPTip := Space(TamSX3('B1_TIPO')[01])
Private oSayCarg, oGetCarg, cGetCarg := Space(10)
//Abrindo o grupo de produtos
DbSelectArea("SBM")
SBM->(DbSetOrder(1)) //BM_FILIAL+BM_GRUPO
SBM->(DbGoTop())
//Abrindo os produtos
DbSelectArea("SB1")
SB1->(DbSetOrder(4)) //B1_FILIAL+B1_GRUPO+B1_COD
SB1->(DbGoTop())
//Criando a janela
oDlgTree := TDialog():New(0, 0, nJanAltu, nJanLarg, cCadastro, , , , , , nCorFundo, , , lDimPixels)
//Criando o DbTree
oDBTree := DBTree():New(;
3,; //nTop
3,; //nLeft
(nJanAltu/2)-100,; //nBottom
(nJanLarg/2)-3,; //nRight
oDlgTree,; //oWnd
{||fProc(oDBTree:GetCargo())},; //bChange
,; //bRClick
.T.; //lCargo
)
//Adiciona raíz
oDBTree:AddTree(;
"Grupo de Produtos" + Space(30),; //cPrompt
.T.,; //lOpened
cBmp1,; //cRes1
cBmp1,; //cRes2
,; //cFile1
,; //cFile2
cValToChar(nAtu)+".0.0"; //cCargo
)
aAdd(aDados, { cValToChar(nAtu)+".0.0",; //Cargo
"",; //Código do Grupo
""}) //Código do Produto
cGetCarg := cValToChar(nAtu)+".0.0"
//Enquanto houver grupo de produtos
While ! SBM->(EoF())
//Adiciona raíz
oDBTree:AddTree(;
SBM->BM_GRUPO+" - "+SBM->BM_DESC,; //cPrompt
.T.,; //lOpened
cBmp1,; //cRes1
cBmp1,; //cRes2
,; //cFile1
,; //cFile2
cValToChar(nAtu)+"."+cValToChar(nAtuGrp)+".0"; //cCargo
)
nAtuPrd := 1
aAdd(aDados, { cValToChar(nAtu)+"."+cValToChar(nAtuGrp)+".0",; //Cargo
SBM->BM_GRUPO,; //Código do Grupo
""}) //Código do Produto
//Tenta posicionar no produto
If SB1->(DbSeek(FWxFilial('SB1') + SBM->BM_GRUPO))
While !SB1->(EoF()) .And. ((FWxFilial('SB1') + SBM->BM_GRUPO) == (SB1->B1_FILIAL + SB1->B1_GRUPO))
oDBTree:AddTreeItem(;
Alltrim(SB1->B1_COD) + " - "+SB1->B1_DESC,; //cPrompt
cBmp2,; //cRes
,; //cFile
cValToChar(nAtu)+"."+cValToChar(nAtuGrp)+"."+cValToChar(nAtuPrd); //cCargo
)
aAdd(aDados, { cValToChar(nAtu)+"."+cValToChar(nAtuGrp)+"."+cValToChar(nAtuPrd),; //Cargo
SBM->BM_GRUPO,; //Código do Grupo
SB1->B1_COD}) //Código do Produto
nAtuPrd++
SB1->(DbSkip())
EndDo
EndIf
//Finaliza raíz
oDBTree:EndTree()
nAtuGrp++
SBM->(DbSkip())
EndDo
//Finaliza raíz
oDBTree:EndTree()
//Montando os says e gets - Grupo de Produto
oSayGCod := TSay():New((nJanAltu/2)-80, 010, {|| "Grupo:"}, oDlgTree, /*cPicture*/, oFontPadrao, , , , lDimPixels, /*nClrText*/, /*nClrBack*/, 30, 8, , , , , , /*lHTML*/)
oGetGCod := TGet():New((nJanAltu/2)-83, 060, {|u| Iif(PCount() > 0 , cGetGCod := u, cGetGCod)}, oDlgTree, 050, 12, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontPadrao, , , lDimPixels)
oSayGDes := TSay():New((nJanAltu/2)-80, 170, {|| "Descrição:"}, oDlgTree, /*cPicture*/, oFontPadrao, , , , lDimPixels, /*nClrText*/, /*nClrBack*/, 30, 8, , , , , , /*lHTML*/)
oGetGDes := TGet():New((nJanAltu/2)-83, 220, {|u| Iif(PCount() > 0 , cGetGDes := u, cGetGDes)}, oDlgTree, 100, 12, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontPadrao, , , lDimPixels)
//Montando os says e gets - Produto
oSayPCod := TSay():New((nJanAltu/2)-60, 010, {|| "Produto:"}, oDlgTree, /*cPicture*/, oFontPadrao, , , , lDimPixels, /*nClrText*/, /*nClrBack*/, 30, 8, , , , , , /*lHTML*/)
oGetPCod := TGet():New((nJanAltu/2)-63, 060, {|u| Iif(PCount() > 0 , cGetPCod := u, cGetPCod)}, oDlgTree, 050, 12, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontPadrao, , , lDimPixels)
oSayPDes := TSay():New((nJanAltu/2)-60, 170, {|| "Prod.Desc:"}, oDlgTree, /*cPicture*/, oFontPadrao, , , , lDimPixels, /*nClrText*/, /*nClrBack*/, 30, 8, , , , , , /*lHTML*/)
oGetPDes := TGet():New((nJanAltu/2)-63, 220, {|u| Iif(PCount() > 0 , cGetPDes := u, cGetPDes)}, oDlgTree, 100, 12, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontPadrao, , , lDimPixels)
oSayPTip := TSay():New((nJanAltu/2)-40, 010, {|| "Prod.Tipo:"}, oDlgTree, /*cPicture*/, oFontPadrao, , , , lDimPixels, /*nClrText*/, /*nClrBack*/, 30, 8, , , , , , /*lHTML*/)
oGetPTip := TGet():New((nJanAltu/2)-43, 060, {|u| Iif(PCount() > 0 , cGetPTip := u, cGetPTip)}, oDlgTree, 030, 12, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontPadrao, , , lDimPixels)
//Cargo
oSayCarg := TSay():New((nJanAltu/2)-20, 010, {|| "Cargo:"}, oDlgTree, /*cPicture*/, oFontPadrao, , , , lDimPixels, /*nClrText*/, /*nClrBack*/, 30, 8, , , , , , /*lHTML*/)
oGetCarg := TGet():New((nJanAltu/2)-23, 060, {|u| Iif(PCount() > 0 , cGetCarg := u, cGetCarg)}, oDlgTree, 100, 12, /*cPict*/, /*bValid*/, /*nClrFore*/, /*nClrBack*/, oFontPadrao, , , lDimPixels)
//Criando um botão para fechar a janela
oBtnFec := TButton():New((nJanAltu/2)-20, (nJanLarg/2)-(61*1), "Fechar", oDlgTree, {|| oDlgTree:End()}, 058, 017, , oFontPadrao, , lDimPixels)
//Deixa todos os gets como ReadOnly
oGetGCod:lReadOnly := .T.
oGetGDes:lReadOnly := .T.
oGetPCod:lReadOnly := .T.
oGetPDes:lReadOnly := .T.
oGetPTip:lReadOnly := .T.
oGetCarg:lReadOnly := .T.
oDlgTree:Activate(, , , .T.)
RestArea(aAreaSB1)
RestArea(aAreaSBM)
RestArea(aArea)
Return
Static Function fProc(cCargo)
Local nEncon := aScan(aDados,{|x| AllTrim(x[1]) == cCargo })
//Se conseguiu encontrar algo
If nEncon > 0
//Se tiver grupo de produto
If !Empty(aDados[nEncon][2])
SBM->(DbSetOrder(1)) //BM_FILIAL+BM_GRUPO
SBM->(DbSeek(FWxFilial('SBM') + aDados[nEncon][2]))
cGetGCod := SBM->BM_GRUPO
cGetGDes := SBM->BM_DESC
//Senão
Else
cGetGCod := ""
cGetGDes := ""
EndIf
//Se tiver produto
If !Empty(aDados[nEncon][3])
SB1->(DbSetOrder(1)) //B1_FILIAL+B1_COD
SB1->(DbSeek(FWxFilial('SB1') + aDados[nEncon][3]))
cGetPCod := SB1->B1_COD
cGetPDes := SB1->B1_DESC
cGetPTip := SB1->B1_TIPO
//Senão
Else
cGetPCod := ""
cGetPDes := ""
cGetPTip := ""
EndIf
//Senão
Else
cGetGCod := ""
cGetGDes := ""
cGetPCod := ""
cGetPDes := ""
cGetPTip := ""
EndIf
//Definindo o cargo
cGetCarg := cCargo
//Atualizando gets
oGetGCod:Refresh()
oGetGDes:Refresh()
oGetPCod:Refresh()
oGetPDes:Refresh()
oGetPTip:Refresh()
oGetCarg:Refresh()
Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.