Instruções passo a passo: chamando APIs do Windows (Visual Basic)

As APIs do Windows são DLLs (bibliotecas de vínculo dinâmico) que fazem parte do sistema operacional Windows. Você as usa para executar tarefas quando for difícil escrever procedimentos equivalentes por conta própria. Por exemplo, o Windows fornece uma função nomeada FlashWindowEx que permite que a barra de título de um aplicativo alterne entre tons claros e escuros.

A vantagem de usar as APIs do Windows em seu código é que elas podem economizar tempo de desenvolvimento porque contêm dezenas de funções úteis que já foram gravadas e estão aguardando para serem usadas. A desvantagem é que pode ser difícil trabalhar com as APIs do Windows e elas são desfavoráveis quando as coisas dão errado.

As APIs do Windows representam uma categoria especial de interoperabilidade. As APIs do Windows não usam código gerenciado, não têm bibliotecas de tipos internos e usam tipos de dados diferentes daqueles usados com o Visual Studio. Devido a essas diferenças e como as APIs do Windows não são objetos COM, a interoperabilidade com APIs do Windows e o .NET Framework é executada usando a invocação de plataforma ou PInvoke. A invocação de plataforma é um serviço que permite que um código gerenciado chame funções não gerenciadas implementadas em DLLs. Para saber mais, veja Consumo de funções de DLL não gerenciadas. Você pode usar o PInvoke no Visual Basic usando a instrução Declare ou aplicando o atributo DllImport a um procedimento vazio.

As chamadas à API do Windows eram uma parte importante da programação do Visual Basic no passado, mas raramente são necessárias com o .NET do Visual Basic. Sempre que possível, você deve usar o código gerenciado do .NET Framework para executar tarefas, em vez de chamadas à API do Windows. Este passo a passo fornece informações para as situações em que o uso de APIs do Windows é necessário.

Observação

Seu computador pode mostrar diferentes nomes ou locais para alguns dos elementos de interface do usuário do Visual Studio nas instruções a seguir. A edição do Visual Studio que você possui e as configurações que você usa determinam esses elementos. Para obter mais informações, consulte Personalizando o IDE.

Chamadas à API usando Declare

A maneira mais comum de chamar APIs do Windows é usando a instrução Declare.

Para declarar um procedimento DLL

  1. Determine o nome da função que deseja chamar, além de seus argumentos, tipos de argumento e valor retornado, bem como o nome e o local da DLL que a contém.

    Observação

    Para obter informações completas sobre as APIs do Windows, consulte a documentação do SDK do Win32 na API do Windows do SDK da Plataforma. Para obter mais informações sobre as constantes que as APIs do Windows usam, examine os arquivos de cabeçalho, como o Windows.h incluído no SDK da Plataforma.

  2. Abra um novo projeto de Aplicativo do Windows clicando em Novo no menu Arquivo e, em seguida, clicando em Projeto. A caixa de diálogo Novo Projeto aparecerá.

  3. Selecione Aplicativo do Windows na lista de modelos de projeto do Visual Basic. O novo projeto é exibido.

  4. Adicione a seguinte função Declare à classe ou ao módulo no qual você deseja usar a DLL:

    Declare Auto Function MBox Lib "user32.dll" Alias "MessageBox" (
        ByVal hWnd As Integer,
        ByVal txt As String,
        ByVal caption As String,
        ByVal Typ As Integer) As Integer
    

Partes da instrução Declare

A instrução Declare inclui os seguintes elementos.

Modificador automático

O modificador Auto instrui o runtime a converter a cadeia de caracteres com base no nome do método de acordo com as regras de Common Language Runtime (ou nome do alias, se especificado).

Palavras-chave Lib e Alias

O nome que segue a palavra-chave Function é o nome que seu programa usa para acessar a função importada. Ele pode ser o mesmo que o nome real da função que você está chamando ou você pode usar qualquer nome de procedimento válido e, em seguida, empregar a palavra-chave Alias para especificar o nome real da função que você está chamando.

Especifique a palavra-chave Lib, seguida pelo nome e local da DLL que contém a função que você está chamando. Não é necessário especificar o caminho para arquivos localizados nos diretórios do sistema Windows.

Use a palavra-chave Alias se o nome da função que você está chamando não for um nome de procedimento válido do Visual Basic ou entrar em conflito com o nome de outros itens em seu aplicativo. Alias indica o nome verdadeiro da função que está sendo chamada.

