No artigo de hoje vamos demonstrar em como mudar a cor de uma linha usando a classe FWBrowse.
Alguns alunos, vira e mexe, acabam me perguntando em como mudar a cor de uma linha, usando a classe FWBrowse.
Então decidi montar dois exemplos, um usando o método SetBlkBackColor direto na FWBrowse e a segunda usando a herança com a TGrid.
Abaixo um print de exemplo:
Forma 1 – Usando os métodos SetBlkBackColor / SetBlkColor
Dessa forma aqui pessoal, basicamente vamos informar um bloco de códigos, antes do nosso Activate, e nesse bloco, o nosso Return, tem que ser o número da cor.
Então notem que antes do Activate, existem dois métodos o SetBlkBackColor (para definir a cor de fundo da linha) e o SetBlkColor (para definir a cor do texto da linha).
Abaixo segue um código fonte desse exemplo:
#Include "Totvs.ch"
/*/{Protheus.doc} User Function zBrwCor2
Função que demonstra como mudar a cor de uma linha
@type Function
@author Atilio
@since 31/10/2023
@version version
/*/
User Function zBrwCor2()
Local aArea := GetArea()
//Fontes
Local cFontUti := "Tahoma"
Local oFontAno := TFont():New(cFontUti,,-38)
Local oFontSub := TFont():New(cFontUti,,-20)
Local oFontSubN := TFont():New(cFontUti,,-20,,.T.)
Local oFontBtn := TFont():New(cFontUti,,-14)
//Janela e componentes
Private oDlgGrp
Private oPanGrid
Private oGetGrid
Private aColunas := {}
Private cAliasTab := "TMPSBM"
//Tamanho da janela
Private aTamanho := MsAdvSize()
Private nJanLarg := aTamanho[5]
Private nJanAltu := aTamanho[6]
//Cria a temporária
oTempTable := FWTemporaryTable():New(cAliasTab)
//Adiciona no array das colunas as que serão incluidas (Nome do Campo, Tipo do Campo, Tamanho, Decimais)
aFields := {}
aAdd(aFields, {"XXCODIGO", "C", 6, 0})
aAdd(aFields, {"XXDESCRI", "C", 30, 0})
aAdd(aFields, {"XXQUANTI", "N", 9, 2})
aAdd(aFields, {"XXEMISSA", "D", 8, 0})
aAdd(aFields, {"XXOBSERV", "C", 100, 0})
//Define as colunas usadas, adiciona indice e cria a temporaria no banco
oTempTable:SetFields( aFields )
oTempTable:AddIndex("1", {"XXCODIGO"} )
oTempTable:Create()
//Monta o cabecalho
fMontaHead()
//Montando os dados, eles devem ser montados antes de ser criado o FWBrowse
FWMsgRun(, {|oSay| fMontDados(oSay) }, "Processando", "Buscando grupos")
//Criando a janela
DEFINE MSDIALOG oDlgGrp TITLE "Dados" FROM 000, 000 TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL
//Labels gerais
@ 004, 003 SAY "FAT" SIZE 200, 030 FONT oFontAno OF oDlgGrp COLORS RGB(149,179,215) PIXEL
@ 004, 050 SAY "Listagem Genérica de" SIZE 200, 030 FONT oFontSub OF oDlgGrp COLORS RGB(031,073,125) PIXEL
@ 014, 050 SAY "Dados Temporários" SIZE 200, 030 FONT oFontSubN OF oDlgGrp COLORS RGB(031,073,125) PIXEL
//Botões
@ 006, (nJanLarg/2-001)-(0052*01) BUTTON oBtnFech PROMPT "Fechar" SIZE 050, 018 OF oDlgGrp ACTION (oDlgGrp:End()) FONT oFontBtn PIXEL
//Dados
@ 024, 003 GROUP oGrpDad TO (nJanAltu/2-003), (nJanLarg/2-003) PROMPT "Browse" OF oDlgGrp COLOR 0, 16777215 PIXEL
oGrpDad:oFont := oFontBtn
oPanGrid := tPanel():New(033, 006, "", oDlgGrp, , , , RGB(000,000,000), RGB(254,254,254), (nJanLarg/2 - 13), (nJanAltu/2 - 45))
oGetGrid := FWBrowse():New()
oGetGrid:DisableFilter()
oGetGrid:DisableConfig()
oGetGrid:DisableReport()
oGetGrid:DisableSeek()
oGetGrid:DisableSaveConfig()
oGetGrid:SetFontBrowse(oFontBtn)
oGetGrid:SetAlias(cAliasTab)
oGetGrid:SetDataTable()
oGetGrid:SetEditCell(.T., {|| .T.})
oGetGrid:lHeaderClick := .F.
oGetGrid:AddLegend(cAliasTab + "->XXQUANTI == 0", "YELLOW", "Quantidade zerada")
oGetGrid:AddLegend(cAliasTab + "->XXQUANTI < 0", "RED", "Quantidade menor que zero")
oGetGrid:AddLegend(cAliasTab + "->XXQUANTI > 0", "GREEN", "Quantidade maior que zero")
oGetGrid:SetColumns(aColunas)
oGetGrid:SetOwner(oPanGrid)
oGetGrid:SetBlkBackColor({|| fCorLinha() })
oGetGrid:SetBlkColor({|| fCorTexto() })
oGetGrid:Activate()
ACTIVATE MsDialog oDlgGrp CENTERED
//Deleta a temporaria
oTempTable:Delete()
RestArea(aArea)
Return
Static Function fMontaHead()
Local nAtual
Local aHeadAux := {}
//Adicionando colunas
//[1] - Campo da Temporaria
//[2] - Titulo
//[3] - Tipo
//[4] - Tamanho
//[5] - Decimais
//[6] - Máscara
//[7] - Editável? .T. = sim, .F. = não
aAdd(aHeadAux, {"XXCODIGO", "Código", "C", 6, 0, "", .F.})
aAdd(aHeadAux, {"XXDESCRI", "Descricao", "C", 30, 0, "", .F.})
aAdd(aHeadAux, {"XXQUANTI", "Quantidade", "N", 9, 2, "@E 999,999.99", .T.})
aAdd(aHeadAux, {"XXEMISSA", "Emissão", "D", 8, 0, "", .T.})
aAdd(aHeadAux, {"XXOBSERV", "Observação", "C", 100, 0, "", .T.})
//Percorrendo e criando as colunas
For nAtual := 1 To Len(aHeadAux)
oColumn := FWBrwColumn():New()
oColumn:SetData(&("{|| " + cAliasTab + "->" + aHeadAux[nAtual][1] +"}"))
oColumn:SetTitle(aHeadAux[nAtual][2])
oColumn:SetType(aHeadAux[nAtual][3])
oColumn:SetSize(aHeadAux[nAtual][4])
oColumn:SetDecimal(aHeadAux[nAtual][5])
oColumn:SetPicture(aHeadAux[nAtual][6])
//Se for ser possível ter o duplo clique
If aHeadAux[nAtual][7]
oColumn:SetEdit(.T.)
oColumn:SetReadVar(aHeadAux[nAtual][1])
//oColumn:SetValid({|| fSuaValid()})
EndIf
aAdd(aColunas, oColumn)
Next
Return
Static Function fMontDados(oSay)
Local aArea := GetArea()
Local nAtual := 0
Local nTotal := 50
Local dDtRef := Date()
Local cCodAtu := "000000"
Local cDescri := ""
Local nQuanti := 0
Local dEmissa := sToD("")
//Faz um laço de repetição
For nAtual := 1 To nTotal
//Muda a mensagem na regua
nAtual++
oSay:SetText("Adicionando registro " + cValToChar(nAtual) + " de " + cValToChar(nTotal) + "...")
//Pega as variáveis que vão ser gravadas
cCodAtu := Soma1(cCodAtu)
cDescri := "[" + Time() + "] Teste - " + cCodAtu
nQuanti := Randomize(-5, 5)
dEmissa := DaySub(dDtRef, nAtual)
//Insere os dados na temporária
RecLock(cAliasTab, .T.)
(cAliasTab)->XXCODIGO := cCodAtu
(cAliasTab)->XXDESCRI := cDescri
(cAliasTab)->XXQUANTI := nQuanti
(cAliasTab)->XXEMISSA := dEmissa
(cAliasTab)->XXOBSERV := ""
(cAliasTab)->(MsUnlock())
Next
RestArea(aArea)
Return
Static Function fCorLinha()
Local nCorFundo := 0
Local nLinha := (cAliasTab)->(Recno())
//Se for a linha 0 a 5, será na cor amarela e o texto na cor cinza meio escuro
If nLinha <= 5
nCorFundo := RGB(232, 216, 000)
//Se for a linha 6 a 10, fundo será vermelho e o texto será branco
ElseIf nLinha >= 6 .And. nLinha <= 10
nCorFundo := RGB(255, 000, 000)
//Senão, fundo será verde o texto será preto
Else
nCorFundo := RGB(000, 255, 000)
EndIf
Return nCorFundo
Static Function fCorTexto()
Local nCorTexto := 0
Local nLinha := (cAliasTab)->(Recno())
//Se for a linha 0 a 5, será na cor amarela e o texto na cor cinza meio escuro
If nLinha <= 5
nCorTexto := RGB(108, 108, 108)
//Se for a linha 6 a 10, fundo será vermelho e o texto será branco
ElseIf nLinha >= 6 .And. nLinha <= 10
nCorTexto := RGB(255, 255, 255)
//Senão, fundo será verde o texto será preto
Else
nCorTexto := RGB(000, 000, 000)
EndIf
Return nCorTexto
Forma 2 – Usando a herança da TGrid
O que acontece pessoal, é que a FWBrowse, logo após o Activate, ela tem um atributo chamado “oBrowse”, que esse cara herda os métodos e atributos da TGrid.
Pensando nisso, um dos métodos disponíveis é o SetRowColor, onde você passa o número da linha, a cor de fundo e a cor da linha.
Então a lógica do nosso exemplo é:
- Criar normalmente nossa dialog e nossa grid com FWBrowse
- Logo após acionar o método Activate, vamos chamar uma função que aqui demos o nome de fDefinCor
- Nessa função, iremos percorrer os dados da temporária, e da linha 0 a 5 vamos pintar de uma cor, da 6 a 10 de outra, e a partir da 11 de outra
Abaixo segue um código fonte desse exemplo:
#Include "Totvs.ch"
/*/{Protheus.doc} User Function zBrwCor
Função que demonstra como mudar a cor de uma linha
@type Function
@author Atilio
@since 31/10/2023
@version version
/*/
User Function zBrwCor()
Local aArea := GetArea()
//Fontes
Local cFontUti := "Tahoma"
Local oFontAno := TFont():New(cFontUti,,-38)
Local oFontSub := TFont():New(cFontUti,,-20)
Local oFontSubN := TFont():New(cFontUti,,-20,,.T.)
Local oFontBtn := TFont():New(cFontUti,,-14)
//Janela e componentes
Private oDlgGrp
Private oPanGrid
Private oGetGrid
Private aColunas := {}
Private cAliasTab := "TMPSBM"
//Tamanho da janela
Private aTamanho := MsAdvSize()
Private nJanLarg := aTamanho[5]
Private nJanAltu := aTamanho[6]
//Cria a temporária
oTempTable := FWTemporaryTable():New(cAliasTab)
//Adiciona no array das colunas as que serão incluidas (Nome do Campo, Tipo do Campo, Tamanho, Decimais)
aFields := {}
aAdd(aFields, {"XXCODIGO", "C", 6, 0})
aAdd(aFields, {"XXDESCRI", "C", 30, 0})
aAdd(aFields, {"XXQUANTI", "N", 9, 2})
aAdd(aFields, {"XXEMISSA", "D", 8, 0})
aAdd(aFields, {"XXOBSERV", "C", 100, 0})
//Define as colunas usadas, adiciona indice e cria a temporaria no banco
oTempTable:SetFields( aFields )
oTempTable:AddIndex("1", {"XXCODIGO"} )
oTempTable:Create()
//Monta o cabecalho
fMontaHead()
//Montando os dados, eles devem ser montados antes de ser criado o FWBrowse
FWMsgRun(, {|oSay| fMontDados(oSay) }, "Processando", "Buscando grupos")
//Criando a janela
DEFINE MSDIALOG oDlgGrp TITLE "Dados" FROM 000, 000 TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL
//Labels gerais
@ 004, 003 SAY "FAT" SIZE 200, 030 FONT oFontAno OF oDlgGrp COLORS RGB(149,179,215) PIXEL
@ 004, 050 SAY "Listagem Genérica de" SIZE 200, 030 FONT oFontSub OF oDlgGrp COLORS RGB(031,073,125) PIXEL
@ 014, 050 SAY "Dados Temporários" SIZE 200, 030 FONT oFontSubN OF oDlgGrp COLORS RGB(031,073,125) PIXEL
//Botões
@ 006, (nJanLarg/2-001)-(0052*01) BUTTON oBtnFech PROMPT "Fechar" SIZE 050, 018 OF oDlgGrp ACTION (oDlgGrp:End()) FONT oFontBtn PIXEL
//Dados
@ 024, 003 GROUP oGrpDad TO (nJanAltu/2-003), (nJanLarg/2-003) PROMPT "Browse" OF oDlgGrp COLOR 0, 16777215 PIXEL
oGrpDad:oFont := oFontBtn
oPanGrid := tPanel():New(033, 006, "", oDlgGrp, , , , RGB(000,000,000), RGB(254,254,254), (nJanLarg/2 - 13), (nJanAltu/2 - 45))
oGetGrid := FWBrowse():New()
oGetGrid:DisableFilter()
oGetGrid:DisableConfig()
oGetGrid:DisableReport()
oGetGrid:DisableSeek()
oGetGrid:DisableSaveConfig()
oGetGrid:SetFontBrowse(oFontBtn)
oGetGrid:SetAlias(cAliasTab)
oGetGrid:SetDataTable()
oGetGrid:SetEditCell(.T., {|| .T.})
oGetGrid:lHeaderClick := .F.
oGetGrid:AddLegend(cAliasTab + "->XXQUANTI == 0", "YELLOW", "Quantidade zerada")
oGetGrid:AddLegend(cAliasTab + "->XXQUANTI < 0", "RED", "Quantidade menor que zero")
oGetGrid:AddLegend(cAliasTab + "->XXQUANTI > 0", "GREEN", "Quantidade maior que zero")
oGetGrid:SetColumns(aColunas)
oGetGrid:SetOwner(oPanGrid)
oGetGrid:Activate()
//Após o activate para carregar o "oBrowse" instanciado da TGrid
fDefinCor()
ACTIVATE MsDialog oDlgGrp CENTERED
//Deleta a temporaria
oTempTable:Delete()
RestArea(aArea)
Return
Static Function fMontaHead()
Local nAtual
Local aHeadAux := {}
//Adicionando colunas
//[1] - Campo da Temporaria
//[2] - Titulo
//[3] - Tipo
//[4] - Tamanho
//[5] - Decimais
//[6] - Máscara
//[7] - Editável? .T. = sim, .F. = não
aAdd(aHeadAux, {"XXCODIGO", "Código", "C", 6, 0, "", .F.})
aAdd(aHeadAux, {"XXDESCRI", "Descricao", "C", 30, 0, "", .F.})
aAdd(aHeadAux, {"XXQUANTI", "Quantidade", "N", 9, 2, "@E 999,999.99", .T.})
aAdd(aHeadAux, {"XXEMISSA", "Emissão", "D", 8, 0, "", .T.})
aAdd(aHeadAux, {"XXOBSERV", "Observação", "C", 100, 0, "", .T.})
//Percorrendo e criando as colunas
For nAtual := 1 To Len(aHeadAux)
oColumn := FWBrwColumn():New()
oColumn:SetData(&("{|| " + cAliasTab + "->" + aHeadAux[nAtual][1] +"}"))
oColumn:SetTitle(aHeadAux[nAtual][2])
oColumn:SetType(aHeadAux[nAtual][3])
oColumn:SetSize(aHeadAux[nAtual][4])
oColumn:SetDecimal(aHeadAux[nAtual][5])
oColumn:SetPicture(aHeadAux[nAtual][6])
//Se for ser possível ter o duplo clique
If aHeadAux[nAtual][7]
oColumn:SetEdit(.T.)
oColumn:SetReadVar(aHeadAux[nAtual][1])
//oColumn:SetValid({|| fSuaValid()})
EndIf
aAdd(aColunas, oColumn)
Next
Return
Static Function fMontDados(oSay)
Local aArea := GetArea()
Local nAtual := 0
Local nTotal := 50
Local dDtRef := Date()
Local cCodAtu := "000000"
Local cDescri := ""
Local nQuanti := 0
Local dEmissa := sToD("")
//Faz um laço de repetição
For nAtual := 1 To nTotal
//Muda a mensagem na regua
nAtual++
oSay:SetText("Adicionando registro " + cValToChar(nAtual) + " de " + cValToChar(nTotal) + "...")
//Pega as variáveis que vão ser gravadas
cCodAtu := Soma1(cCodAtu)
cDescri := "[" + Time() + "] Teste - " + cCodAtu
nQuanti := Randomize(-5, 5)
dEmissa := DaySub(dDtRef, nAtual)
//Insere os dados na temporária
RecLock(cAliasTab, .T.)
(cAliasTab)->XXCODIGO := cCodAtu
(cAliasTab)->XXDESCRI := cDescri
(cAliasTab)->XXQUANTI := nQuanti
(cAliasTab)->XXEMISSA := dEmissa
(cAliasTab)->XXOBSERV := ""
(cAliasTab)->(MsUnlock())
Next
RestArea(aArea)
Return
Static Function fDefinCor()
Local nCor := 0
Local nLinha := -1
//Percorre a temporária
While ! (cAliasTab)->(EoF())
nLinha++
//Se for a linha 0 a 5, será na cor amarela e o texto na cor cinza meio escuro
If nLinha <= 5
nCorFundo := RGB(232, 216, 000)
nCorTexto := RGB(108, 108, 108)
//Se for a linha 6 a 10, fundo será vermelho e o texto será branco
ElseIf nLinha >= 6 .And. nLinha <= 10
nCorFundo := RGB(255, 000, 000)
nCorTexto := RGB(255, 255, 255)
//Senão, fundo será verde o texto será preto
Else
nCorFundo := RGB(000, 255, 000)
nCorTexto := RGB(000, 000, 000)
EndIf
//Caso queira ver a documentação do método - https://tdn.totvs.com/display/tec/TGrid%3ASetRowColor
oGetGrid:oBrowse:SetRowColor(nLinha, nCorFundo, nCorTexto )
(cAliasTab)->(DbSkip())
EndDo
(cAliasTab)->(DbGoTop())
Return nCor
Bom pessoal, por hoje é só.
Abraços e até a próxima.

Otímo conteúdo! Saberia informar se seria possivel alterar a cor do fonte de uma coluna utilizando o FWBrowse?
Bom dia Gabriel, tudo joia?
Infelizmente, nunca precisei alterar apenas cor da fonte de uma coluna.
Tenha uma ótima e abençoada quinta feira.
Um forte abraço.