检测窗口还原操作即将开始 [英] Detect window restore operation is about to begin

查看:123
本文介绍了检测窗口还原操作即将开始的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当最大化操作即将开始时,将生成WM_GETMINMAXINFO ,而最大化操作完成后,将生成 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