Sintomas

A barra de rolagem é rolada continuamente até que você solte o botão esquerdo do mouse. O tipo de barra de rolagem é irrelevante para esse problema, isto é, o mesmo problema ocorre independentemente de a barra de rolagem fazer parte da janela ou um controle de barra de rolagem.

Causa

Esse problema ocorre geralmente quando um loop de recuperação de mensagem é executado como resultado de ações executadas para rolagem após receber uma das mensagens de notificação de barra de rolagem. Durante a rolagem, um loop de recuperação de mensagem interna é iniciado no Windows. A tarefa deste loop de mensagem é acompanhar a rolagem e enviar as mensagens de notificação de barra de rolagem apropriadas, WM_HSCROLL e WM_VSCROLL. A rolagem é terminada quando WM_LBUTTONUP é recebido. Se outro loop de mensagem for iniciado durante a rolagem, o WM_LBUTTONUP é recuperado por esse loop de mensagem e, como um aplicativo não tem acesso ao loop de recuperação de mensagens interna da barra de rolagem, WM_LBUTTONUP não pode ser despachado corretamente. Portanto, o WM_LBUTTONUP nunca é recebido pelo recuperador de mensagens interna, e a rolagem nunca terminou. O aplicativo que é rolável não precisa recuperar mensagens explicitamente para causar esse problema. Chamar qualquer uma das funções a seguir ou processar qualquer mensagem que tenha um loop de recuperação de mensagens durante a rolagem pode fazer com que a WM_LBUTTONUP seja perdida. As funções listadas abaixo caem nesta categoria:

DialogBox() DialogBoxIndirect() DialogBoxIndirectParam() DialogBoxParam() GetMessage() MessageBox() PeekMessage()

Resolução

Durante a rolagem, a mensagem WM_LBUTTONUP não deve ser recuperada da fila por qualquer loop de recuperação de mensagens que não seja o interno da barra de rolagem. Um aplicativo pode vir este problema da seguinte maneira:

  • Um aplicativo implementa um loop de recuperação de mensagem para implementar o processamento em segundo plano, por exemplo, processamento em segundo plano durante a execução de uma pintura que consome tempo.

  • Um aplicativo implementa um loop de recuperação de mensagens para implementar a comunicação com outro aplicativo ou DLL. Por exemplo, para rolar, o aplicativo precisa receber dados de outro lugar.

Possíveis soluções alternativas

Duas soluções possíveis estão listadas abaixo. A primeira solução alternativa é usada por muitos aplicativos de saída e pelo Windows; no entanto, em circunstâncias raras, a primeira solução alternativa pode não ser uma viável. Nesse caso, a segunda alternativa pode ser usada. No entanto, se possível, tente evitar a implementação completa da recuperação de mensagens durante a rolagem.

  • Use o processamento baseado em temporizador/mensagem. Divida o processamento complicado em tarefas menores e controle o local de início e término de cada tarefa e execute cada tarefa com base em uma mensagem de temporizador. Quando todos os componentes do processamento estiverem concluídos, desative o temporizador. Veja abaixo um exemplo dessa solução alternativa.

  • Implemente um loop de recuperação de mensagens, mas certifique-se de que WM_LBUTTONUP não seja recuperada por ele. Isso pode ser feito com o uso de filtros. Veja abaixo alguns exemplos dessa solução alternativa.

Exemplo que demonstra a solução alternativa 1

Um aplicativo tem um procedimento complexo de pintura. Chamar ScrollWindow (), para rolar, gera mensagens de pintura. O processamento em segundo plano ocorre durante a pintura.

  1. Quando receber a mensagem WM_PAINT faça o seguinte:

    1. Chame BeginPaint ().

    2. Copie o Rect invalidado para uma variável Rect global (por exemplo, grcPaint) a ser usado na etapa 2. O grcPaint global Rect seria uma União do Rect anteriormente obtido (grcPaint) e o novo Rect invalidado (PS. rcPaint). O código para isso será semelhante ao seguinte:

               RECT grcPaint;    // Should be initialized before getting the                           // first paint message.            :            :         UnionRect(&grcPaint, &ps.rcPaint,&grcPaint);
    3. Chame ValidateRect () com PS. rcPaint.

    4. Chame EndPaint ().

    5. Definir um temporizador.

    Dessa forma, não são geradas mais mensagens WM_PAINT porque não há regiões inválidas, e um temporizador é configurado, o que gerará WM_TIMER mensagens.

  2. Ao receber uma mensagem de WM_TIMER, verifique a variável de retângulo global; Se não estiver vazio, faça uma seção e pinte-a. Em seguida, ajuste a variável de retângulo global para que ela não inclua mais a região pintada.

  3. Depois que a variável Rect global estiver vazia, desative o temporizador.

Exemplo que demonstra a solução alternativa 2

Um aplicativo precisa obter alguns dados por meio de DDE ou outro mecanismo de outro aplicativo, que será exibido na janela. Para poder rolar, o aplicativo precisa solicitar e obter os dados de um aplicativo de servidor. Há três filtros diferentes que podem ser usados para configurar um PeekMessage () e obter as informações. Os filtros podem ser configurados usando os parâmetros uFilterFirst e uFilterLast de PeekMessage (). uFilterFirst especifica a mensagem punho no intervalo a ser marcada e uFilterLast especifica a última mensagem no intervalo a ser marcada.

  1. Verifique e recupere somente as mensagens relacionadas para obter os dados necessários.

  2. Verifique se há WM_LBUTTONUP sem removê-lo para a fila; Se estiver na fila, interrompa. Caso contrário, recupere e envie todas as mensagens.

  3. Recuperar todas as mensagens com menos de WM_LBUTTONUP e maiores do que WM_LBUTTONUP, mas não recuperar WM_LBUTTONUP.

Informações adicionais

Etapas para reproduzir o problema

Veja a seguir a sequência de eventos que levam à perda da mensagem WM_LBUTTONUP:

  1. Clique na barra de rolagem usando o mouse.

  2. A etapa 1 gera uma mensagem de WM_NCLBUTTONDOWN.

  3. A etapa 2 faz com que um loop de mensagem interna do Windows seja iniciado. Este loop de mensagem procura mensagens relacionadas à barra de rolagem. A finalidade desse loop de mensagem é gerar mensagens WM_HSCROLL ou WM_VSCROLL apropriadas. O loop de mensagem e a rolagem são encerrados uma vez WM_LBUTTONUP são recebidos.

  4. Ao receber a mensagem WM_HSCROLL ou WM_VSCROLL, o aplicativo se torna um loop de recuperação de mensagens diretamente ou chama funções que resultam na recuperação de mensagens.

  5. WM_LBUTTONUP é removido da fila pelo loop de mensagem mencionado na etapa 4. Em seguida, WM_LBUTTONUP será despachado.

  6. Como resultado da etapa 5 WM_LBUTTONUP mensagem é despachada em outro lugar e o loop de recuperação de mensagem interna, mencionado na etapa 3 nunca a recebe. O loop de mensagem na etapa 3 está procurando o WM_LBUTTONUP para interromper a rolagem. Como não é recebido, a barra de rolagem continua rolando.

Precisa de mais ajuda?

Expanda suas habilidades
Explore o treinamento
Obtenha novos recursos primeiro
Ingressar no Microsoft Insider

Estas informações foram úteis?

Qual é o seu grau de satisfação com a qualidade da tradução?
O que afetou sua experiência?

Obrigado por seus comentários!

×