使用DeferWindowPos更新z顺序?

时间:2019-05-24 09:19:28

标签: c++ mfc

我正在尝试使用DeferWindowPos更新某些对话框的z顺序,但是它不起作用。好吧,z顺序确实会更改,但并不总是按请求的顺序更改。为什么会这样呢?应该可以,对吧?

我正在检查所有返回值。我观察到,如果添加标志SWP_NOSENDCHANGING,则DeferWindowPos返回0,而GetLastError()不返回任何错误代码。我没有在任何对话框类中为WM_WINDOWPOSCHANGING添加消息处理程序。

现在我改用SetWindowPos。总是可以,但速度较慢。

我写了一个测试,请参见下面的代码。任何帮助将不胜感激。

void test()
{
#ifdef DEFER_WINDOW_POS
    class DeferPos
    {
    public:
        DeferPos( const int innWindowCount = 1 )
        {
            m_hdwp = BeginDeferWindowPos( innWindowCount );
            assert( m_hdwp != nullptr );
        }
        ~DeferPos()
        {
            if( !EndDeferWindowPos(m_hdwp) ) { assert( false ); }
        }

        void Set( HWND hWnd, HWND hWndAfter, int x, int y, int nWidth, int nHeight, UINT uFlags )
        {
            assert( m_hdwp != nullptr );
            assert( GetLastError() == 0 );

            m_hdwp = DeferWindowPos( m_hdwp, hWnd, hWndAfter, x, y, nWidth, nHeight, uFlags );

            assert( m_hdwp != nullptr );
            assert( GetLastError() == 0 );
        }

    private:
        HDWP m_hdwp = nullptr;
    };

    auto update_z_order = [](const std::vector<HWND>& vec, UINT flags)
    {       
        DeferPos dp( static_cast<int>(vec.size()) );
        HWND hWndAfter = HWND_TOP;
        for( HWND hWnd : vec )
        {
            dp.Set( hWnd, hWndAfter, 0, 0, 0, 0, flags );
            hWndAfter = hWnd;
        }
    };
#else
    auto update_z_order = [](const std::vector<HWND>& vec, UINT flags)
    {       
        HWND hWndAfter = HWND_TOP;
        for( HWND hWnd : vec )
        {
            ::SetWindowPos(hWnd, hWndAfter, 0, 0, 0, 0, flags );
            hWndAfter = hWnd;
        }
    };
#endif

    auto get_dialog_z_order = []()
    {
        std::vector<HWND> vec;
        EnumWindows( [](HWND hWnd, LPARAM lparam)-> BOOL
        {
            if( dynamic_cast<CDialog*>(CWnd::FromHandle(hWnd)) )
            {
                reinterpret_cast<std::vector<HWND>*>(lparam)->push_back( hWnd );
            }
            return TRUE;
        }, reinterpret_cast<LPARAM>(&vec) );

        return vec;
    };

    const std::vector<HWND> original_order = get_dialog_z_order();
    const std::vector<HWND> reverse_order( original_order.rbegin(), original_order.rend() );

    const UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE;
    update_z_order( reverse_order, flags );

    const std::vector<HWND> new_order = get_dialog_z_order();

    assert( new_order == reverse_order ); // this assert sometimes fails when DEFER_WINDOW_POS is defined
}

0 个答案:

没有答案