Declarações de tipo de dados e argumentos

Declare os argumentos e seus tipos de dados. Essa parte pode ser desafiadora porque os tipos de dados usados pelo Windows não correspondem aos tipos de dados do Visual Studio. O Visual Basic faz muito trabalho para você convertendo argumentos em tipos de dados compatíveis, um processo chamado marshaling. Você pode controlar explicitamente como os argumentos realizam marshaling usando o MarshalAsAttribute atributo definido no namespace System.Runtime.InteropServices.

Observação

As versões anteriores do Visual Basic permitiram que você declarasse parâmetros As Any, o que significa que os dados de qualquer tipo de dados poderiam ser usados. O Visual Basic exige que você use um tipo de dados específico para todas as instruções Declare.

Constantes de API do Windows

Alguns argumentos são combinações de constantes. Por exemplo, a API MessageBox mostrada neste passo a passo aceita um argumento inteiro chamado Typ que controla como a caixa de mensagem é exibida. Você pode determinar o valor numérico dessas constantes examinando as instruções #define no arquivo WinUser.h. Os valores numéricos geralmente são mostrados em hexadecimal, portanto, talvez seja necessário usar uma calculadora para adicioná-los e convertê-los em decimais. Por exemplo, se você quiser combinar as constantes para o estilo de exclamação MB_ICONEXCLAMATION 0x00000030 e o estilo Sim/Não MB_YESNO 0x00000004, você poderá adicionar os números e obter um resultado de 0x00000034 ou 52 decimais. Embora você possa usar o resultado decimal diretamente, é melhor declarar esses valores como constantes em seu aplicativo e combiná-los usando o operador Or.

Para declarar constantes para chamadas à API do Windows
  1. Consulte a documentação da função do Windows que você está chamando. Determine o nome das constantes que ele usa e o nome do arquivo .h que contém os valores numéricos dessas constantes.

  2. Use um editor de texto, como o Bloco de Notas, para exibir o conteúdo do arquivo de cabeçalho (.h) e localizar os valores associados às constantes sendo usadas. Por exemplo, a API MessageBox usa a constante MB_ICONQUESTION para mostrar um ponto de interrogação na caixa de mensagem. A definição de MB_ICONQUESTION está em WinUser.h e aparece da seguinte maneira:

    #define MB_ICONQUESTION 0x00000020L

  3. Adicione instruções Const equivalentes à sua classe ou módulo para disponibilizar essas constantes ao seu aplicativo. Por exemplo:

    Const MB_ICONQUESTION As Integer = &H20
    Const MB_YESNO As Integer = &H4
    Const IDYES As Integer = 6
    Const IDNO As Integer = 7
    
Para chamar o procedimento DLL
  1. Adicione um botão nomeado Button1 ao formulário de inicialização do projeto e clique duas vezes nele para exibir o código. O manipulador de eventos para o botão é exibido.

  2. Adicione código ao manipulador de eventos Click para o botão que você adicionou, para chamar o procedimento e fornecer os argumentos apropriados:

    Private Sub Button1_Click(ByVal sender As System.Object,
        ByVal e As System.EventArgs) Handles Button1.Click
    
        ' Stores the return value.
        Dim RetVal As Integer
        RetVal = MBox(0, "Declare DLL Test", "Windows API MessageBox",
            MB_ICONQUESTION Or MB_YESNO)
    
        ' Check the return value.
        If RetVal = IDYES Then
            MsgBox("You chose Yes")
        Else
            MsgBox("You chose No")
        End If
    End Sub
    
  3. Execute o projeto pressionando F5. A caixa de mensagem é exibida com botões de resposta Sim e Não. Clique em qualquer um deles.

Marshalling de dados

O Visual Basic converte automaticamente os tipos de dados de parâmetros e os valores retornados para chamadas à API do Windows, mas você pode usar o atributo MarshalAs para especificar explicitamente os tipos de dados não gerenciados esperados por uma API. Para obter mais informações sobre o marshalling de interoperabilidade, consulte Marshaling de interoperabilidade.

