mar*_*000 8 winapi message loops resize freeze
我写了一个win32应用程序.我自己实现了这样的消息循环:
bool programcontinue = true;
while(programcontinue)
{
while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
IdleProcess();
}
Run Code Online (Sandbox Code Playgroud)
我的应用程序中有一个可调整大小的窗口.通常,IdleProcess()每秒被调用几次.当用户抓住可调整大小窗口的角落或边缘时,在用户释放鼠标按钮之前不再调用IdleProcess().
这里发生了什么?
我尝试用if交换内部,但这不会改变行为.似乎在调整大小开始时,该消息的处理程序在调整大小完成之前不会返回?
有没有办法改变这个并在每秒调整大小几次期间调用IdleProcess()?
谢谢马克
编辑:
用if代替内部的意思是:
bool programcontinue = true;
while(programcontinue)
{
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) // <<<<
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
IdleProcess();
}
Run Code Online (Sandbox Code Playgroud)
我的窗口Proc有点冗长,但我用一个小测试应用程序得到了同样的行为.这与VS Project Wizard创建的wndproc相同:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*cke 14
Windows上有许多模态操作.Win32模态操作指的是通过启动自己的事件处理循环将应用程序置于"模式"直到模式完成的函数.常见的应用程序模式包括拖放操作,移动/大小操作,在应用程序可以继续之前弹出需要输入的对话框.
所以发生的事情是:你的消息循环没有被运行.您的窗口收到了传递给DefWindowProc的WM_LBUTTONDOWN消息.DefWindowProc确定用户正在尝试以交互方式调整窗口大小或移动窗口并输入大小/移动模态函数.此功能在消息处理循环中查看鼠标消息,以便它可以拦截它们以提供交互式大小调整体验,并且仅在调整大小操作完成时退出 - 通常是通过用户释放保持按钮或按下escape.
您会收到通知 - DefWindowProc在进入和退出模态事件处理循环时发送WM_ENTERSIZEMOVE和WM_EXITSIZEMOVE消息.
要继续生成"空闲"消息,通常在调用模态函数之前创建一个计时器(SetTimer) - 或者当收到DefWindowProc正在进入模态函数的消息时 - 模态循环将继续调度WM_TIMER消息...并调用来自计时器消息处理程序的idle proc.当模态函数返回时销毁计时器.
当DefWindowProc在wParam中使用SC_MOVE或SC_SIZE处理WM_SYSCOMMAND时,它将进入循环,直到用户通过释放鼠标按钮或按Enter或转义将其停止为止。这样做是因为它允许程序通过处理WM_PAINT和WM_NCPAINT消息(您仍应在“窗口过程”中接收这些事件)来渲染客户区(绘制小部件或游戏或绘制任何内容的区域)以及边框和标题区域。
对于正常的Windows应用程序,它工作正常,由于收到消息,它们在窗口过程中完成了大部分处理。它仅影响在Window Procedure之外进行处理的程序,例如游戏(通常是全屏播放且不会受到影响的游戏)。
但是,有一种解决方法:自己处理WM_SYSCOMMAND,调整大小或移动自己。这需要付出很多努力,但事实证明是值得的。另外,发送WM_SIZING时,也可以使用setjmp / longjmp退出“窗口过程”,或者使用Windows Fibers沿同一行;这些都是骇人听闻的解决方案。
上个周末,我(使用第一种方法)解决了该问题,如果您有兴趣,我已将代码发布到sourceforge上的公共领域。只要确保阅读自述文件,尤其是警告部分即可。在这里是:https : //sourceforge.net/projects/win32loopl/