检测窗口还原操作即将开始 [英] Detect window restore operation is about to begin
问题描述
WM_SIZE
。 还原操作完成后也会生成WM_SIZE
。
但是如何检测窗口恢复操作即将开始?
我需要检测窗口即将恢复的确切时刻,但不是已经恢复的时刻。我正在开发多线程 DirectX
应用程序。我在专用的二级线程渲染。当窗口即将开始最大化或恢复时,我需要更改渲染缓冲区大小( DirectX Device
重置
)。我可以从主线程重新调整缓冲区的大小,所以我使用关键部分
与渲染线程同步。问题是我不能中断呈现线程中的
操作,并且当最大化或恢复操作即将开始时,我等到当前存在
操作完成,然后才开始调整大小(最大化/恢复)。如果您将缓冲区大小更改为太晚(最大化/还原操作完成时( WM_SIZE
消息),您可以注意到,旧帧的大小(图像被拉伸)被绘制。 / p>
嗯,很高兴看到有人还在思考这些问题,这个小事情,像一秒的图像拉伸在调整大小时,区分专业的应用程序与卧室编码的一个。
在我的旧代码中,我发现可能会对你有趣的技巧
第一件事你可以查看 WM_SYSCOMMAND
:
case WM_SYSCOMMAND:
{
switch(wParam)
{
case SC_MAXIMIZE:
std :: cout<<转到MAXIMIZE:<< std :: endl;
break;
case SC_MINIMIZE:
std :: cout<<去最小化:<的std :: ENDL;
break;
case SC_RESTORE:
std :: cout<<< 进入RESTORE:<<的std :: ENDL;
break;
默认值:
break;
}
返回DefWindowProc(m_hWnd,msg,wParam,lParam);
}
但问题是,当用户没有捕获最大化/恢复事件时
所以我发现一个小技巧,解析 WM_WINDOWPOSCHANGING
。
首先让我们做一些有趣的研究。我们阅读文档这里和此处在那里我们发现:
WM_WINDOWPOSCHANGING消息发送到一个窗口,其大小,位置或Z位置是关于更改
因为在通用调试器中调试事件几乎是不可能的(如何测试调试器是否经常更改z-窗口的顺序),所以为了测试的目的,我们将使用 int main()
制作一个小程控应用程序,我们像往常一样初始化一个窗口(HINSTANCE我们可以从的GetModuleHandle(0);
)。所以我们同时有一个控制台和一个窗口。在窗口过程中,我们捕获 WM_WINDOWPOSCHANGING
并打印信息,它会告诉我们,控制台:
code> case WM_WINDOWPOSCHANGING:
{
WINDOWPOS * wp =((WINDOWPOS *)lParam);
//检查保存在成员(或全局)bools中的当前状态
//设置它们在
之前检查WM_SIZE if(m_bMaximized)
{
std :: cout<<< 目前MAXIMIZED:;
}
else if(m_bMinimized)
{
std :: cout<<< 目前MINIMIZED:;
}
else
{
std :: cout<<< 目前正常:;
}
dbgPrintPositionCurrent();
std :: cout<<< 要改变为:;
dbgPrintPosition(wp-> x,wp-> y,wp-> cx,wp-> cy,wp-> flags);
std :: cout<<< std :: endl<<的std :: ENDL;
返回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!);
//最大化
if(m_bMaximized&& bFrameChanged&!bNoCopyBits)
{
std :: cout< MAXIMIZED - > NORMAL<的std :: ENDL;
}
if(m_bMaximized&& bFrameChanged&& bNoCopyBits)
{
std :: cout<< MAXIMIZED - > MINIMIZED<<的std :: ENDL;
}
//从正常状态
如果(bNormal&& bFrameChanged&!bNoCopyBits)
{
std :: cout << NORMAL - > MAXIMIZED<的std :: ENDL;
}
if(bNormal&& bFrameChanged&& bNoCopyBits)
{
std :: cout<< NORMAL - > MINIMIZED<的std :: ENDL;
}
//从最小化
if(m_bMinimized&& bFrameChanged)
{
std :: cout<< MINIMIZED - > MAXIMIZED<的std :: ENDL;
}
if(m_bMinimized&& m_bMaximized&& bFrameChanged)
{
std :: cout<< MINIMIZED - > MAXIMIZED<的std :: ENDL;
}
返回DefWindowProc(m_hWnd,msg,wParam,lParam);
我真的不知道这是一个最简单的甚至是正确的方式来做到这一点。但是它现在适用于=
此外,我认为您的应用程序不会正确地发现 :最大化,恢复或调整大小。它只是关心如果大小已经改变,所以你需要调整你的缓冲区/重新创建交换链等...
希望它有帮助!快乐的编码!
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).
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!
这篇关于检测窗口还原操作即将开始的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!