9
votes

WIN32: mon application se fige pendant que l'utilisateur redimensionne la fenêtre

J'écris une application Win32. J'ai mis en œuvre le message en boucle comme ceci: xxx

Il y a une fenêtre redimensionnable dans mon application. Habituellement, IdleProcess () est appelé plusieurs fois par seconde. Lorsque l'utilisateur attrape un coin ou un bord de la fenêtre redimensable, IdleProcess () ne s'en appelle plus avant que l'utilisateur libère le bouton de la souris.

Que se passe-t-il ici?

i essayé d'échanger l'intérieur pendant un si, mais cela ne change pas le comportement. Il semble que le redimensionnement commence, le gestionnaire de ce message ne revient pas tant que le redimensionnement n'est pas effectué?

est un moyen de modifier cela et d'appeler l'immobilisation () pendant le redimensionnement de quelques fois par seconde?

merci Marc

EDIT:

Qu'est-ce que je veux dire en remplaçant l'intérieur de l'intérieur avec si: xxx

My Window Proc est un peu long, mais j'ai le même comportement avec une petite application de test. Ceci est identique à la WNDProc L'assistant de projet VS crée: xxx


3 commentaires

Pourriez-vous publier votre procédure de fenêtre WNDProc (...) qui recevra des messages de DispatchMessage () puisque votre commentaire sur la modification de la modification du moment est un peu curieux


fait + une explication du "si" au lieu de "tout".


Basé sur la mise à jour, il est évident que TRUCTMATMessage ou DispatchMessage ne revient pas immédiatement. Votre prochaine tâche consiste à déterminer lequel et quel message déclenche cela.


4 Réponses :


0
votes

Pendant le redimensionnement Windows envoie assez de messages à votre programme. Je n'ai pas prouvé cela, mais le comportement que vous décrivez est familier. Je suggérerais d'appeler votre fonction IdleProcess () également dans la boucle tandis que (...) pour certains événements tels que WM_Sizing que votre application recevra fréquemment lors de la redimensionnement des fenêtres:

 bool programcontinue = true;
 while(programcontinue)
 {
          while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
          {
                   TranslateMessage(&Msg);
                   DispatchMessage(&Msg);
                   if(Msg.message == WM_SIZING)
                       IdleProcess();
          }

          IdleProcess();
 }


1 commentaires

Ça n'aide pas. Comme je l'ai écrit dans ma question "J'ai essayé d'échanger le intérieur pendant un si"



16
votes

Il existe un certain nombre d'opérations modales sur Windows. Les opérations modales Win32 font référence à des fonctions qui placent une application en un "mode" en démarrant leur propre boucle de traitement d'événement jusqu'à ce que le mode se termine. Les modes d'application courants comprennent les opérations de glisser-déposer, les opérations de déplacement / taille, à tout moment une boîte de dialogue apparaît qui nécessite une entrée avant que l'application puisse continuer.

Alors que ce qui se passe est: votre boucle de message n'est pas exécutée. Votre fenêtre a reçu un message WM_LButTondown que vous avez transmis à DefwindowProc. DefwindowProc a déterminé que l'utilisateur tentait de former ou de déplacer la fenêtre de manière interactive et entra dans une fonction modale de dimensionnement / déplacement. Cette fonction est dans une boucle de traitement de message sur des messages de la souris afin qu'il puisse les intercepter pour fournir l'expérience de dimensionnement interactive et ne quittera que lorsque l'opération de dimensionnement est terminée - typiquement par l'utilisateur libérant le bouton TENU ou en appuyant sur Echap. < / p>

Vous êtes informé de ceci - DEFWINDOWOWPROC envoie un message WM_ENTERSIZEMOVE et WM_EXITSIZEMOVE, car il entre et quitte la boucle de traitement de l'événement modal.

Continuer à générer des messages "inactifs", créez généralement une minuterie (SETTIMER) avant d'appeler une fonction modale - ou lorsque DEFWINDOWPROCK entra dans une fonction modale - la boucle modale continuera de répartir les messages WM_TIMER ... et appelez le PROC IDLE du gestionnaire de messages de la minuterie. Détruire la minuterie lorsque la fonction modale revient.


0 commentaires

6
votes

Lorsque DefwindowProc gère WM_SYSCOMMAND avec SC_MOVE ou SC_SIZE dans le WPARAM, il entre une boucle jusqu'à ce que l'utilisateur l'arrête en relâchant le bouton de la souris ou en appuyant sur Entrer ou vous échapper. Cela le fait car il permet au programme de rendre à la fois la zone client (où vos widgets ou votre jeu ou autre sont dessinés) et la zone des bordures et de la légende en manipulant les messages WM_PAINT et WM_NCPAINT (vous devez toujours recevoir ces événements dans votre procédure de fenêtre).

Cela fonctionne bien pour les applications Windows normales, qui font la majeure partie de leur traitement à l'intérieur de leur procédure de fenêtre à la suite de messages récepteurs. Seuls des programmes d'effets qui traitent en dehors de la procédure de fenêtre, tels que des jeux (qui sont généralement du plein écran et non affectés de toute façon).

Cependant, il y a un moyen de le faire: gérer WM_SYSCOMMAND vous-même, redimensionner ou vous déplacer. Cela nécessite une bonne affaire, mais peut s'avérer en valoir la peine. Vous pouvez également utiliser SETJMP / LONDJMP pour vous échapper à partir de la procédure de fenêtre lorsque WM_SIZING est envoyé ou des fibres Windows le long des mêmes lignes; Ce sont des solutions pirates cependant.

Je l'ai résolu (en utilisant la première méthode) ce week-end dernier, si vous êtes intéressé, j'ai publié le code au domaine public sur Sourceforge. Assurez-vous simplement de lire le Readme, en particulier la section de mise en garde. Ici, il est: https://sourceforge.net/projects/win32loopl/


0 commentaires

1
votes

Vous pouvez toujours recevoir le message wm_paint code>, vous venez de dire au WinapI que vous le souhaitez (vu dans NEHE OpenGL Tutoriels):

windowClass.style           = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;   // Redraws The Window For Any Movement / Resizing


0 commentaires