WM_GETMINMAXINFO
,最大化操作完成时生成WM_SIZE
。
WM_SIZE
。
但是如何检测窗口恢复操作即将开始?
我需要检测窗口即将恢复的确切时刻,但不是已经恢复的时刻。我正在开发多线程DirectX
应用程序。我在专用的辅助线程中渲染。当窗口即将开始最大化或恢复时,我需要更改渲染后缓冲区大小(DirectX Device
Reset
)。我只能从主线程重新调整缓冲区大小,所以我使用Critical Sections
与渲染线程同步。问题是我无法在渲染线程中中断Present
操作,当最大化或恢复操作即将开始时,我等到当前Present
操作完成,然后才开始调整大小(最大化/恢复)。如果更改后退缓冲区大小太晚(当最大化/恢复操作完成时(WM_SIZE
消息),您可以注意到绘制的旧框架尺寸错误(图像被拉伸)。
答案 0 :(得分:2)
嗯,很高兴看到有人仍然在思考这些问题。这些小东西,比如调整大小时的一秒钟图像拉伸,将专业外观应用与卧室编码应用区分开来。
在我的旧代码中,我发现了一些可能对您感兴趣的技巧。
首先,您可以查看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
时找到了一个小技巧。
首先让我们做一些有趣的研究。我们阅读了文档here和here,其中我们发现:
发送到窗口的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);
}
请参阅实用程序函数here。
当我们玩得足够时,我们现在可以使它变得有用:
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);
我真的不确定这是最简单的,甚至是正确的方法。但它现在适用=) 此外,我认为您的应用不关心完全发生了什么:最大化,恢复或调整大小。它只关心大小是否已更改,因此您需要调整缓冲区大小/重新创建交换链等...
希望它有所帮助!快乐的编码!