2013-02-07 60 views
0

我试图从一个全局的WindowProc函数发送一个消息给一个GUI类。 该消息被定义如下:PostMessage只能使用一次?

#define WM_ENV_RESIZED (WM_APP + 0) 

我WindowProc函数看起来像这样

LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    int res; 
    switch (message) 
    { 
     case WM_SIZE: 
      std::cout << "window resized" << std::endl; 

      res = PostMessage(hWnd, WM_ENV_RESIZED, 0, 0); 
      if (res == 0) //<-- res is never 0 
      { 
       std::cout << "PostMessage failure!" << std::endl; 
       std::cout << "Error code: " << GetLastError() << std::endl; 
      } 
      break; 
     default: 
      return DefWindowProc(hWnd, message, wParam, lParam); 
    } 

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

该消息随后在GUI类收到像这样:

MSG msg; 
while (running) 
{ 
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
     processWindowsMessage(&msg); 

    //DirectX render calls 
} 

现在我的问题是PeekMessage()永远不会收到该消息。只有在创建窗口时才会收到一次。之后,它从未收到。

在PostMessage()后直接调用GetLastError()总是返回错误代码6,根据MSDN代表ERROR_INVALID_HANDLE。但是这没有任何意义,因为PostMessage()永远不会返回0,这意味着在发布过程中出现问题。 我尝试绕过消息队列,并使用SendMessage()直接发送消息到窗口,但始终返回0(具有相同的错误代码6 ..)。

我真的不知道我做错了什么。如何确保在使用PeekMessage()时总是收到张贴的消息?

编辑: 我已经更新了Remy建议的消息循环。下面是processWindowsMessage()的代码

void Environment::processWindowsMessage(MSG *msg) 
{ 
    switch (msg->message) 
    { 
     case WM_ENV_RESIZED: 
      std::cout << "WM_ENV_RESIZED caught" << std::endl; 
      break; 
     case WM_QUIT: 
      running = false; 
      break; 
     default: 
      TranslateMessage(msg); 
      DispatchMessage(msg); 
      break; 
    } 
} 
+4

如果'PostMessage'说它成功了,那么它成功了。在这种情况下调用'GetLastError'没有用处,因为错误代码只在失败时定义。某些API函数预期设置错误代码,*以防*出现错误。除非文档建议你,否则不要调用'GetLastError'。文档通常只在失败时提供建议。成功的原因很少见。 –

+0

你可以发布你的processWindowsMessage函数的相关部分吗? –

+0

PostMessage调用中使用的窗口句柄没有意义。它当然不应该是hWnd。 –

回答

1

由于您的消息被发布到要调整大小相同的窗口,DispatchMessage()将消息发送到窗口的程序像任何其他消息靶向那个窗口。因此,要么:

1)处理的windowProcedure()内的消息:

LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
     case WM_SIZE: 
      std::cout << "window resized" << std::endl; 

      if (!PostMessage(hWnd, WM_ENV_RESIZED, 0, 0)) 
      { 
       std::cout << "PostMessage failure!" << std::endl; 
       std::cout << "Error code: " << GetLastError() << std::endl; 
      } 
      break; 

     case WM_ENV_RESIZED: 
      std::cout << "env resized" << std::endl; 
      //... 
      return 0; 
    } 

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

MSG msg; 
while (running) 
{ 
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    //DirectX render calls 
} 

2)如果你不希望你的窗口过程中处理自定义消息,然后改变你的消息循环的TranslateMessage()DispatchMessage()呼叫转移到processWindowsMessage(),只叫他们非自定义消息,不翻译/派遣自定义消息:

LRESULT CALLBACK windowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
     case WM_SIZE: 
      std::cout << "window resized" << std::endl; 

      if (!PostMessage(hWnd, WM_ENV_RESIZED, 0, 0)) 
      { 
       std::cout << "PostMessage failure!" << std::endl; 
       std::cout << "Error code: " << GetLastError() << std::endl; 
      } 
      break; 
    } 

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

MSG msg; 
while (running) 
{ 
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
     processWindowsMessage(&msg); 

    //DirectX render calls 
} 

void processWindowsMessage(MSG *msg) 
{ 
    switch (msg->message) 
    { 
     case WM_ENV_RESIZED: 
      std::cout << "env resized" << std::endl; 
      //... 
      break; 

     default: 
      TranslateMessage(msg); 
      DispatchMessage(msg); 
      break; 
    } 
} 
+0

一般的好建议。我想说,这并没有解决OP的问题,但说实话,他现在已经没有了杂草,这些都是很好的提示。 – HerrJoebob

+0

给出显示的原始代码,唯一可以看到它不起作用的方法是如果'TranslateMessage()'正在将'MSG'修改为'processWindowsMessage()'无法识别的其他东西。 –

+0

感谢Remy的回复。我按照你的建议修改了我的代码,但是这条消息仍然没有被捕获。但我注意到,如果我在processWindowsMessage()中的某个开关上休息一下,等一会儿,然后继续运行代码,就会收到并处理该消息。这是相当好奇的行为,我不知道为什么会发生这种情况...... – Krienie