IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Discussion :

déplacer une fenêtre semble bloquer la boucle des messages


Sujet :

Windows

  1. #1
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut déplacer une fenêtre semble bloquer la boucle des messages
    Je porte une bibliothèque Linux sous Windows. Celle-ci a une boucle principale dans laquelle je gère les messages, les événements et autres petites choses. Sous Linux,la boucle principale utilise juste select(). Sous Windows, j'utilise cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    static int
    _ecore_main_win32_select(int nfds __UNUSED__, fd_set *readfds, fd_set *writefds,
                             fd_set *exceptfds, struct timeval *tv)
    {
       HANDLE       objects[MAXIMUM_WAIT_OBJECTS];
       int          sockets[MAXIMUM_WAIT_OBJECTS];
       Ecore_Fd_Handler *fdh;
       Ecore_Win32_Handler *wh;
       unsigned int objects_nbr = 0;
       unsigned int handles_nbr = 0;
       unsigned int events_nbr = 0;
       DWORD        result;
       DWORD        timeout;
       MSG          msg;
       unsigned int i;
       int          res;
    
       /* Create an event object per socket */
       EINA_INLIST_FOREACH(fd_handlers, fdh)
         {
            WSAEVENT event;
            long network_event;
    
            network_event = 0;
            if (FD_ISSET(fdh->fd, readfds))
              network_event |= FD_READ;
            if (FD_ISSET(fdh->fd, writefds))
              network_event |= FD_WRITE;
            if (FD_ISSET(fdh->fd, exceptfds))
              network_event |= FD_OOB;
    
            if (network_event)
              {
                 event = WSACreateEvent();
                 WSAEventSelect(fdh->fd, event, network_event);
                 objects[objects_nbr] = event;
                 sockets[events_nbr] = fdh->fd;
                 events_nbr++;
                 objects_nbr++;
              }
         }
    
       /* store the HANDLEs in the objects to wait for */
       EINA_INLIST_FOREACH(win32_handlers, wh)
         {
            objects[objects_nbr] = wh->h;
            handles_nbr++;
            objects_nbr++;
         }
    
       /* Empty the queue before waiting */
       while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
         {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
         }
    
       /* Wait for any message sent or posted to this queue */
       /* or for one of the passed handles be set to signaled. */
       if (!tv)
         timeout = INFINITE;
       else
         timeout = (DWORD)((tv->tv_sec * 1000.0) + (tv->tv_usec / 1000.0));
    
       if (timeout == 0) return 0;
    
       result = MsgWaitForMultipleObjects(objects_nbr, (const HANDLE *)objects, EINA_FALSE,
                                          timeout, QS_ALLINPUT);
    
       FD_ZERO(readfds);
       FD_ZERO(writefds);
       FD_ZERO(exceptfds);
    
       /* The result tells us the type of event we have. */
       if (result == WAIT_FAILED)
         {
            char *msg;
    
            msg = evil_last_error_get();
            ERR(" * %s\n", msg);
            free(msg);
            res = -1;
         }
       else if (result == WAIT_TIMEOUT)
         {
            /* ERR("time out\n"); */
            res = 0;
         }
       else if (result == (WAIT_OBJECT_0 + objects_nbr))
         {
            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
              {
                 TranslateMessage(&msg);
                 DispatchMessage(&msg);
              }
    
            res = 0;
         }
       else if ((result >= 0) && (result < WAIT_OBJECT_0 + events_nbr))
         {
            WSANETWORKEVENTS network_event;
    
            WSAEnumNetworkEvents(sockets[result], objects[result], &network_event);
    
            if (network_event.lNetworkEvents & FD_READ)
               FD_SET(sockets[result], readfds);
            if (network_event.lNetworkEvents & FD_WRITE)
               FD_SET(sockets[result], writefds);
            if (network_event.lNetworkEvents & FD_OOB)
               FD_SET(sockets[result], exceptfds);
    
            res = 1;
         }
       else if ((result >= (WAIT_OBJECT_0 + events_nbr)) &&
                (result < (WAIT_OBJECT_0 + objects_nbr)))
         {
            if (!win32_handler_current)
              {
                 /* regular main loop, start from head */
                 win32_handler_current = win32_handlers;
              }
            else
              {
                 /* recursive main loop, continue from where we were */
                 win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next;
              }
    
            while (win32_handler_current)
              {
                 wh = win32_handler_current;
    
                 if (objects[result - WAIT_OBJECT_0] == wh->h)
                   {
                      if (!wh->delete_me)
                        {
                           wh->references++;
                           if (!wh->func(wh->data, wh))
                             {
                                wh->delete_me = 1;
                                win32_handlers_delete_me = 1;
                             }
                           wh->references--;
                        }
                   }
                 if (win32_handler_current) /* may have changed in recursive main loops */
                   win32_handler_current = (Ecore_Win32_Handler *)EINA_INLIST_GET(win32_handler_current)->next;
              }
            res = 1;
         }
       else
         {
            ERR("unknown result...\n");
            res = -1;
         }
    
       /* Remove event objects again */
       for (i = 0; i < events_nbr; i++) WSACloseEvent(objects[i]);
    
       return res;
    }
    2 boucles utilisant PeekMessage() sont utilisées. Je n'ai pas de problème particulier, à part dans 2 cas:quand je déplace une fenêtre ou bien quand je la redimensionne.

    Par exemple, quand je redimensionne la fenêtre:

    1) J'appuie sur le bord et je laisse le bouton appuyé : on rentre dans la boucle (mais on n'en sort pas)
    2) je déplace la souris pour redimensionner la fenêtre. La encore on reste dans la boucle
    3) quand je relache le bouton pour terminer le redimensionnement, on sort de la boucle

    La conséquence est que le contenu de la fenêtre n'est mis à jour que quand je relache le bouton de la souris, pas pendant le redimensionnement.

    Quelqu'un sait pourquoi il y a un tel comportement, et comment faire en sorte que je sorte de la boucle à chaque déplacement de la souris ?

    merci

    PS: si c'est nécessaire, je peux poster la window procedure

    EDIT: ca a l'air d'etre DispatchMessage() qui bloque
    L'Opus attire les Prélats

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le redimensionnement/déplacement se fait dans une boucle de messages imbriquée, en effet.

    Pour Win32, si tu as une fenêtre, je te conseillerais plutôt de repenser complètement l'application et utiliser WSAAsyncSelect()...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Au passage, désolé, je ne connais aucun moyen d'intercepter les boucles modales de ce type pour utiliser MsgWaitForMultipleObjectsEx(). À part, bien sûr, recoder ton propre traitement pour le redimensionnement, mais dans le même registre, tu ne dois pas non plus utiliser MessageBox()...

    Le mieux peut être de créer carrément un thread séparé qui poste des messages à une fenêtre du thread d'IHM quand quelque se passe. Ce qui est précisément ce que fait WSAAsyncSelect()...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    Et utiliser les messages WM_NCL* (WM_NCHITTEST WM_NCLBUTTONDOWN et WM_NCLBUTTONUP) pour redéfinir le comportement de la partie non client ? Ca serait faisable ?
    L'Opus attire les Prélats

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Oui. Difficile, mais faisable.

    Pour ce genre de truc, je te conseille d'utiliser le debugger pour savoir exactement quel messafe est en train d'être traité quand la fenêtre reçoit WM_ENTERSIZEMOVE...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    Voici ce que donne spy++:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    <00001> 0015087C S WM_NCHITTEST xPos:336 yPos:496
    <00002> 0015087C R WM_NCHITTEST nHittest:HTRIGHT
    <00003> 0015087C S WM_SETCURSOR hwnd:0015087C nHittest:HTRIGHT wMouseMsg:WM_MOUSEMOVE
    <00004> 0015087C R WM_SETCURSOR fHaltProcessing:True
    <00005> 0015087C P WM_NCMOUSEMOVE nHittest:HTRIGHT xPos:336 yPos:496
    <00006> 0015087C S WM_NCHITTEST xPos:336 yPos:496
    <00007> 0015087C R WM_NCHITTEST nHittest:HTRIGHT
    <00008> 0015087C S WM_MOUSEACTIVATE hwndTopLevel:0015087C nHittest:HTRIGHT uMsg:WM_LBUTTONDOWN
    <00009> 0015087C R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE
    <00010> 0015087C S WM_WINDOWPOSCHANGING lpwp:0028F72C
    <00011> 0015087C R WM_WINDOWPOSCHANGING
    <00012> 0015087C S WM_WINDOWPOSCHANGED lpwp:0028F72C
    <00013> 0015087C R WM_WINDOWPOSCHANGED
    <00014> 0015087C S WM_ACTIVATEAPP fActive:True dwThreadID:00000000
    <00015> 0015087C R WM_ACTIVATEAPP
    <00016> 0015087C S WM_NCACTIVATE fActive:True
    <00017> 0015087C R WM_NCACTIVATE
    <00018> 0015087C S WM_ACTIVATE fActive:WA_ACTIVE fMinimized:False hwndPrevious:(null)
    <00019> 0015087C S WM_IME_SETCONTEXT fSet:1 iShow:C000000F
    <00020> 0015087C S WM_IME_NOTIFY dwCommand:IMN_OPENSTATUSWINDOW dwCommand:00000002 dwData:00000000
    <00021> 0015087C R WM_IME_NOTIFY
    <00022> 0015087C R WM_IME_SETCONTEXT
    <00023> 0015087C S WM_SETFOCUS hwndLoseFocus:(null)
    <00024> 0015087C R WM_SETFOCUS
    <00025> 0015087C R WM_ACTIVATE
    <00026> 0015087C S WM_SETCURSOR hwnd:0015087C nHittest:HTRIGHT wMouseMsg:WM_LBUTTONDOWN
    <00027> 0015087C R WM_SETCURSOR fHaltProcessing:True
    <00028> 0015087C P WM_NCLBUTTONDOWN nHittest:HTRIGHT xPos:336 yPos:496
    <00029> 0015087C S WM_SYSCOMMAND uCmdType:SC_SIZE xPos:336 yPos:496
    <00030> 0015087C S WM_GETMINMAXINFO lpmmi:0028F08C
    <00031> 0015087C R WM_GETMINMAXINFO lpmmi:0028F08C
    <00032> 0015087C S WM_ENTERSIZEMOVE
    <00033> 0015087C R WM_ENTERSIZEMOVE
    <00034> 0015087C P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:328 yPos:466
    <00035> 0015087C P WM_NCMOUSELEAVE
    <00036> 0015087C P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:329 yPos:466
    <00037> 0015087C S WM_SIZING fwSide:WMSZ_RIGHT lprc:0028F0A4
    <00038> 0015087C R WM_SIZING fProcessed:True
    <00039> 0015087C S WM_WINDOWPOSCHANGING lpwp:0028F094
    <00040> 0015087C S WM_GETMINMAXINFO lpmmi:0028ED70
    <00041> 0015087C R WM_GETMINMAXINFO lpmmi:0028ED70
    <00042> 0015087C R WM_WINDOWPOSCHANGING
    <00043> 0015087C S WM_NCCALCSIZE fCalcValidRects:True lpncsp:0028F06C
    <00044> 0015087C R WM_NCCALCSIZE fuValidRect:0000 lpncsp:0028F06C
    <00045> 0015087C S WM_NCPAINT hrgn:00000001
    <00046> 0015087C R WM_NCPAINT
    <00047> 0015087C S WM_ERASEBKGND hdc:46011442
    <00048> 0015087C R WM_ERASEBKGND fErased:True
    <00049> 0015087C S WM_WINDOWPOSCHANGED lpwp:0028F094
    <00050> 0015087C R WM_WINDOWPOSCHANGED
    <00051> 0015087C S WM_PAINT hdc:00000000
    <00052> 0015087C R WM_PAINT
    <00053> 0015087C P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:330 yPos:466
    <00054> 0015087C S WM_SIZING fwSide:WMSZ_RIGHT lprc:0028F0A4
    <00055> 0015087C R WM_SIZING fProcessed:True
    <00056> 0015087C S WM_WINDOWPOSCHANGING lpwp:0028F094
    <00057> 0015087C S WM_GETMINMAXINFO lpmmi:0028ED70
    <00058> 0015087C R WM_GETMINMAXINFO lpmmi:0028ED70
    <00059> 0015087C R WM_WINDOWPOSCHANGING
    <00060> 0015087C S WM_NCCALCSIZE fCalcValidRects:True lpncsp:0028F06C
    <00061> 0015087C R WM_NCCALCSIZE fuValidRect:0000 lpncsp:0028F06C
    <00062> 0015087C S WM_NCPAINT hrgn:00000001
    <00063> 0015087C R WM_NCPAINT
    <00064> 0015087C S WM_ERASEBKGND hdc:46011442
    <00065> 0015087C R WM_ERASEBKGND fErased:True
    <00066> 0015087C S WM_WINDOWPOSCHANGED lpwp:0028F094
    <00067> 0015087C R WM_WINDOWPOSCHANGED
    <00068> 0015087C S WM_PAINT hdc:00000000
    <00069> 0015087C R WM_PAINT
    <00070> 0015087C P WM_LBUTTONUP fwKeys:0000 xPos:330 yPos:466
    <00071> 0015087C S WM_CAPTURECHANGED hwndNewCapture:00000000
    <00072> 0015087C R WM_CAPTURECHANGED
    <00073> 0015087C S WM_WINDOWPOSCHANGING lpwp:0028F094
    <00074> 0015087C S WM_GETMINMAXINFO lpmmi:0028ED70
    <00075> 0015087C R WM_GETMINMAXINFO lpmmi:0028ED70
    <00076> 0015087C R WM_WINDOWPOSCHANGING
    <00077> 0015087C S WM_EXITSIZEMOVE
    <00078> 0015087C R WM_EXITSIZEMOVE
    <00079> 0015087C R WM_SYSCOMMAND
    <00080> 0015087C S WM_NCHITTEST xPos:338 yPos:496
    <00081> 0015087C R WM_NCHITTEST nHittest:HTRIGHT
    <00082> 0015087C S WM_SETCURSOR hwnd:0015087C nHittest:HTRIGHT wMouseMsg:WM_MOUSEMOVE
    <00083> 0015087C R WM_SETCURSOR fHaltProcessing:True
    <00084> 0015087C P WM_NCMOUSEMOVE nHittest:HTRIGHT xPos:338 yPos:496
    <00085> 0015087C S WM_WINDOWPOSCHANGING lpwp:0028FAA4
    <00086> 0015087C R WM_WINDOWPOSCHANGING
    <00087> 0015087C S WM_NCCALCSIZE fCalcValidRects:True lpncsp:0028FA7C
    <00088> 0015087C R WM_NCCALCSIZE fuValidRect:0000 lpncsp:0028FA7C
    <00089> 0015087C S WM_NCPAINT hrgn:4D041777
    <00090> 0015087C R WM_NCPAINT
    <00091> 0015087C S WM_ERASEBKGND hdc:32011154
    <00092> 0015087C R WM_ERASEBKGND fErased:True
    <00093> 0015087C S WM_WINDOWPOSCHANGED lpwp:0028FAA4
    <00094> 0015087C R WM_WINDOWPOSCHANGED
    <00095> 0015087C S WM_NCHITTEST xPos:338 yPos:496
    <00096> 0015087C R WM_NCHITTEST nHittest:HTRIGHT
    <00097> 0015087C S WM_SETCURSOR hwnd:0015087C nHittest:HTRIGHT wMouseMsg:WM_MOUSEMOVE
    <00098> 0015087C R WM_SETCURSOR fHaltProcessing:True
    <00099> 0015087C P WM_NCMOUSEMOVE nHittest:HTRIGHT xPos:338 yPos:496
    <00100> 0015087C P WM_NCMOUSELEAVE
    <00101> 0015087C S WM_NCACTIVATE fActive:False
    <00102> 0015087C R WM_NCACTIVATE fDeactivateOK:True
    <00103> 0015087C S WM_ACTIVATE fActive:WA_INACTIVE fMinimized:False hwndPrevious:(null)
    <00104> 0015087C R WM_ACTIVATE
    <00105> 0015087C S WM_ACTIVATEAPP fActive:False dwThreadID:00000408
    <00106> 0015087C R WM_ACTIVATEAPP
    <00107> 0015087C S WM_KILLFOCUS hwndGetFocus:(null)
    <00108> 0015087C R WM_KILLFOCUS
    <00109> 0015087C S WM_IME_SETCONTEXT fSet:0 iShow:C000000F
    <00110> 0015087C S WM_IME_NOTIFY dwCommand:IMN_CLOSESTATUSWINDOW dwCommand:00000001 dwData:00000000
    <00111> 0015087C R WM_IME_NOTIFY
    <00112> 0015087C R WM_IME_SETCONTEXT
    Tu en penses quoi ?
    L'Opus attire les Prélats

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est plutôt une stack trace qu'il faudrait, je pense: Typiquement, les appels imbriqués à ta WindowProc (qui pour la plupart, seront forwardés à DefWindowProc) et la valeur du message à chaque fois...

    Ainsi, tu saurais où intercepter le comportement (même s'il y a des chances que ce soit directement dans WM_NCLBUTTONDOWN, hélas).

    Edit: Encore que, le WM_SYSCOMMAND (SC_SIZE) parait soudain très intéressant...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    j'utilise peu les outils microsoft (je suis un codeur linux à la base), et j'utilise MSYS/MinGW. Il y a un outils independant de Visual Studio pour récupérer la stack trace ?
    L'Opus attire les Prélats

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si tu as pris MinGW avec un EDI, tu peux avoir accès à un debugger, mais sinon, je ne sais pas trop. Et puis, rien n'arrive au niveau du debugger de Visual...

    Mais de toute façon, c'est le WM_SYSCOMMAND(SC_MOVE) qu'il faut réimplémenter pour le déplacement de la fenêtre (et il doit y avoir un truc à peu près pareil pour le redimensionnement).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    j'ai un problème avec WM_SYSCOMMAND + SC_MOVE. Le code dans la window procedure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    case WM_SYSCOMMAND:
           INF("sys command window message (%4x)", (int)window_param);
           if ((DWORD)window_param == (SC_MOVE & 0xFFF0))
             {
               int x,y;
    
               INF("sys command MOVE window message : %dx%d", GET_X_LPARAM(data_param), GET_Y_LPARAM(data_param));
               ecore_win32_window_geometry_get((struct Ecore_Win32_Window *)GetWindowLong(window, GWL_USERDATA),
                                               &x, &y, NULL, NULL);
               printf (" ** %dx%d\n", x, y);
    
               return 0;
             }
           if ((DWORD)window_param == (SC_SIZE & 0xfff0))
             {
               INF("sys command SIZE window message");
               return 0;
             }
           return DefWindowProc(window, message, window_param, data_param);
    J'affiche certaines données : la position renvoyée dans lParam (dans mon code, lParam est noté data_param) et la position de la fenêtre (dans x et y). La fenêtre ne bouge plus (x et y restent aussi constant, donc c'est cohérent) donc c'est à moi de faire un MoveWindow(). Problème: je n'arrive pas à récupérer les nouvelles coordonnées avec juste lParam.

    J'ai cherché sur google pendant pas mal de temps sans succès...

    C'est anormalement difficile, je trouve :/
    L'Opus attire les Prélats

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ((DWORD)window_param == (SC_MOVE & 0xFFF0))
    Y'a pas un truc qui te choque là-dedans?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    si tu parles de (SC_MOVE & 0xFFF0), non, vu que c'est ce que msdn dit de faire http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx :

    "In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator."

    SC_MOVE vaut 0Xf010 selon msdn, mais dans les faits, quand on utilise la souris, c'est 0xf012 (0Xf010 est lorsqu'on utilise le clavier).

    De toute facon, le probleme n'est pas la. Mes messages sont bien affichés, le test n'est pas en cause.
    L'Opus attire les Prélats

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    N'empêche, ceci devrait être plus approprié:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ((window_param & 0xFFF0) == SC_MOVE)
    Pour la suite de ton problème: Tu n'as pas encore de nouvelles coordonnées, à ce point-là: Le message que tu as reçu est un début de mouvement, maintenant il te faut surveiller ce que fait l'utilisateur jusqu'à ce qu'il lâche le bouton (tu peux faire ça par une boucle modale qui utiliserait ton PeekMessage() ou MsgWaitForMultipleObjects(), mais ça peut peut-être marcher si tu fais plutôt des "modes" pour ta fenêtre: Tu traites les messages NC_* différemment tant que tu es "en mode déplacement"...)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    Je pense avoir compris. Voici l'algo:

    WM_NCLBUTTONDOWN : on vérifie qu'on est dans la barre de titre, on sauve les coords de la fenêtre et du pointeur

    WM_SYSCOMMAND : si on a SC_MOVE, on mets un flag disant que on fait un move de la fenêtre. C'est le début du drag

    WM_NCMOUSEMOVE : si on est en 'drag mode', on recupère les coord du pointeur et on calcule le déplacement par rapport aux coord du pointeur, puis on déplace la fenêtre par rapport a la position sauvegardée précédemment (peut-etre que récupérer maintenant les coord de la fenêtre marcherait aussi mais ca serait peut-être moins réactif). On fait le MoveWindow()

    WM_NCLBUTTONUP : on arrête le drag.

    cet algo marche bien (je l'ai implémenté).

    Il faudrait peut-être aussi que je gère WM_NCMOUSELEAVE et arrêter le drag si on sort.

    Le resize est, je pense, similaire, mais plus compliqué à gérer (entre autre, je gère des tailles min et max, et la fenêtre peut être resizée avec des "sauts" comme quand on diminue la taille d'une console DOS, etc...)

    merci pour ta patience. Je fermerai le thread quand j'aurai implémenté le resize.
    L'Opus attire les Prélats

  15. #15
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Normalement, tu ne devrais pas avoir à faire un NCMOUSELEAVE. Par contre, pense à faire un SetCapture() lors du LBUTTONDOWN (et un ReleaseCapture() lors du LBUTTONUP, mais celui-ci est plus ou moins automatique de toute façon).

    De plus, pour bien faire il faudrait que tu agisses différemment selon le setting SystemParametersInfo(SPI_GETDRAGFULLWINDOWS) (afficher juste un rectangle au lieu de vraiment redimensionner) mais ça devient peut-être compliqué de faire ça sans utiliser sa propre boucle modale.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #16
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Normalement, tu ne devrais pas avoir à faire un NCMOUSELEAVE.
    Je pense que si. Si je déplace trop vite la souris, par exemple pour le resize que j'ai implémenté, la souris sort du bord et donc plus de resize. En regardant le comportement des applis, je remarque que si je bouge trop vite la souris, elle sort du bord mais le resize continue. Je pensais le faire avec le NCMOUSELEAVE, mais il y a peut-être une autre méthode.

    Par contre, pense à faire un SetCapture() lors du LBUTTONDOWN (et un ReleaseCapture() lors du LBUTTONUP, mais celui-ci est plus ou moins automatique de toute façon).
    ok.

    De plus, pour bien faire il faudrait que tu agisses différemment selon le setting SystemParametersInfo(SPI_GETDRAGFULLWINDOWS) (afficher juste un rectangle au lieu de vraiment redimensionner) mais ça devient peut-être compliqué de faire ça sans utiliser sa propre boucle modale.
    J'ai regardé la doc, mais je ne sais pas à quoi ça sert vraiment. Quand je resize, j'ai un scintillement. Plus présicément, j'ai affiché un rectangle rouge comme fond avec la bibliothèque graphique que j'utilise pour la partie client. Quand je resize, j'ai le fond gris de la fenêtre puis juste après le rectangle rouge qui apparaît. Gérer SPI_GETDRAGFULLWINDOWS permettrait d'enlever ce scintillement ?
    L'Opus attire les Prélats

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Non. C'est juste que par "bonne pratique", on n'est pas censé redimensionner une fenêtre "instantanément" quand SPI_GETDRAGFULLWINDOWS n'est pas activé: Il s'agit de la case à cocher "Afficher le contenu de la fenêtre pendant son déplacement (ou redimensionnement)".
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    Je reviens sur un problème que je n'ai toujours pas résolu (et qui est dans mon précédent message). C'est à propos du redimensionnement. Je le gère donc moi-même avec les messages WM_NC*.

    Si je redimensionne la fenêtre avec la souris, et que celle-ci se déplace lentement et reste toujours dans la partie non-client, pas de problème. Je récupère les coordonnées de la souris et je redimensionne comme il faut.

    Mais si je déplace trop vite la souris, je sors de la partie non-client et je n'ai plus les messages WM_NC*, donc plus de redimensionnement possible.

    Autre example où être hors de la zone non-client est nécessaire : si j'ai une application style un éditeur de code ou un terminal que je veux redimensionner. Je veux que je redimensionnement ne soit fait que quand la largeur ou hauteur d'un "caractère" supplémentaire est atteinte (cf emacs sous windows par exemple).

    Avec WM_NCMOUSELEAVE, je ne vois pas comment faire.

    Que dois-je faire pour résoudre ce problème ?

    merci
    L'Opus attire les Prélats

  19. #19
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    SetCapture() ? Cela te permet de recevoir les messages où que soit la souris, jusqu'à ce que le bouton soit relâché.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #20
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    340
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 340
    Points : 177
    Points
    177
    Par défaut
    Après pas mal de recherche à propos de SetCapture(), je reviens à mon problème. Il ne me reste plus grand chose à faire

    Déjà, quand SetCapture() est utilisé, les messages de la partie non client ne sont plus envoyés. Donc je dois gérer le redimensionnement dans WM_MOUSEMOVE.

    Et si je n'appelle pas ReleaseCapture() (dans WM_LBUTTONUP), je ne peux plus utiliser le bord. Donc il faut vraiment l'appeler.

    Il faut aussi éviter d'afficher le fond en gérant WM_ERASEBKGND pour ne pas avoir de scintillement. Là je pense que j'ai tout ce qu'il me faut. Ce n'était pas évident du tout (pour moi)... J'ai un redimensionnement qui est bien fluide

    Pas de question pour l'instant, je voulais juste compléter tes réponses, au cas où ça intéresserait quelqu'un.

    Merci pour toutes tes réponses. Je fermerai le thread quand tout sera au point.
    L'Opus attire les Prélats

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Déplacer une fenêtre
    Par r0t0r dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 16/10/2008, 18h51
  2. Evenement déplacer une fenêtre
    Par manu_b dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 18/07/2008, 16h13
  3. [WPF] Déplacer une fenêtre sans barre de titre
    Par tomlev dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 12/09/2007, 11h25
  4. [souris] déplacer une fenêtre sans bords
    Par if_zen dans le forum AWT/Swing
    Réponses: 6
    Dernier message: 15/07/2006, 02h20
  5. Déplacer une fenêtre en bsNone
    Par mobee dans le forum C++Builder
    Réponses: 5
    Dernier message: 10/03/2006, 20h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo