gpt4 book ai didi

自定义 WM_APP 消息未发布到消息队列中

转载 作者:行者123 更新时间:2023-11-30 18:44:14 24 4
gpt4 key购买 nike

当 WM_SIZE 发送到窗口过程时,我试图发送自定义消息(WM_APP + 1)。我希望能够使用 PeekMessage 从其他函数捕获它并执行某些操作。但是当我测试它时,消息似乎没有发送到队列。添加一些 printf 语句表明它转到窗口过程。奇怪的是,当我在调试器中单步执行代码时,它工作正常,但当我正常运行时,它又回到不工作状态。

存在问题的工作示例程序,调整窗口大小以进行测试:

#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "user32.lib")

#define OBG_EVENT_QUIT 0
#define OBG_EVENT_RESIZE 1
#define OBG_EVENT_NO -1
#define OBG_EVENT_UNKNOWN -2

//user defined event
#define OBG_WM_RESIZE (WM_APP + 1)

typedef union
{
int type;

struct
{
int type;
int width;
int height;

} resizeEvent;

} obg_event;

LRESULT CALLBACK obgpf_DefaultWindowCallback(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;

switch(message)
{
case WM_CLOSE:
{
PostMessageA(window, WM_QUIT, 0, 0);
} break;

//this should be handled by OBGGetEvent
case OBG_WM_RESIZE:
{
printf("MESSAGE WENT THROUGH. DON'T WANT THIS\n");
} break;

case WM_SIZE:
{
PostMessageA(window, OBG_WM_RESIZE, wParam, lParam);
} break;

default:
{
result = DefWindowProc(window, message, wParam, lParam);
} break;
}

return result;
}

int OBGGetEvent(obg_event *event)
{
int moreMessages = 0;
MSG message;

if(PeekMessage(&message, 0, 0, 0, PM_REMOVE))
{
moreMessages = 1;
switch(message.message)
{
case WM_QUIT:
{
event->type = OBG_EVENT_QUIT;
} break;


case OBG_WM_RESIZE:
{
event->type = OBG_EVENT_RESIZE;
event->resizeEvent.type = OBG_EVENT_RESIZE;
event->resizeEvent.width = LOWORD(message.lParam);
event->resizeEvent.height = HIWORD(message.lParam);
} break;

default:
{
event->type = OBG_EVENT_UNKNOWN;
TranslateMessage(&message);
DispatchMessage(&message);
} break;
}
}
else
{
event->type = OBG_EVENT_NO;
}

return moreMessages;
}

int main()
{
HINSTANCE instance = GetModuleHandleA(0);

WNDCLASSEX windowClass = {0};
windowClass.cbSize = sizeof(windowClass);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = obgpf_DefaultWindowCallback;
windowClass.hInstance = instance;
windowClass.lpszClassName = "testClass";
windowClass.hIcon = LoadIcon(0, IDI_APPLICATION);
windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
windowClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
windowClass.hCursor = LoadCursorA(0, IDC_ARROW);

HWND window;

if(RegisterClassEx(&windowClass))
{
window = CreateWindowEx(0,
windowClass.lpszClassName,
"test window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
300,
0,
0,
instance,
0);

if(window)
{
int appIsRunning = 1;
obg_event event = {0};
event.type = -1;
while(appIsRunning)
{
while(OBGGetEvent(&event))
{
if(event.type == OBG_EVENT_QUIT)
{
printf("event quit\n");
appIsRunning = 0;
break;
}
else if(event.type == OBG_EVENT_RESIZE)
{
printf("window resized: width %d height %d\n", event.resizeEvent.width, event.resizeEvent.height);
}
}

Sleep(33);
}
}
else
{
printf("window error\n");
}
}
else
{
printf("windowClass error\n");
}

return 0;
}

我尝试使用 SendMessage 而不是 PeekMessage 执行此操作,但发生了同样的事情。不确定我错过了什么或误解了什么,但感谢任何帮助!

编辑:添加了一个完整的工作程序来重现问题

最佳答案

感谢您提供示例代码。

您所看到的行为是因为当使用鼠标调整窗口大小时,操作系统会进入模式消息循环来处理鼠标输入。在此循环期间,您的消息循环不会运行 - 这意味着您的 PeekMessage() 和特殊消息处理也不会运行。相反,消息只是像平常一样分派(dispatch)到您的窗口过程。

立即想到两种解决方案,但如何处理这个问题实际上取决于程序的设计以及为什么要以这种方式处理大小事件。

我的第一个想法是跟踪您是否处于模式大小调整循环中,并推迟发布通知消息,直到循环完成。下面是如何使用您提供的窗口过程执行此操作的示例。

第二种解决方案是每当您获得 WM_SIZE 时直接调用您的调整大小事件处理程序(或者,如果您必须通过事件系统,请将其处理程序放在窗口过程中而不是使用PostMessage)。

第一个建议的示例代码:

LRESULT CALLBACK obgpf_DefaultWindowCallback(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
static bool fResized = false;
static bool fInSizeLoop = false;

switch(message)
{
case WM_CLOSE:
{
PostMessageA(window, WM_QUIT, 0, 0);
} break;

//this should be handled by OBGGetEvent
case OBG_WM_RESIZE:
{
printf("MESSAGE WENT THROUGH. DON'T WANT THIS\n");
} break;

case WM_SIZE:
{
if (fInSizeLoop) // in modal size loop, defer notification
fResized = true;
else
PostMessageA(window, OBG_WM_RESIZE, wParam, lParam);
} break;

case WM_ENTERSIZEMOVE:
fInSizeLoop = true; // begin modal size loop
break;

case WM_EXITSIZEMOVE:
fInSizeLoop = false; // left modal size loop
// post resize notification now
if (fResized) {
RECT rc;
GetClientRect(window, &rc);
PostMessageA(window, OBG_WM_RESIZE, 0, MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
fResized = false;
}
break;

default:
{
result = DefWindowProc(window, message, wParam, lParam);
} break;
}

return result;
}

(抱歉,这是 C++ 代码,我刚刚注意到您已标记为 C - 但原理是相同的)。

关于自定义 WM_APP 消息未发布到消息队列中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58635493/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com