Die Bildlaufleiste führt weiterhin einen Bildlauf durch, nachdem Sie die Maustaste losgelassen haben


Problembeschreibung


Die Bildlaufleiste führt kontinuierlich einen Bildlauf durch, auch wenn Sie die linke Maustaste loslassen. Der Typ der Bildlaufleiste ist für dieses Problem irrelevant, das heißt, das gleiche Problem tritt unabhängig davon auf, ob die Bildlaufleiste Teil des Fensters ist oder ein Bildlaufleisten-Steuerelement ist.

Ursache


Dieses Problem tritt normalerweise auf, wenn eine Nachrichtenabruf Schleife als Ergebnis von Aktionen ausgeführt wird, die zum Scrollen beim Empfang einer der Bildlaufleisten-Benachrichtigungsmeldungen ergriffen wurden. Beim Scrollen wird eine interne Nachrichtenabruf Schleife in Windows gestartet. Die Aufgabe dieser Nachrichtenschleife besteht darin, den Bildlauf nachzuverfolgen und die entsprechenden Benachrichtigungsmeldungen, WM_HSCROLL und WM_VSCROLL für die Bildlaufleiste zu senden. Der Bildlauf wird beendet, sobald WM_LBUTTONUP empfangen wird. Wenn beim Scrollen eine andere Meldungsschleife gestartet wird, wird die WM_LBUTTONUP von dieser Nachrichtenschleife abgerufen, und da eine Anwendung keinen Zugriff auf die interne Nachrichtenabruf Schleife der Bildlaufleiste hat, kann WM_LBUTTONUP nicht ordnungsgemäß gesendet werden. Daher wird der WM_LBUTTONUP nie vom internen Nachrichtenabruf empfangen, und der Bildlauf wird nie beendet. Die Anwendung, die einen Bildlauf ausführt, muss keine Nachrichten explizit abrufen, um dieses Problem zu verursachen. Wenn Sie eine der folgenden Funktionen aufrufen oder alle Nachrichten mit einer Nachrichtenabruf Schleife beim Scrollen verarbeiten, kann dies dazu führen, dass die WM_LBUTTONUP verloren gehen. Die nachstehend aufgeführten Funktionen fallen in diese Kategorie:
DialogBox() DialogBoxIndirect() DialogBoxIndirectParam() DialogBoxParam() GetMessage() MessageBox() PeekMessage()

Fehlerbehebung


Während des Bildlaufs sollte die WM_LBUTTONUP Nachricht nicht von einer anderen Nachrichtenabruf Schleife als der internen Bildlaufleiste abgerufen werden. Eine Anwendung kann dieses Problem folgendermaßen beheben:
  • Eine Anwendung implementiert eine Nachrichtenabruf Schleife, um die Hintergrundverarbeitung zu implementieren, beispielsweise die Hintergrundverarbeitung, während eine zeitaufwändige Lackierung durchgeführt wird.
  • Eine Anwendung implementiert eine Nachrichtenabruf Schleife, um die Kommunikation mit einer anderen Anwendung oder dll zu implementieren. Um beispielsweise einen Bildlauf durchführen zu können, muss die Anwendung Daten von anderswo empfangen.

Mögliche Problemumgehungen

Nachfolgend sind zwei mögliche Problemumgehungen aufgeführt. Die erste Problemumgehung wird von vielen beendenden Anwendungen und von Windows verwendet; in seltenen Fällen ist die erste Problemumgehung jedoch möglicherweise nicht praktikabel. In diesem Fall kann die zweite Problemumgehung verwendet werden. Versuchen Sie jedoch, nach Möglichkeit zu vermeiden, dass der Nachrichtenabruf beim Scrollen vollständig durchgeführt wird.
  • Verwenden Sie die Timer-nachrichtenbasierte Verarbeitung. Gliedern Sie die komplizierte Verarbeitung in kleinere Aufgaben auf, und verfolgen Sie, wo die einzelnen Vorgänge beginnen und enden, und führen Sie dann die einzelnen Aufgaben auf der Grundlage einer Timer-Nachricht aus. Wenn alle Komponenten der Verarbeitung abgeschlossen sind, beenden Sie den Timer. Im folgenden finden Sie ein Beispiel für diese Problemumgehung.
  • Implementieren Sie eine Nachrichtenabruf Schleife, stellen Sie sicher, dass WM_LBUTTONUP nicht von ihr abgerufen wird. Dies kann mithilfe von Filtern erfolgen. Nachfolgend finden Sie einige Beispiele für diese Problemumgehung.

Beispiel zur Veranschaulichung der Problemumgehung 1

