No artigo de hoje vou mostrar como fazer um box com borda arredondada via AdvPL / TL++ em um relatório usando FWMSPrinter.
Pessoal, um amigo certa vez me perguntou se tinha como fazer um box / quadro com borda arredondada usando a classe FWMSPrinter.
Eu achei que tinha no padrão, mas então falando com ele falei que não era possível. Teria que customizar, fazendo manualmente os cálculos, ou gerar uma imagem em png tendo apenas o quadro com o fundo transparente e usando o método SayBitmap.
Depois de um tempo, eu comecei a pensar na lógica para fazer, e montei rapidamente uma função que faz isso nativamente via AdvPL / TL++. Abaixo um print do resultado:
Pode não ser totalmente perfeita rs, mas dá pro gasto. A lógica basicamente foi a seguinte:
- Receber as coordenadas de linha inicial e final, coluna inicial e final
- Calcular a largura e altura, conforme diferença entre linha final e inicial e entre coluna final e inicial
- Calcular 10% da largura e da altura, que será o tamanho dos círculos / elipses que serão impressas
- Imprimir 4 elipses uma em cada canto (superior esquerdo, superior direito, inferior esquerdo, inferior direito)
- Imprimir 4 linhas, juntando com as extremidades dos 4 círculos
- Imprimir dois fundos branco para limpar as bordas internas dos 4 círculos
Abaixo o código fonte desenvolvido:
//Bibliotecas #Include "TOTVS.ch" #Include "RPTDef.ch" #Include "FWPrintSetup.ch" /*/{Protheus.doc} User Function zCxArren Função que faz um box / caixa com borda arredondada em um FWMSPrinter @type Function @author Atilio @since 30/06/2021 @version version @param oPrint, Object, Objeto instanciado usando a classe FWMSPrinter @param nLinIni, Numeric, Linha Inicial (Topo) @param nColIni, Numeric, Coluna Inicial (Esquerda) @param nLinFin, Numeric, Linha Final (Rodapé) @param nColFin, Numeric, Coluna Final (Direita) @example u_zCxArren(oPrintPvt, 10, 10, 200, 200) /*/ User Function zCxArren(oPrint, nLinIni, nColIni, nLinFin, nColFin) Local aArea := GetArea() Local nLargura := 0 Local nAltura := 0 Local nLargElip := 0 Local nAltuElip := 0 Local nCorBranc := RGB(255, 255, 255) Local oBrush := TBrush():New(, nCorBranc) Default nLinIni := 0 Default nColIni := 0 Default nLinFin := 0 Default nColFin := 0 //Somente se a linha final e coluna final forem maior que linha inicial e coluna inicial If nLinFin > nLinIni .And. nColFin > nColIni //Calcula a largura e altura do quadro nLargura := nColFin - nColIni nAltura := nLinFin - nLinIni //Pega 10% como largura e altura do circulo que será criado nLargElip := nLargura * 0.1 nAltuElip := nAltura * 0.1 //4 circulos um em cada canto oPrintPvt:Ellipse(nColIni, nLinIni, nLargElip, nAltuElip, nCorBranc) //Circulo no canto superior esquerdo oPrintPvt:Ellipse(nColFin - nAltuElip, nLinIni, nLargElip, nAltuElip, nCorBranc) //Circulo no canto superior direito oPrintPvt:Ellipse(nColIni, nLinFin - nLargElip, nLargElip, nAltuElip, nCorBranc) //Circulo no canto inferior esquerdo oPrintPvt:Ellipse(nColFin - nAltuElip, nLinFin - nLargElip, nLargElip, nAltuElip, nCorBranc) //Circulo no canto inferior direito //4 linhas ligando os circulos oPrintPvt:Line(nLinIni, nColIni + (nLargElip/2), nLinIni, nColFin - (nLargElip /2)) //Linha de cima oPrintPvt:Line(nLinFin, nColIni + (nLargElip/2), nLinFin, nColFin - (nLargElip /2)) //Linha de baixo oPrintPvt:Line(nLinIni + (nAltuElip/2), nColIni, nLinFin - (nAltuElip/2), nColIni) //Coluna da esquerda oPrintPvt:Line(nLinIni + (nAltuElip/2), nColFin, nLinFin - (nAltuElip/2), nColFin) //Coluna da direita //Faz dois quadros branco para limpar as bordas internas dos circulos oPrintPvt:FillRect({nLinIni + 0.5, nColIni + (nLargElip / 2), nLinFin - 1.5, nColFin - (nLargElip / 2)}, oBrush) oPrintPvt:FillRect({nLinIni + (nAltuElip / 2), nColIni + 0.5, nLinFin - (nAltuElip / 2), nColFin - 1.5}, oBrush) EndIf RestArea(aArea) Return
E abaixo como acionar a função de exemplo:
User Function zTestes() Local aArea := GetArea() Local cArquivo := "zTst_" + dToS(Date()) + "_" + StrTran(Time(), ':', '-') + ".pdf" //Linhas e colunas Private nLinAtu := 0 Private nLinFin := 800 Private nColIni := 010 Private nColFin := 580 Private nEspCol := (nColFin-(nColIni+150))/13 Private nColMeio := (nColFin-nColIni)/2 //Objetos de impressão e fonte Private oPrintPvt Private cNomeFont := "Arial" Private oFontDet := TFont():New(cNomeFont, 9, -11, .T., .F., 5, .T., 5, .T., .F.) Private oFontDetN := TFont():New(cNomeFont, 9, -13, .T., .T., 5, .T., 5, .T., .F.) //Criando o objeto de impressao oPrintPvt := FWMSPrinter():New(cArquivo, IMP_PDF, .F., , .T., , @oPrintPvt, , , , ,.T.) oPrintPvt:cPathPDF := GetTempPath() oPrintPvt:SetResolution(72) oPrintPvt:SetPortrait() oPrintPvt:SetPaperSize(DMPAPER_A4) oPrintPvt:SetMargin(0, 0, 0, 0) oPrintPvt:StartPage() //Faz o box / caixa u_zCxArren(oPrintPvt, 10, 10, 200, 200) //Encerrando a impressão e exibindo o pdf oPrintPvt:EndPage() oPrintPvt:Preview() RestArea(aArea) Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Ótimo, outro dia um cliente pediu pra alterar os cantos no Danfe.
Opa, eu que agradeço pelo comentário Marco.
Um grande abraço.