Win32: Meine Anwendung friert ein, wenn der Benutzer die Größe des Fensters ändert

8

Ich schreibe eine Win32-Anwendung. Ich habe die Nachrichtenschleife selbst so implementiert:

%Vor%

In meiner Anwendung gibt es ein veränderbares Fenster. Normalerweise wird IdleProcess () mehrmals pro Sekunde aufgerufen. Wenn der Benutzer eine Ecke oder einen Rand des veränderbaren Fensters ergreift, wird IdleProcess () nicht mehr aufgerufen, bis der Benutzer die Maustaste loslässt.

Was passiert hier?

Ich habe versucht, die innere Zeit mit einem if zu tauschen, aber das ändert nichts am Verhalten. Es scheint, als wenn die Größenänderung startet, der Handler für diese Nachricht nicht zurückkehrt, bis die Größenänderung abgeschlossen ist?

Gibt es eine Möglichkeit, dies zu ändern und IdleProcess () während der Größenänderung einige Male pro Sekunde aufzurufen?

Danke    Marc

BEARBEITEN:

Was ich meine, indem ich die innere while durch if ersetzt habe:

%Vor%

Mein Fenster Proc ist ein bisschen lang, aber ich bekomme das gleiche Verhalten mit einer kleinen Test-App. Dies ist identisch mit dem wndproc, den der VS Project Wizard erstellt:

%Vor%     
marc40000 23.06.2010, 13:33
quelle

4 Antworten

14

Es gibt eine Reihe von modalen Operationen, die unter Windows passieren. Win32-Modaloperationen beziehen sich auf Funktionen, die eine Anwendung in einen "Modus" versetzen, indem sie ihre eigene Ereignisverarbeitungsschleife starten, bis der Modus beendet ist. Zu den üblichen Anwendungsmodi gehören Drag & Drop-Operationen, Verschiebungs- / Größenoperationen, immer wenn ein Dialogfeld angezeigt wird, das eine Eingabe erfordert, bevor die Anwendung fortgesetzt werden kann.

Was passiert ist also: Ihre Nachrichtenschleife wird NICHT ausgeführt. Ihr Fenster hat eine WM_LBUTTONDOWN-Nachricht empfangen, die Sie an DefWindowProc übergaben. DefWindowProc hat festgestellt, dass der Benutzer versucht hat, das Fenster interaktiv zu skalieren oder zu verschieben, und eine Modifikationsfunktion für Bemaßung / Bewegung eingegeben. Diese Funktion befindet sich in einer Nachrichtenverarbeitungsschleife, die nach Mausnachrichten sucht, sodass sie sie abfangen kann, um die interaktive Dimensionierung zu ermöglichen. Sie wird erst beendet, wenn die Größenänderung abgeschlossen ist - in der Regel durch Loslassen der gehaltenen Schaltfläche oder durch Drücken von Escape / p>

Sie werden darauf hingewiesen - DefWindowProc sendet eine WM_ENTERSIZEMOVE- und eine WM_EXITSIZEMOVE-Nachricht, wenn sie in die modale Ereignisverarbeitungsschleife eintritt und diese verlässt.

Um weiterhin "idle" Nachrichten zu generieren, erstellen Sie in der Regel einen Timer (SetTimer) vor dem Aufruf einer modalen Funktion - oder beim Abrufen einer Nachricht, dass DefWindowProc eine modale Funktion eingibt - die modale Schleife wird weiterhin WM_TIMER Nachrichten versenden ... und rufe den Idle-Proc vom Timer-Message-Handler auf. Zerstöre den Timer, wenn die modale Funktion zurückkehrt.

    
Chris Becke 23.06.2010, 15:35
quelle
4

Wenn DefWindowProc WM_SYSCOMMAND entweder mit SC_MOVE oder mit SC_SIZE im wParam behandelt, tritt eine Schleife ein, bis der Benutzer sie stoppt, indem er die Maustaste loslässt oder Enter oder Escape drückt. Dies geschieht, weil es dem Programm ermöglicht, sowohl den Clientbereich (wo Ihre Widgets oder Spiel oder was auch immer gezeichnet wird) als auch den Rahmen und den Beschriftungsbereich darzustellen, indem Sie WM_PAINT und WM_NCPAINT Nachrichten verarbeiten (Sie sollten diese Ereignisse in Ihrer Fensterprozedur erhalten).

Es funktioniert gut für normale Windows-Apps, die den größten Teil ihrer Verarbeitung innerhalb ihrer Fensterprozedur als Ergebnis des Empfangs von Nachrichten erledigen. Es betrifft nur Programme, die außerhalb der Window Procedure arbeiten, wie z. B. Spiele (die in der Regel im Vollbildmodus sind und ohnehin nicht betroffen sind).

Es gibt jedoch einen Weg darum: Behandle WM_SYSCOMMAND selbst, verändere deine Größe oder bewege dich. Dies erfordert viel Aufwand, kann sich aber als lohnend erweisen. Alternativ könnten Sie setjmp / longjmp verwenden, um aus der Fensterprozedur zu entkommen, wenn WM_SIZING gesendet wird, oder Windows Fibers entlang der gleichen Linien; Das sind jedoch hackische Lösungen.

Ich habe es am vergangenen Wochenende (mit der ersten Methode) gelöst. Wenn Sie interessiert sind, habe ich den Code in der Public Domain auf SourceForge veröffentlicht. Stellen Sie sicher, dass Sie die README lesen, insbesondere den Abschnitt zum Vorbehalt. Hier ist es: Ссылка

    
nfries88 20.01.2014 17:26
quelle
1

Während der Größenänderung sendet Windows einige Nachrichten an Ihr Programm. Ich habe das nicht bewiesen, aber das Verhalten, das du beschreibst, ist vertraut. Ich würde vorschlagen, Ihre Funktion IdleProcess () auch innerhalb der while (...) Schleife für bestimmte Ereignisse wie WM_SIZING aufzurufen, die Ihre Anwendung während der Fenstergrößenanpassung häufig erhalten wird:

%Vor%

Beachten Sie jedoch, dass davon ausgegangen wird, dass IdleProcess () keine Ereignisse erstellt oder verwendet. Wenn das der Fall ist, werden die Dinge viel komplizierter.

    
RED SOFT ADAIR 23.06.2010 14:28
quelle
1

Sie können immer noch die Nachricht WM_PAINT empfangen, Sie müssen der WinAPI nur mitteilen, dass Sie sie haben wollen (siehe NeHe OpenGL Tutorials):

%Vor%

Es wird jedoch weiterhin Ihre while / PeekMessage -loop blockieren! WinAPI ruft nur Ihre WndProc direkt auf.

    
lama12345 27.09.2015 09:53
quelle

Tags und Links