Win32:用户调整窗口大小时,我的应用程序冻结 [英] Win32: My Application freezes while the user resizes the window

查看:69
本文介绍了Win32:用户调整窗口大小时,我的应用程序冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个win32应用程序.我自己这样实现了消息循环:

     bool programcontinue = true;
     while(programcontinue)
     {
              while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
              {
                       TranslateMessage(&Msg);
                       DispatchMessage(&Msg);
              }

              IdleProcess();
     }

我的应用程序中有一个可调整大小的窗口.通常,IdleProcess()每秒被调用几次.当用户抓住可调整大小的窗口的拐角或边缘时,在用户释放鼠标按钮之前,不会再调用IdleProcess().

这里会发生什么?

我尝试用if交换内部,但这并没有改变行为.似乎在调整大小开始时,直到调整大小后,该消息的处理程序才会返回?

有没有办法改变它并在每秒调整大小几次期间调用IdleProcess()?

谢谢 马克

我用if替换内部while的意思是:

 bool programcontinue = true;
 while(programcontinue)
 {
          if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))  // <<<<
          {
                   TranslateMessage(&Msg);
                   DispatchMessage(&Msg);
          }

          IdleProcess();
 }

我的窗口Proc有点长,但是使用小型测试应用程序,我会得到相同的行为.这与VS Project向导创建的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;
}

解决方案

在Windows上发生了许多模式操作. Win32 Modal操作是指通过启动其自己的事件处理循环直到模式结束而将应用程序置于模式"的函数.常见的应用程序模式包括拖放操作,移动/大小操作,只要弹出对话框需要输入,应用程序就可以继续.

所以正在发生的事情是:您的消息循环未在运行. 您的窗口收到传递给DefWindowProc的WM_LBUTTONDOWN消息. DefWindowProc确定用户正在尝试以交互方式调整窗口大小或移动窗口,并输入了调整大小/移动模式的功能.此功能位于消息处理循环中,监视鼠标消息,以便可以拦截鼠标消息以提供交互式的大小调整体验,并且仅在大小调整操作完成时才会退出-通常是由用户释放按住的按钮或通过按Escape键. /p>

您会收到通知-DefWindowProc在进入和退出模态事件处理循环时会发送WM_ENTERSIZEMOVE和WM_EXITSIZEMOVE消息.

要继续生成空闲"消息,通常在调用模态函数之前或在收到DefWindowProc正在输入模态函数的消息时,创建一个计时器(SetTimer)-模态循环将继续分派WM_TIMER消息...并从计时器消息处理程序中调用空闲proc.模态函数返回时销毁计时器.

I write a win32 application. I implemented the message loop myself like this:

     bool programcontinue = true;
     while(programcontinue)
     {
              while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
              {
                       TranslateMessage(&Msg);
                       DispatchMessage(&Msg);
              }

              IdleProcess();
     }

There is a resizable window in my application. Usually, IdleProcess() gets called several times per second. When the user grabs a corner or an edge of the resizable window, IdleProcess() doesn't get called anymore until the user releases the mouse button.

What happens here?

I tried exchanging the inner while with an if, but that doesn't change the behaviour. It seems like when resizing starts, the handler for that message does not return until the resizing is done?

Is there a way to change this and call IdleProcess() during resizing a few times per second?

Thanks Marc

EDIT:

What I mean by replacing the inner while with if is:

 bool programcontinue = true;
 while(programcontinue)
 {
          if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))  // <<<<
          {
                   TranslateMessage(&Msg);
                   DispatchMessage(&Msg);
          }

          IdleProcess();
 }

My window Proc is a bit lengthy, but I get the same behavior with a small test app. This is identical to the wndproc the VS Project Wizard creates:

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

解决方案

There are a number of modal operations that happen on windows. Win32 Modal operations refer to functions that put an application into a "mode" by starting their own event processing loop until the mode finishes. Common application modes include drag and drop operations, move/size operations, anytime a dialog pops up that needs input before the application can continue.

So what is happening is: Your message loop is NOT being run. Your window recieved a WM_LBUTTONDOWN message that you passed to DefWindowProc. DefWindowProc determined that the user was trying to size or move the window interactively and entered a sizing/moving modal function. This function is in a message processing loop watching for mouse messages so that It can intercept them to provide the interactive sizing experience, and will only exit when the sizing operation completes - typically by the user releasing the held button, or by pressing escape.

You get notified of this - DefWindowProc sends a WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE messages as it enters and exits the modal event processing loop.

To continue to generate "idle" messages, typically create a timer (SetTimer) before calling a modal function - or when getting a message that DefWindowProc is entering a modal function - the modal loop will continue to dispatch WM_TIMER messages... and call the idle proc from the timer message handler. Destroy the timer when the modal function returns.

这篇关于Win32:用户调整窗口大小时,我的应用程序冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