quarta-feira, 6 de novembro de 2013

Integração Protheus x Balança rodoviária Lider

Abordando mais uma vez integrações entre protheus e balanças, hoje irei demonstrar uma rotina em advpl que lê o peso da balança rodoviária Lider pela porta serial. Para testar nossa aplicação, podemos baixar o emulador da balança Líder gratuitamente no site  http://www.liderbalancas.com.br/2012/manuais-balancas.html no primeiro link de download.

Para que eu consiga acessar a mesma porta COM com dois programas diferentes (emulador da balança e a rotina advpl), eu não uso a porta física e sim um emulador de porta serial VSPE,o qual pode ser baixado pelo site  http://www.baixaki.com.br/download/free-virtual-serial-ports-emulator.htm. Com o VSPE eu crio uma porta virtual COM1 e é com ela que iremos trabalhar.

A rotina em advpl pode ser baixada no link  http://www.4shared.com/file/EcFWKLrC/BalRodov.html?Compile o fonte e em seguida iremos seguir os passos abaixo:

1) Com o VSPE crie a porta serial virtual COM1
2)Acione o emulador da balança Líder ( arquivo Emulador.exe)
3)Deixe o emulador configurado conforme imagem abaixo:







4) Abra a IDE do protheus e com o fonte BALRODOV.PRW compilado,  execute a rotina.



5) No emulador da balança, clique em modo contínuo



















6)Se tudo estiver ok, teremos a captura do peso pelo protheus conforme print abaixo:























7) Abaixo a rotina em advpl :




#INCLUDE 'RWMAKE.CH'

/*ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÚÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄ¿±±
±±³Programa  ³          ³ Autor ³ LUIS LACOMBE          ³ Data ³          ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄ´±±
±±³Locacao   ³                  ³Contato ³83 8819-6539                    ³±±
±±³   ³                         ³        ³gustavo.lacombe@gmail.com       ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´±±
±±³Descricao ³  Le peso da balanca rodoviaria Lider modelo LD 1001        ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´±±
±±³Parametros³                                                            ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´±±
±±³Retorno   ³                                                            ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´±±
±±³Aplicacao ³                                                            ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´±±
±±³Uso       ³                                                            ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÁÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´±±
±±³Analista Resp.³  Data  ³                                               ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´±±
±±³              ³  /  /  ³                                               ³±±
±±³              ³  /  /  ³                                               ³±±
±±ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß*/

User Function BalRodov

Private cPesoAt      := Space(30)
Private cPesStr    := Space(30)    
Private cCfg     :="COM1:4800,n,8,1"
Private nH       := 0


SetPrvt("oDlg1","oSay1","oSay2","oPesStr","oPeso","oSBtn1")

oDlg1      := MSDialog():New( 091,232,304,578,"Balança rodoviária",,,.F.,,,,,,.T.,,,.T. )
oSay1      := TSay():New( 028,016,{||"STRING DA COM1"},oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,060,008)
oSay2      := TSay():New( 045,017,{||"PESO TRATADO"},oDlg1,,,.F.,.F.,.F.,.T.,CLR_BLACK,CLR_WHITE,059,008)
oPesStr    := TGet():New( 028,088,{|u| If(PCount()>0,cPesStr:=u,cPesStr)},oDlg1,060,008,'',,CLR_BLACK,CLR_WHITE,,,,.T.,"",,,.F.,.F.,,.F.,.F.,"","cPesStr",,)
oPeso      := TGet():New( 048,088,{|u| If(PCount()>0,cPesoAt:=u,cPesoAt)},oDlg1,060,008,'',,CLR_BLACK,CLR_WHITE,,,,.T.,"",,,.F.,.F.,,.F.,.F.,"","cPesoAt",,)
oSBtn1     := SButton():New( 072,120,1,{|| LerPeso()},oDlg1,,"", )

oDlg1:Activate(,,,.T.)

Return




