2012-05-29 22 views
6

Ésta es mi bucle principal:aplicación My Win32 no saldrá del bucle principal

while(TRUE) 
    { 

    PeekMessage(&msg,hWnd,0,0,PM_REMOVE); 
     if (msg.message==WM_QUIT) 
      break; 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 


    } 

y este es mi procedimiento de devolución de llamada:

LRESULT CALLBACK WinProc(HWND hWnd,UINT msg1,WPARAM wParam,LPARAM lParam) 
{ 
    switch(msg1) 
    { 
     case WM_DESTROY : 
     { 
      PostQuitMessage(0); 
      return 0; 
     } 
     break; 
    } 

    return DefWindowProc(hWnd,msg1,wParam,lParam); 
} 

descubrí que cuando se presiona el botón Cerrar WM_NCLBUTTONDOWN será devuelto por la función PeekMessage en el siguiente ciclo, y no WM_QUIT!

+0

Había otra pregunta sobre este mismo problema hace un par de semanas: [ventanas infinito bucle de mensajes] (http://stackoverflow.com/questions/10658813/infinite -windows-message-loop) – jamesdlin

Respuesta

3

El correct way hacer un bucle de mensajes es

BOOL bRet; 
MSG msg; 
while ((bRet = GetMessage(&msg, hWnd, 0, 0)) != 0) 
{ 
    if (bRet == -1) 
    { 
     // handle the error and possibly exit 
    } 
    else 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

Puede utilizar PeekMessage si realmente necesita ... pero ¿por qué estás ignorando el valor de retorno?

Además, tenga en cuenta que esto es específico a una ventana. Creo que PostQuitMessage es para un hilo ... No lo recuerdo en la cabeza, pero es posible que deba pasar NULL en lugar de hWnd.

Si tiene alguna otra ventana, también puede secuestrar su ciclo de mensajes; no creo que sea un problema, pero podría ser uno; mantenlo en mente.

+2

Tengo que usar PeekMessage. –

+0

@ThePianist: Editado. – Mehrdad

+0

¡WOW! ¡Gracias! (Damet garm!: D) Lo cambié a Null y funcionó! –

0

recomiendo pegarse con esto, para asegurarse de errores (-1) devueltos por GetMessage pueden ser manejados adecuadamente:

while(GetMessage(&Msg, NULL, 0, 0) > 0) { 
    TranslateMessage(&Msg); 
    DispatchMessage(&Msg); 
} 

Además, otro error no está manejando WM_CLOSE correctamente. Intente esto en su lugar para hacer que su programa realmente escuche WM_CLOSE (el botón de cerrar):

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { 
    switch(Message) { 
     case WM_CLOSE: { 
      DestroyWindow(hwnd); // this 
      break; 
     } 
     case WM_DESTROY: { 
      PostQuitMessage(0); 
      break; 
     } 
     default: 
      return DefWindowProc(hwnd, Message, wParam, lParam); 
    } 
    return 0; 
} 
+0

Tengo que usar PeekMessage. –

+0

Bueno, PeekMessage no bloquea. No recomiendo vincular un núcleo de CPU pidiendo mensajes. ¿Por qué lo necesitas realmente? – Orwell

+0

@ Orwell: Definitivamente hay situaciones en las que necesitas usar 'PeekMessage'. Si piensas lo contrario, considera por qué existe esa función en primer lugar ... – Mehrdad

2

Aquí hay un código que encontré. Debería darte algo con lo que trabajar.

// Main message loop: 
do 
{ 
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
    { 
     if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
     { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
    } 

    // Run game code here. 
    gTradeApp->ExecuteNextAction(); 
} 
while (msg.message != WM_QUIT); 

y el WndProc

LRESULT CALLBACK WndProc(HWND aHWnd, UINT aMessage, WPARAM aWParam, LPARAM aLParam) 
{ 
    switch (aMessage) 
    { 
    case WM_COMMAND: 
     return HandleCommand(aHWnd, aMessage, aWParam, aLParam); 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 

    default: 
     return DefWindowProc(aHWnd, aMessage, aWParam, aLParam); 
    } 

    return 0; 
} 
Cuestiones relacionadas