2011-06-26 2 views
9

В объекте GUI моего C++ приложения, я бы следующее в основной оконной процедуре:PostMessage() завершается успешно, но мой код обработки сообщений никогда не получает сообщение

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; 

Объект GUI также имеет метод следующий 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; 
} 

объект приложения вызывает этот метод следующим образом:

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; 
    } 
} 

Объект приложения интересуется размером окна, поскольку он хранит эту информацию в файле конфигурации.

Когда я запускаю это в отладчике Visual Studio, окно вывода выглядит следующим образом после изменения размеров окна:

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

PostMessage() функция никогда не выходит из строя, но, кажется, только послать GUI_MSG_SIZECHANGED (с помощью #define, как WM_APP + 0x000d), когда обрабатывается WM_SIZE, что сразу после обработки WM_CREATE.

Я понятия не имею, что может быть причиной этого. Я попытался использовать SendMessage и PostThreadMessage, но результат тот же. Также прочитайте документацию по обработке сообщений MSDN, но не можете найти, что не так с моим кодом.

Может ли кто-нибудь помочь?

+4

Почему бы вам не запустить обычный цикл сообщений. Какова же точка цикла 'while' в' GUI :: getMessage'? Кажется, у вас два вложенных сообщения! Я вообще не могу об этом подумать. Если вы запустили обычный насос сообщений, было бы легче быть мотивированным, чтобы попытаться ответить на вопрос. В ее нынешнем виде можно только догадываться, что происходит с другой странностью. –

+0

И '(msg.message> (GUI_MSG_BASE-1) && msg.message <(GUI_MSG_LAST + 1))' вместо использования '> =' и '<='? Зачем? –

+1

Попробуйте добавить некоторый отладочный вывод при вводе и выходе из функции «GUI :: getMessage» и после цикла «_gui.GetMessage». Я думаю, что это что-то в ваших потоках управления программами, это проблема, но я не могу точно определить, где именно. –

ответ

6

Взлом пользовательского цикла сообщений - это то, о чем вы будете жить, чтобы сожалеть о некотором дне. Вы ударяете его рано.

Не размещайте сообщения с помощью дескриптора окна NULL, они могут работать только в том случае, если вы можете гарантировать, что ваша программа только когда-либо накачивает ваш настраиваемый цикл сообщений. Вы не можете сделать такую ​​гарантию. Эти сообщения попадают в бит-бит, как только вы начинаете диалог, или Windows решает перекачать сам цикл сообщений. В случае, когда пользователь изменяет размер окна, логика изменения размера является модальной. Windows запускает собственный цикл сообщений, сообщает WM_ENTERSIZEMOVE. Это также является причиной того, что PostThreadMessage - это evil, если поток способен отображать любое окно. Даже MessageBox является фатальным. DispatchMessage не может доставить сообщение.

Создайте скрытое окно, которое действует как контроллер. Теперь вы можете обнаружить GUI_MSG_SIZECHANGED в своей оконной процедуре, и никакие хаки к контуру сообщения не нужны. Этот контроллер нередко является главным окном вашего приложения.

+0

Хотя мне не очень нравится идея скрытого окна внутри моего объекта приложения (поскольку я пытаюсь сохранить код GUI в моем объекте GUI), это, вероятно, то, что я в конечном итоге если я не смогу найти более элегантное решение. Пожалуйста, прочитайте мой ответ Дэвиду, возможно, у вас есть хороший вклад в мой вопрос дизайна OO. – Jehjoa

+0

Я в порядке, когда сообщения о потоках отбрасываются на пол во время модальных циферблатов, но затем * как первый проходит через *? :) –

+1

@ Frédéric - первый, вероятно, WM_SIZE из начального создания окна. Что-то вроде того. –

 Смежные вопросы

  • Нет связанных вопросов^_^