Rullefeltet fortsetter å rulle når du slipper museknappen


Symptomer


Rullefeltet ruller hele tiden etter at du slipper opp venstre museknapp. Rullefeltet er ikke relevant for dette problemet, det vil si det samme problemet oppstår uansett om rullefeltet er en del av vinduet, eller er et rullefelt.

Årsak


Dette problemet oppstår vanligvis når en meldingsløkke for henting kjøres som et resultat av handlinger som er utført for rulling ved mottak av en av meldingene ruller linjen.


Når du ruller, startes en intern meldingsløkke for nettverkshenting i Windows. Oppgaven med dette meldingsløkke er å holde oversikt over rulling og sende aktuelle ruller linjen meldingene, WM_HSCROLL og WM_VSCROLL. Rulling er avsluttet når WM_LBUTTONUP er mottatt. Hvis en annen meldingsløkke startes under rulling, WM_LBUTTONUP blir hentet ved at meldingsløkke, og fordi et program ikke har tilgang til rullefeltet er intern henting meldingsløkke, WM_LBUTTONUP kan ikke sendes riktig. Derfor WM_LBUTTONUP mottas aldri av interne meldings-retriever, og rulling er aldri avsluttet.


Programmet er rulling trenger ikke å hente meldinger eksplisitt å forårsake dette problemet. Kall til noen av følgende funksjoner eller behandler alle meldinger som har en meldingsløkke for henting, mens du blar, kan føre til at WM_LBUTTONUP kan gå tapt. Funksjonene nedenfor faller inn i denne kategorien:

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

Løsning


Samtidig rulling, bør WM_LBUTTONUP meldingen ikke hentes fra køen av en meldingsløkke for henting enn rullefeltet er interne.


Et program kan kommer over dette problemet som følger:

  • Et program implementerer en meldingsløkke for henting for å implementere bakgrunnsbehandling, for eksempel bakgrunnsbehandling under utføring av en tidkrevende paint.
  • Et program implementerer en meldingsløkke for henting for å implementere kommunikasjon med et annet program eller en DLL. Hvis du vil rulle, må for eksempel programmet mottar data fra et annet sted.

Mulige løsninger

To mulige løsninger, er oppført nedenfor. Den første løsningen brukes av mange eksisterende programmer og av Windows. i sjeldne tilfeller kan første løsningen imidlertid ikke være en mulig. I dette tilfellet kan den andre løsningen brukes. Imidlertid hvis mulig, prøv å unngå å implementere meldingshenting fullstendig mens du ruller.

  • Bruk timer-melding-basert behandling. Bryte ned en komplisert behandling i mindre aktiviteter, og holde orden på hvor hver aktivitet starter og slutter, deretter utføre hver oppgave basert på en tidtaker-melding. Når alle komponenter av behandlingen er fullført, kill tidtakeren. Nedenfor finner du et eksempel på denne løsningen.
  • Implementere en meldingsløkke for henting, men Pass på at WM_LBUTTONUP ikke er hentet av den. Dette kan gjøres ved hjelp av filtre. Nedenfor finner du noen eksempler på denne løsningen.

Eksemplet demonstrerer løsning 1

Et program har en omfattende paint-prosedyre. Kaller ScrollWindow() til å rulle, genererer paint-meldinger. Bakgrunnsbehandling finner sted når du maler.

  1. Når du mottar WM_PAINT-postmeldingen gjør du følgende:


    1. Kall BeginPaint().
    2. Kopier den ugyldige rektangel til en variabel med global rektangel (for eksempel grcPaint) som skal brukes i trinn 2. Global rektangel-grcPaint er en sammenslutning av tidligere oppnådde rektangel (grcPaint) og den nye ugyldige rektangel (ps.rcPaint). Koden for dette vil ligne på følgende:
               RECT grcPaint;    // Should be initialized before getting the
      // first paint message.
      :
      :
      UnionRect(&grcPaint, &ps.rcPaint,&grcPaint);
    3. Kall ValidateRect() med ps.rcPaint.
    4. Kall EndPaint().
    5. Angi en tidtaker.
    På denne måten, genereres ingen flere WM_PAINT-meldinger, fordi det finnes ingen ugyldig områder, og en tidtaker som er satt opp, som vil generere WM_TIMER-meldinger.
  2. Ved mottak av en WM_TIMER-melding, kan du se globale rektangel-variabel. Hvis den ikke er tom, kan du ta en inndeling og male det. Juster globale rektangel variabelen slik at den ikke lenger inneholder malte området.
  3. Når den globale rektangel-variabelen er tom kill deretter tidtakeren.

Eksemplet demonstrerer løsning 2

Et program trenger for å få noen data via DDE eller noen annen måte fra et annet program, som deretter vises i vinduet. Hvis du vil rulle, må programmet til å be om og deretter hente data fra et serverprogram.


Det finnes tre ulike filtre som kan brukes til å definere en PeekMessage() og få tak i informasjonen. Filtrene kan settes opp ved hjelp av parameterne uFilterFirst og uFilterLast av PeekMessage(). uFilterFirst angir meldingen først i området som skal kontrolleres, og uFilterLast angir den siste meldingen i området som skal kontrolleres.
  1. Kontrollere og hente de relaterte melding(er) for å få de nødvendige dataene.
  2. Se etter WM_LBUTTONUP uten å fjerne den skjemaet køen. Hvis det er i køen, brytes. Hvis ikke, kan du hente og sende alle meldinger.
  3. Hente alle meldingene mindre enn WM_LBUTTONUP og større enn WM_LBUTTONUP, men ikke hente WM_LBUTTONUP.

Hvis du vil ha mer informasjon


Fremgangsmåte for å gjenskape problemet

Nedenfor finner du rekkefølgen av hendelser som fører til tap av WM_LBUTTONUP-melding:

  1. Klikk rullefeltet ved hjelp av musen.
  2. Trinn 1 genererer en WM_NCLBUTTONDOWN-melding.
  3. Trinn 2 får en intern meldingsløkke Windows startes. Denne meldingsløkke ser etter rulle-stolpe-relaterte meldinger. Formålet med denne meldingsløkke er å generere riktige meldinger som WM_HSCROLL eller WM_VSCROLL. Meldingsløkke og rulling avsluttes når WM_LBUTTONUP er mottatt.
  4. Når du mottar meldingen WM_HSCROLL eller WM_VSCROLL, programmet enten får direkte inn en meldingsløkke for henting eller kaller funksjonene som kan føre til henting av meldinger.
  5. WM_LBUTTONUP er fjernet fra køen av meldingsløkke nevnt i trinn 4. WM_LBUTTONUP fordeles deretter.
  6. Den som et resultat trinn 5 WM_LBUTTONUP-melding er sendt ut et annet sted, og den interne henting meldingsløkke, nevnt i trinn 3 mottar aldri den. Meldingsløkker i trinn 3 ser etter WM_LBUTTONUP å stoppe rullingen. Fordi det ikke er mottatt, fortsetter rullefeltet rulling.