Visual Basic, VB .NET, ASP, Active X, Access, SQL Server

Criando uma fila de eventos para o seu programa

Os programas realizam tarefas dentro de procedimentos, mas certas situações exigem que a continuidade de uma tarefa só deva ser retomada após a saída do procedimento em curso. Pode ser que o programa esteja tratando um evento, que deva ser finalizado para que o componente se ajuste à nova situação; ou pode estar recebendo um aviso do servidor, que não pode ficar esperando pelo tratamento do aviso. Em fim, várias podem ser as razões para abandonar um procedimento e querer retomar as atividades na seqüência. 

Sabendo que toda janela possui uma fila de mensagens, onde são depositadas as mensagens para ela, você pode compartilhar a fila de mensagens de uma janela da sua aplicação. Basta que esta janela esteja carregada nos momentos em que você precisar usar a fila. A técnica consiste em criar um ou mais identificadores próprios de mensagens para a sua aplicação usando a API RegisterWindowMessage. Feito isto, você deve subclassificar a janela para ter acesso à sua fila de mensagens. Quando quiser interromper um procedimento e retomar as atividades após sair dele, use a API PostMessage para postar mensagens com identificadores iguais àqueles retornados pela chamada a RegisterWindowMessage. No procedimento de janela substituto, que você criou na subclassificação, teste pelo identificador da mensagem que chega e, se for um dos seus, chame  o procedimento desejado para tratar a mensagem. 

Você não vai poder passar referências a objetos como parâmetros destas mensagens, mas, usando a função não documentada ObjPtr, você poderá obter um Long contendo um ponteiro para qualquer objeto e passar este ponteiro como parâmetro em PostMessage. Ao receber a mensagem no procedimento de janela, recupere o objeto usando a rotina ObjectFromPtr escrita abaixo:

Public Function ObjectFromPtr(ByVal lPtr As Long) As Object
    Dim objT As Object
    ' código de Bruce McKinney para obter um objeto
    ' de um ponteiro:
    CopyMemory objT, lPtr, 4
    Set ObjectFromPtr = objT
    CopyMemory objT, 0&, 4
End Function

Como você vê, esta rotina exige a declaração da API CopyMemory. Veja abaixo a declaração:

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Você também pode usar os dois parâmetros de PostMessage criativamente dividindo-os em duas metades. Use a metade superior do Long para conter uma informação e a metade inferior para conter outra.  Abaixo você tem algumas funções para manipular Longs. Como dependem da declaração de MoveMemory, abaixo está a declaração:

Public Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)

' Retorna os primeiros 16 bits de um inteiro de 32 bits

Public Function LOWORD(dwValue As Long) As Integer
     MoveMemory LOWORD, dwValue, 2
End Function


' Retorna a segunda metade de 16 bits de um inteiro de 32 bits

Public Function HIWORD(dwValue As Long) As Integer
     MoveMemory HIWORD, ByVal VarPtr(dwValue) + 2, 2
End Function 

Monta um Long dados os valores que cabem nas suas metades inferior e superior 

Public Function MAKELONG(wLow As Long, wHigh As Long) As Long
     MAKELONG = wLow
     MoveMemory ByVal VarPtr(MAKELONG) + 2, wHigh, 2
End Function