问题
WM_GETMINMAXINFO
is generated when maximize operation is about to begin and WM_SIZE
when maximize operation is finished.
WM_SIZE
is also generated when restore operation is finished.
But how to detect window restore operation is about to begin?
I need detect exact moment when window is about to restore , but not the moment when already restored. I am developing multithread DirectX
application. I render in dedicated secondary thread. When window is about to begin maximize or restore I need to change render back buffer size (DirectX Device
Reset
). I can resize back buffer only from main thread so I use Critical Sections
to sync with render thread. The problem is that I cant interrupt Present
operation in render thread and when maximize or restore operation is about to begin I wait until current Present
operation is finished and only then begin to resize (maximize / restore). If you change back buffer size too late (when maximize / restore operation is finished (WM_SIZE
message) you can notice old frame is drawn with wrong size (image is stretched).
回答1:
Well, it is nice to see that someone is still ponder over such issues. This small things, like one-second image stretching when resizing, distinguish a professional looking application from bedroom coded one.
In my old code I found tricks that probably will be interesting to you.
A first thing is that you can check 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);
}
But the problem is that it don't catch maximize / restore events when user double-clicks titlebar.
So I found a little trick, when parse WM_WINDOWPOSCHANGING
.
First let's do a little fun research. We read docs here and here where we found that:
WM_WINDOWPOSCHANGING message sent to a window whose size, position, or place in the Z order is ABOUT to change
Because it is nearly impossible to debug events in common debugger (how would you test if debugger often changes z-order of window?), so for testing purposes we will make a little console app with int main()
, where we initialize a window as usual (HINSTANCE we can get from GetModuleHandle(0);
). So we have a console and a window at same time. In window procedure we catch WM_WINDOWPOSCHANGING
and print info, it will tell us, to console:
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);
}
See utility functions here.
When we played enough we can now make it useful:
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);
I'm really not sure that is it a simplest or even is it right way to do this. But it works for now =) Also, I think your app dont'care what exactly happened: maximizing, restoration or resizing. It just cares if size has changed, so you need to resize your buffers / recreate swap chain etc...
Hope it helps! Happy coding!
来源:https://stackoverflow.com/questions/16204488/detect-window-restore-operation-is-about-to-begin