/*/
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÚÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄ¿±±
±±³ Programa ³ LerPeso  ³ Autor ³ LUIS LACOMBE          ³ Data ³ 18/04/13 ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄ´±±
±±³Descri‡…o ³Faz a requisicao de peso para a balanca e le o retorno.     ³±±
±±³          ³Para funcionar, eh importante verificar o protocolo de      ³±±
±±³          ³comunicacao da balanca. No caso da TOLEDO,ela tem que estar ³±±
±±³          ³usando o protocolo que responda ao sinal ENQ, por exemplo   ³±±
±±³          ³o protocolo P05 ou P05A. Importante lembrar que a funcao    ³±±
±±³          ³nao trata a estabilizacao de peso. Se quiser receber o peso ³±±
±±³          ³somente quando ele estabilizar,use o protocolo adequado como³±±
±±³          ³P05 da TOLEDO.                                              ³±±
±±ÀÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
/*/
Static Function LerPeso()

Local cPeso := 0
Local cBuffer

cCfg      :="COM1:4800,n,8,1"

lRet       := msOpenPort(nH,cCfg)
if(!lRet)
Alert("Falha ao conectar com a porta serial")
Return
EndIf

//msWrite(nH,Chr(5))
//Sleep(200)
For ncont := 1 To 50
msRead(nH,@cBuffer)
if(!Empty(cBuffer))
  // ALERT(cBuffer)
   cPesStr := cBuffer
cPeso := IsNumber(cBuffer)
Exit
EndIf
Next
msClosePort(nH)

cPesoAt  := cPeso

// PRA TESTAR O PROGRAMA SEM BALANCA
//nPeso := Val(cSimPes)

Return



/*/
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
±±ÚÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄ¿±±
±±³ Programa ³ IsNumber ³ Autor ³ LUIS LACOMBE          ³ Data ³ 18/04/13 ³±±
±±ÃÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄ´±±
±±³Descri‡…o ³Separa os caracteres numericos da string recebida da balanca³±±
±±ÀÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ±±
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
/*/
Static Function IsNumber(cNum)

Local nPosPar  
Local cPesB     := ""
Local cNumeros  := "0123456789."
Local cNewNum   := ""
Local nPes      := 0


//bloco que separa o numero da string enviada pela balanca
For nCont := 1 To Len(cNum)
    if(SubStr(cNum,nCont,1)=="E")    
        Exit
    EndIf
   
    if(SubStr(cNum,nCont,1)=="I") // peso instavel
        Return "-1"      
    EndIf
   
    if(SubStr(cNum,nCont,1)$cNumeros)
       cNewNum += SubStr(cNum,nCont,1)
    EndIf
Next nCont

cPesB  :=  cNewNum

Return cPesB


domingo, 1 de setembro de 2013

Integração Protheus X Balança via comunicação serial sem DLL

 Neste artigo irei mostrar como podemos fazer uma rotina em advpl que irá requisitar o peso a uma balança Filizola via porta serial. Essa requisição funciona também para balanças TOLEDO, porém o layout de retorno é um pouco diferente. A vantagem desse método é não depender de DLL e assim não ficar preso a uma marca específica. Antes de tudo é preciso que a balança esteja com o protocolo adequado para funcionar com requisição serial. Em muitos modelos da TOLEDO, o protocolo é o P05, já algumas balanças FILIZOLA já vem preparadas para responder a esse tipo de requisição. 

O esquema abaixo resume o processo:









Primeiramente iremos fazer a comunicação com a porta serial. Para isso usamos o seguinte código Advpl:

Local cCfg :=”COM1:4800,n,8,1″
lRet := msOpenPort(nH,cCfg)
if(!lRet)

    Alert(“Falha ao conectar com a porta serial”)
     Return 

EndIf 

 O próximo passo será enviar um comando 5 HEXADECIMAL (ENQ) para a porta aonde em que a balança está conectada. Eu tinha até aberto um chamado na TOTVS perguntando como isso poderia ser feito e responderam que não era possível, enfim , eu não acredite e pesquisei alguma forma de fazer isso. Até que consegui usando um comando super simples que é : 
 msWrite(nH,Chr(5))

 Ou seja, eu escrevo na porta COM o Chr(5) e se tudo estiver certo a balança irá devolver o peso. Resumidamente, a rotina básica ficaria assim:
lRet := msOpenPort(nH,cCfg)
if(!lRet)
    Alert(“Falha ao conectar com a porta serial”)
    Return
EndIf 

msWrite(nH,Chr(5))
Sleep(200)

