2011-06-26 13 views
9

En objeto GUI mi C++ de aplicación Tengo el siguiente en el procedimiento de la ventana principal:PostMessage() tiene éxito pero mi código de procesamiento de mensajes nunca recibe el mensaje

case WM_SIZE: 
    { 
     OutputDebugString(L"WM_SIZE received.\n"); 
     RECT rect = {0}; 
     GetWindowRect(hwnd, &rect); 
     if (!PostMessage(0, GUI_MSG_SIZECHANGED, w, MAKELONG(rect.bottom - rect.top, rect.right - rect.left))) { 
      OutputDebugString(L"PostMessage failed.\n"); // <--- never called 
     } 
    } 

    return 0; // break; 

El objeto GUI también tiene el siguiente método getMessage() :

int GUI::getMessage(MSG & msg) { 
    BOOL result = 0; 

    while ((result = GetMessage(&msg, 0, 0, 0)) > 0) { 
     if (msg.message > (GUI_MSG_BASE-1) && msg.message < (GUI_MSG_LAST+1)) { 
      OutputDebugString(L"GUI message received.\n"); 
      break; 
     } 
     else { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
    } 

    return result; 
} 

el objeto de la aplicación llama a este método de la siguiente manera:

while ((result = _gui.getMessage(msg)) > 0) { 
    switch (msg.message) { 
     // TODO: Add gui message handlers 
     case GUI_MSG_SIZECHANGED: 
      OutputDebugString(L"GUI_MSG_SIZECHANGED received.\n"); 
      _cfg.setWndWidth(HIWORD(msg.lParam)); 
      _cfg.setWndHeight(LOWORD(msg.lParam)); 
      if (msg.wParam == SIZE_MAXIMIZED) 
       _cfg.setWndShow(SW_MAXIMIZE); 
      else if (msg.wParam == SIZE_MINIMIZED) 
       _cfg.setWndShow(SW_MINIMIZE); 
      else if (msg.wParam == SIZE_RESTORED) 
       _cfg.setWndShow(SW_SHOWNORMAL); 
      break; 
    } 
} 

El objeto de la aplicación está interesado en el tamaño de la ventana porque almacena esta información en un archivo de configuración.

Cuando ejecuto esto en depurador de Visual Studio, la ventana de salida se parece a esto después de cambiar el tamaño de la ventana:

WM_SIZE received. 
GUI message received. 
GUI_MSG_SIZECHANGED received. 
WM_SIZE received. 
WM_SIZE received. 
WM_SIZE received. 
WM_SIZE received. 
...etc... 

El PostMessage() función nunca falla, pero parece que sólo para enviar GUI_MSG_SIZECHANGED (#defined como WM_APP + 0x000d) la primera vez que se maneja WM_SIZE, que es justo después de manejar WM_CREATE.

No tengo idea de qué podría estar causando esto. Intenté usar SendMessage y PostThreadMessage, pero el resultado es el mismo. También leo a través de la documentación de manejo de mensajes de MSDN pero no pude encontrar lo que está mal con mi código.

¿Alguien podría ayudar?

+4

¿Por qué no ejecuta un bucle de mensaje normal? ¿Qué diablos es el punto del bucle 'while' en' GUI :: getMessage'? ¡Parece que tienes dos bombas de mensajes anidados! No puedo entender esto en absoluto. Si ejecutó una bomba de mensaje normal, sería más fácil sentirse motivado para tratar de responder la pregunta. Tal como está, uno solo puede adivinar qué otras rarezas están sucediendo. –

+0

Y '(msg.message> (GUI_MSG_BASE-1) && msg.message <(GUI_MSG_LAST + 1))' en lugar de usar '> =' y '<='? ¿Por qué? –

+1

Intenta agregar algún resultado de depuración cuando ingresas y dejas la función 'GUI :: getMessage' y después del ciclo alrededor de' _gui.GetMessage'. Creo que es algo en el flujo de control de tus programas el problema, pero no puedo identificar exactamente dónde. –

Respuesta

6

Hackear un ciclo de mensajes personalizados es algo de lo que te arrepentirás algún día. Lo golpeas temprano.

No publique mensajes con un identificador de ventana NULL, solo pueden funcionar si puede garantizar que su programa solo bombea su ciclo de mensajes personalizados. No puedes hacer tal garantía. Estos mensajes caen en el cubo de bits tan pronto como inicia un diálogo o Windows decide bombear un bucle de mensaje. Lo cual es el caso cuando el usuario cambia el tamaño de una ventana, la lógica de cambio de tamaño es modal. Windows bombea su propio bucle de mensaje, WM_ENTERSIZEMOVE lo anuncia. Esta es también la razón por la que PostThreadMessage es evil si el subproceso es capaz de mostrar cualquier ventana. Incluso un MessageBox es fatal. DispatchMessage no puede entregar el mensaje.

Crea una ventana oculta que actúa como controlador. Ahora puede detectar GUI_MSG_SIZECHANGED en su procedimiento de ventana y no es necesario hackear el bucle de mensajes. Ese controlador no es con poca frecuencia la ventana principal de su aplicación por cierto.

+0

Aunque realmente no me gusta la idea de una ventana oculta dentro de mi objeto de aplicación (como yo estoy tratando de mantener el código GUI en mi objeto GUI), esto es probablemente lo voy a terminar si no puedo encontrar una solución más elegante. Por favor, lea mi respuesta a David, tal vez usted tiene alguna entrada agradable a mi pregunta diseño orientado a objetos. – Jehjoa

+0

estoy bien con mensajes de rosca que se dejó caer en el suelo durante los bucles de tamaño modal, pero luego * ¿cómo llegar el primero a través de *? :) –

+1

@ Frédéric - el primero es probablemente un WM_SIZE desde la creación de la ventana inicial. Algo como eso. –

Cuestiones relacionadas