Às vezes, nosso componente COM deve enviar uma notificação ao cliente ou chamar a função de retorno de chamada. O esquema é simples: o componente publica a interface, o cliente cria um objeto herdado da interface e o passa para o componente, o componente, por sua vez, chama as funções da interface, chamando as funções no lado do cliente.
No caso do Visual Basic ou Visual Basic for Applicatons, podemos escrever uma classe herdada de qualquer interface, mas isso não é possível para arquivos de script VBScript.
Aqui a interface do IDispatch corre em nosso auxílio. Usando essa interface, nosso componente poderoso assumirá humildemente o papel modesto de um cliente, e um pequeno script se tornará um servidor de automação real.
Vamos desenvolver o componente na linguagem de programação FreeBASIC.
Classes no arquivo de script
Você pode declarar e usar classes em arquivos de script. Tais classes são herdadas implicitamente da interface IDispatch e são classes COM reais.
Declaramos uma classe, uma instância da qual passaremos para o nosso componente mais tarde:
Class CallBack Function CallBack(Param)
Nosso componente receberá uma instância da classe CallBack , chamará a função CallBack e passará uma string com texto no parâmetro
IDispatch
Essa interface é o obstáculo da automação. Normalmente, a implementação do IDispatch baseada em uma biblioteca de tipos através da função ITypeInfo->Invoke ou CreateStdDispatch , mas nesse caso o servidor de automação está localizado em um script e não possui uma biblioteca de tipos, e nosso componente atua como um cliente. Para simplificar, o IDipatch funciona assim: pega o nome da função e transfere o controle para ela.
A definição da interface está no cabeçalho "oaidl.bi" (recuos e quebras de linha são adicionados para facilitar a leitura):
Type IDispatch As IDispatch_ Type LPDISPATCH As IDispatch Ptr Type IDispatchVtbl
As funções GetIDsOfNames e Invoke são mais interessantes nessa interface.
GetIDsOfNames
Ele pega o nome da função e retorna seu identificador de despacho DISPID . DISPID é um alias para o tipo LONG .
Do ponto de vista do cliente, DISPID é simplesmente uma ferramenta de otimização que evita DISPID linha. Para o servidor, DISPID é o identificador da função que o cliente deseja chamar.
Invocar
Por identificador de despacho executa a função correspondente.
DISPPARAMS
Essa estrutura contém os parâmetros da função chamada. Todos os parâmetros são empacotados em VARIANT .
Type tagDISPPARAMS
Para simplificar o código, não usaremos argumentos nomeados; em vez disso, definiremos NULL .
Componente
Para uso em scripts, os componentes também devem herdar direta ou indiretamente do IDipatch .
Interface ITestCOMServer
ITestCOMServer criar a interface ITestCOMServer com duas funções SetCallBack e InvokeCallBack . O primeiro salvará o objeto do servidor de automação, o segundo chamará a função de objeto.
Type ITestCOMServer As ITestCOMServer_ Type LPITESTCOMSERVER As ITestCOMServer Ptr Type ITestCOMServerVirtualTable
Classe TestCOMServer
Agora você pode declarar uma classe COM:
Type TestCOMServer
Função setcallback
A implementação da função SetCallBack simples: salvamos o objeto do servidor de automação transmitido pelo cliente e o parâmetro de chamada da função.
Function TestCOMServerSetCallBack( _ ByVal pTestCOMServer As TestCOMServer Ptr, _ ByVal CallBack As IDispatch Ptr, _ ByVal UserName As BSTR _ )As HRESULT
Função InvokeCallBack
Mas a função InvokeCallBack terá InvokeCallBack trabalhar duro. Primeiro, você precisa obter o identificador de despachante da função CallBack do servidor de automação.
Function TestCOMServerInvokeCallBack( _ ByVal pTestCOMServer As TestCOMServer Ptr _ )As HRESULT If pTestCOMServer->CallBack = NULL Then Return E_POINTER End If
Depois que o DISPID função é recebido, ele pode ser chamado:
Conclusão
Como você pode ver, mesmo com um arquivo de script, um componente pode receber feedback. Isso é útil para notificar o cliente sobre as operações concluídas pelo componente.
As classes em scripts podem ser registradas no registro, caso em que estarão disponíveis para todo o sistema usando ProgID , mas essa é uma história completamente diferente.
Referências
Código do projeto no site do github: https://github.com/zamabuvaraeu/TestCOMServer
PS De alguma forma, o destaque para a sintaxe BASIC desapareceu, usou o VBScript e alguns operadores não são destacados.