For ncont := 1 To 20
      msRead(nH,@cBuffer)
      if(!Empty(cBuffer))
                 cPeso :=IsNumber(cBuffer) // IsNumber função que criei para tirar os caracteres especiais                            cBuffer := “” 
                 Exit 
      EndIf 
Next 
msClosePort(nH)

Para que essa comunicação dê certo, é preciso atentar para alguns detalhes:
 1) Tentei várias combinações de velocidades para a porta COM1 do micro e a que deu mais certo foi Bits         por segundo : 4800, Bits de dados: 7,Paridade: Even, Bits de parada: 2 e controle de fluxo: nenhum.

 2) Com relação a configuração da velocidade da balança, a melhor que eu achei foi A mesma configuração      da COM1 dita no primeiro item mudando apenas Bits de dados para 8.



 Espero que este artigo tenha sido útil . Até a próxima.

sexta-feira, 23 de dezembro de 2011

Importar produtos de outros sistemas para o Protheus

Pessoal, desenvolvi um programa em C# que faz a importação de produtos de qualquer base de dados para o Protheus. Fica aí mais um exemplo de integração entre Protheus e C#.

Este vídeo fala do passo a passo dos procedimentos iniciais





Este outro vídeo mostra o programa funcionando



Aqui o link para baixar o programa
www.4shared.com/rar/qDP_ytZM/Imp_SB1.html?

quarta-feira, 16 de novembro de 2011

Navegador Web feito em Advpl

Abaixo estou disponibilizando um código que monta um navegador em advpl. Ele guarda as páginas visitadas e permite a navegação entre elas como acontece em um navegador web.

Obs: Para funcionar, é preciso configurar o smartcliente.ini e colocar logo abaixo da marcação [config] a opção:
BrowserEnabled=1




#include "protheus.ch"


User Function Navegador()

Private aPages := {} // array que guarda os endereços visitados
Private nPgVist := -1 // controle a posicao do array aPages

Private aSize := MsAdvSize() // pega o tamanho da tela
Private oDlg1, oTIBrw
Private cNavegado := Space(80) // usado no objeto get para guardar os endereços web
Private lcont := .T.

DEFINE MSDIALOG oDlg1 TITLE "Navegador" From aSize[7],0 to aSize[6],aSize[5] of oMainWnd PIXEL

cNavegado := "http://www.google.com" // pagina inicial
oNav:= TGet():New(10,10,{|u| if(PCount()>0,cNavegado:=u,cNavegado)}, oDlg1,340,5,,,,,,,,.T.,,,,,,,,,,)

@ 010, 350 Button oBtnIr PROMPT "Ir" Size 40,10 Action(Processa({||Navegar()},"Abrindo","Aguarde...")) Of oDlg1 Pixel
@ 010, 390 Button oBtnImp PROMPT "Imprimir" Size 40,10 Action oTIBrw:Print() Of oDlg1 Pixel



@ 010, 430 Button oBtnAnte PROMPT "Anterior" Size 40,10 Action (Retorna()) Of oDlg1 Pixel
@ 010, 470 Button oBtnDep PROMPT "Avançar" Size 40,10 Action(Avanca()) Of oDlg1 Pixel
@ 010, 510 Button oBtnSair PROMPT "Sair" Size 40,10 Action(Sair()) Of oDlg1 Pixel



oTIBrw:= TIBrowser():New( 025,010,aSize[5]-640, 270, "http://www.google.com", oDlg1 )

aaDD(aPages,"http://www.google.com")

oNav:bLostFocus := { || Valido()}


Activate MsDialog oDlg1 Centered

Return


Static Function Navegar()

Ir()

Return


Static Function Ir()

oTIBrw:Navigate(AllTrim(cNavegado),oDlg1)
aaDD(aPages,AllTrim(cNavegado))
nPgVist := Len(aPages)

Return



Static Function Avanca() // proxima proxima pagina que jah foi visitada

if(Len(aPages) > nPgVist .and. Len(aPages) > 1 )
nPgVist++
oTIBrw:Navigate(aPages[nPgVist],oDlg1)
cNavegado := aPages[nPgVist]
oNav:Refresh()
EndIf

Return


Static Function Retorna() // pagina anterior que foi visitada
if(nPgVist>1)
nPgVist--
oTIBrw:Navigate(aPages[nPgVist],oDlg1)
cNavegado := aPages[nPgVist]
oNav:Refresh()
EndIf