Para usar Declare e MarshalAs em uma chamada à API
  1. Determine o nome da função que deseja chamar, além de seus argumentos, tipos de dados e valor retornado.

  2. Para simplificar o acesso ao atributo MarshalAs, adicione uma instrução Imports à parte superior do código para a classe ou módulo, como no exemplo a seguir:

    Imports System.Runtime.InteropServices
    
  3. Adicione um protótipo de função para a função importada à classe ou módulo que você está usando e aplique o atributo MarshalAs aos parâmetros ou valor retornado. No exemplo a seguir, uma chamada à API que espera que o tipo void* tenha realizado marshaling como AsAny:

    Declare Sub SetData Lib "..\LIB\UnmgdLib.dll" (
        ByVal x As Short,
        <MarshalAsAttribute(UnmanagedType.AsAny)>
            ByVal o As Object)
    

Chamadas à API usando DllImport

O atributo DllImport fornece uma segunda maneira de chamar funções em DLLs sem bibliotecas de tipos. DllImport é aproximadamente equivalente ao uso de uma instrução Declare, mas fornece mais controle sobre como as funções são chamadas.

Você pode usar DllImport com a maioria das chamadas à API do Windows, desde que a chamada se refira a um método compartilhado (às vezes chamado de estático). Você não pode usar métodos que exigem uma instância de uma classe. Ao contrário das instruções Declare, DllImport as chamadas não podem usar o atributo MarshalAs.

Para chamar uma API do Windows usando o atributo DllImport

  1. Abra um novo projeto de Aplicativo do Windows clicando em Novo no menu Arquivo e, em seguida, clicando em Projeto. A caixa de diálogo Novo Projeto aparecerá.

  2. Selecione Aplicativo do Windows na lista de modelos de projeto do Visual Basic. O novo projeto é exibido.

  3. Adicione um botão nomeado Button2 ao formulário de inicialização.

  4. Clique duas vezes em Button2 para abrir o modo de exibição de código do formulário.

  5. Para simplificar o acesso DllImport, adicione uma instrução Imports à parte superior do código para a classe do formulário de inicialização:

    Imports System.Runtime.InteropServices
    
  6. Declare uma função vazia antes da instrução End Class do formulário e nomeie a função MoveFile.

  7. Aplique os modificadores Public e Shared à declaração de função e defina os parâmetros para MoveFile com base nos argumentos usados pela função de API do Windows:

    Public Shared Function MoveFile(
        ByVal src As String,
        ByVal dst As String) As Boolean
        ' Leave the body of the function empty.
    End Function
    

    Sua função pode ter qualquer nome de procedimento válido; o atributo DllImport especifica o nome na DLL. Ele também identifica o marshalling de interoperabilidade para os parâmetros e valores retornados, para que você possa escolher tipos de dados do Visual Studio semelhantes aos tipos de dados que a API usa.

  8. Aplique o atributo DllImport à função vazia. O primeiro parâmetro é o nome e o local da DLL que contém a função que você está chamando. Não é necessário especificar o caminho para arquivos localizados nos diretórios do sistema Windows. O segundo parâmetro é um argumento nomeado que especifica o nome da função na API do Windows. Neste exemplo, o atributo DllImport força as chamadas a MoveFile a serem encaminhadas para MoveFileW no KERNEL32.DLL. O método MoveFileW copia um arquivo do caminho src para o caminho dst.

    <DllImport("KERNEL32.DLL", EntryPoint:="MoveFileW", SetLastError:=True,
        CharSet:=CharSet.Unicode, ExactSpelling:=True,
        CallingConvention:=CallingConvention.StdCall)>
    Public Shared Function MoveFile(
        ByVal src As String,
        ByVal dst As String) As Boolean
        ' Leave the body of the function empty.
    End Function
    
  9. Adicione código ao manipulador de eventos Button2_Click para chamar a função:

    Private Sub Button2_Click(ByVal sender As System.Object,
        ByVal e As System.EventArgs) Handles Button2.Click
    
        Dim RetVal As Boolean = MoveFile("c:\tmp\Test.txt", "c:\Test.txt")
        If RetVal = True Then
            MsgBox("The file was moved successfully.")
        Else
            MsgBox("The file could not be moved.")
        End If
    End Sub
    
  10. Crie um arquivo chamado Test.txt e coloque-o no diretório C:\Tmp no disco rígido. Crie o diretório Tmp, se necessário.

  11. Pressione F5 para iniciar o aplicativo. O formulário principal é exibido.

  12. Clique em Button2. A mensagem "O arquivo foi movido com êxito" será exibida se o arquivo puder ser movido.

Confira também