Обнаружена операция по восстановлению окна.
WM_GETMINMAXINFO
генерируется, когда начинается операция максимизации и WM_SIZE
когда операция максимизации закончена.
WM_SIZE
также генерируется, когда операция восстановления завершена.
Но как определить, что операция восстановления окна вот-вот начнется?
Мне нужно определить точный момент, когда окно собирается восстановить, но не момент, когда уже восстановлено. Я разрабатываю многопоточность DirectX
приложение. Я рендеринг в выделенной вторичной теме. Когда окно собирается начать максимизировать или восстановить, мне нужно изменить размер буфера рендеринга (DirectX Device
Reset
). Я могу изменить размер заднего буфера только из основного потока, поэтому я использую 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);
Я действительно не уверен, что это самый простой или даже правильный способ сделать это. Но пока это работает =) Кроме того, я думаю, что вашему приложению все равно, что именно произошло: максимизация, восстановление или изменение размера. Просто важно , изменился ли размер, поэтому вам нужно изменить размер буферов / воссоздать цепочку подкачки и т. Д.
Надеюсь, поможет! Удачного кодирования!