Return



Static Function Sair() // fecha a tela
oDlg1:End()
Return



Abaixo um print da tela:


quarta-feira, 5 de outubro de 2011

Relatórios Mensais

Algumas vezes eu preciso gerar relatórios que mostrem dados entre determinados meses. Abaixo, um trecho desse tipo de relatório.


Basicamente, o usuário informa o mês e ano inicial, mês e ano final e a partir daí eu gero um array contendo o intervalo. Ele tem a estrutura conforme figura abaixo:


Posso então usar os elementos deste array como parâmetros em consultas que gerem tabelas temporárias além de imprimi-los no relatório conforme a primeira figura.
Abaixo, as funções que geram o array.


Agora a função auxiliar da função acima que retorna o nome do mês:

quarta-feira, 10 de agosto de 2011

Integração do Protheus com C# e .Net


Hoje irei mostrar um outro exemplo de integração do Protheus com DotNet usando a linguagem C#. Neste exemplo irei solicitar ao protheus o cálculo do valor de parcelas (simulação de parcelas), ou seja,irei fazer a conexão da minha aplicação em DotNet com o servidor de aplicações, passarei alguns parâmetros como valor total, código da condição de pagamento e irei obter um array como retorno informando a data de vencimento e valor da parcela. Pra começar é necessário registrar a ocx apconnxcontrol.ocx e fazer referência da mesma no Visual Studio, para isso crie um novo projeto do tipo Console e siga os passos mostrados da publicação anterior "Integração do Protheus com C# ". Feito isso, minimize o Visual Studio, crie e compile o seguinte código fonte no Protheus.


No fonte eu expliquei que poderia referenciar diretamente a função do Protheus que realiza as simulações, mas tive dificuldade em passar como parâmetro o tipo data, então pra não ficar defendendo teoria, criei a user function que faz o tratamento da data que é passada pelo Visual Studio como string.

Voltando ao Visual Studio, criei uma classe que realiza a conexão com o Protheus e também um método que aciona minha user function e obtém o resultado da simulaçao de parcelas. Observe o código da classe e seus comentários.



E na classe principal irei criar o seguinte código:


Para ver o programa funcionando, veja o vídeo abaixo:
obs: Veja em tela cheia para melhor visualização.











segunda-feira, 8 de agosto de 2011

integração do Protheus com C#


Nessa postagem darei um exemplo bem simples de como integrar o Protheus com Csharp. Primeiramente temos que registrar no windows um arquivo ocx que está dentro do smartclient chamado apconnxcontrol.ocx . Para registrar é simples, eu copiei o arquivo para a pasta System32 do windows, logo depois executei o cmd.exe e fiz o seguinte comando:
regsvr32 apconnxcontrol.ocx . Lembrando que no Windows 7 você tem que executar o cmd.exe como administrador, caso contrário não dará certo.









Concluída essa etapa, é hora de abrir o Visual Studio.
No exemplo a seguir eu usei o VS 2010 e criei um novo projeto do tipo Console. Faça o mesmo e com o Program.cs aberto clique em adicionar uma nova referencia conforme figura abaixo:


Usando a guia Browse vá até a pasta System32 do Windows e selecione o arquivo apconnxcontrol.ocx:


Nessa etapa já temos o "link" com nossa ocx do protheus. Agora é só por a mão na massa e começar a brincar com as funções. No exemplo abaixo criei uma User Function no protheus que retorna um array de string. Após compilado, fui no Visual Studio e feito as devidas referências eu fiz com que o código em C# executasse a minha User Function do protheus e exibisse o retorno dela no Console.

//user function compilada no protheus
#INCLUDE "rwmake.ch"

User Function RetTest()

Local aTeste := {}

aaDD(aTeste,"teste1")
aaDD(aTeste,"teste2")
aaDD(aTeste,"teste3")

Return aTeste

Código no C#, observe as referências :






Se tudo der certo teremos o resultado abaixo:



Tem uma documentação de RPC nos fóruns de advpl, lá tem mais detalhes. Espero ter colaborado com algum conhecimento e lembrando que podemos usar a ocx em outras linguagens que tem suporte a esse tipo de arquivo. Até a próxima.