Árvore de páginas

Este arquivo PRW contém o ferramental necessário para customizações ADVPL à partir do CloudBridge, nele você entenderá todo o mecanismo de comunicação entre o Navegador Embedado (JavaScript) e o ADVPL.

As funções mais importantes são:

Function u_CBCustom()
Função principal, deve ser inserida na TAG mainFunction no arquivo .cloud, base do aplicativo, para ser instanciada no momento da abertura.

Function loadFinished()
Função atribuida como bloco de código do oWebEngine:bLoadFinished, ela será disparada ao termino da carga das páginas e como parâmetro recebe a URL carregada.

Function notificationTapped()
Função atribuida como bloco de código do oMobile:bNotificationTapped, ela será disparada quando a notificação for selecionada no dispositivo móvel. Ela recebe o ID inserido na notificação.

Function jsToAdvpl()
Função atribuida como bloco de código do oWebChannel:bJsToAdvpl, ela será disparada durante o recebimento da Função dialog.jsToAdvpl() que será disparada via JavaScript.

Arquivo

#include "TOTVS.CH"
#include "FILEIO.CH"
#INCLUDE "TBIConn.ch"
Function u_CBCustom()
	// ---------------------------------------------------------------
	local i
	local oWebChannel
	local cMultGet := ""
	local cHost,nPort,lConnected
	local tempPath := GetTempPath()
	PRIVATE oWebEngine
	PRIVATE oMultGet
	PRIVATE oGetLink
	PRIVATE	oDlg
	oDlg := TWindow():New(10, 10, 800, 600, "TOTVS - CloudBridge", NIL, NIL, NIL, NIL, NIL, NIL, NIL,;
	CLR_BLACK, CLR_WHITE, NIL, NIL, NIL, NIL, NIL, NIL, .T. )
	oDlg:setCSS("QPushButton{margin: 1px; background-color: "+_colorTOTVS+"; border: none; color: #fff; }")
	// Android ou iOS
	if _rmtType == 8 .Or. _rmtType == 9
		// Libera rotacao do dispositivo
		PRIVATE oMobile := TMobile():New(oDlg)
		oMobile:SetScreenOrientation(-1)
		// Temporario do dispositivo
		tempPath := oMobile:GetTempPath() + "/"
		// Prepara bloco de codigo pra callBack de notificacao
		oMobile:bNotificationTapped := {|id| notificationTapped(id) }
	endif
	// Prepara o conector WebSocket, sempre pra LOCALHOST e retorna a PORTA LIVRE
	oWebChannel := TWebChannel():New()
	nPort  		:= oWebChannel::connect()
	cHost 		:= oWebChannel:cHost
	nPort 		:= oWebChannel:nPort
	lConnected 	:= oWebChannel:lConnected
	// Verifica conexão
	if !lConnected
		msgStop("Erro na conexão com o WebSocket")
		return
	endif
	// Define o CallBack JavaScript
	oWebChannel:bJsToAdvpl := {|self,codeType,codeContent| jsToAdvpl(self,codeType,codeContent) }
	// Monta link GLOBAL
	if subs(tempPath,1,2) == "C:"
		tempPath := "file:///" + strTran(tempPath, "\", "/")
	endif
	mainHtml := tempPath + mainHtml
	oWebEngine := TWebEngine():New(oDlg, 0, 0, 100, 100,, nPort)
	oWebEngine:bLoadFinished := {|self,url| loadFinished(self,url) }
	oWebEngine:setAsMain() // Define como WebEngine que recebera o KEY_BACK (Android)
	// Painel superior
	@ 000, 000 MSPANEL pnTop SIZE 250, 024 OF oDlg COLORS 0, 16777215 RAISED // Mansano: 250, 012
	pnTop:setCss("QFrame{background-color: #6BB4F1;}")
	// Alinha componentes
	pnTop:Align := CONTROL_ALIGN_TOP
	oWebEngine:Align := CONTROL_ALIGN_ALLCLIENT
	// CONOUT fake para exibir a mensageria
	oFont1 := TFont():New("Courier",,018,,.F.,,,,,.F.,.F.)
	@ 038, 000 MSPANEL ConOut SIZE 250, 16 OF oDlg COLORS 0, 16777215 RAISED
	oMultGet := TSimpleEditor():New( 0,0,ConOut, 50,50,"",, {| u | if( pCount() > 0, cMultGet := u, cMultGet )}, oFont1, .T.)
	ConOut:Align := CONTROL_ALIGN_BOTTOM
	oMultGet:Align := CONTROL_ALIGN_ALLCLIENT
	CreateFormTop(pnTop)
	oDlg:Activate("MAXIMIZED")
Return
// Parseia o Json em um Hash
Static Function getJsonHash(jsonData, oHash)
	// ---------------------------------------------------------------
	Local oJson := tJsonParser():New()
	Local jsonfields := {}
	Local nRetParser := 0
	if empty(jsonData)
		return .F.
	endif
	// Converte JSON pra Hash
	return oJson:Json_Hash(jsonData, len(jsonData), @jsonfields, @nRetParser, @oHash)
return
// Retorna valor do campo no Hash
Static Function getHField(oHash, jsonField)
	// ---------------------------------------------------------------
	Local xGet := Nil
	// Recupera valor do campo
	if HMGet(oHash, jsonField, xGet)
		return xGet
	else
		return ""
	endif
return
// Bloco de codigo do termino da carga da pagina
static function loadFinished(self,url)
	// ---------------------------------------------------------------
	oGetLink:cText := url+space(1000)
return
// CALLBACK das notificacoes
static function notificationTapped(id)
	conout("createNotification: id: " + cValToChar(id))
return
// CALLBACK JavaScript
static function jsToAdvpl(self,codeType,codeContent)
	// ---------------------------------------------------------------
	Local i
	Local oTmpHash := .F.
	Local xRet, lRet, scalesize
	Local xVal, fnCallBack, cFile, aBarResult,;
	aDevicesResult, sMsg, cPosition, id, title, message,;
	cQuery, nFields, nRecords, aAccelerometerSensor
	if valType(codeType) == "C"
		_conout("jsToAdvpl->codeType: " + codeType + " = " + codeContent)
		if codeType == "runAdvpl"
			if getJsonHash(codeContent, @oTmpHash)
				xVal := &("{|| " + getHField(oTmpHash, "codeBlock") + "}")
				if valType(xVal) == "B"
				  conout("vou rodar o advpl - {|| " + getHField(oTmpHash, "codeBlock") + "}")
					xRet := eval(xVal)
					xRet := cValToChar(xRet) // Converte pra String
					// Executa o CallBack
					fnCallBack = getHField(oTmpHash, "callBack")+"('" +xRet+ "')"
					conout("rodei o advpl, agora vou chamar o callback - " + fnCallBack)
					oWebEngine:runJavaScript(fnCallBack)
					conout("chamei o callback")
				endif
			else
				_msgAlert("RunAdvpl command not executed", "CloudBridge")
			endif
			return
		endif
		
		if codeType == "decode64"
		  if getJsonHash(codeContent, @oTmpHash)
        strDec := getHField(oTmpHash, "strDecode")
        strFile := getHField(oTmpHash, "strFile")
        lChangeCase := getHField(oTmpHash, "lChangeCase")
        if valType(strDec) == "C"
          Decode64(strDec,oMobile:GetTempPath() + "/" + strFile,lChangeCase)
          // Executa o CallBack
          fnCallBack = getHField(oTmpHash, "callBack")+"('" + oMobile:GetTempPath() + "/" + strFile + "')"
          conout("rodei o advpl, agora vou chamar o callback - " + fnCallBack)
          oWebEngine:runJavaScript(fnCallBack)
          conout("chamei o callback")
        endif
      else
        _msgAlert("RunAdvpl command not executed", "CloudBridge")
      endif
      return
		endif
		// Android Ou iOS
		if _rmtType == 8 .Or. _rmtType == 9
			// Tira foto
			if codeType == "getPicture"
			  if getJsonHash(codeContent, @oTmpHash)
			    scalesize := getHField(oTmpHash, "ScaletoWidth")
          cFile:= oMobile:TakePicture(scalesize)
			    fnCallBack = getHField(oTmpHash, "callBack")+"('" +cFile+ "')"
			  else
			    
			  endif
        _conout("[getPicture] - " + cFile)
        // Executa o CallBack
        oWebEngine:runJavaScript(fnCallBack)
        return
      endif
			// Codigo de  barras
			if codeType == "barCodeScanner"
				aBarResult := oMobile:BarCode()
				If aBarResult[1] = ""
					_conout("[barCode] - " + "Nenhum código de barras disponível.")
				Else
					_conout("[barCode] - " + "Código: " + aBarResult[1] + chr(13) + "Formato: " + aBarResult[2])
					// Executa o CallBack
					fnCallBack = codeContent+"('" +aBarResult[1]+ "')"
					oWebEngine:runJavaScript(fnCallBack)
				EndIf
				return
			endif
			// Verifica dispositivos pareados
			if codeType == "pairedDevices"
				aDevicesResult:= oMobile:GetPairedBluetoothDevices()
				sMsg := ""
				For i := 1 to len(aDevicesResult)
					sMsg := sMsg + "Nome: " + aDevicesResult[i][1] + chr(13)
					sMsg := sMsg + "Endereço: " + aDevicesResult[i][2] + chr(13) + chr(13)
				Next i
				If sMsg = ""
					sMsg := "Nenhum dispositivo pareado ou interface Bluetooth desligada."
				Else
					sMsg := "Dispositivos Bluetooth Pareados:" + chr(13) + chr(13) + sMsg
				EndIf
				_conout("[bluetooth] - " + sMsg)
				// Executa o CallBack
				fnCallBack = codeContent+"('" +SubStr(sMsg,1,30)+ "')"
				oWebEngine:runJavaScript(fnCallBack)
				return
			endif
			// Libera orientacao
			if codeType == "unlockOrientation"
				oMobile:SetScreenOrientation(-1)
				_conout("[unlockOrientation]")
				return
			endif
			// Trava orientacao
			if codeType == "lockOrientation"
				oMobile:SetScreenOrientation(2)
				_conout("[lockOrientation]")
				return
			endif
			// GPS
			if codeType == "getCurrentPosition"
				cPosition := oMobile:getGeoCoordinate(1)
				_conout("[getCurrentPosition] - " + cPosition)
				// PARA LIMPAR O SINAL DE GRAUS CHR(176)
				cPosition := StrTran(cPosition, chr(176), "")
				// Executa o CallBack
				fnCallBack = codeContent+"('" +cPosition+ "');"
				oWebEngine:runJavaScript(fnCallBack)
				return
			endif
			// Testa perifericos
			if codeType == "testDevice"
				if getJsonHash(codeContent, @oTmpHash)
					lRet := oMobile:TestDevice(getHField(oTmpHash, "testFeature"))
					// Executa o CallBack
					fnCallBack = getHField(oTmpHash, "callBack")+"('" +cValToChar(lRet)+ "')"
					oWebEngine:runJavaScript(fnCallBack)
				else
					_msgAlert("testDevice command not executed", "CloudBridge")
				endif
				return
			endif
			// Cria notificacao
			// O callBack sera disparado pelo bloco de codigo bNotificationTapped
			if codeType == "createNotification"
				if getJsonHash(codeContent, @oTmpHash)
					id := getHField(oTmpHash, "id")
					title := getHField(oTmpHash, "title")
					message := getHField(oTmpHash, "message")
					oMobile:CreateNotification(id, title, message)
				else
					_msgAlert("createNotification command not executed", "CloudBridge")
				endif
				return
			endif
			// Abre configuracoes
			if codeType == "openSettings"
				oWebEngine:runJavaScript("openSettings")
				oMobile:OpenSettings(val(codeContent))
				return
			endif
			
			// Recupera diretorio temporario 
			if codeType == "getTempPath"
				fnCallBack = codeContent + "('" + oMobile:GetTempPath() + "');"
				oWebEngine:runJavaScript(fnCallBack)
			endif
			
			// Aciona o vibracall do dispositivo 
			if codeType == "vibrate"
				oMobile:vibrate(val(codeContent))
			endif
			
			// Efetua uma leitura no sensor de acelerômetro do dispositivo 
			if codeType == "readAccelerometer"
				aAccelerometerSensor:= oMobile:ReadAccelerometer()
				sMsg := "Valores lidos do sensor acelerometro (m/s2):" + "\n"
				sMsg += "x:" + str(aAccelerometerSensor[1]) + "\n"
				sMsg += "y:" + str(aAccelerometerSensor[2]) + "\n"
				sMsg += "z:" + str(aAccelerometerSensor[3])
				_conout("accelerometer - " + sMsg)
				// Executa o CallBack
				fnCallBack = codeContent+"('" +sMsg+ "')"
				oWebEngine:runJavaScript(fnCallBack)
				return
			endif
			
			// Habilita bloco de código bOnPause
			if codeType == "enblOnPause"
			  _msgAlert("Conferir resultado na barra de status.", "CloudBridge")
			  _conout("[bOnPause] - Cada evento OnPause sera exibido aqui com o horario.")
			  oMobile:bOnPause := { || _conout("bOnPause >> Aplicativo entrou em background as " + TIME()) }
			  return
			endif
			// Habilita bloco de código bOnResume
			if codeType == "enblOnResume"
			  _msgAlert("Conferir resultado na barra de status.", "CloudBridge")
			  _conout("[bOnResume] - Cada evento OnResume sera exibido aqui com o horario.")
			  oMobile:bOnResume := { || _conout("bOnResume >> Aplicativo voltou em primeiro plano as " + TIME()) }
			  return
			endif
			// Pre-insere um contato da agenda do dispositivo 
			if codeType == "addContact"
				if getJsonHash(codeContent, @oTmpHash)
					aEmails := {}
					aPhones := {}
					aPostals := {}
					oTMobCont := TMobileContact():New()
					oTMobCont:cName := getHField(oTmpHash, "name")
					oTMobCont:cCompany := getHField(oTmpHash, "company")
					oTMobCont:cJobTitle := getHField(oTmpHash, "jobTitle")
					oTMobCont:cNote := getHField(oTmpHash, "note")
					cEmail1 := getHField(oTmpHash, "email1")
					nEmailType1 := getHField(oTmpHash, "emailType1")
					aAdd( aEmails, TMobileContactEmail():New2( nEmailType1, cEmail1 ) )
					cPhone1 := getHField(oTmpHash, "phone1")
					nPhoneType1 := getHField(oTmpHash, "phoneType1")
					aAdd( aPhones, TMobileContactPhone():New2( nPhoneType1, cPhone1 ) )
					aAdd( aPostals, TMobileContactPostal():New2( 2, getHField(oTmpHash, "postal") ) )
					oTMobCont:aEmails := aEmails
					oTMobCont:aPhones := aPhones
					oTMobCont:aPostals := aPostals
					oMobile:AddContact( oTMobCont )
				else
					_msgAlert("addContact command not executed", "CloudBridge")
				endif
				return
			endif
			
			// Procura contatos no dispositivo
			if codeType == "findContact"
				if getJsonHash(codeContent, @oTmpHash)
					aContacts := {}
					aContacts := oMobile:FindContact( getHField( oTmpHash, "filter" ) )
					//VarInfo( "Contatos encontrados", aContacts )
					sMsg := "Resultado da busca por contatos:"
					For i := 1 to len( aContacts )
					  sMsg += "\n\n"
					  If len( aContacts[i]:cName ) > 0
					    sMsg += "Nome: " + aContacts[i]:cName + "\n"
					  EndIf
					  If len( aContacts[i]:aPhones ) > 0
					    sMsg += "Fone: " + aContacts[i]:aPhones[1]:cNumber + "\n"
					  EndIf
					  If len( aContacts[i]:aEmails ) > 0
					    sMsg += "E-mail: " + aContacts[i]:aEmails[1]:cAddress + "\n"
					  EndIf
					Next i
					fnCallBack = getHField(oTmpHash, "callBack")+"('" + sMsg + "')"
					oWebEngine:runJavaScript(fnCallBack)
				else
					_msgAlert("findContact command not executed", "CloudBridge")
				endif
				return
			endif
			// Pre-insere um evento de calendario do dispositivo 
      if codeType == "addCalendar"
        if getJsonHash(codeContent, @oTmpHash)
          datai := getHField(oTmpHash, "startdate")
          datae := getHField(oTmpHash, "enddate")
          dataictod := right(datai,2) + "/" + substr(datai,6,2) + "/" + left(datai,4)
          dataectod := right(datae,2) + "/" + substr(datae,6,2) + "/" + left(datae,4)
          oTmpCalEv := TCalendarEvent():New()
          oTmpCalEv:cTitle := getHField(oTmpHash, "title")
          oTmpCalEv:cDescription := getHField(oTmpHash, "descr")
          oTmpCalEv:cLocation := getHField(oTmpHash, "addr")
          oTmpCalEv:dStartDate := ctod(dataictod,"ddmmyyyy")
          oTmpCalEv:cStartTime := getHField(oTmpHash, "starttime")
          oTmpCalEv:dEndDate := ctod(dataectod,"ddmmyyyy")
          oTmpCalEv:cEndTime := getHField(oTmpHash, "endtime")
          if getHField(oTmpHash, "allday") == "True"
            oTmpCalEv:lAllDay := .T.
          else
            oTmpCalEv:lAllDay := .F.
          endif
          iRet := oMobile:addCalendarEvent(oTmpCalEv)
          fnCallBack = getHField(oTmpHash, "callBack")+"('" +cValToChar(iRet)+ "')"
          oWebEngine:runJavaScript(fnCallBack)
        endif
      endif
      
      // Procura eventos de calendario no dispositivo
      if codeType == "findCalendar"
        if getJsonHash(codeContent, @oTmpHash)
          datai := getHField(oTmpHash, "startdate")
          datae := getHField(oTmpHash, "enddate")
          dataictod := right(datai,2) + "/" + substr(datai,6,2) + "/" + left(datai,4)
          dataectod := right(datae,2) + "/" + substr(datae,6,2) + "/" + left(datae,4)
          aCalIds := oMobile:findCalendarEvent(ctod(dataictod,"ddmmyyyy"), ctod(dataectod,"ddmmyyyy"))
          cIds := '{"ids": ['
          if Len(aCalIds) > 0
            for i := 1 to len(aCalIds)
              cIds += '"' + cvaltochar(aCalIds[i]) + '",'
            next
            cIds := left(cIds,Len(cIds)-1)
          endif
          cIds += "]}"
          fnCallBack = getHField(oTmpHash, "callBack")+"('" +cIds+ "')"
          oWebEngine:runJavaScript(fnCallBack)
        endif
      endif
      
      // Visualiza evento do calendario do dispositivo
      if codeType == "viewCalendar"
        oMobile:viewCalendarEvent(codecontent)
      endif
      
      // Retorna informações do evento informado
      if codeType == "getCalendar"
        if getJsonHash(codeContent, @oTmpHash)
          id := getHField(oTmpHash, "id")
          oCalEv := oMobile:getCalendarEvent(id)
          
          dateic := dtos(oCalEv:dStartDate)
          dateec := dtos(oCalEv:dEndDate)
          dateijs := ""
          dateejs := ""
          if Len(dateic) == 8 .AND. Len(dateec) == 8
            dateijs := left(dateic,4) + "-" + substr(dateic,5,2) + "-" + right(dateic,2)
            dateejs := left(dateec,4) + "-" + substr(dateec,5,2) + "-" + right(dateec,2)
          endif
          if oCalEv:lAllDay
            cAllday := "True"
          else
            cAllDay := "False"
          endif 
          
          cCalEv := "{"
          cCalEv += '"title":"'     + oCalEv:cTitle           + '",'
          cCalEv += '"descr":"'     + oCalEv:cDescription     + '",'
          cCalEv += '"addr":"'      + oCalEv:cLocation        + '",'
          cCalEv += '"startdate":"'  + dateijs                 + '",'
          cCalEv += '"starttime":"'  + oCalEv:cStartTime       + '",'
          cCalEv += '"enddate":"'   + dateejs                 + '",'
          cCalEv += '"endtime":"'   + oCalEv:cEndTime         + '",'
          cCalEv += '"allday":"'    + cAllDay                 + '"}'
          
          fnCallBack = getHField(oTmpHash, "callBack")+"('" +cCalEv+ "')"
          oWebEngine:runJavaScript(fnCallBack)
        endif
      endif
      
		endif
		
		
		if codeType == "change_link"
			oGetLink:cText := codeContent+space(1000)
			return
		endif
		// SQLITE - BEGIN -----------------------------------------------------------------------------
		// SQLITE - Begin transction
		if codeType == "dbBegin" .and. getJsonHash(codeContent, @oTmpHash)
			if TCSQLExec("BEGIN") < 0
				// Executa o CallBack de ERRO
				fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
				oWebEngine:runJavaScript(fnCallBack)
			else
				// Executa o CallBack de SUCESSO
				fnCallBack = getHField(oTmpHash, "callBackSuccess") + "();"
				oWebEngine:runJavaScript(fnCallBack)
			endif
		endif
		// SQLITE - Commit
		if codeType == "dbCommit" .and. getJsonHash(codeContent, @oTmpHash)
			if TCSQLExec("COMMIT") < 0
				// Executa o CallBack de ERRO
				fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
				oWebEngine:runJavaScript(fnCallBack)
			else
				// Executa o CallBack de SUCESSO
				fnCallBack = getHField(oTmpHash, "callBackSuccess") + "();"
				oWebEngine:runJavaScript(fnCallBack)
			endif
		endif
		// SQLITE - RollBack
		if codeType == "dbRollback" .and. getJsonHash(codeContent, @oTmpHash)
			if TCSQLExec("ROLLBACK") < 0
				// Executa o CallBack de ERRO
				fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
				oWebEngine:runJavaScript(fnCallBack)
			else
				// Executa o CallBack de SUCESSO
				fnCallBack = getHField(oTmpHash, "callBackSuccess") + "();"
				oWebEngine:runJavaScript(fnCallBack)
			endif
		endif
		// SQLITE - Executa query
		if codeType == "dbExec"
			if getJsonHash(codeContent, @oTmpHash)
				cQuery := getHField(oTmpHash, "query")
				// Testa query
				if TCSQLExec(cQuery) < 0
					// Executa o CallBack de ERRO
					fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
					oWebEngine:runJavaScript(fnCallBack)
				else
					// Executa o CallBack de SUCESSO
					fnCallBack = getHField(oTmpHash, "callBackSuccess") + "();"
					oWebEngine:runJavaScript(fnCallBack)
				endif
			else
				_msgAlert("dbExec command not executed", "CloudBridge")
			endif
		endif
		// SQLITE - Recupera dados da query
		if codeType == "dbGet"
			if getJsonHash(codeContent, @oTmpHash)
				cQuery := getHField(oTmpHash, "query")
				// Testa query
				if TCSQLExec(cQuery) < 0
					// Executa o CallBack de ERRO
					fnCallBack = getHField(oTmpHash, "callBackError") + "('" +TcSqlError()+ "');"
					oWebEngine:runJavaScript(fnCallBack)
					return
				endif
				// Recupera os dados
				dbUseArea(.T., 'TOPCONN', TCGenQry(,,cQuery),'TRB', .F., .T.)
				nFields := TRB->(fCount())
				nRecords := TRB->(recCount())
				xRet := "["
				while !TRB->(eof())
					xRet += '{'
					for i :=  1 to nFields
						xRet += quotedStr( fieldName(i) )+":"
						xRet += quotedStr( fieldGet(i) ) + iif(i < nFields, ",", "")
					next i
					xRet += '}' + iif(TRB->(recno()) < nRecords, ",", "")
					TRB->(DbSkip())
				end
				xRet += "]"
				TRB->(dbCloseArea())
				// Executa o CallBack
				fnCallBack = getHField(oTmpHash, "callBackSuccess") + "(" +xRet+ ");"
				oWebEngine:runJavaScript(fnCallBack)
			else
				_msgAlert("dbGet command not executed", "CloudBridge")
			endif
		endif
		// SQLITE - END -----------------------------------------------------------------------------
		if codeType == "page_started"
			//form:loadForm()
		endif
	endif
return
// Cria componentes superiores
static function CreateFormTop(pnTop)
	// ---------------------------------------------------------------
	Local oButton1
	Local cLink := mainHtml + space(1000)
	Local oFontBtn := TFont():New("Arial Narrow",,022,,.F.,,,,,.F.,.F.)
	Local oFontGet := TFont():New("Arial",,022,,.F.,,,,,.F.,.F.)
	oWebEngine:navigate(mainHtml)
	@ 000, 221 BUTTON oButtonL1 PROMPT "<" SIZE 028, 011 OF pnTop ACTION {|| oWebEngine:goBack() } FONT oFontBtn PIXEL
	@ 000, 221 BUTTON oButtonL2 PROMPT ">" SIZE 028, 011 OF pnTop ACTION {|| oWebEngine:goForward() } FONT oFontBtn PIXEL
	oGetLink := TGet():New( 000, 000, { | u | If( PCount() == 0, cLink, cLink := u ) },pnTop, 220, 011,,, 0, 16777215,,.F.,,.T.,,.F.,,.F.,.F.,,.F.,.F. ,,"cLink",,,, )
	oGetLink:setFont(oFontGet)
	@ 000, 221 BUTTON oButton1 PROMPT "Go" SIZE 028, 011 OF pnTop ACTION {|| oWebEngine:navigate(cLink) } FONT oFontBtn PIXEL
	@ 000, 221 BUTTON oButton2 PROMPT "Menu" SIZE 028, 011 OF pnTop ACTION {|| oGetLink:cText:=mainHtml, oMultGet:Load(""), oWebEngine:Navigate(mainHtml) } FONT oFontBtn PIXEL
	@ 000, 221 BUTTON oButtonClose PROMPT "X" SIZE 028, 011 OF pnTop ACTION {|| oDlg:end() } FONT oFontBtn PIXEL
	oButtonClose:setCSS("QPushButton{margin: 1px; background-color: #C75050; border: none; color: #fff; }")
	oGetLink:setCSS("QLineEdit{margin: 1px; border: 1px solid "+_colorTOTVS)
	oButtonL1:Align 	:= CONTROL_ALIGN_LEFT
	oButtonL2:Align 	:= CONTROL_ALIGN_LEFT
	oButtonClose:Align 	:= CONTROL_ALIGN_RIGHT
	oButton2:Align 		:= CONTROL_ALIGN_RIGHT
	oButton1:Align 		:= CONTROL_ALIGN_RIGHT
	oGetLink:Align 		:= CONTROL_ALIGN_ALLCLIENT
return
// ---------------------------------------------------------------
// Funcoes de apoio
// ---------------------------------------------------------------
static function _conout(cText)
	conOut(cText)
	oMultGet:Load(cText)
Return
Static function _msgAlert(cText)
	// Android Ou iOS
	if _rmtType == 8 .Or. _rmtType == 9
		oMobile:CreateNotification(999, "CloudBridge", cText)
	else
		msgAlert(cText,"")
		conout(cText)
	endif
Return
static function quotedStr(xText)
return ('"'+ cValToChar(xText) +'"')

  • Sem rótulos