Eine Anwendung verfügt über eine komplexe Paint-Prozedur. Durch Aufrufen von ScrollWindow () zum Scrollen werden Paint-Nachrichten generiert. Die Hintergrundverarbeitung findet während des Zeichnens statt.
  1. Wenn Sie die WM_PAINT Nachricht erhalten, gehen Sie folgendermaßen vor:
    1. Rufen Sie BeginPaint () auf.
    2. Kopieren Sie das Invalidated Rect in eine globale Rect-Variable (beispielsweise grcPaint), die in Schritt 2 verwendet werden soll. Das globale Rect-grcPaint wäre eine Union des zuvor erhaltenen Rect (grcPaint) und des neuen Invalidated Rect (PS. rcPaint). Der Code für dieses Beispiel sieht wie folgt aus:
               RECT grcPaint;    // Should be initialized before getting the                           // first paint message.            :            :         UnionRect(&grcPaint, &ps.rcPaint,&grcPaint);
    3. Rufen Sie ValidateRect () mit PS. rcPaint.
    4. Rufen Sie EndPaint () auf.
    5. Einen Timer einstellen.
    Auf diese Weise werden keine weiteren WM_PAINT Nachrichten generiert, da keine ungültigen Bereiche vorhanden sind und ein Zeitgeber eingerichtet wird, der WM_TIMER Nachrichten generiert.
  2. Überprüfen Sie beim Empfang einer WM_TIMER Nachricht die globale Rect-Variable; Wenn Sie nicht leer ist, nehmen Sie einen Abschnitt auf, und malen Sie ihn. Passen Sie dann die globale Rect-Variable so an, dass Sie den bemalten Bereich nicht mehr enthält.
  3. Nachdem die globale Rect-Variable leer ist, beenden Sie den Timer.

Beispiel zur Veranschaulichung der Problemumgehung 2

Eine Anwendung muss einige Daten über DDE oder einen anderen Mechanismus aus einer anderen Anwendung abrufen, die dann im Fenster angezeigt wird. Um einen Bildlauf durchführen zu können, muss die Anwendung die Daten von einer Serveranwendung anfordern und dann abrufen. Es gibt drei verschiedene Filter, die verwendet werden können, um einen PeekMessage () einzurichten und die Informationen abzurufen. Die Filter können mithilfe der uFilterFirst-und uFilterLast-Parameter von PeekMessage () eingerichtet werden. uFilterFirst gibt die erste Nachricht im Bereich an, die überprüft werden soll, und uFilterLast gibt die letzte Nachricht im Bereich an, die überprüft werden soll.
  1. Überprüfen und Abrufen nur der zugehörigen Nachricht (en) zum Abrufen der benötigten Daten.
  2. Überprüfen auf WM_LBUTTONUP, ohne die Warteschlange zu entfernen; Wenn Sie sich in der Warteschlange befindet, brechen Sie. Andernfalls können Sie alle Nachrichten abrufen und senden.
  3. Abrufen aller Nachrichten, die kleiner als WM_LBUTTONUP und größer als WM_LBUTTONUP sind, aber keine WM_LBUTTONUP abrufen.

Weitere Informationen


Schritte zum Reproduzieren des Problems

Im folgenden wird die Abfolge der Ereignisse angezeigt, die zum Verlust der WM_LBUTTONUP Nachricht führen:
  1. Klicken Sie mit der Maus auf die Bildlaufleiste.
  2. Schritt 1 generiert eine WM_NCLBUTTONDOWN Nachricht.
  3. Schritt 2 bewirkt, dass eine interne Windows-Nachrichtenschleife gestartet wird. Diese Nachrichtenschleife sucht nach Nachrichten im Scroll-Bar-Bereich. Der Zweck dieser Nachrichtenschleife besteht darin, geeignete WM_HSCROLL oder WM_VSCROLL Meldungen zu generieren. Die Nachrichtenschleife und der Bildlauf werden beendet, sobald WM_LBUTTONUP empfangen wird.
  4. Beim Empfang der WM_HSCROLL-oder WM_VSCROLL Nachricht wird die Anwendung entweder direkt in eine Nachrichtenabruf Schleife oder ruft Funktionen auf, die zum Abrufen von Nachrichten führen.
  5. WM_LBUTTONUP wird aus der Warteschlange durch die in Schritt 4 genannte Nachrichtenschleife entfernt. WM_LBUTTONUP wird dann versandt.
  6. Als Ergebnis von Schritt 5 wird WM_LBUTTONUP Nachricht an eine andere Stelle weitergeleitet, und die in Schritt 3 erwähnte interne Nachrichtenabruf Schleife erhält Sie nie. Die Nachrichtenschleife in Schritt 3 sucht nach dem WM_LBUTTONUP, um den Bildlauf zu beenden. Da es nicht empfangen wird, wird die Bildlaufleiste weiterhin scrollen.