Обнаружена операция по восстановлению окна.

WM_GETMINMAXINFO генерируется, когда начинается операция максимизации и WM_SIZE когда операция максимизации закончена.

WM_SIZE также генерируется, когда операция восстановления завершена.

Но как определить, что операция восстановления окна вот-вот начнется?


Мне нужно определить точный момент, когда окно собирается восстановить, но не момент, когда уже восстановлено. Я разрабатываю многопоточность DirectX приложение. Я рендеринг в выделенной вторичной теме. Когда окно собирается начать максимизировать или восстановить, мне нужно изменить размер буфера рендеринга (DirectX DeviceReset). Я могу изменить размер заднего буфера только из основного потока, поэтому я использую Critical Sections синхронизировать с потоком рендеринга. Проблема в том, что я не могу прервать Present Операция в потоке рендеринга и когда операция максимизации или восстановления вот-вот начнется, я жду, пока текущий Present Операция закончена и только после этого начинают изменяться размеры (максимизировать / восстанавливать). Если вы слишком поздно измените размер буфера (когда операция максимизации / восстановления завершена (WM_SIZE сообщение) вы можете заметить, что старая рамка нарисована с неправильным размером (изображение растянуто).

1 ответ

Решение

Что ж, приятно видеть, что кто-то до сих пор размышляет над такими вопросами. Эти мелкие детали, например растягивание изображения за одну секунду при изменении размера, отличают профессионально выглядящее приложение от спальни, закодированной.

В моем старом коде я нашел трюки, которые, вероятно, будут вам интересны. Первое, что вы можете проверить WM_SYSCOMMAND:

        case WM_SYSCOMMAND:
           {
               switch (wParam)
               {
               case SC_MAXIMIZE:
                   std::cout << "Going to MAXIMIZE: " << std::endl;
                   break;

               case SC_MINIMIZE:
                   std::cout << "Going to MINIMIZE: " << std::endl;

                   break;

               case SC_RESTORE:
                   std::cout << "Going to RESTORE: " << std::endl;
                   break;


               default:
                   break;
               }
               return DefWindowProc(m_hWnd, msg, wParam, lParam);
           }

Но проблема в том, что он не перехватывает события максимизации / восстановления, когда пользователь дважды щелкает заголовок заголовка.

Итак, я нашел маленький трюк, когда разбираю WM_WINDOWPOSCHANGING,

Сначала давайте проведем небольшое забавное исследование. Мы читаем документы здесь и здесь, где мы обнаружили, что:

Сообщение WM_WINDOWPOSCHANGING, отправленное окну, размер, позиция или место которого в Z-порядке - ОБ ИЗМЕНЕНИИ

Поскольку почти невозможно отладить события в обычном отладчике (как вы будете проверять, часто ли отладчик изменяет z-порядок окна?), Поэтому для целей тестирования мы создадим небольшое консольное приложение с int main()где мы инициализируем окно как обычно (HINSTANCE мы можем получить из GetModuleHandle(0);). Таким образом, у нас есть консоль и окно одновременно. В оконной процедуре мы ловим WM_WINDOWPOSCHANGING и распечатайте информацию, она скажет нам, чтобы утешить:

        case WM_WINDOWPOSCHANGING:
        {
            WINDOWPOS* wp = ((WINDOWPOS*)lParam);

            // We checking current state which is saved in member (or global) bools
            // Set them checking WM_SIZE before
            if (m_bMaximized)
            {
                std::cout << "Currently MAXIMIZED: ";
            }
            else if (m_bMinimized)
            {
                std::cout << "Currently MINIMIZED: ";
            }
            else
            {
                std::cout << "Currently NORMAL: ";
            }

            dbgPrintPositionCurrent();

            std::cout << "Going to change to: ";
            dbgPrintPosition(wp->x, wp->y, wp->cx, wp->cy, wp->flags);
            std::cout << std::endl << std::endl;

            return DefWindowProc(m_hWnd, msg, wParam, lParam);
        }

Смотрите полезные функции здесь.

Когда мы наигрались, мы можем сделать это полезным:

                bool bFrameChanged = ((wp->flags) & SWP_FRAMECHANGED) > 0;
            bool bNoCopyBits = ((wp->flags) & SWP_NOCOPYBITS) > 0;
            bool bNormal = (!m_bMaximized) && (!m_bMinimized);

            // from maximized
            if(m_bMaximized && bFrameChanged && !bNoCopyBits)
            {
                std::cout << " MAXIMIZED -> NORMAL " << std::endl;
            }
            if (m_bMaximized && bFrameChanged && bNoCopyBits)
            {
                std::cout << " MAXIMIZED -> MINIMIZED " << std::endl;
            }

            // from normal states
            if (bNormal && bFrameChanged && !bNoCopyBits)
            {
                std::cout << " NORMAL -> MAXIMIZED " << std::endl;
            }
            if (bNormal && bFrameChanged && bNoCopyBits)
            {
                std::cout << " NORMAL -> MINIMIZED"  << std::endl;
            }

            // from minimized
            if(m_bMinimized && bFrameChanged)
            {
                std::cout << " MINIMIZED -> MAXIMIZED " << std::endl;
            }
            if(m_bMinimized && m_bMaximized && bFrameChanged)
            {
                std::cout << " MINIMIZED -> MAXIMIZED " << std::endl;
            }


            return DefWindowProc(m_hWnd, msg, wParam, lParam);

Я действительно не уверен, что это самый простой или даже правильный способ сделать это. Но пока это работает =) Кроме того, я думаю, что вашему приложению все равно, что именно произошло: максимизация, восстановление или изменение размера. Просто важно , изменился ли размер, поэтому вам нужно изменить размер буферов / воссоздать цепочку подкачки и т. Д.

Надеюсь, поможет! Удачного кодирования!

Другие вопросы по тегам