Criando um ícone na bandeja do S.O. com TSystemTray – Maratona AdvPL e TL++ 511

Nesse vídeo demonstraremos a utilização da classe TSystemTray, que serve para criar um ícone na bandeja do sistema operacional, sendo possível interagir com ele.

Abaixo o código fonte desenvolvido para o exemplo em vídeo acima:

//Bibliotecas
#Include "TOTVS.ch"

/*/{Protheus.doc} User Function zExe511
Classe para criar um ícone na bandeja do sistema operacional (só funciona com TWindow)
@type  Function
@author Atilio
@since 05/04/2023
@see https://tdn.totvs.com/display/tec/TSystemTray
@obs 
    
    **** Apoie nosso projeto, se inscreva em https://www.youtube.com/TerminalDeInformacao ****
/*/

User Function zExe511()
    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.)

        //Cria o menu de popup que vai ser acionado ao clicar com o botão direito no ícone da bandeja
        oMenu  := TMenu():New(0, 0, 0, 0, .T., , oDlgCentral)
        oItem1 := TMenuItem():New(oDlgCentral,'Mudar a Cor de Fundo', , , , {|| nCor := ColorTriangle(), oDlgCentral:nClrPane := nCor, oDlgCentral:Refresh() }, , 'BR_VERDE', , , , , , , .T.)
        oItem2 := TMenuItem():New(oDlgCentral,'Exibir Data e Hora',   , , , {|| FWAlertInfo(dToC(Date()) + " - " + Time(), "Atenção") }                       , , 'HISTORIC', , , , , , , .T.)
        oItem3 := TMenuItem():New(oDlgCentral,'Encerrar Aplicação',   , , , {|| oDlgCentral:End() }                                                           , , 'EXCLUIR' , , , , , , , .T.)
        oMenu:Add(oItem1)
        oMenu:Add(oItem2)
        oMenu:Add(oItem3)
    
        //Cria o ícone da bandeja do sistema operacional
        cIcon := "pesquisa.png"
        oSysTray := TSystemTray():New(oDlgCentral, cIcon)
        oSysTray:cToolTip := "Exemplo de TSystemTray"
        oSysTray:SetMenu(oMenu)
    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é próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

Deixe uma resposta

Terminal de Informação